moving old trunk out of the way to move bigbang branch into this position


git-svn-id: https://svn.apache.org/repos/asf/directory/shared/tags/old_trunk@686915 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3bb1675
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,222 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+----
+
+Copyright (c) 2000 - 2006 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of 
+this software and associated documentation files (the "Software"), to deal in the 
+Software without restriction, including without limitation the rights to use, copy, 
+modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
+and to permit persons to whom the Software is furnished to do so, subject to the 
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..c213a74
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,7 @@
+Apache Directory Shared
+Copyright 2003-2008 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
diff --git a/README.txt b/README.txt
new file mode 100755
index 0000000..13378f8
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,23 @@
+This distribution includes cryptographic software.  The country in 
+   which you currently reside may have restrictions on the import, 
+   possession, use, and/or re-export to another country, of 
+   encryption software.  BEFORE using any encryption software, please 
+   check your country's laws, regulations and policies concerning the
+   import, possession, or use, and re-export of encryption software, to 
+   see if this is permitted.  See <http://www.wassenaar.org/> for more
+   information.
+
+   The U.S. Government Department of Commerce, Bureau of Industry and
+   Security (BIS), has classified this software as Export Commodity 
+   Control Number (ECCN) 5D002.C.1, which includes information security
+   software using or performing cryptographic functions with asymmetric
+   algorithms.  The form and manner of this Apache Software Foundation
+   distribution makes it eligible for export under the License Exception
+   ENC Technology Software Unrestricted (TSU) exception (see the BIS 
+   Export Administration Regulations, Section 740.13) for both object 
+   code and source code.
+
+   The following provides more details on the included cryptographic
+   software:
+
+   http://www.bouncycastle.org/
diff --git a/asn1-codec/pom.xml b/asn1-codec/pom.xml
index deb21fe..3d540d0 100644
--- a/asn1-codec/pom.xml
+++ b/asn1-codec/pom.xml
@@ -1,27 +1,30 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-asn1-codec</artifactId>
   <name>Apache Directory MINA ASN.1 Codec Shared</name>
diff --git a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecDecoder.java b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecDecoder.java
index d575ed6..4577c15 100644
--- a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecDecoder.java
+++ b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecDecoder.java
@@ -19,7 +19,7 @@
  */
 package org.apache.directory.shared.asn1.codec;
 
-import org.apache.directory.shared.asn1.codec.DecoderException;
+
 import org.apache.directory.shared.asn1.codec.stateful.DecoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.StatefulDecoder;
 import org.apache.mina.common.ByteBuffer;
@@ -27,6 +27,7 @@
 import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
 import org.apache.mina.filter.codec.ProtocolDecoderOutput;
 
+
 /**
  * Adapts {@link StatefulDecoder} to MINA <tt>ProtocolDecoder</tt>
  * 
@@ -35,24 +36,24 @@
  */
 public class Asn1CodecDecoder extends ProtocolDecoderAdapter
 {
-
     private final StatefulDecoder decoder;
-
     private final DecoderCallbackImpl callback = new DecoderCallbackImpl();
 
+
     public Asn1CodecDecoder( StatefulDecoder decoder )
     {
         decoder.setCallback( callback );
         this.decoder = decoder;
     }
 
-    public void decode( IoSession session, ByteBuffer in,
-                        ProtocolDecoderOutput out ) throws DecoderException
+
+    public void decode( IoSession session, ByteBuffer in, ProtocolDecoderOutput out ) throws DecoderException
     {
         callback.decOut = out;
         decoder.decode( in.buf() );
     }
 
+
     private class DecoderCallbackImpl implements DecoderCallback
     {
         private ProtocolDecoderOutput decOut;
diff --git a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecEncoder.java b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecEncoder.java
index 1312e28..2d36226 100644
--- a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecEncoder.java
+++ b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/Asn1CodecEncoder.java
@@ -19,11 +19,11 @@
  */
 package org.apache.directory.shared.asn1.codec;
 
+
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Iterator;
 
-import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.StatefulEncoder;
 import org.apache.mina.common.ByteBuffer;
@@ -31,6 +31,7 @@
 import org.apache.mina.filter.codec.ProtocolEncoder;
 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
 
+
 /**
  * Adapts {@link StatefulEncoder} to MINA <tt>ProtocolEncoder</tt>
  * 
@@ -40,30 +41,33 @@
 public class Asn1CodecEncoder implements ProtocolEncoder
 {
     private final StatefulEncoder encoder;
-
     private final EncoderCallbackImpl callback = new EncoderCallbackImpl();
 
+
     public Asn1CodecEncoder( StatefulEncoder encoder )
     {
         encoder.setCallback( callback );
         this.encoder = encoder;
     }
 
-    public void encode( IoSession session, Object message,
-                        ProtocolEncoderOutput out ) throws EncoderException
+
+    public void encode( IoSession session, Object message, ProtocolEncoderOutput out ) throws EncoderException
     {
         callback.encOut = out;
         encoder.encode( message );
     }
 
+
     public void dispose( IoSession session ) throws Exception
     {
     }
 
+
     private class EncoderCallbackImpl implements EncoderCallback
     {
         private ProtocolEncoderOutput encOut;
 
+
         public void encodeOccurred( StatefulEncoder codec, Object encoded )
         {
             if( encoded instanceof java.nio.ByteBuffer )
@@ -76,9 +80,9 @@
             else if( encoded instanceof Object[] )
             {
                 Object[] bufArray = ( Object[] ) encoded;
-                for( int i = 0; i < bufArray.length; i ++ )
+                for ( Object buf : bufArray )
                 {
-                    this.encodeOccurred( codec, bufArray[ i ] );
+                    this.encodeOccurred( codec, buf );
                 }
 
                 encOut.mergeAll();
@@ -95,10 +99,9 @@
             }
             else if( encoded instanceof Collection )
             {
-                Iterator it = ( ( Collection ) encoded ).iterator();
-                while( it.hasNext() )
+                for ( Object o : ( ( Collection ) encoded ) )
                 {
-                    this.encodeOccurred( codec, it.next() );
+                    this.encodeOccurred( codec, o );
                 }
                 
                 encOut.mergeAll();
diff --git a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/package.html b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/package.html
index e57c4f7..c5d2e39 100644
--- a/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/package.html
+++ b/asn1-codec/src/main/java/org/apache/directory/shared/asn1/codec/package.html
@@ -1,4 +1,23 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
 <html>
 <head>
 </head>
diff --git a/asn1-codec/src/site/site.xml b/asn1-codec/src/site/site.xml
new file mode 100644
index 0000000..020b38e
--- /dev/null
+++ b/asn1-codec/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+-->
+<project name="${project.name}">
+    <bannerLeft>
+        <name>${project.name}</name>
+    </bannerLeft>
+    <publishDate position="navigation-bottom" format="dd-MM-yyyy HH:mm" />
+    <body>
+        <menu name="Parent">
+            <item name="Apache Directory Shared" href="../index.html" />
+        </menu>
+        <menu ref="reports" />
+    </body>
+</project>
diff --git a/asn1/pom.xml b/asn1/pom.xml
index 9da6f7e..c3e0012 100644
--- a/asn1/pom.xml
+++ b/asn1/pom.xml
@@ -1,38 +1,43 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-asn1</artifactId>
   <name>Apache Directory ASN.1 Shared</name>
   <packaging>jar</packaging>  
   
+  <!--
   <distributionManagement>
     <site>
       <id>apacheds.websites</id>
       <url>scp://minotaur.apache.org/www/directory.apache.org/newsite/subprojects/asn1/</url>
     </site>
   </distributionManagement>
+  -->
 
 </project>
 
diff --git a/asn1/src/main/appended-resources/META-INF/LICENSE b/asn1/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..e7b65c0
--- /dev/null
+++ b/asn1/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,20 @@
+----
+
+Copyright (c) 2000 - 2006 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of 
+this software and associated documentation files (the "Software"), to deal in the 
+Software without restriction, including without limitation the rights to use, copy, 
+modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
+and to permit persons to whom the Software is furnished to do so, subject to the 
+following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/AbstractAsn1Object.java b/asn1/src/main/java/org/apache/directory/shared/asn1/AbstractAsn1Object.java
index 7d4f136..be1d5c5 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/AbstractAsn1Object.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/AbstractAsn1Object.java
@@ -30,6 +30,7 @@
  * An abstract class which implements basic TLV operations.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public abstract class AbstractAsn1Object implements Asn1Object
 {
@@ -47,7 +48,7 @@
 
     
     /** The identifier of the asqsocaited TLV */
-    private transient int tlvId;
+    private int tlvId;
 
     // ~ Methods
     // ------------------------------------------------------------------------------------
@@ -97,9 +98,9 @@
     /**
      * Encode the object to a PDU.
      * 
-     * @param buffer
-     *            The buffer where to put the PDU
+     * @param buffer The buffer where to put the PDU
      * @return The PDU.
+     * @throws EncoderException if the buffer can't be encoded
      */
     public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
     {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/Asn1Object.java b/asn1/src/main/java/org/apache/directory/shared/asn1/Asn1Object.java
index 1399bac..45d2474 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/Asn1Object.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/Asn1Object.java
@@ -30,6 +30,7 @@
  * An abstract class which implements basic TLV operations.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface Asn1Object
 {
@@ -53,9 +54,9 @@
     /**
      * Encode the object to a PDU.
      * 
-     * @param buffer
-     *            The buffer where to put the PDU
+     * @param buffer The buffer where to put the PDU
      * @return The PDU.
+     * @throws EncoderException if the buffer can't be encoded
      */
     ByteBuffer encode( ByteBuffer buffer ) throws EncoderException;
 
@@ -85,7 +86,7 @@
      * @param expectedLength
      *            The expectedLength to set.
      */
-    public void setExpectedLength( int expectedLength );
+    void setExpectedLength( int expectedLength );
 
 
     /**
@@ -94,7 +95,7 @@
      * @param currentLength
      *            The currentLength to set.
      */
-    public void setCurrentLength( int currentLength );
+    void setCurrentLength( int currentLength );
 
 
     /**
@@ -102,5 +103,5 @@
      * 
      * @return Returns the parent.
      */
-    public Asn1Object getParent();
+    Asn1Object getParent();
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/AbstractContainer.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/AbstractContainer.java
index 7fb4680..9824bdf 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/AbstractContainer.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/AbstractContainer.java
@@ -32,7 +32,8 @@
  * the informations needed to decode a PDU.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
+  * @version $Rev$, $Date$
+*/
 public class AbstractContainer implements IAsn1Container
 {
     // ~ Instance fields
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/Asn1Decoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/Asn1Decoder.java
index 189b22e..b29c1df 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/Asn1Decoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/Asn1Decoder.java
@@ -20,6 +20,8 @@
 package org.apache.directory.shared.asn1.ber;
 
 
+import java.nio.ByteBuffer;
+
 import org.apache.directory.shared.asn1.ber.grammar.IStates;
 import org.apache.directory.shared.asn1.ber.tlv.ITLVBerDecoderMBean;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -30,8 +32,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.nio.ByteBuffer;
-
 
 /**
  * A BER TLV Tag component decoder. This decoder instanciate a Tag. The tag
@@ -39,7 +39,8 @@
  * delivered but should copy the data if they need it over the long term.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
+ * @version $Rev$, $Date$
+*/
 public class Asn1Decoder implements ITLVBerDecoderMBean
 {
     // ~ Static fields/initializers
@@ -95,7 +96,6 @@
      * the result and other informations.
      * @return <code>true</code> if there are more bytes to read, <code>false 
      * </code> otherwise
-     * @throws DecoderException If something went wrong.
      */
     private boolean treatTagStartState( ByteBuffer stream, IAsn1Container container )
     {
@@ -166,6 +166,7 @@
      * Check if the TLV tree is fully decoded
      * 
      * @param container The container
+     * @return <code>true</code> if the TLV has been decoded
      */
     private boolean isTLVDecoded( IAsn1Container container )
     {
@@ -264,7 +265,6 @@
      * the result and other informations.
      * @return <code>true</code> if there are more bytes to read, <code>false 
      * </code> otherwise
-     * @throws DecoderException Thrown if anything went wrong
      */
     private boolean treatLengthPendingState( ByteBuffer stream, IAsn1Container container )
     {
@@ -288,7 +288,7 @@
                 tlv.incLengthBytesRead();
                 length = ( length << 8 ) | ( octet & 0x00FF );
                 
-                if ( stream.hasRemaining() == false )
+                if ( !stream.hasRemaining() )
                 {
                     tlv.setLength( length );
                     
@@ -520,7 +520,6 @@
      * the result and other informations.
      * @return <code>true</code> if there are more bytes to read, <code>false 
      * </code> otherwise
-     * @throws DecoderException Thrown if anything went wrong
      */
     private boolean treatValueStartState( ByteBuffer stream, IAsn1Container container )
     {
@@ -568,7 +567,6 @@
      * @return <code>MORE</code> if some bytes remain in the buffer when the
      * value has been decoded, <code>END</code> if whe still need to get some 
      * more bytes.
-     * @throws DecoderException Thrown if anything went wrong
      */
     private boolean treatValuePendingState( ByteBuffer stream, IAsn1Container container )
     {
@@ -807,6 +805,9 @@
                     hasRemaining = false;
 
                     break;
+                    
+                default :
+                    break;
             }
         }
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/IAsn1Container.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/IAsn1Container.java
index 8e70d31..3fc76f9 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/IAsn1Container.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/IAsn1Container.java
@@ -29,6 +29,7 @@
  * Every ASN1 container must implement this interface.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface IAsn1Container
 {
@@ -57,7 +58,7 @@
      * 
      * @param tlv The current TLV
      */
-    public void setCurrentTLV( TLV tlv );
+    void setCurrentTLV( TLV tlv );
 
 
     /**
@@ -65,7 +66,7 @@
      * 
      * @return Returns the current TLV being decoded
      */
-    public TLV getCurrentTLV();
+    TLV getCurrentTLV();
 
 
     /**
@@ -73,7 +74,7 @@
      * 
      * @return Returns the grammar used to decode a LdapMessage.
      */
-    public IGrammar getGrammar();
+    IGrammar getGrammar();
 
 
     /**
@@ -81,7 +82,7 @@
      * 
      * @return Returns the transition from the previous state to the new state
      */
-    public int getTransition();
+    int getTransition();
 
 
     /**
@@ -89,18 +90,18 @@
      * 
      * @param transition The transition to set
      */
-    public void setTransition( int transition );
+    void setTransition( int transition );
 
     /**
      * @return Returns the states.
      */
-    public IStates getStates();
+    IStates getStates();
 
 
     /**
      * @return get the parent TLV.
      */
-    public TLV getParentTLV();
+    TLV getParentTLV();
 
 
     /**
@@ -108,7 +109,7 @@
      * 
      * @param parentTLV The new parent TLV
      */
-    public void setParentTLV( TLV parentTLV );
+    void setParentTLV( TLV parentTLV );
 
 
     /**
@@ -116,7 +117,7 @@
      * 
      * @return true if this can be the last transition
      */
-    public boolean isGrammarEndAllowed();
+    boolean isGrammarEndAllowed();
 
 
     /**
@@ -125,17 +126,17 @@
      * @param grammarEndAllowed true or false, depending on the next transition
      * being an end or not.
      */
-    public void grammarEndAllowed( boolean grammarEndAllowed );
+    void grammarEndAllowed( boolean grammarEndAllowed );
     
     /**
      * Get a new TLV id
      * @return a unique value representing the current TLV id
      */
-    public int getNewTlvId();
+    int getNewTlvId();
 
     /**
      * Get the current TLV id
      * @return a unique value representing the current TLV id
      */
-    public int getTlvId();
+    int getTlvId();
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/AbstractGrammar.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/AbstractGrammar.java
index 27683af..b604c10 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/AbstractGrammar.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/AbstractGrammar.java
@@ -23,9 +23,9 @@
 import org.apache.directory.shared.asn1.ber.IAsn1Container;
 import org.apache.directory.shared.asn1.codec.DecoderException;
 import org.apache.directory.shared.asn1.util.Asn1StringUtils;
-import org.slf4j.LoggerFactory;
 
 import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -33,6 +33,7 @@
  * the transitions table.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public abstract class AbstractGrammar implements IGrammar
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarAction.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarAction.java
index 3a2fa68..c6b2559 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarAction.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarAction.java
@@ -25,6 +25,7 @@
  * Those informations are not mandatory, but they can be usefull for debugging.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public abstract class GrammarAction implements IAction
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarTransition.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarTransition.java
index f9a1c0e..da107d4 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarTransition.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/GrammarTransition.java
@@ -28,6 +28,7 @@
  * state, and the action to execute while transiting.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class GrammarTransition
 {
@@ -49,7 +50,9 @@
     /**
      * Creates a new GrammarTransition object.
      * 
-     * @param currentState The current transition
+     * @param previousState the previous state
+     * @param currentState The current state
+     * @param currentTag the current TLV's tag
      * @param action The action to execute. It could be null.
      */
     public GrammarTransition( int previousState, int currentState, int currentTag, IAction action )
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IAction.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IAction.java
index 503b4d5..e840a57 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IAction.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IAction.java
@@ -29,6 +29,7 @@
  * in all the implementong classes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface IAction
 {
@@ -43,5 +44,5 @@
      * @throws DecoderException
      *             Thrown if something went wrong.
      */
-    public void action( IAsn1Container container ) throws DecoderException;
+    void action( IAsn1Container container ) throws DecoderException;
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IGrammar.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IGrammar.java
index 7c72ebd..1f1baa1 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IGrammar.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IGrammar.java
@@ -28,6 +28,7 @@
  * The interface which expose common behavior of a Gramar implementer.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface IGrammar
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IStates.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IStates.java
index f84a393..414728b 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IStates.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/grammar/IStates.java
@@ -20,33 +20,46 @@
 package org.apache.directory.shared.asn1.ber.grammar;
 
 
-import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
-
-
 /**
  * This interface is used to store the different states of a grammar. While
  * tracing debugging information, the methods to dump the current state as a
  * string are called.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface IStates
 {
     /** The initial state of every grammar */
-    static int INIT_GRAMMAR_STATE = 0;
+    int INIT_GRAMMAR_STATE = 0;
 
     /** The ending state for every grammars */
-    static int GRAMMAR_END = -1;
+    int GRAMMAR_END = -1;
 
     /** The END_STATE */
-    static int END_STATE = -1;
+    int END_STATE = -1;
 
-    /** Get the current state */
+    /** 
+     * Get the current state's name 
+     * 
+     * @param state the current state
+     * @return the associated name for this state
+     */
     String getState( int state );
 
-    /** Return the grammar name from a grammar */
+    /** 
+     * Return the grammar name of a grammar
+     * 
+     * @param grammar the grammar from which we want the name
+     * @return the grammar's name
+     */
     String getGrammarName( IGrammar grammar );
 
-    /** Return the grammar name from a grammar number */
+    /** 
+     * Return the grammar name from a grammar number 
+     * 
+     * @param grammar the grammar number from which we want the name
+     * @return the grammar's name
+     */
     String getGrammarName( int grammar );
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/ITLVBerDecoderMBean.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/ITLVBerDecoderMBean.java
index 7050928..319a09a 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/ITLVBerDecoderMBean.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/ITLVBerDecoderMBean.java
@@ -25,6 +25,7 @@
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface ITLVBerDecoderMBean
 {
@@ -36,8 +37,8 @@
      * including the first byte. Max is 127 if the Length use a definite form,
      * default is 1
      * 
-     * @param length
-     *            The number of byte to use
+     * @param length the number of byte to use
+     * @throws DecoderException 
      */
     void setMaxLengthLength( int length ) throws DecoderException;
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLV.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLV.java
index ca79c55..bc38e0b 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLV.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLV.java
@@ -27,6 +27,7 @@
  * This class is used to store Tag, Length and Value decoded from a PDU.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class TLV
 {
@@ -103,6 +104,8 @@
 
     /**
      * Creates a new TLV object.
+     * 
+     * @param id the TLV's id
      */
     public TLV( int id )
     {
@@ -122,6 +125,7 @@
     /**
      * Checks to see if the tag is constructed.
      * 
+     * @param tag the TLV's tag 
      * @return true if constructed, false if primitive
      */
     public static boolean isConstructed( byte tag )
@@ -144,6 +148,7 @@
      * Checks to see if the tag represented by this Tag is primitive or
      * constructed.
      * 
+     * @param tag the tag to be checked 
      * @return true if it is primitive, false if it is constructed
      */
     public static boolean isPrimitive( byte tag )
@@ -154,6 +159,7 @@
     /**
      * Tells if the tag is Universal or not
      * 
+     * @param tag the tag to be checked
      * @return true if it is primitive, false if it is constructed
      */
     public static boolean isUniversal( byte tag )
@@ -183,7 +189,9 @@
     }
 
     /**
-     * @return Returns the tag.
+     * Set a tag value for this TLV.
+     * 
+     * @param tag the tag field for this TLV.
      */
     public void setTag( byte tag )
     {
@@ -372,46 +380,78 @@
     }
 
 
+    /**
+     * @return the number of bytes necessary to store the TLV's length
+     */
     public int getLengthNbBytes()
     {
         return lengthNbBytes;
     }
 
 
+    /**
+     * Set the number of bytes we should use to store the TLV's length
+     *  @param lengthNbBytes the number of bytes necessary to store the TLV's length
+     */
     public void setLengthNbBytes( int lengthNbBytes )
     {
         this.lengthNbBytes = lengthNbBytes;
     }
 
 
+    /**
+     * @return the tLV's length
+     */
     public int getLength()
     {
         return length;
     }
 
 
+    /**
+     * Set the TLV's length
+     *
+     * @param length the TLV's length
+     */
     public void setLength( int length )
     {
         this.length = length;
     }
 
 
+    /**
+     * @return the currently read TLV's length bytes
+     */
     public int getLengthBytesRead()
     {
         return lengthBytesRead;
     }
 
 
+    /**
+     * Set the currently read TLV's length bytes.
+     * 
+     * @param lengthBytesRead the currently read TLV's length bytes
+     */
     public void setLengthBytesRead( int lengthBytesRead )
     {
         this.lengthBytesRead = lengthBytesRead;
     }
     
+    
+    /**
+     * Increment the number of bytes read for this TLV
+     *
+     */
     public void incLengthBytesRead()
     {
         lengthBytesRead++;
     }
 
+    
+    /**
+     * @return the TLV's ID 
+     */
     public int getId()
     {
         return id;
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLVStateEnum.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLVStateEnum.java
index b1499c0..531ccf2 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLVStateEnum.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/TLVStateEnum.java
@@ -24,6 +24,7 @@
  * Stores the different states of a PDU parsing.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class TLVStateEnum
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/UniversalTag.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/UniversalTag.java
index 41b0783..fbed9a0 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/UniversalTag.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/UniversalTag.java
@@ -166,6 +166,7 @@
  * </table>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class UniversalTag
 {
@@ -271,13 +272,13 @@
     /** String representation of the tags */
     private static final String[] UNIVERSAL_TAG_STRING =
         { 
-    		"RESERVED_0", 
-    	    "BOOLEAN", 
-    	    "INTEGER", 
-    	    "BIT_STRING", 
-    	    "OCTET_STRING", 
-    	    "NULL", 
-    	    "OBJECT_IDENTIFIER",
+            "RESERVED_0", 
+            "BOOLEAN", 
+            "INTEGER", 
+            "BIT_STRING", 
+            "OCTET_STRING", 
+            "NULL", 
+            "OBJECT_IDENTIFIER",
             "OBJECT_DESCRIPTOR", 
             "EXTERNAL_INSTANCE_OF", 
             "REAL", 
@@ -306,24 +307,34 @@
         };
 
     /** ASN.1 primitive tag values */
+    /** Boolean TAG */
     public static final byte BOOLEAN_TAG = 0x01;
 
+    /** Integer TAG */
     public static final byte INTEGER_TAG = 0x02;
 
+    /** BIT_STRING TAG */
     public static final byte BIT_STRING_TAG = 0x03;
 
+    /** OCTET_STRING TAG */
     public static final byte OCTET_STRING_TAG = 0x04;
 
+    /** ENUMERATED TAG */
     public static final byte ENUMERATED_TAG = 0x0A;
     
+    /** UTF8_STRING TAG */
     public static final byte UTF8_STRING_TAG = 0x0C;
 
+    /** GENERALIZED_TIME TAG */
     public static final byte GENERALIZED_TIME_TAG = 0x18;
 
+    /** GENERALIZED_STRING TAG */
     public static final byte GENERALIZED_STRING_TAG = 0x1B;
 
+    /** SEQUENCE TAG */
     public static final byte SEQUENCE_TAG = 0x30;
 
+    /** SET TAG */
     public static final byte SET_TAG = 0x31;
 
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/Value.java b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/Value.java
index a37a3b3..25dc358 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/Value.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/ber/tlv/Value.java
@@ -20,25 +20,25 @@
 package org.apache.directory.shared.asn1.ber.tlv;
 
 
-import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
+import java.io.Serializable;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.asn1.primitives.BitString;
 import org.apache.directory.shared.asn1.primitives.OID;
 import org.apache.directory.shared.asn1.util.Asn1StringUtils;
 
-import java.io.Serializable;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-
 
 /**
  * This class stores the data decoded from a TLV.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
-public class Value implements Cloneable, Serializable
+public class Value implements Serializable
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
     // ~ Instance fields
     // ----------------------------------------------------------------------------
@@ -82,8 +82,10 @@
 
     /**
      * The constructor.
+     * 
+     * @param value the associated value
      */
-    public Value(byte[] value)
+    public Value( byte[] value )
     {
         // Do a copy of the byte array
         data = new byte[value.length];
@@ -125,19 +127,6 @@
 
 
     /**
-     * Clone the Value
-     * 
-     * @return An object that is a copy of this Value
-     * @throws CloneNotSupportedException Thrown when the cloning failed
-     */
-    public Object clone() throws CloneNotSupportedException
-    {
-
-        return super.clone();
-    }
-
-
-    /**
      * Get the Values'data
      * 
      * @return Returns the data.
@@ -164,12 +153,12 @@
     /**
      * Append some bytes to the data buffer.
      * 
-     * @param data The data to append.
+     * @param buffer The data to append.
      */
-    public void addData( ByteBuffer data )
+    public void addData( ByteBuffer buffer )
     {
-        int length = data.remaining();
-        data.get( this.data, currentPos, length );
+        int length = buffer.remaining();
+        buffer.get( data, currentPos, length );
         currentPos += length;
     }
 
@@ -189,12 +178,12 @@
     /**
      * Append some bytes to the data buffer.
      * 
-     * @param data The data to append.
+     * @param array The data to append.
      */
-    public void addData( byte[] data )
+    public void addData( byte[] array )
     {
-        System.arraycopy( data, 0, this.data, currentPos, data.length );
-        currentPos = data.length;
+        System.arraycopy( array, 0, this.data, currentPos, array.length );
+        currentPos = array.length;
     }
 
 
@@ -339,6 +328,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param string The String to be encoded. It is supposed to be UTF-8
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, String string ) throws EncoderException
     {
@@ -373,6 +364,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param bitString The BitString to be encoded.
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, BitString bitString ) throws EncoderException
     {
@@ -407,6 +400,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param bytes The bytes to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, byte[] bytes ) throws EncoderException
     {
@@ -443,6 +438,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param oid The OID to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, OID oid ) throws EncoderException
     {
@@ -475,6 +472,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param value The integer to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, int value ) throws EncoderException
     {
@@ -504,6 +503,8 @@
      * @param buffer The PDU in which the value will be put
      * @param tag The tag if it's not an UNIVERSAL one
      * @param value The integer to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, byte tag, int value ) throws EncoderException
     {
@@ -532,6 +533,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param value The integer to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encodeEnumerated( ByteBuffer buffer, int value ) throws EncoderException
     {
@@ -560,6 +563,8 @@
      * 
      * @param buffer The PDU in which the value will be put
      * @param bool The boolean to be encoded
+     * @throws EncoderException if the PDU in which the value should be encoded is
+     * two small
      */
     public static void encode( ByteBuffer buffer, boolean bool ) throws EncoderException
     {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/binary/Hex.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/binary/Hex.java
index b3f2c28..6595868 100755
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/binary/Hex.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/binary/Hex.java
@@ -75,7 +75,7 @@
         {
             int f = toDigit( data[j], j ) << 4;
             j++;
-            f = f | toDigit( data[j], j );
+            f |= toDigit( data[j], j );
             j++;
             out[i] = ( byte ) ( f & 0xFF );
         }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderMonitor.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderMonitor.java
index d18e591..c1defae 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderMonitor.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderMonitor.java
@@ -78,10 +78,9 @@
     /**
      * Monitors callbacks that deliver a fully decoded object.
      * 
-     * @param decoder
-     *            the stateful decoder driving the callback
-     * @param decoded
-     *            the object that was decoded
+     * @param decoder the stateful decoder driving the callback
+     * @param cb the callback to call when the decoder has done its job
+     * @param decoded the object that was decoded
      */
     void callbackOccured( StatefulDecoder decoder, DecoderCallback cb, Object decoded );
 
@@ -89,12 +88,9 @@
     /**
      * Monitors changes to the callback.
      * 
-     * @param decoder
-     *            the decoder whose callback was set
-     * @param oldcb
-     *            the unset old callback, or null if none was set
-     * @param newcb
-     *            the newly set callback, or null if callback is cleared
+     * @param decoder the decoder whose callback was set
+     * @param oldcb the unset old callback, or null if none was set
+     * @param newcb the newly set callback, or null if callback is cleared
      */
     void callbackSet( StatefulDecoder decoder, DecoderCallback oldcb, DecoderCallback newcb );
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStack.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStack.java
index 1ee3d46..9770013 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStack.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStack.java
@@ -115,10 +115,10 @@
      * Decodes an encoded object by calling decode on the decoder at the bottom
      * of the stack. Callbacks are chained to feed the output of one decoder
      * into the input decode method of another. If the stack is empty then the
-     * arguement is delivered without change to this StatefulDecoder's callback.
+     * argument is delivered without change to this StatefulDecoder's callback.
      * 
-     * @see org.apache.directory.shared.asn1.codec.stateful.StatefulDecoder#
-     *      decode(java.lang.Object)
+     * @param encoded an object representing a piece of encoded data
+     * @throws DecoderException if the encoded element can't be decoded
      */
     public synchronized void decode( Object encoded ) throws DecoderException
     {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderCallback.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderCallback.java
index c45ab92..d79fa97 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderCallback.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderCallback.java
@@ -24,7 +24,7 @@
  * Document me.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$, $Date$
  */
 public interface EncoderCallback
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitor.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitor.java
index 36ae94e..45a9cb3 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitor.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitor.java
@@ -24,12 +24,12 @@
  * Document me.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$, $Date$
  */
 public interface EncoderMonitor
 {
     /** Use this if you don't want to recreate this as just a NOOP monitor */
-    public EncoderMonitor INSTANCE = new EncoderMonitorAdapter();
+    EncoderMonitor INSTANCE = new EncoderMonitorAdapter();
 
 
     /**
@@ -77,10 +77,9 @@
     /**
      * Monitors callbacks that deliver a fully decoded object.
      * 
-     * @param encoder
-     *            the stateful encoder driving the callback
-     * @param decoded
-     *            the object that was decoded
+     * @param encoder the stateful encoder driving the callback
+     * @param cb the callback to call when the encoder has done its job
+     * @param decoded the object that was decoded
      */
     void callbackOccured( StatefulEncoder encoder, EncoderCallback cb, Object decoded );
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitorAdapter.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitorAdapter.java
index d2db936..ca5458e 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitorAdapter.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/EncoderMonitorAdapter.java
@@ -24,7 +24,7 @@
  * Document me.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$, $Date$
  */
 public class EncoderMonitorAdapter implements EncoderMonitor
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulDecoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulDecoder.java
index c76bd4d..bc64cc5 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulDecoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulDecoder.java
@@ -39,14 +39,14 @@
 public interface StatefulDecoder
 {
     /**
-     * Decodes a peice of encoded data. The nature of this call, synchronous
+     * Decodes a piece of encoded data. The nature of this call, synchronous
      * verses asynchonous, with respect to driving the actual decoding of the
      * encoded data argument is determined by an implementation. A return from
-     * this method does not guarrantee any callbacks: zero or more callbacks may
+     * this method does not guarantee any callbacks: zero or more callbacks may
      * occur during this call.
      * 
-     * @param encoded
-     *            an object representing a peice of encoded data
+     * @param encoded an object representing a piece of encoded data
+     * @throws DecoderException if the encoded element can't be decoded
      */
     void decode( Object encoded ) throws DecoderException;
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulEncoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulEncoder.java
index f860e2c..cb10fc3 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulEncoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/StatefulEncoder.java
@@ -27,16 +27,35 @@
  * The StatefulEncoder interface.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$, $Date$
  */
 public interface StatefulEncoder
 {
-    public void encode( Object obj ) throws EncoderException;
+    /**
+     * Encodes a Message object piece by piece often emitting chunks of the
+     * final PDU to the callback if present.
+     * 
+     * @param obj the message object to encode into a PDU
+     * @throws EncoderException if there are problems while encoding
+     */
+    void encode( Object obj ) throws EncoderException;
 
 
-    public void setCallback( EncoderCallback cb );
+    /**
+     * Sets the callback of the underlying implementation. There is no need for
+     * any special callbacks because when encoding we do not need to transform
+     * before a value return as we did in the decoder.
+     * 
+     * @param cb the callback to set on the underlying provider specific encoder
+     */
+    void setCallback( EncoderCallback cb );
 
 
-    public void setEncoderMonitor( EncoderMonitor monitor );
+    /**
+     * Sets the monitor of the underlying implementation.
+     * 
+     * @param monitor the monitor to set on the underlying implementation
+     */
+    void setEncoderMonitor( EncoderMonitor monitor );
 
 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoder.java
index 31ac2ed..e1f3414 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoder.java
@@ -30,7 +30,7 @@
  * Document me.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$
  */
 public class HexDecoder extends AbstractStatefulDecoder
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoder.java
index 0b60ff9..bdb363d 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoder.java
@@ -33,7 +33,7 @@
  * Document me.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$
  */
 public class HexEncoder implements StatefulEncoder
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/ASN1InputStream.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/ASN1InputStream.java
index 2a8bafa..60034ac 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/ASN1InputStream.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/ASN1InputStream.java
@@ -48,6 +48,10 @@
         }
 
 
+        /**
+         * Compute the instance hash code
+         * @return the instance's hashcode 
+         */
         public int hashCode()
         {
             return 0;
@@ -188,15 +192,22 @@
                 return new DERNull();
             case DERObject.SEQUENCE | DERObject.CONSTRUCTED:
                 ASN1InputStream ais = new ASN1InputStream( bytes );
-
+                DEREncodable obj = null;
                 DERSequence sequence = new DERSequence();
 
-                DEREncodable obj = ais.readObject();
-
-                while ( obj != null )
+                try
                 {
-                    sequence.add( obj );
                     obj = ais.readObject();
+    
+                    while ( obj != null )
+                    {
+                        sequence.add( obj );
+                        obj = ais.readObject();
+                    }
+                }
+                finally
+                {
+                    ais.close();
                 }
 
                 return sequence;
@@ -204,12 +215,19 @@
                 ais = new ASN1InputStream( bytes );
                 DERSet set = new DERSet();
 
-                obj = ais.readObject();
-
-                while ( obj != null )
+                try
                 {
-                    set.add( obj );
                     obj = ais.readObject();
+    
+                    while ( obj != null )
+                    {
+                        set.add( obj );
+                        obj = ais.readObject();
+                    }
+                }
+                finally
+                {
+                    ais.close();
                 }
 
                 return set;
@@ -292,25 +310,32 @@
 
                     ais = new ASN1InputStream( bytes );
 
-                    DEREncodable encodable = ais.readObject();
-
-                    // Explicitly tagged - if it isn't we'd have to tell from
-                    // the context.
-                    if ( ais.available() == 0 )
+                    try
                     {
-                        return new DERTaggedObject( true, tagNo, encodable, bytes );
+                        DEREncodable encodable = ais.readObject();
+    
+                        // Explicitly tagged - if it isn't we'd have to tell from
+                        // the context.
+                        if ( ais.available() == 0 )
+                        {
+                            return new DERTaggedObject( true, tagNo, encodable, bytes );
+                        }
+    
+                        // Another implicit object, create a sequence.
+                        DERSequence derSequence = new DERSequence();
+    
+                        while ( encodable != null )
+                        {
+                            derSequence.add( encodable );
+                            encodable = ais.readObject();
+                        }
+
+                        return new DERTaggedObject( false, tagNo, derSequence );
                     }
-
-                    // Another implicit object, create a sequence.
-                    DERSequence derSequence = new DERSequence();
-
-                    while ( encodable != null )
+                    finally
                     {
-                        derSequence.add( encodable );
-                        encodable = ais.readObject();
+                        ais.close();
                     }
-
-                    return new DERTaggedObject( false, tagNo, derSequence );
                 }
 
                 return new DERUnknownTag( tag, bytes );
@@ -345,7 +370,7 @@
 
     private BERConstructedOctetString buildConstructedOctetString() throws IOException
     {
-        Vector octets = new Vector();
+        Vector<DEREncodable> octets = new Vector<DEREncodable>();
 
         for ( ;; )
         {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERConstructedOctetString.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERConstructedOctetString.java
index 6d34059..11a03c9 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERConstructedOctetString.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERConstructedOctetString.java
@@ -31,7 +31,7 @@
 
 public class BERConstructedOctetString extends DEROctetString
 {
-    private Vector octets;
+    private Vector<DEREncodable> octets;
 
 
     /**
@@ -44,7 +44,7 @@
     }
 
 
-    public BERConstructedOctetString(Vector octets)
+    public BERConstructedOctetString(Vector<DEREncodable> octets)
     {
         super( toBytes( octets ) );
 
@@ -55,7 +55,7 @@
     /**
      * Convert a vector of octet strings into a single byte string.
      */
-    static private byte[] toBytes( Vector octs )
+    private static byte[] toBytes( Vector<DEREncodable> octs )
     {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
@@ -85,7 +85,7 @@
     /**
      * @return Enumeration the DER octets that make up this string.
      */
-    public Enumeration getObjects()
+    public Enumeration<DEREncodable> getObjects()
     {
         if ( octets == null )
         {
@@ -96,11 +96,11 @@
     }
 
 
-    private Vector generateOcts()
+    private Vector<DEREncodable> generateOcts()
     {
         int start = 0;
         int end = 0;
-        Vector vector = new Vector();
+        Vector<DEREncodable> vector = new Vector<DEREncodable>();
 
         while ( ( end + 1 ) < value.length )
         {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSequence.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSequence.java
index 1a23f38..47a4c58 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSequence.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSequence.java
@@ -34,7 +34,8 @@
         out.write( DERObject.SEQUENCE | DERObject.CONSTRUCTED );
         out.write( DERObject.TAGGED );
 
-        Enumeration e = getObjects();
+        Enumeration<DEREncodable> e = getObjects();
+        
         while ( e.hasMoreElements() )
         {
             out.writeObject( e.nextElement() );
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSet.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSet.java
index 9c2bcc8..96e0cdb 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSet.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERSet.java
@@ -34,7 +34,8 @@
         out.write( DERObject.SET | DERObject.CONSTRUCTED );
         out.write( DERObject.TAGGED );
 
-        Enumeration e = getObjects();
+        Enumeration<DEREncodable> e = getObjects();
+        
         while ( e.hasMoreElements() )
         {
             out.writeObject( e.nextElement() );
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERTaggedObject.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERTaggedObject.java
index 10fcd3b..c1f23be 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERTaggedObject.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/BERTaggedObject.java
@@ -69,7 +69,7 @@
             {
                 if ( obj instanceof DEROctetString )
                 {
-                    Enumeration e;
+                    Enumeration<DEREncodable> e;
 
                     if ( obj instanceof BERConstructedOctetString )
                     {
@@ -90,7 +90,7 @@
                 }
                 else if ( obj instanceof DERSequence )
                 {
-                    Enumeration e = ( ( DERSequence ) obj ).getObjects();
+                    Enumeration<DEREncodable> e = ( ( DERSequence ) obj ).getObjects();
 
                     while ( e.hasMoreElements() )
                     {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERApplicationSpecific.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERApplicationSpecific.java
index fef2a2e..4168321 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERApplicationSpecific.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERApplicationSpecific.java
@@ -68,8 +68,16 @@
 
 
     public DEREncodable getObject() throws IOException
-    {
-        return new ASN1InputStream( getOctets() ).readObject();
+    {   
+        final ASN1InputStream ais = new ASN1InputStream( getOctets() );
+        try
+        {
+            return ais.readObject();
+        }
+        finally
+        {
+            ais.close();
+        }
     }
 
 
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERObjectIdentifier.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERObjectIdentifier.java
index 70985c7..2646b35 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERObjectIdentifier.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERObjectIdentifier.java
@@ -62,6 +62,7 @@
                         default:
                             objId.append( '2' );
                             value -= 80;
+                            break;
                     }
                     first = false;
                 }
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSequence.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSequence.java
index 22a86c4..0c76e98 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSequence.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSequence.java
@@ -31,7 +31,7 @@
 
 public class DERSequence implements DEREncodable
 {
-    private Vector v = new Vector();
+    private Vector<DEREncodable> v = new Vector<DEREncodable>();
 
 
     public void add( DEREncodable obj )
@@ -40,7 +40,7 @@
     }
 
 
-    public Enumeration getObjects()
+    public Enumeration<DEREncodable> getObjects()
     {
         return v.elements();
     }
@@ -69,7 +69,7 @@
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ASN1OutputStream aos = new ASN1OutputStream( baos );
 
-        Enumeration e = getObjects();
+        Enumeration<DEREncodable> e = getObjects();
 
         while ( e.hasMoreElements() )
         {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSet.java b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSet.java
index ba73813..c410663 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSet.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/der/DERSet.java
@@ -34,10 +34,10 @@
  */
 public class DERSet implements DEREncodable
 {
-    protected Vector set = new Vector();
+    protected Vector<DEREncodable> set = new Vector<DEREncodable>();
 
 
-    public Enumeration getObjects()
+    public Enumeration<DEREncodable> getObjects()
     {
         return set.elements();
     }
@@ -66,7 +66,7 @@
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ASN1OutputStream aos = new ASN1OutputStream( baos );
 
-        Enumeration e = getObjects();
+        Enumeration<DEREncodable> e = getObjects();
 
         while ( e.hasMoreElements() )
         {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/BitString.java b/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/BitString.java
index 926e0e1..3b43e9e 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/BitString.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/BitString.java
@@ -28,6 +28,7 @@
  * an array of int.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class BitString implements Serializable
 {
@@ -71,18 +72,6 @@
     // ~ Constructors
     // -------------------------------------------------------------------------------*
     /**
-     * A private constructor used to initialized the empty BitString
-     */
-    private BitString()
-    {
-        nbBits = 0;
-        nbBytes = 0;
-        nbUnusedBits = 8;
-        isStreamed = false;
-        bytes = new byte[]{};
-    }
-    
-    /**
      * Creates a BitString with a specific length (length is the number of
      * bits).
      * 
@@ -170,13 +159,13 @@
 
             // It will be a streamed OctetString.
             // TODO : implement the streaming
-            bytes = new byte[nbBytes];
+            this.bytes = new byte[nbBytes];
         }
         else
         {
             isStreamed = false;
 
-            bytes = new byte[nbBytes];
+            this.bytes = new byte[nbBytes];
         }
 
         setBytes( bytes, nbBytes );
@@ -222,18 +211,18 @@
             return;
         }
 
-        int nbBytes = bytes.length - 1;
+        int nbb = bytes.length - 1;
 
-        if ( ( nbBytes > DEFAULT_LENGTH ) && ( bytes.length < nbBytes ) )
+        if ( ( nbb > DEFAULT_LENGTH ) && ( bytes.length < nbb ) )
         {
 
             // The current size is too small.
             // We have to allocate more space
             // TODO : implement the streaming
-            bytes = new byte[nbBytes];
+            bytes = new byte[nbb];
         }
 
-        setBytes( bytes, nbBytes );
+        setBytes( bytes, nbb );
     }
 
 
@@ -272,9 +261,9 @@
             throw new IndexOutOfBoundsException( "Bad bit number : out of bound" );
         }
         
-        int posInt = pos / 8;
+        int posInt = nbBytes - 1 - ( ( pos + nbUnusedBits ) >> 3 );
+        int bitNumber = ( pos + nbUnusedBits ) % 8;
 
-        int bitNumber = 7 - ( pos % 8 );
         bytes[posInt] |= ( 1 << bitNumber );
     }
     
@@ -293,27 +282,27 @@
             throw new IndexOutOfBoundsException( "Bad bit number : out of bound" );
         }
         
-        int posInt = pos / 8;
+        int posInt = nbBytes - 1 - ( ( pos + nbUnusedBits ) >> 3 );
+        int bitNumber = ( pos + nbUnusedBits ) % 8;
 
-        int bitNumber = 7 - ( pos % 8 );
         bytes[posInt] &= ~( 1 << bitNumber );
     }
     
     /**
      * Get the bit stored into the BitString at a specific position. 
-     * The bits are stored from left to right.
-     * For instance, if we have 10 bits, then they are coded as b0 b1 b2 b3 b4 b5 b6 b7 - b8 b9 x x x x x x
+     * The bits are stored from left to right, the LSB on the right and the
+     * MSB on the left
+     * For instance, if we have 10 bits, then they are coded as 
+     * b9 b8 b7 b6 - b5 b4 b3 b2 - b1 b0 x x - x x x x
      * 
      * With '1001 000x', where x is an unused bit, 
-     *       ^ ^    ^^ 
-     *       | |    || 
-     *       | |    |+---- getBit(7) IndexOutOfBoundException  
-     *       | |    +----- getBit(6) = 0 
-     *       | +---------- getBit(2) = 0 
-     *       +------------ getBit(0) = 1
+     *       ^ ^    ^ 
+     *       | |    | 
+     *       | |    |  
+     *       | |    +----- getBit(0) = 0 
+     *       | +---------- getBit(4) = 0 
+     *       +------------ getBit(6) = 1
      *       
-     * getBit(7) -> IndexOutOfBoundsException
-     * 
      * @param pos The position of the requested bit.  
      * 
      * @return <code>true</code> if the bit is set, <code>false</code>
@@ -328,9 +317,9 @@
                 + nbBits + " ints" );
         }
 
-        int posInt = pos / 8;
+        int posInt = nbBytes - 1 - ( ( pos + nbUnusedBits ) >> 3 );
+        int bitNumber = ( pos + nbUnusedBits ) % 8;
 
-        int bitNumber = 7 - ( pos % 8 );
         int res = bytes[posInt] & ( 1 << bitNumber );
         return res != 0;
     }
@@ -354,7 +343,7 @@
 
         StringBuffer sb = new StringBuffer();
 
-        for ( int i = 0; i < nbBits; i++ )
+        for ( int i = nbBits; i > 0; i-- )
         {
 
             if ( getBit( i ) )
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/OID.java b/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/OID.java
index ce74bb2..dfcf3e9 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/OID.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/primitives/OID.java
@@ -58,6 +58,7 @@
  * .2    -> 0x02
  *  
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class OID implements Serializable
 {
@@ -83,14 +84,16 @@
     {
         // We should not create this kind of object directly, it must
         // be created through the factory.
-    	hash = 0;
+        hash = 0;
     }
 
 
     /**
      * Create a new OID object from a byte array
      * 
-     * @param oid
+     * @param oid the byte array containing the OID
+     * @throws DecoderException if the byte array does not contain a 
+     * valid OID
      */
     public OID( byte[] oid ) throws DecoderException
     {
@@ -103,6 +106,8 @@
      * Create a new OID object from a String
      * 
      * @param oid The String which is supposed to be an OID
+     * @throws DecoderException if the byte array does not contain a 
+     * valid OID
      */
     public OID( String oid ) throws DecoderException
     {
@@ -118,6 +123,7 @@
      * representation.
      * 
      * @param oid The bytes containing the OID
+     * @throws DecoderException if the byte array does not contains a valid OID 
      */
     public void setOID( byte[] oid ) throws DecoderException
     {
@@ -217,6 +223,7 @@
      * OID = ( [ '0' | '1' ] '.' [ 0 .. 39 ] | '2' '.' int) ( '.' int )*
      * 
      * @param oid The String containing the OID
+     * @throws DecoderException if the byte array does not contains a valid OID 
      */
     public void setOID( String oid ) throws DecoderException
     {
@@ -227,14 +234,14 @@
         }
 
         int nbValues = 1;
-        char[] bytes = oid.toCharArray();
+        char[] chars = oid.toCharArray();
         boolean dotSeen = false;
 
         // Count the number of int to allocate.
-        for ( int i = 0; i < bytes.length; i++ )
+        for ( char c:chars )
         {
 
-            if ( bytes[i] == '.' )
+            if ( c == '.' )
             {
 
                 if ( dotSeen )
@@ -269,7 +276,7 @@
         boolean ituOrIso = false;
 
         // The first value
-        switch ( bytes[pos] )
+        switch ( chars[pos] )
         {
 
             case '0': // itu-t
@@ -278,7 +285,7 @@
             // fallthrough
 
             case '2': // joint-iso-itu-t
-                oidValues[intPos++] = bytes[pos++] - '0';
+                oidValues[intPos++] = chars[pos++] - '0';
                 break;
 
             default: // error, this value is not allowed
@@ -286,7 +293,7 @@
         }
 
         // We must have a dot
-        if ( bytes[pos++] != '.' )
+        if ( chars[pos++] != '.' )
         {
             throw new DecoderException( "Invalid OID : " + oid );
         }
@@ -295,10 +302,10 @@
 
         int value = 0;
 
-        for ( int i = pos; i < bytes.length; i++ )
+        for ( int i = pos; i < chars.length; i++ )
         {
 
-            if ( bytes[i] == '.' )
+            if ( chars[i] == '.' )
             {
 
                 if ( dotSeen )
@@ -322,10 +329,10 @@
                 oidValues[intPos++] = value;
                 value = 0;
             }
-            else if ( ( bytes[i] >= 0x30 ) && ( bytes[i] <= 0x39 ) )
+            else if ( ( chars[i] >= 0x30 ) && ( chars[i] <= 0x39 ) )
             {
                 dotSeen = false;
-                value = ( ( value * 10 ) + bytes[i] ) - '0';
+                value = ( ( value * 10 ) + chars[i] ) - '0';
 
             }
             else
@@ -336,16 +343,16 @@
             }
         }
 
-        oidValues[intPos++] = value;
+        oidValues[intPos] = value;
 
         hash = computeHashCode();
     }
 
 
     /**
-     * Get an array of int from the OID
+     * Get an array of long from the OID
      * 
-     * @return An array of int representing the OID
+     * @return An array of long representing the OID
      */
     public long[] getOIDValues()
     {
@@ -506,23 +513,25 @@
 
 
     /**
-     * Compute the hashcode for this object. No need to copute
+     * Compute the hash code for this object. No need to compute
      * it live when calling the hashCode() method, as an OID
      * never change.
+     * 
+     * @return the OID's hash code
      */
     private int computeHashCode()
     {
-    	int h = 37;
-    	
-    	for ( long val:oidValues )
-    	{
-    		int low = (int)(val & 0x0000FFFFL);
-    		int high = (int)(val >> 32);
-    		h = h*17 + high;
-    		h = h*17 + low;
-    	}
-    	
-    	return h;
+        int h = 37;
+        
+        for ( long val:oidValues )
+        {
+            int low = (int)(val & 0x0000FFFFL);
+            int high = (int)(val >> 32);
+            h = h*17 + high;
+            h = h*17 + low;
+        }
+        
+        return h;
     }
     
     /**
@@ -542,10 +551,10 @@
         boolean dotSeen = false;
 
         // Count the number of int to allocate.
-        for ( int i = 0; i < bytes.length; i++ )
+        for ( byte b:bytes )
         {
 
-            if ( bytes[i] == '.' )
+            if ( b == '.' )
             {
 
                 if ( dotSeen )
@@ -581,9 +590,10 @@
         {
 
             case '0': // itu-t
+                // fallthrough
             case '1': // iso
                 ituOrIso = true;
-            // fallthrough
+                // fallthrough
 
             case '2': // joint-iso-itu-t
                 break;
@@ -666,14 +676,13 @@
         return sb.toString();
     }
 
-    /**
-     * @see Object#hashCode()
-     */
+
     public int hashCode()
     {
-    	return hash;
+        return hash;
     }
-    
+
+
     public boolean equals( Object oid )
     {
         if ( this == oid )
@@ -692,15 +701,15 @@
         }
         
         OID instance = (OID)oid;
-   	
-    	if ( instance.hash != hash )
-    	{
-    		return false;
-    	}
-    	else
-    	{
-    		return Arrays.equals( instance.oidValues, oidValues );
-    	}
+       
+        if ( instance.hash != hash )
+        {
+            return false;
+        }
+        else
+        {
+            return Arrays.equals( instance.oidValues, oidValues );
+        }
     }
     
 }
\ No newline at end of file
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/util/Asn1StringUtils.java b/asn1/src/main/java/org/apache/directory/shared/asn1/util/Asn1StringUtils.java
index 69a066c..8fd0d8a 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/util/Asn1StringUtils.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/util/Asn1StringUtils.java
@@ -27,6 +27,7 @@
  * Little helper class.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class Asn1StringUtils
 {
@@ -76,10 +77,10 @@
 
         StringBuffer sb = new StringBuffer();
 
-        for ( int i = 0; i < buffer.length; i++ )
+        for ( byte b:buffer )
         {
-            sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append(
-                ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " );
+            sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( b & 0x00F0 ) >> 4] ) ).append(
+                ( char ) ( HEX_CHAR[b & 0x000F] ) ).append( " " );
         }
 
         return sb.toString();
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoder.java
index b8b1142..a28038a 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoder.java
@@ -21,7 +21,6 @@
 
 
 import org.apache.directory.shared.asn1.ber.tlv.Value;
-import org.apache.directory.shared.asn1.codec.DecoderException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,6 +29,7 @@
  * Parse and decode a Boolean value.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class BooleanDecoder
 {
@@ -46,7 +46,7 @@
      * @param value
      *            The byte buffer to parse
      * @return A boolean.
-     * @throws DecoderException
+     * @throws BooleanDecoderException
      *             Thrown if the byte stream does not contains a boolean
      */
     public static boolean parse( Value value ) throws BooleanDecoderException
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoderException.java b/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoderException.java
index 5b6a72f..e26b76e 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoderException.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/util/BooleanDecoderException.java
@@ -26,6 +26,7 @@
  * during a decode.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class BooleanDecoderException extends Exception
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoder.java b/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoder.java
index 5836415..ef95e1f 100644
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoder.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoder.java
@@ -27,6 +27,7 @@
  * Parse and decode an Integer value.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class IntegerDecoder
 {
diff --git a/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoderException.java b/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoderException.java
index 93de152..3ac8599 100755
--- a/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoderException.java
+++ b/asn1/src/main/java/org/apache/directory/shared/asn1/util/IntegerDecoderException.java
@@ -26,6 +26,7 @@
  * decode.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class IntegerDecoderException extends Exception
 {
diff --git a/asn1/src/site/resources/images/BERDecoder.gif b/asn1/src/site/resources/images/BERDecoder.gif
deleted file mode 100644
index 43d6151..0000000
--- a/asn1/src/site/resources/images/BERDecoder.gif
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/BERDecoderCallback.gif b/asn1/src/site/resources/images/BERDecoderCallback.gif
deleted file mode 100644
index 28c7edb..0000000
--- a/asn1/src/site/resources/images/BERDecoderCallback.gif
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/PrimitiveTupleDecoder-uml.gif b/asn1/src/site/resources/images/PrimitiveTupleDecoder-uml.gif
deleted file mode 100644
index 3d71b27..0000000
--- a/asn1/src/site/resources/images/PrimitiveTupleDecoder-uml.gif
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/TagTree.png b/asn1/src/site/resources/images/TagTree.png
deleted file mode 100755
index e724f35..0000000
--- a/asn1/src/site/resources/images/TagTree.png
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/WildTagTree.png b/asn1/src/site/resources/images/WildTagTree.png
deleted file mode 100755
index 462ffea..0000000
--- a/asn1/src/site/resources/images/WildTagTree.png
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/all-uml.gif b/asn1/src/site/resources/images/all-uml.gif
deleted file mode 100644
index 7ff37fc..0000000
--- a/asn1/src/site/resources/images/all-uml.gif
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/state-helper-classes.gif b/asn1/src/site/resources/images/state-helper-classes.gif
deleted file mode 100644
index 4910e97..0000000
--- a/asn1/src/site/resources/images/state-helper-classes.gif
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/resources/images/tag-integer-encoding.png b/asn1/src/site/resources/images/tag-integer-encoding.png
deleted file mode 100644
index 811a6af..0000000
--- a/asn1/src/site/resources/images/tag-integer-encoding.png
+++ /dev/null
Binary files differ
diff --git a/asn1/src/site/site.xml b/asn1/src/site/site.xml
deleted file mode 100644
index cea7355..0000000
--- a/asn1/src/site/site.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<project name="Apache Directory Project">
-  <bannerLeft>
-    <name>Apache Diretory Project</name>
-    <src>images/apache-directory-logo.png</src>
-    <href>http://directory.apache.org/</href>
-  </bannerLeft>
-
- <body>
-
-    <links>
-      <item name="Directory" href="../../index.html"/>
-      <item name="ApacheDS" href="../apacheds/index.html"/>
-      <item name="LDAP" href="../ldap.html"/>
-      <item name="Naming" href="../naming/index.html"/>
-      <item name="ASN.1" href="../asn1/index.html"/>
-      <item name="Kerberos" href="../kerberos.html"/>
-      <item name="AuthX" href="../authx/index.html"/>
-      <item name="MINA" href="../network/index.html"/>
-      <item name="Protocols" href="../providers.html"/>
-    </links>
-
-    <menu name="Apache ASN.1">
-      <item name="Overview" href="/index.html"/>
-      <item name="ASN.1 Codecs" href="/asn1-codec/index.html"/>
-      <item name="BER Runtime" href="/asn1-ber/index.html"/>
-      <item name="DER Runtime" href="/asn1-der/index.html"/>
-      <item name="Stub Compiler" href="/stub-compiler/index.html"/>
-    </menu>
-    
-    <menu name="Project Information">
-      <item name="Combined javadocs" href="/apidocs/index.html"/>
-      <item name="Wiki" href="http://wiki.apache.org/directory"/>
-      <item name="Open Issues" href="http://issues.apache.org/jira/browse/DIRSNICKERS"/>
-      <item name="Source Repositories" href="http://svn.apache.org/viewcvs.cgi/directory/asn1/trunk/?root=Apache-SVN"/>
-    </menu>
-
-    <menu name="ApacheCon Europe 2005"> 	 
-      <item name="ApacheCon Europe 2005" href="http://www.apachecon.com/"
-            img="http://apache.org/images/ac2005eu_135x50.gif" />
-    </menu>
- </body>
-
-</project>
diff --git a/asn1/src/site/xdoc/index.xml b/asn1/src/site/xdoc/index.xml
deleted file mode 100644
index fd03a7a..0000000
--- a/asn1/src/site/xdoc/index.xml
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document>
-  <properties>
-    <author email="akarasulu@apache.org">Alex Karasulu</author>
-    <title>ASN.1 Subproject</title>
-  </properties> 
-
-  <body>
-    <section name="Overview">
-      <p>
-        The Apache ASN.1 runtime is a high performance non-blocking replacement for 
-        the Snacc4J runtime and eventually its Java stub compiler for ASN.1.  It 
-        is designed from the ground up to work with NIO constructs like Channels and 
-        ByteBuffers.  There are currently three sub subprojects associated with the 
-        asn1 project.  They are described below:
-      </p>
-
-      <table>
-        <tr><th>Subproject</th><th>Description</th></tr>
-        
-        <tr>
-          <td><a href="asn1-codec/index.html">ASN.1 Codecs</a></td>
-          <td>
-            Extensions to commons-codec interfaces for non-blocking stateful encode
-            and decode operations for chunking. 
-          </td>
-        </tr>
-
-        <tr>
-          <td><a href="asn1-ber/index.html">ASN.1 BER Runtime</a></td>
-          <td>
-            Library used for ASN.1 data structures encoded onto and decoded off of the
-            wire using Basic Encoding Rules (BER).  By dealing only with BER TLV tuples
-            this library remains independent of any ASN.1 based protocol.
-          </td>
-        </tr>
-
-        <tr>
-          <td><a href="asn1-der/index.html">ASN.1 DER Runtime</a></td>
-          <td>
-            Library used for ASN.1 data structures encoded onto and decoded off of the
-            wire using Distinguished Encoding Rules (DER).  By dealing only with DER TLV tuples
-            this library remains independent of any ASN.1 based protocol.
-          </td>
-        </tr>
-
-        <tr>
-          <td><a href="stub-compiler/index.html">Java Stub Compiler</a></td>
-          <td>
-            The Apache ASN.1 Java Stub Compiler generates interfaces and 
-            classes for complex ASN.1 data types.  These classes are used with
-            the BER codec runtime API to marshal and demarshal protocol data
-            units (PDU).
-          </td>
-        </tr>
-      </table>
- 
-      <subsection name="Refactoring in 0.3 Branch">
-        <p>
-          For the next dev cycle we're radically refactoring the structure of
-          these modules.  For more information you can take a look 
-          <a href="./refactor.html">here</a>.
-        </p>
-      </subsection>
-    </section>
-
-    <section name="Motivation">
-      <p>
-        Non-blocking IO in stateful protocol servers imposes stricter performance
-        requirements on codecs.  In the Eve Directory Server, the BER codec 
-        must be fast, efficient, and take a very small relatively fixed 
-        size memory footprint while actively encoding or decoding variable sized
-        messages.
-      </p>
-
-      <p>
-        ASN.1 BER codecs for Java are few and far between.  No BSD license
-        compatible open source API is currently available for Java.  Initially
-        the Snacc4J runtime from IBM was used however it has mysteriously
-        disappeared and is no longer available.  Furthermore Snacc4J is completely
-        incompatible with any licence we know of: it's practically not even Open 
-        Source.  Even with license issues Snacc4J is terribly inefficient and
-        imposes security threats especially where decodes are concerned.  Snacc4J
-        decoders block until an entire message is read and decoded.  They hence 
-        require approximately twice the transfer footprint of a message to 
-        decode it and there is no limit to the accepted transfer footprint size.
-        DoS attacks could easily be mounted using a single large request to bring
-        the server to its knees making it totally unresponsive.
-      </p>
-
-      <p>
-        The ASN.1 BER runtime is a high performance codec optimized for use with
-        selectable channels and non blocking IO: it's processes the substrate
-        in small chunks rather than in a single massive peice.  The runtime is
-        destined to replace stateless BER codecs like Snacc4J, and keep ASN.1
-        based high performance protocol server implementors satisfied.  A user
-        definable parameter will be used to set the fixed in memory footprint of
-        the decoder while actively decoding ASN.1 data structures encoded using
-        Basic Encoding Rules.  Furthermore, when large indivisible parts of messages
-        like byte[] fields are encountered, they are streamed to disk and referred
-        to using a URL rather than allocating primary memory to store such an object.
-        Note: this experimental feature is being added as we speak.  Access to the
-        object is provided to the application via a URL.  The handling of the
-        large streamable data is left to the discretion of the application.
-      </p>
-    </section>
-  </body>
-</document>
diff --git a/asn1/src/site/xdoc/refactor.xml b/asn1/src/site/xdoc/refactor.xml
deleted file mode 100644
index a3b9051..0000000
--- a/asn1/src/site/xdoc/refactor.xml
+++ /dev/null
@@ -1,591 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document>
-  <properties>
-    <author email="akarasulu@apache.org">Alex Karasulu</author>
-    <title>Refactoring the ASN.1 Runtime</title>
-  </properties> 
-
-  <body>
-    <section name="Refactoring the ASN.1 Runtime">
-      <p>
-        The use of Snacc4J as the runtime ASN.1 BER codec for LDAP impossed an 
-        IP issue for the new Directory Project under incubation.  This resulted
-        in the creation of our own implementation, and hence the Apache ASN.1 
-        Runtime library was created.  
-      </p>
-
-      <p>
-        Before continuing any further it might be a good idea to read about 
-        the existing architecture to understand the changes that are being 
-        proposed.
-      </p>
-
-      <subsection name="High Level Goals and Changes">
-      <p>
-        The internal 0.2 release was the first successful attempt to produce a 
-        replacement for Snacc4J.  As of release 0.8 of ApacheDS it provides 
-        BER encoders and decoders for LDAP requests and responses.  The library
-        was designed with performance in mind.  Some very good ideas were 
-        introduced and really put to the test.  However the library does have 
-        performance problems.  The designs to make this into a high performance
-        library were not totally followed through.  Furthermore the code base
-        is very difficult to maintain needing some reorganization.  We hope to 
-        refactor the library so it is more efficient, and easier to maintain 
-        while reducing the number of dependencies it has.  In the process we 
-        would like to introduce some new features and improvements which are 
-        listed below:
-      </p>
-      
-      <ul>
-        <li>
-	  Better ByteBuffer utilization by splicing buffers instead of copying 
-          them.
-        </li>
-
-        <li>
-	  Repace current Tuple class with well defined Tuple interfaces: 
-          specifically we need to remove TLV field processing from a Tuple
-          as well as tag cooking functionality.  Tag cooking refers to the 
-          application of transformations that turn tag bytes into a 4 byte 
-          Java primitive integers.  These functions need to be localized 
-          within utility classes.
-        </li>
-
-        <li>
-	  Some BER based protocols only use a subset of the encoding rules.  
-          For example LDAP only uses definite length encodings for constructed 
-          tuples.  A reduced set of rules are much easier to code, maintain, 
-          and often will perform significantly better than codecs designed for 
-          the entire rule set.  The key here however is to make sure that
-          the core of the codec can be replaced transparently without imposing
-          code changes. 
-        </li>
-
-        <li>
-	  The Tuples of primitives like binary values store the Tag, Length 
-          and Value of the primitive TLV Tuple in memory.  Sometimes primitive 
-          values can be dangerously large for a server to encode or decode.  
-          Primitive tuples could be blobs of large binaries like images.  If 
-          tuple values are larger than some application defined limit they 
-          aught to be streamed to disk rather than kept in main memory.  
-          Streaming to disk makes the server more efficient overall since it 
-          can maintain a constant sized decoding footprint.  However switching
-          to disk based storage will rightfully slow down the current operation
-          which involves a large primitive.  This is a tradeoff that should
-          be configurable by API users and ultimately ApacheDS administrators.
-        </li>
-
-        <li>
-	  Better logging and error handling for codecs with pershaps some
-          management interfaces to control the properties of codecs.
-        </li>
-
-        <li>
-	  A single deployable artifact where the ber and codec jars are fused.  
-        </li>
-
-        <li>
-	  Make the code easier to maintain while improving its structure.
-        </li>
-        </ul>
-      </subsection>
-
-      
-    </section>
-
-    <section name="Tuple Interface/Class Hierarchies">
-      <p>
-        Presently Tuples contain the functionality to decode and encode 
-        fields.  Tuples can even encode themselves to a buffer as BER or
-        DER.  A Tuple is not a simple bean and that's all that it should be.  
-        Hence one of our goals is to factor out this additional functionality.
-      </p>
-
-      <p>
-        A Tuple is a single class that acts more like a union of different 
-        types rather than using inheritance to differentiate.  There are 
-        distinct types of tuples, constructed verses primitive for example.  
-        Instead of using complex logic to differentiate what kind of Tuple an 
-        instance is it is much better to differentiate the Tuple into 
-        subclasses.  Hence we propose a new interface and implementation 
-        hierarchy for Tuples.
-      </p>
-
-      <p>
-        Let's start by proposing a minimal Tuple interface.
-      </p>
-
-<source>
-interface Tuple
-{
-    /**
-     * Gets the zero based index into a PDU where the first byte of this
-     * Tuple's tag resides.
-     *
-     * @return zero based index of Tag's first byte in the PDU
-     */ 
-    int getTagStartIndex();
-
-    /**
-     * Gets this TLV Tuple's Tag (T) as a type safe enumeration.
-     *
-     * @return type safe enumeration for the Tag
-     */
-    TagEnum getTag();
-
-    /**
-     * Gets whether or not this Tuple is constructed.
-     *
-     * @return true if the Tag is constructed false if it is primitive.
-     */
-    boolean isConstructed();
-}
-</source>
-
-      <p>
-        These interfaces give the minimum information needed for a Tuple
-        that is not specific to another specialized type of Tuple.  Meaning
-        all Tuples share these methods.  We can also go a step further and
-        implement an AbstractTuple where protected members are used to 
-        implement these methods.  Note that isConstructed() will probably be
-        left abstract so subclasses can just return true or false.  For 
-        brevity this code is not shown but other classes in the section below
-        will extend from AbstractTuple.
-      </p>
-
-      <subsection name="Primitive Vs. Constructed Tuples">
-        <p>
-          We need to go a step further and start differentiating between Tuples
-          that are primitive and those that are constructed.  In this step we
-          introduce two new abstract classes PrimitiveTuple and 
-          ConstructedTuple.
-        </p>
-
-        <p>
-          These two classes will be described below but one might ask why both
-          are still abstract.  This is because we need to differentiate further
-          for buffered verses streamed Tuples in the case of primitive Tuples.
-          For constructed Tuples we need to differentiate between definate
-          length verses indefinite length Tuples.  With our approach, only the 
-          leaf nodes of the inheritance hierarchy will be concrete.  Below is
-          the definition for the PrimitiveTuple.
-        </p>
-
-<source>
-public abstract class PrimitiveTuple extends AbstractTuple
-{
-    /** the number of bytes used to compose the Tuple's length field */
-    protected int lengthFieldSz = 0;
-    /** the number of bytes used to compose the Tuple's value field */
-    protected int valueFieldSz = 0;
-
-    ...
-
-    public final boolean isConstructed()
-    {
-        return false;
-    }
-
-    /**
-     * Gets whether or not this Tuple's value is buffered in memory or 
-     * streamed to disk.
-     *
-     * @return true if the value is buffered in memory, false if it is streamed
-     * to disk
-     */
-    public abstract boolean isBuffered();
-
-    /**
-     * Gets the number of bytes in the length (L) field of this TLV Tuple.
-     *
-     * @return number of bytes for the length
-     */
-    public final int getLengthFieldSize()
-    {
-        return lengthFieldSz;
-    }
-
-    /**
-     * Gets the number of bytes in the value (V) field of this TLV Tuple.
-     *
-     * @return number of bytes for the value
-     */
-    public final int getValueFieldSize();
-    {
-        return valueFieldSz;
-    }
-
-    ... 
-}
-</source>
-        <p>
-          This abstract class adds two new concrete methods for tracking the
-          size of the length and value fields.  Constructed Tuples may not
-          necessarily have a length value associated with them if they are
-          of the indeterminate form.  Furthermore the value of constructed
-          Tuples are the nested child Tuples subordinate to them.  So there
-          is no need to track the value prematurely now for anything other 
-          than primitive Tuples.
-        </p>
-
-        <p>
-          Note that the isBuffered() method is implemented as final and always 
-          returns false for this lineage of Tuples.  A final modifier on the
-          method makes sense and sometimes helps the compiler inline this 
-          method so we don't always pay a price for using it in addition to 
-          subclassing.  A new abstract method isBuffered() is introduced which 
-          is discussed in detail within the Buffered Vs. Streamed section.
-        </p>
-
-        <p> 
-          Now let's take a look at the ConstructedTuple abstract class.
-        </p>
-
-<source>
-public abstract class ConstructedTuple extends AbstractTuple
-{
-    public final boolean isConstructed()
-    {
-        return true;
-    }
-
-    /**
-     * Gets whether or not the length of this constructed Tuple is of the 
-     * definate form or of the indefinite length form.
-     *
-     * @return true if the length is definate, false if the length is of the
-     * indefinite form
-     */
-    public abstract boolean isLengthDefinate();
-}
-</source>
-
-        <p>
-          ConstructedTuple implements the <code>isConstructed()</code> method 
-          as final since it will always return false for this lineage of 
-          Tuples.  Also a new abstract method isLengthDefinate() is introduced 
-          to see if the Tuple uses the indefinite length form or not.  
-        </p>
-      </subsection>
-
-      <subsection name="Definate Vs. Indefinite Length">
-        <p>
-          The ConstructedTuple can be further differentiated into two 
-          subclasses to represent definate and indefinite length constructed 
-          TLV Tuples.  The indefinite form does not have a length value 
-          associated with it where as the definate lenght form does.  Let's
-          explore the concrete IndefiniteLegthTuple definition.
-        </p>
-
-<source>
-public class IndefiniteLength extends ConstructedTuple
-{
-    public final boolean isLengthDefinate()
-    {
-        return false;
-    }
-}
-</source>
-
-        <p>
-          Yep this is pretty simple.  There is very little to track for this
-          Tuple since most of the tracking is handled by its decendent Tuples.
-          The class also is concrete.  What about the DefinateLength 
-          implementation ...
-        </p>
-
-<source>
-public class DefinateLength extends ConstructedTuple
-{
-    /** the number of bytes used to compose the Tuple's length field */
-    protected int lengthFieldSz = 0;
-    /** the number of bytes used to compose the Tuple's value field */
-    protected int valueFieldSz = 0;
-
-    ...
-
-    public final boolean isLengthDefinate()
-    {
-        return true;
-    }
-
-    /**
-     * Gets the number of bytes in the length (L) field of this TLV Tuple.
-     *
-     * @return number of bytes for the length
-     */
-    public final int getLengthFieldSize()
-    {
-        return lengthFieldSz;
-    }
-
-    /**
-     * Gets the number of bytes in the value (V) field of this TLV Tuple.
-     *
-     * @return number of bytes for the value
-     */
-    public final int getValueFieldSize();
-    {
-        return valueFieldSz;
-    }
-}
-</source>
-        <p>
-          Now this introduces two new concrete methods for getting the length
-          of the length field and the length of the value field.  A determinate
-          length TLV has a valid value within the Length (L) field.  The value
-          of the length field is the length of the value field.  Hence the 
-          reason why we include both these concrete methods.
-        </p>
-      </subsection>
-
-      <subsection name="Buffered Vs. Streamed PrimitiveTuples">
-        <p>
-          As we mentioned before, there are two kinds of primitive Tuples.  
-          Those that keep there value in a buffer within the TLV Tuple object,
-          in which case it is buffered within memory, and those that stream
-          the value to disk and store a referral to the value on disk.  These
-          two beasts are so different it makes sense to differentiate between
-          them using subclasses.  Let's take a look at a BufferedTuple which
-          is the simplest one.
-        </p>
-
-<source>
-public class BufferedTuple extends PrimitiveTuple
-{
-    /** contains ByteBuffers which contain parts of the value */
-    private final ArrayList value = new ArrayList();
-    /** pre-fab final unmodifiable wrapper around our modifiable list */
-    private final List unmodifiable = Collections.unmodifiableList( value );
-
-    public final boolean isBuffered()
-    {
-        return true;
-    }
-
-    /**
-     * Gets the value of this Tuple as a List of ByteBuffers.
-     *
-     * @return a list of ByteBuffers containing parts of the value
-     */
-    public final List getValue()
-    {
-        return unmodifiable;
-    }
-}
-</source>
-
-        <p>
-          The implementation introduces a final <code>getValue()</code> method
-          which returns an unmodifiable wrapper around a modifiable list of 
-          ByteBuffers.  The <code>isBuffered()</code> method is made final and
-          implemented to return true all the time.  This is easy so let's now
-          take a look at the StreamedTuple implementation.
-        </p>
-
-<source>
-public abstract class StreamedTuple extends PrimitiveTuple
-{
-    public final boolean isBuffered()
-    {
-        return false;
-    }
-
-    // might experiment with a getURL to represent the source of 
-    // the data stream - we need to discuss this on the list
-
-    /**
-     * Depending on the backing store used for accessing streamed data there
-     * may need to be multiple subclasses that implement this method.
-     *
-     * @return an InputStream that can be used to read this Tuple's streamed 
-     * value data
-     */
-    public abstract InputStream getValueStream();   
-
-    // another question is whether or not to offer a readable Channel instead
-    // of an InputStream?  This is another topic for discussion.
-}
-</source>        
-        
-        <p>
-          At this point we know that there could be multiple ways to implement
-          this kind of StreamedTuple.  Notice though the value is accessed 
-          through a stream provided by the Tuple.  This way the large value 
-          stored on disk need not all be kept in memory at one time during the
-          decode or encode process.
-        </p>
-
-      </subsection>
-    
-      <p>
-        Some code will be removed from the Tuple class today during the 
-        refactoring and kept in a TupleUtils class.  Functionality like
-        the encoding, decoding of Tuple fields and tag cooking can be
-        offloaded to this class.
-      </p>
-    </section>
-
-    <section name="notes">
-      <p>
-        By far the largest part of the refactoring effort is in introducing 
-        this new hierarchy and introducing some patterns that improve the
-        maintainability of the code like the State pattern.  Other minor 
-        details for this dev cycle are discussed below.
-      </p>
-
-      <subsection name="Termination Tuples">
-        <p>
-          A lot of effort is made to track the position of a Tuple within a
-          PDU.  This is why we have methods like getTagStartIndex().  We want
-          to know where the first byte of a Tuple's tag is within a PDU.  This
-          positional accounting enables better error reporting when problems
-          result.  They also allow us to detect when we start and stop 
-          processing a PDU.  
-        </p>
-
-        <p>
-          The minimum amount of information needed to track the position of a
-          Tuple within a PDU or the start and stop points of a PDU is to have 
-          the Tuple's tag start index, and the lengths of fields within the 
-          Tuple.
-        </p>
-
-        <p>
-          In a decoder for example we know that we've processed the last 
-          topmost Tuple of a PDU when we get a Tuple whose <code>
-          getTagStartIndex()</code> returns 0.  <b>WARNING</b>: AbstractTuple
-          should default the value the start tag index to -1 so it cannot 
-          be interpretted as a terminator.
-        </p>
-      </subsection>
-
-      <subsection name="New Coherent Replacement for Stateful Codec API">
-        <p>
-          There have been many complaints about the codec API being too 
-          generic or the callback mechanism being somewhat unintuitive.
-          Perhaps we can work on more specific interfaces which incorporate
-          the concepts of producer and consumer.  Plus let's see if we can
-          make these interfaces specific so we don't have ugly codes and casts
-          all over the place.
-        </p>
-
-        <p>
-          Also in the end we want to do away with this codec API which was
-          originally intended to fuse back into commons.  I've abandoned this
-          idea because it is too difficult to make all parties happy.  The 
-          best thing to do is create our own interface that fit well and 
-          enable them to be wrapped for other APIs.  Hence going towards custom
-          codec API's is not an issue.  The old codec stuff can be pushed into
-          the protocol framework API.
-        </p>
-
-        <p>
-          Furthermore at the end of the day we want there to be a single runtime
-          jar without any dependencies for the ASN.1 stuff.  That means no more
-          codec API as it is with jar today within the ASN.1 project. 
-        </p>
-
-        <p>
-          Some new producer consumer interface ideas are listed below:
-        </p>
-
-        <ul>
-          <li>
-            BufferConsumer: consumes ByteBuffers. Something like <code>void
-            consume(ByteBuffer bb)</code> comes to mind.  Perhaps even with 
-            overloads to take a list or array of BBs.
-          </li>
-
-          <li>
-            TupleProducer: generates Tuples (often is a BufferConsumer).  Some
-            thing like <code>void setConsumer(TupleConsumer consumer)</code>
-            comes to mind.
-          </li>
-
-          <li>
-            TupleConsumer: consumes Tuples generated by a TupleProducer.
-            Something like <code>void consume(Tuple tlv)</code> comes to mind.
-          </li>
-
-          <li>
-            MessageProducer: produces populated message stubs
-          </li>
-        </ul>
-      </subsection>
-
-      <subsection name="Possibly Merging TupleNode and Tuple">
-        <p>
-          Right now to build Tuple trees we use yet another class to wrap 
-          Tuples called TupleNodes.  This kept the contents of the Tuple
-          class less conjested.  The Tuple class will no longer exist and the
-          conjestion issues is no longer valid.  The question now is, is it
-          worth keeping parent child methods in TupleNode when creating trees
-          while paying for extra object creation?
-        </p>
-
-        <p>
-          Note that the TupleNode methods are not required on Tuple to process
-          a byte stream of encoded TLV data in a sax-like fashion.  These 
-          methods are only required for higher level operations like visitations
-          from visitors during the encoding process.  The question really is 
-          whether we will make Tuple impure to save a little time so we don't 
-          have to create TupleNode objects to wrap Tuples and model the 
-          hierarchy?  This is something that needs to be discussed.
-        </p>
-
-        <p>
-          Contrary to the purist approach of keeping Tuple and TupleNode 
-          separate one can merge the two.  A codec need not honor these methods
-          by building the tree.  Meaning these tree node (TupleNode) methods
-          may simply return null.  If these methods are honored then it is the
-          intent of the codec to build a tree.  If the tree is built the 
-          processing is more like DOM and if not then it is more like SAX.  We
-          should not tax the DOM like processing use case by forcing the need 
-          to create extra wrappers, while accomodating the purist view.
-        </p>
-      </subsection>
-
-      <subsection name="Removing the Digester Concept">
-        <p>
-          I don't know what I was thinking when I devised this rule based
-          approach similar to the Digester in commons.  This was a big mistake
-          and IMO one of the reasons why we have performance issues.  This 
-          datastructure can be removed entirely from upper layers that depend
-          on it.
-        </p>
-
-        <p>
-          Granted this means we are going to have to weave once again our own
-          classes for handling LDAP specific PDU's however I think this will be
-          easy to do.  I will essentially rewrite the LDAP provider based on
-          our runtime to hardcode the switching rather than using this rule 
-          based triggering approach.  The new approach is also going to 
-          simplify the code significantly making it more maintainable.  
-          Hopefully these changes will also speed up the code since less
-          objects will need to be created every time a decoder is instantiated.
-        </p>
-      </subsection>
-
-      <subsection name="It's Time For DER and CER">
-        <p>
-          We need to find a way to make the rules used while decoding and 
-          encoding Tuples plugable.  This way we can change the rules to 
-          encode as generic BER, reduced BER (for increases in performance 
-          in the case of specific protocol needs).  DER likewise is a reduced
-          set of BER with restrictions on the encoding and range of values 
-          that can be interpreted from primitive values.  If the plugability
-          is there the runtime is a flexible TLV Tuple codec that can change
-          the rules use to handle the substrate.
-        </p>
-
-        <p>
-          We could easily have BerDecoder, CerDecoder and even protocol specific
-          decoders with those BER rules used by a protocol such as 
-          LdapBerDecoder for those BER decoding rules that only apply to LDAP.
-        </p>
-      </subsection>
-
-    </section>
-  </body>
-</document>
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/LengthTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/LengthTest.java
index 3c22132..175341d 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/LengthTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/LengthTest.java
@@ -22,13 +22,13 @@
 
 import java.util.Arrays;
 
-import junit.framework.Assert;
 import junit.framework.TestCase;
 
 /**
  * This class is used to test the Length class
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LengthTest extends TestCase
 {
@@ -38,17 +38,17 @@
      */
     public void testLengthGetNbBytes()
     {
-        Assert.assertEquals( 1, TLV.getNbBytes( 0 ) );
-        Assert.assertEquals( 1, TLV.getNbBytes( 1 ) );
-        Assert.assertEquals( 1, TLV.getNbBytes( 127 ) );
-        Assert.assertEquals( 2, TLV.getNbBytes( 128 ) );
-        Assert.assertEquals( 2, TLV.getNbBytes( 255 ) );
-        Assert.assertEquals( 3, TLV.getNbBytes( 256 ) );
-        Assert.assertEquals( 3, TLV.getNbBytes( 65535 ) );
-        Assert.assertEquals( 4, TLV.getNbBytes( 65536 ) );
-        Assert.assertEquals( 4, TLV.getNbBytes( 16777215 ) );
-        Assert.assertEquals( 5, TLV.getNbBytes( 16777216 ) );
-        Assert.assertEquals( 5, TLV.getNbBytes( 0xFFFFFFFF ) );
+        assertEquals( "1 expected", 1, TLV.getNbBytes( 0 ) );
+        assertEquals( "1 expected", 1, TLV.getNbBytes( 1 ) );
+        assertEquals( "1 expected", 1, TLV.getNbBytes( 127 ) );
+        assertEquals( "2 expected", 2, TLV.getNbBytes( 128 ) );
+        assertEquals( "2 expected", 2, TLV.getNbBytes( 255 ) );
+        assertEquals( "3 expected", 3, TLV.getNbBytes( 256 ) );
+        assertEquals( "3 expected", 3, TLV.getNbBytes( 65535 ) );
+        assertEquals( "4 expected", 4, TLV.getNbBytes( 65536 ) );
+        assertEquals( "4 expected", 4, TLV.getNbBytes( 16777215 ) );
+        assertEquals( "5 expected", 5, TLV.getNbBytes( 16777216 ) );
+        assertEquals( "5 expected", 5, TLV.getNbBytes( 0xFFFFFFFF ) );
     }
 
 
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/ValueTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/ValueTest.java
index 7c8686f..16215d1 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/ValueTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/ber/tlv/ValueTest.java
@@ -23,20 +23,21 @@
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
 
-import org.apache.directory.shared.asn1.ber.tlv.Value;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.asn1.primitives.BitString;
 import org.apache.directory.shared.asn1.util.Asn1StringUtils;
 import org.apache.directory.shared.asn1.util.IntegerDecoder;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
 
 
 /**
  * This class is used to test the Value class
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ValueTest extends TestCase
 {
@@ -244,13 +245,13 @@
                 -256, -255, -128, -127, -1, 0, 1, 127, 128, 255, 256, 32767, 32768, 65535, 65536, 8388607, 8388608,
                 16777215, 16777216, Integer.MAX_VALUE };
 
-        for ( int i = 0; i < testedInt.length; i++ )
+        for ( int i:testedInt )
         {
-            encoded = Value.getBytes( testedInt[i] );
+            encoded = Value.getBytes( i );
 
             int value = new BigInteger( encoded ).intValue();
 
-            Assert.assertEquals( testedInt[i], value );
+            Assert.assertEquals( i, value );
         }
     }
 
@@ -263,13 +264,13 @@
                 -256, -255, -128, -127, -1, 0, 1, 127, 128, 255, 256, 32767, 32768, 65535, 65536, 8388607, 8388608,
                 16777215, 16777216, Integer.MAX_VALUE };
 
-        for ( int i = 0; i < testedInt.length; i++ )
+        for ( int i:testedInt )
         {
-            encoded = new BigInteger( Integer.toString( testedInt[i] ) ).toByteArray();
+            encoded = new BigInteger( Integer.toString( i ) ).toByteArray();
 
             int value = IntegerDecoder.parse( new Value( encoded ) );
 
-            Assert.assertEquals( testedInt[i], value );
+            Assert.assertEquals( i, value );
         }
     }
     
@@ -301,10 +302,10 @@
         }
         catch ( EncoderException ee )
         {
-            
+            fail();
         }
         
-        assertEquals( "0x03 0x03 0x06 0x00 0x40 ", Asn1StringUtils.dumpBytes( buffer.array() )  );
+        assertEquals( "0x03 0x03 0x06 0x80 0x00 ", Asn1StringUtils.dumpBytes( buffer.array() )  );
     }
 }
 
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStackTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStackTest.java
index 0aa84bb..95ead7f 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStackTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/DecoderStackTest.java
@@ -23,10 +23,6 @@
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.asn1.codec.stateful.AbstractStatefulDecoder;
-import org.apache.directory.shared.asn1.codec.stateful.CallbackHistory;
-import org.apache.directory.shared.asn1.codec.stateful.DecoderStack;
-import org.apache.directory.shared.asn1.codec.stateful.StatefulDecoder;
 
 
 /**
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoderTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoderTest.java
index d31568b..e7ffad8 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoderTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexDecoderTest.java
@@ -29,7 +29,6 @@
 import org.apache.directory.shared.asn1.codec.binary.Hex;
 import org.apache.directory.shared.asn1.codec.stateful.DecoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.StatefulDecoder;
-import org.apache.directory.shared.asn1.codec.stateful.examples.HexDecoder;
 
 
 /**
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoderTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoderTest.java
index ecb0a96..e8e64f2 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoderTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/codec/stateful/examples/HexEncoderTest.java
@@ -29,7 +29,6 @@
 import org.apache.directory.shared.asn1.codec.binary.Hex;
 import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.StatefulEncoder;
-import org.apache.directory.shared.asn1.codec.stateful.examples.HexEncoder;
 
 
 /**
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/BitStringTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/BitStringTest.java
index 512d209..1f07482 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/BitStringTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/BitStringTest.java
@@ -24,7 +24,6 @@
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.asn1.primitives.BitString;
 import org.apache.directory.shared.asn1.util.Asn1StringUtils;
 
 
@@ -84,7 +83,7 @@
 
 
     /**
-     * Test a single bit BitString BitString
+     * Test a single bit BitString
      */
     public void testSingleBitBitString() throws DecoderException
     {
@@ -197,7 +196,7 @@
         {
             if ( bits[i] == 1 )
             {
-                bitString.setBit( i );
+                bitString.setBit( bits.length - i - 1 );
             }
         }
         
@@ -212,7 +211,7 @@
             {
                 1, 0, 1, 0 ,   1, 0, 1, 0,
                 0, 0, 0, 1,    0, 0, 0, 1,
-                1, 0, 0, 0,    1, 0, 0, 0,
+                1, 0, 0, 0,    1, 0, 0, 0,  // After modification, will become 8A
                 1, 1, 1, 1,    1, 1, 1, 0
             };
 
@@ -220,13 +219,13 @@
         {
             if ( bits[i] == 1 )
             {
-                bitString.setBit( i );
+                bitString.setBit( bits.length - i - 1 );
             }
         }
         
         bitString.setBit( 9 );
         byte[] bytesModified = new byte[]
-            { (byte)0xAA, 0x51, (byte)0x88, (byte)0xFE };
+            { (byte)0xAA, 0x11, (byte)0x8A, (byte)0xFE };
                             
         assertEquals( Asn1StringUtils.dumpBytes( bytesModified ), Asn1StringUtils.dumpBytes( bitString.getData() ) );
     }
@@ -247,13 +246,13 @@
         {
             if ( bits[i] == 1 )
             {
-                bitString.setBit( i );
+                bitString.setBit( bits.length - i - 1 );
             }
         }
         
         bitString.clearBit( 11 );
         byte[] bytesModified = new byte[]
-            { (byte)0xAA, 0x01, (byte)0x88, (byte)0xFE };
+            { (byte)0xAA, 0x11, (byte)0x80, (byte)0xFE };
                             
         assertEquals( Asn1StringUtils.dumpBytes( bytesModified ), Asn1StringUtils.dumpBytes( bitString.getData() ) );
     }
diff --git a/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/OIDTest.java b/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/OIDTest.java
index bb80648..579f8e1 100644
--- a/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/OIDTest.java
+++ b/asn1/src/test/java/org/apache/directory/shared/asn1/primitives/OIDTest.java
@@ -24,7 +24,6 @@
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.asn1.primitives.OID;
 
 
 /**
@@ -374,10 +373,10 @@
      */
     public void testOidEqualsPerf() throws DecoderException
     {
-    	String s1 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
-    	String s2 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
-    	String s3 = "1.3.6.1.5.5.2";
-    	
+        String s1 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
+        String s2 = "1.2.840.113554.1.2.2.1.2.840.113554.1.2.2.1.2.840.113554.1.2.2";
+        String s3 = "1.3.6.1.5.5.2";
+        
         OID oid1 = new OID( s1 );
         OID oid2 = new OID( s2 );
         OID oid3 = new OID( s3 );
diff --git a/bouncycastle-reduced/pom.xml b/bouncycastle-reduced/pom.xml
new file mode 100644
index 0000000..d2a34c9
--- /dev/null
+++ b/bouncycastle-reduced/pom.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>shared-parent</artifactId>
+    <groupId>org.apache.directory.shared</groupId>
+    <version>0.9.12-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.directory.shared</groupId>
+  <artifactId>shared-bouncycastle-reduced</artifactId>
+  <name>Apache Directory Reduced Bouncycastle (repackaged)</name>
+  <description>
+    Repackages the BouncyCastle jar including only those files we require
+    rather than everything which includes patented algorithms like IDEA.
+  </description>
+  <dependencies>
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcprov-jdk15</artifactId>
+      <version>136</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-shade-plugin</artifactId>
+          <version>1.0.1</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <artifactSet>
+                <excludes>
+                  <exclude>org.slf4j:slf4j-api</exclude>
+                </excludes>
+              </artifactSet>
+              <filters>
+                <filter>
+                  <artifact>bouncycastle:bcprov-jdk15</artifact>
+                  <!-- includes contains some of the bc classes needed for startTLS functionality.  List is not yet complete-->
+                  <!-- It is much easier to experiment with the installer noarch bundle which is extracting files from bc directly -->
+<!--
+                  <includes>
+                    <include>org/bouncycastle/jce/provider/BouncyCastleProvider.class</include>
+                    <include>org/bouncycastle/x509/X509V1CertificateGenerator.class</include>
+                    <include>org/bouncycastle/jce/interfaces/ConfigurableProvider.class</include>
+                    <include>org/bouncycastle/jce/provider/symmetric/AESMappings.class</include>
+                    <include>org/bouncycastle/asn1/nist/NISTObjectIdentifiers.class</include>
+                    <include>org/bouncycastle/asn1/DERObjectIdentifier.class</include>
+                    <include>org/bouncycastle/asn1/ASN1Object.class</include>
+                    <include>org/bouncycastle/asn1/DERObject.class</include>
+                    <include>org/bouncycastle/asn1/DERTags.class</include>
+                    <include>org/bouncycastle/asn1/ASN1Encodable.class</include>
+                    <include>org/bouncycastle/asn1/DEREncodable.class</include>
+                    <include>org/bouncycastle/jce/provider/symmetric/CamelliaMappings.class</include>
+                    <include>org/bouncycastle/asn1/ntt/NTTObjectIdentifiers.class</include>
+                  </includes>
+-->
+                  <excludes>
+                    <!-- signature files -->
+                    <exclude>META-INF/BCKEY.SF</exclude>
+                    <exclude>META-INF/BCKEY.DSA</exclude>
+                    <!-- IDEA patent implementation -->
+                    <exclude>org/bouncycastle/crypto/engines/IDEAEngine.class</exclude>
+                    <exclude>org/bouncycastle/asn1/misc/IDEACBCPar.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JDKAlgorithmParameterGenerator$IDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEKeyGenerator$IDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEBlockCipher$IDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCESecretKeyFactory$PBEWithSHAAndIDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEBlockCipher$PBEWithSHAAndIDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JDKAlgorithmParameters$IDEAAlgorithmParameters.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEStreamCipher$IDEA_OFB8.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEMac$IDEACFB8.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEBlockCipher$IDEACBC.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEMac$IDEA.class</exclude>
+                    <exclude>org/bouncycastle/jce/provider/JCEStreamCipher$IDEA_CFB8.class</exclude>
+                  </excludes>
+                </filter>
+              </filters>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/convert/pom.xml b/convert/pom.xml
index 892ed0e..1abcd26 100644
--- a/convert/pom.xml
+++ b/convert/pom.xml
@@ -1,27 +1,30 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-converter</artifactId>
   <name>Apache Directory Protocol Ldap Converters</name>
@@ -32,37 +35,19 @@
     <url>http://issues.apache.org/jira/browse/DIRSERVER</url>
   </issueManagement>
 
+  <!--
   <distributionManagement>
     <site>
       <id>apache.websites</id>
       <url>scp://minotaur.apache.org/www/directory.apache.org/subprojects/ldap/common</url>
     </site>
   </distributionManagement>
+  -->
 
   <description>
     Common LDAP converters : LDIF, DSML, CSV, etc
   </description>
 
-  <mailingLists>
-    <mailingList>
-      <name>Apache Directory Project</name>
-      <subscribe>dev-subscribe@directory.apache.org</subscribe>
-      <unsubscribe>dev-unsubscribe@directory.apache.org</unsubscribe>
-      <archive>http://mail-archives.apache.org/mod_mbox/dev/</archive>
-      <otherArchives>
-        <otherArchive>http://www.archivum.info/dev@directory.apache.org/</otherArchive>
-      </otherArchives>
-    </mailingList>
-  </mailingLists>
-
-  <licenses>
-    <license>
-      <name>Apache 2.0 License</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
   <dependencies>
 
     <dependency>
diff --git a/convert/src/main/antlr/schema.g b/convert/src/main/antlr/schema.g
index 5b86d95..f45f87f 100644
--- a/convert/src/main/antlr/schema.g
+++ b/convert/src/main/antlr/schema.g
@@ -99,11 +99,6 @@
         ( 'a' .. 'z') ( 'a' .. 'z' | '0' .. '9' | '-' | ';' )*
     ;
 
-//XSTRING 
-//	: 
-//		"x-" ( 'a' .. 'z' ) ( 'a' .. 'z' | '-' | '_' )*
-//	;
-
 DESC
     :
         "desc" WS QUOTE ( ~'\'' )+ QUOTE
diff --git a/convert/src/main/appended-resources/META-INF/LICENSE b/convert/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..857d336
--- /dev/null
+++ b/convert/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,21 @@
+--------------------------------------------------------------
+                            ANTLR 2 License
+
+ANTLR 2 License
+
+We reserve no legal rights to the ANTLR--it is fully in the public domain. An 
+individual or company may do whatever they wish with source code distributed 
+with ANTLR or the code generated by ANTLR, including the incorporation of 
+ANTLR, or its output, into commerical software.
+
+We encourage users to develop software with ANTLR. However, we do ask that 
+credit is given to us for developing ANTLR. By "credit", we mean that if you 
+use ANTLR or incorporate any source code into one of your programs (commercial 
+product, research project, or otherwise) that you acknowledge this fact 
+somewhere in the documentation, research report, etc... If you like ANTLR 
+and have developed a nice tool with the output, please mention that you 
+developed it using ANTLR. In addition, we ask that the headers remain intact 
+in our source code. As long as these guidelines are kept, we expect to 
+continue enhancing this system and expect to make other tools available as 
+they are completed. 
+
diff --git a/convert/src/main/appended-resources/META-INF/NOTICE b/convert/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..c4d94e5
--- /dev/null
+++ b/convert/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+
+This software includes code generated by ANTLR 2.
+
diff --git a/convert/src/main/java/org/apache/directory/shared/converter/schema/ParserException.java b/convert/src/main/java/org/apache/directory/shared/converter/schema/ParserException.java
index 9e634dd..554aa3b 100644
--- a/convert/src/main/java/org/apache/directory/shared/converter/schema/ParserException.java
+++ b/convert/src/main/java/org/apache/directory/shared/converter/schema/ParserException.java
@@ -22,10 +22,11 @@
 /**
  * An exception thrown if we have an error while parsing a schema file.
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ParserException extends Exception
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
     
     /**
      * A strandard constuctor
diff --git a/convert/src/main/java/org/apache/directory/shared/converter/schema/Schema.java b/convert/src/main/java/org/apache/directory/shared/converter/schema/Schema.java
index 877fe0e..52cc91a 100644
--- a/convert/src/main/java/org/apache/directory/shared/converter/schema/Schema.java
+++ b/convert/src/main/java/org/apache/directory/shared/converter/schema/Schema.java
@@ -29,6 +29,7 @@
  * in which the ldif file will be dumped.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class Schema
 {
diff --git a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java
index 647a8d7..cdfda1b 100644
--- a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java
+++ b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java
@@ -37,6 +37,7 @@
  * description, names and extensions (not implemented)
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public abstract class SchemaElementImpl implements SchemaElement
 {
diff --git a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaParser.java b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaParser.java
index 7db28df..c0fa7cc 100755
--- a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaParser.java
+++ b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaParser.java
@@ -19,12 +19,6 @@
  */
 package org.apache.directory.shared.converter.schema;
 
-
-import org.apache.directory.shared.converter.schema.antlrSchemaLexer;
-import org.apache.directory.shared.converter.schema.antlrSchemaParser;
-import org.apache.directory.shared.ldap.util.ExceptionUtils;
-
-import java.util.List;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -34,15 +28,37 @@
 import java.io.PipedOutputStream;
 import java.io.Writer;
 import java.text.ParseException;
+import java.util.List;
+
+import org.apache.directory.shared.ldap.util.ExceptionUtils;
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
 
+/*
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.Writer;
+import java.text.ParseException;
+import java.util.List;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+import org.apache.directory.shared.ldap.util.ExceptionUtils;
+*/
+
 
 /**
  * A reusable wrapper for antlr generated schema parsers.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class SchemaParser
 {
diff --git a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaToLdif.java b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaToLdif.java
index 6f7728c..42aac46 100644
--- a/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaToLdif.java
+++ b/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaToLdif.java
@@ -23,7 +23,6 @@
 import java.io.Writer;
 import java.util.List;
 
-import org.apache.directory.shared.converter.schema.Schema;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,6 +31,7 @@
  * with the Apache DS meta schema format
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class SchemaToLdif
 {
@@ -100,7 +100,6 @@
             }
             catch ( Exception e )
             {
-                e.printStackTrace();
                 throw new ParserException( "Failed while generating sources for " + schema.getName() );
             }
         }
diff --git a/convert/src/site/site.xml b/convert/src/site/site.xml
new file mode 100644
index 0000000..020b38e
--- /dev/null
+++ b/convert/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+-->
+<project name="${project.name}">
+    <bannerLeft>
+        <name>${project.name}</name>
+    </bannerLeft>
+    <publishDate position="navigation-bottom" format="dd-MM-yyyy HH:mm" />
+    <body>
+        <menu name="Parent">
+            <item name="Apache Directory Shared" href="../index.html" />
+        </menu>
+        <menu ref="reports" />
+    </body>
+</project>
diff --git a/ldap-constants/pom.xml b/ldap-constants/pom.xml
index 6b4201b..4fd0694 100644
--- a/ldap-constants/pom.xml
+++ b/ldap-constants/pom.xml
@@ -1,27 +1,30 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-ldap-constants</artifactId>
   <name>Apache Directory Protocol Ldap Shared Constants</name>
@@ -32,36 +35,18 @@
     <url>http://issues.apache.org/jira/browse/DIRSERVER</url>
   </issueManagement>
 
+  <!--
   <distributionManagement>
     <site>
       <id>apache.websites</id>
       <url>scp://minotaur.apache.org/www/directory.apache.org/subprojects/ldap/common</url>
     </site>
   </distributionManagement>
+  -->
 
   <description>
     Common LDAP constants used by clients and servers.
   </description>
 
-  <mailingLists>
-    <mailingList>
-      <name>Apache Directory Project</name>
-      <subscribe>dev-subscribe@directory.apache.org</subscribe>
-      <unsubscribe>dev-unsubscribe@directory.apache.org</unsubscribe>
-      <archive>http://mail-archives.apache.org/mod_mbox/dev/</archive>
-      <otherArchives>
-        <otherArchive>http://www.archivum.info/dev@directory.apache.org/</otherArchive>
-      </otherArchives>
-    </mailingList>
-  </mailingLists>
-
-  <licenses>
-    <license>
-      <name>Apache 2.0 License</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
 </project>
 
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/AuthenticationLevel.java b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/AuthenticationLevel.java
new file mode 100644
index 0000000..b6593e3
--- /dev/null
+++ b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/AuthenticationLevel.java
@@ -0,0 +1,78 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.constants;
+
+
+/**
+ * An enumeration that represents the level of authentication.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public enum AuthenticationLevel
+{
+    /**
+     * No authentication (anonymous access)
+     */
+    NONE( 0, "none" ),
+
+    /**
+     * Simple authentication (bound with plain-text credentials)
+     */
+    SIMPLE( 1, "simple" ),
+
+    /**
+     * Strong authentication (bound with encrypted cerdentials)
+     */
+    STRONG( 2, "string" );
+    
+    private int level;
+    
+    private final String name;
+
+    private AuthenticationLevel( int level, String name )
+    {
+        this.level = level;
+        this.name = name;
+    }
+
+    /**
+     * Returns the integer value of this level (greater value, stronger level).
+     */
+    public int getLevel()
+    {
+        return level;
+    }
+
+
+    /**
+     * Returns the name of this level.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+
+    public String toString()
+    {
+        return name;
+    }
+}
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/LdapSecurityConstants.java b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/LdapSecurityConstants.java
index 902bada..321693a 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/LdapSecurityConstants.java
+++ b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/LdapSecurityConstants.java
@@ -20,20 +20,77 @@
 package org.apache.directory.shared.ldap.constants;
 
 /**
- * A class to store all the security constants used in the server
+ * An enum to store all the security constants used in the server
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev:$
  */
-public class LdapSecurityConstants
+public enum LdapSecurityConstants
 {
-    public static final String HASH_METHOD_SHA = "sha";
+    HASH_METHOD_SHA( "sha" ),
 
-    public static final String HASH_METHOD_SSHA = "ssha";
+    HASH_METHOD_SSHA( "ssha" ),
 
-    public static final String HASH_METHOD_MD5 = "md5";
+    HASH_METHOD_MD5( "md5" ),
 
-    public static final String HASH_METHOD_SMD5 = "smd5";
+    HASH_METHOD_SMD5( "smd5" ),
 
-    public static final String HASH_METHOD_CRYPT = "crypt";
+    HASH_METHOD_CRYPT( "crypt" );
+    
+    private String name;
+    
+    /**
+     * Creates a new instance of LdapSecurityConstants.
+     */
+    private LdapSecurityConstants( String name )
+    {
+        this.name = name;
+    }
+
+    /**
+     * Return the name associated with the constant.
+     */
+    public String getName()
+    {
+        return name;
+    }
+    
+    
+    /**
+     * Get the associated constant from a string
+     *
+     * @param name The algorithm's name
+     * @return The associated constant
+     */
+    public static LdapSecurityConstants getAlgorithm( String name )
+    {
+        String algorithm = ( name == null ? "" : name.toLowerCase() );
+        
+        if ( HASH_METHOD_SHA.getName().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_SHA;
+        }
+
+        if ( HASH_METHOD_SSHA.getName().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_SSHA;
+        }
+
+        if ( HASH_METHOD_MD5.getName().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_MD5;
+        }
+
+        if ( HASH_METHOD_SMD5.getName().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_SMD5;
+        }
+        
+        if ( HASH_METHOD_CRYPT.getName().equalsIgnoreCase( algorithm ) )
+        {
+            return HASH_METHOD_CRYPT;
+        }
+        
+        return null;
+    }
 }
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SaslQoP.java
similarity index 77%
rename from ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
rename to ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SaslQoP.java
index ddf0842..da0b008 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
+++ b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SaslQoP.java
@@ -20,13 +20,17 @@
 package org.apache.directory.shared.ldap.constants;
 
 /**
- * A utility class where we declare all the statically defined DN used in the server.
- *
+ * Contains constants used for populating the SASL QoP 
+ * in the RootDSE.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev:$
+ * @version $Rev$
  */
-public class ServerDNConstants 
+public interface SaslQoP
 {
-	public static final String ADMINISTRATORS_GROUP_DN = "cn=Administrators,ou=groups,ou=system";
+    String ATTRIBUTE = "supportedQoP";
 
+    String QOP_AUTH      = "auth" ;
+    String QOP_AUTH_INT  = "auth-int" ;
+    String QOP_AUTH_CONF = "auth-conf" ;
 }
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SchemaConstants.java b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SchemaConstants.java
index e44440d..653c886 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SchemaConstants.java
+++ b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SchemaConstants.java
@@ -40,7 +40,7 @@
     String[] ALL_OPERATIONAL_ATTRIBUTES_ARRAY = new String[]{ ALL_OPERATIONAL_ATTRIBUTES };
     
     // ---- ObjectClasses -----------------------------------------------------
-	// Krb5Principal
+    // Krb5Principal
     String KRB5_PRINCIPAL_OC = "krb5Principal";
     String KRB5_PRINCIPAL_OC_OID = "1.3.6.1.4.1.5322.10.2.1";
     
@@ -100,6 +100,10 @@
     String ACCESS_CONTROL_SUBENTRY_OC = "accessControlSubentry";
     String ACCESS_CONTROL_SUBENTRY_OC_OID = "2.5.17.1";
     
+    // CollectiveAttributeSubentry
+    String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC = "collectiveAttributeSubentry";
+    String COLLECTIVE_ATTRIBUTE_SUBENTRY_OC_OID = "2.5.17.2";
+
     // Subschema
     String SUBSCHEMA_OC = "subschema";
     String SUBSCHEMA_OC_OID = "2.5.20.1";
@@ -152,7 +156,11 @@
     String UNIQUE_MEMBER_AT = "uniqueMember";
     String UNIQUE_MEMBER_AT_OID = "2.5.4.50";
 
-    // CreateTimestamp
+    // ExcludeAllColectiveAttributes
+    String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT = "excludeAllCollectiveAttributes";
+    String EXCLUDE_ALL_COLLECTIVE_ATTRIBUTES_AT_OID = "2.5.18.0";
+    
+        // CreateTimestamp
     String CREATE_TIMESTAMP_AT = "createTimestamp";
     String CREATE_TIMESTAMP_AT_OID = "2.5.18.1";
     
@@ -240,11 +248,43 @@
     // UidObject
     String UID_OBJECT_AT = "uidObject";
     String UID_OBJECT_AT_OID = "1.3.6.1.1.3.1";
+    
+    // VendorName
+    String VENDOR_NAME_AT = "vendorName";
+    String VENDOR_NAME_AT_OID = "1.3.6.1.1.4";
+    
+    // VendorVersion
+    String VENDOR_VERSION_AT = "vendorVersion";
+    String VENDOR_VERSION_AT_OID = "1.3.6.1.1.5";
+    
+    // NamingContexts
+    String NAMING_CONTEXTS_AT = "namingContexts";
+    String NAMING_CONTEXTS_AT_OID = "1.3.6.1.4.1.1466.101.120.5";
+    
+    // SupportedExtension
+    String SUPPORTED_EXTENSION_AT = "supportedExtension";
+    String SUPPORTED_EXTENSION_AT_OID = "1.3.6.1.4.1.1466.101.120.7";
+
+    // supportedSASLMechanisms
+    String SUPPORTED_SASL_MECHANISMS_AT = "supportedSASLMechanisms";
+    String SUPPORTED_SASL_MECHANISMS_AT_OID = "1.3.6.1.4.1.1466.101.120.14";
+    
+    // supportedControl
+    String SUPPORTED_CONTROL_AT = "supportedControl";
+    String SUPPORTED_CONTROL_AT_OID = "1.3.6.1.4.1.1466.101.120.13";
+    
+    // SupportedLdapVersion
+    String SUPPORTED_LDAP_VERSION_AT = "supportedLDAPVersion";
+    String SUPPORTED_LDAP_VERSION_AT_OID = "1.3.6.1.4.1.1466.101.120.15";
 
     // LdapSyntaxes
     String LDAP_SYNTAXES_AT = "ldapSyntaxes";
     String LDAP_SYNTAXES_AT_OID = "1.3.6.1.4.1.1466.101.120.16";
-
+    
+    // SupportedFeatures
+    String SUPPORTED_FEATURES_AT = "supportedFeatures";
+    String SUPPORTED_FEATURES_AT_OID = "1.3.6.1.4.1.4203.1.3.5";
+    
     // AccessControlSubentries
     String ACCESS_CONTROL_SUBENTRIES_AT = "accessControlSubentries";
     String ACCESS_CONTROL_SUBENTRIES_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.11";
@@ -268,7 +308,7 @@
     // Ref
     String REF_AT = "ref";
     String REF_AT_OID = "2.16.840.1.113730.3.1.34";
-    	
+
     // DisplayName
     String DISPLAY_NAME_AT = "displayName";
     String DISPLAY_NAME_AT_OID = "2.16.840.1.113730.3.1.241";
@@ -301,4 +341,7 @@
     String BIT_STRING_MR = "bitStringMatch";
     String GENERALIZED_TIME_MR = "generalizedTimeMatch";
     String GENERALIZED_TIME_ORDERING_MR = "generalizedTimeOrderingMatch";
+    
+    // ---- Features ----------------------------------------------------------
+    String FEATURE_ALL_OPERATIONAL_ATTRIBUTES = "1.3.6.1.4.1.4203.1.5.1";
 }
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SupportedSaslMechanisms.java
similarity index 68%
copy from ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
copy to ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SupportedSaslMechanisms.java
index ddf0842..6910651 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
+++ b/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/SupportedSaslMechanisms.java
@@ -20,13 +20,21 @@
 package org.apache.directory.shared.ldap.constants;
 
 /**
- * A utility class where we declare all the statically defined DN used in the server.
- *
+ * Contains constants used for populating the supportedSASLMechanisms 
+ * in the RootDSE.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev:$
+ * @version $Rev$
  */
-public class ServerDNConstants 
+public interface SupportedSaslMechanisms
 {
-	public static final String ADMINISTRATORS_GROUP_DN = "cn=Administrators,ou=groups,ou=system";
+    String CRAM_MD5 = "CRAM-MD5";
+    String DIGEST_MD5 = "DIGEST-MD5";
+    String GSSAPI = "GSSAPI";
+    String PLAIN = "PLAIN";
 
+    /** Not a SASL JDK supported mechanism */
+    String NTLM = "NTLM";
+    /** Not a SASL JDK supported mechanism */
+    String GSS_SPNEGO = "GSS-SPNEGO";
 }
diff --git a/ldap-constants/src/site/site.xml b/ldap-constants/src/site/site.xml
new file mode 100644
index 0000000..020b38e
--- /dev/null
+++ b/ldap-constants/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+-->
+<project name="${project.name}">
+    <bannerLeft>
+        <name>${project.name}</name>
+    </bannerLeft>
+    <publishDate position="navigation-bottom" format="dd-MM-yyyy HH:mm" />
+    <body>
+        <menu name="Parent">
+            <item name="Apache Directory Shared" href="../index.html" />
+        </menu>
+        <menu ref="reports" />
+    </body>
+</project>
diff --git a/ldap-jndi/pom.xml b/ldap-jndi/pom.xml
index fc9d729..b40d837 100644
--- a/ldap-jndi/pom.xml
+++ b/ldap-jndi/pom.xml
@@ -1,27 +1,30 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-ldap-jndi</artifactId>
   <name>Apache Directory JNDI Shared</name>
@@ -32,12 +35,14 @@
     both in the server and in studio.
   </description>
   
+  <!--
   <distributionManagement>
     <site>
-      <id>apacheds.websites</id>
-      <url>scp://minotaur.apache.org/www/directory.apache.org/newsite/subprojects/jndi-shared/</url>
+      <id>apache.websites</id>
+      <url>scp://minotaur.apache.org/www/directory.apache.org/subprojects/ldap/common</url>
     </site>
   </distributionManagement>
+  -->
 
 </project>
 
diff --git a/ldap-jndi/src/site/site.xml b/ldap-jndi/src/site/site.xml
new file mode 100644
index 0000000..020b38e
--- /dev/null
+++ b/ldap-jndi/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+-->
+<project name="${project.name}">
+    <bannerLeft>
+        <name>${project.name}</name>
+    </bannerLeft>
+    <publishDate position="navigation-bottom" format="dd-MM-yyyy HH:mm" />
+    <body>
+        <menu name="Parent">
+            <item name="Apache Directory Shared" href="../index.html" />
+        </menu>
+        <menu ref="reports" />
+    </body>
+</project>
diff --git a/ldap/pom.xml b/ldap/pom.xml
index 0c873df..55ac293 100644
--- a/ldap/pom.xml
+++ b/ldap/pom.xml
@@ -1,27 +1,30 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
+
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
 -->
-<!-- $Rev:  $ $Date:  $ -->
+
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.shared</groupId>
     <artifactId>shared-parent</artifactId>
-    <version>0.9.8-SNAPSHOT</version>
+    <version>0.9.12-SNAPSHOT</version>
   </parent>
   <artifactId>shared-ldap</artifactId>
   <name>Apache Directory Protocol Ldap Shared</name>
@@ -32,37 +35,19 @@
     <url>http://issues.apache.org/jira/browse/DIRSERVER</url>
   </issueManagement>
 
+  <!--
   <distributionManagement>
     <site>
       <id>apache.websites</id>
       <url>scp://minotaur.apache.org/www/directory.apache.org/subprojects/ldap/common</url>
     </site>
   </distributionManagement>
+  -->
 
   <description>
     Common LDAP packages used by clients and servers.
   </description>
 
-  <mailingLists>
-    <mailingList>
-      <name>Apache Directory Project</name>
-      <subscribe>dev-subscribe@directory.apache.org</subscribe>
-      <unsubscribe>dev-unsubscribe@directory.apache.org</unsubscribe>
-      <archive>http://mail-archives.apache.org/mod_mbox/dev/</archive>
-      <otherArchives>
-        <otherArchive>http://www.archivum.info/dev@directory.apache.org/</otherArchive>
-      </otherArchives>
-    </mailingList>
-  </mailingLists>
-
-  <licenses>
-    <license>
-      <name>Apache 2.0 License</name>
-      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-
   <dependencies>
 
     <dependency>
diff --git a/ldap/src/main/antlr/ACIItem.g b/ldap/src/main/antlr/ACIItem.g
index aa25c5f..3646ec2 100644
--- a/ldap/src/main/antlr/ACIItem.g
+++ b/ldap/src/main/antlr/ACIItem.g
@@ -32,7 +32,6 @@
 import java.util.Enumeration;
 
 import javax.naming.directory.Attribute;
-import javax.naming.Name;
 
 import org.apache.directory.shared.ldap.filter.BranchNode;
 import org.apache.directory.shared.ldap.filter.AndNode;
@@ -54,7 +53,9 @@
 import org.apache.directory.shared.ldap.util.OptionalComponentsMonitor;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
 import org.apache.directory.shared.ldap.schema.OidNormalizer;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -125,8 +126,8 @@
     private Set<UserPermission> userPermissions;
     private Map<String, OidNormalizer> oidsMap;
     
-    private Set<Name> chopBeforeExclusions;
-    private Set<Name> chopAfterExclusions;
+    private Set<LdapDN> chopBeforeExclusions;
+    private Set<LdapDN> chopAfterExclusions;
     private SubtreeSpecificationModifier ssModifier = null;
     
     private ComponentsMonitor mainACIItemComponentsMonitor;
@@ -144,7 +145,7 @@
      */
     public void init( Map<String, OidNormalizer> oidsMap )
     {
-    	this.oidsMap = oidsMap;
+        this.oidsMap = oidsMap;
     }
 
     /**
@@ -882,7 +883,7 @@
 name
 {
     log.debug( "entered name()" );
-    Set<Name> names = new HashSet<Name>();
+    Set<LdapDN> names = new HashSet<LdapDN>();
     LdapDN distinguishedName = null;
 }
     :
@@ -905,7 +906,7 @@
 userGroup
 {
     log.debug( "entered userGroup()" );
-    Set<Name> userGroup = new HashSet<Name>();
+    Set<LdapDN> userGroup = new HashSet<LdapDN>();
     LdapDN distinguishedName = null;
 }
     :
@@ -1021,8 +1022,8 @@
     // in case something is left from the last parse
     ss = null;
     ssModifier = new SubtreeSpecificationModifier();
-    chopBeforeExclusions = new HashSet<Name>();
-    chopAfterExclusions = new HashSet<Name>();
+    chopBeforeExclusions = new HashSet<LdapDN>();
+    chopAfterExclusions = new HashSet<LdapDN>();
     subtreeSpecificationComponentsMonitor = new OptionalComponentsMonitor( 
             new String [] { "base", "specificExclusions", "minimum", "maximum" } );
 }
@@ -1223,7 +1224,7 @@
     :
     ID_item ( SP )* COLON ( SP )* oid=oid
     {
-        node = new EqualityNode( SchemaConstants.OBJECT_CLASS_AT , oid );
+        node = new EqualityNode( SchemaConstants.OBJECT_CLASS_AT , new ClientStringValue( oid ) );
     }
     ;
 
diff --git a/ldap/src/main/antlr/ACIItemChecker.g b/ldap/src/main/antlr/ACIItemChecker.g
index de05dbc..0150581 100644
--- a/ldap/src/main/antlr/ACIItemChecker.g
+++ b/ldap/src/main/antlr/ACIItemChecker.g
@@ -422,7 +422,7 @@
         OPEN_CURLY ( SP )*
             distinguishedName ( SP )*
                 ( SEP ( SP )* distinguishedName ( SP )*
-			)*
+            )*
         CLOSE_CURLY
     ;
 
diff --git a/ldap/src/main/antlr/SubtreeSpecificationChecker.g b/ldap/src/main/antlr/SubtreeSpecificationChecker.g
index 17ae819..bfaf6d2 100644
--- a/ldap/src/main/antlr/SubtreeSpecificationChecker.g
+++ b/ldap/src/main/antlr/SubtreeSpecificationChecker.g
@@ -236,12 +236,12 @@
     
 filter
 {
-	log.debug( "entered filter()" );
+    log.debug( "entered filter()" );
 }
-	:
-	( filterToken:FILTER { FilterParser.parse( filterToken.getText() ); } )
-	;
-	exception
+    :
+    ( filterToken:FILTER { FilterParser.parse( filterToken.getText() ); } )
+    ;
+    exception
     catch [Exception e]
     {
         throw new RecognitionException( "filterParser failed. " + e.getMessage() );
diff --git a/ldap/src/main/antlr/TriggerSpecification.g b/ldap/src/main/antlr/TriggerSpecification.g
index b85ea57..1fa22da 100644
--- a/ldap/src/main/antlr/TriggerSpecification.g
+++ b/ldap/src/main/antlr/TriggerSpecification.g
@@ -79,9 +79,9 @@
     
     private String triggerStoredProcedureName;
     
-	private List<StoredProcedureParameter> triggerStoredProcedureParameters;
-	
-	private List<StoredProcedureOption> triggerStoredProcedureOptions;
+    private List<StoredProcedureParameter> triggerStoredProcedureParameters;
+    
+    private List<StoredProcedureOption> triggerStoredProcedureOptions;
     
     private List<SPSpec> spSpecs;   
     
@@ -165,7 +165,7 @@
         ( modifyStoredProcedureParameterList )?
     CLOSE_PARAN ( SP )* SEMI ( SP )*
     {
-    	spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
+        spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
     })+
     ;
 
@@ -180,7 +180,7 @@
         ( addStoredProcedureParameterList )?
     CLOSE_PARAN ( SP )* SEMI ( SP )*
     {
-    	spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
+        spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
     }
     )+
     ;
@@ -196,7 +196,7 @@
         ( deleteStoredProcedureParameterList )?
     CLOSE_PARAN ( SP )* SEMI ( SP )*
     {
-    	spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
+        spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
     }
     )+
     ;
@@ -215,7 +215,7 @@
         ( modifyDNStoredProcedureParameterList )?
     CLOSE_PARAN ( SP )* SEMI ( SP )*
     {
-    	spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
+        spSpecs.add( new SPSpec(triggerStoredProcedureName, triggerStoredProcedureOptions, triggerStoredProcedureParameters ) );
     }
     )+
     ;
@@ -236,9 +236,9 @@
     :
     ID_CALL
     {
-    	triggerStoredProcedureName = null;
-    	triggerStoredProcedureParameters = new ArrayList<StoredProcedureParameter>();
-		triggerStoredProcedureOptions = new ArrayList<StoredProcedureOption>();
+        triggerStoredProcedureName = null;
+        triggerStoredProcedureParameters = new ArrayList<StoredProcedureParameter>();
+        triggerStoredProcedureOptions = new ArrayList<StoredProcedureOption>();
     }
     ( SP )+ triggerStoredProcedureName=fullyQualifiedStoredProcedureName ( SP )*
         ( genericStoredProcedureOptionList ( SP )* )?
@@ -349,7 +349,7 @@
 }
     : ID_ldapContext ( SP )+ ldapContext=distinguishedName
     { triggerStoredProcedureParameters.add( StoredProcedureParameter.Generic_LDAP_CONTEXT.instance( ldapContext ) ); }
-	;
+    ;
 
 // -----------------------------------------------------------------------------
 
diff --git a/ldap/src/main/antlr/schema-extension.g b/ldap/src/main/antlr/schema-extension.g
index 844d895..b638ca8 100644
--- a/ldap/src/main/antlr/schema-extension.g
+++ b/ldap/src/main/antlr/schema-extension.g
@@ -39,18 +39,31 @@
     k = 2 ;
     exportVocab=AntlrSchemaExtension ;
     charVocabulary = '\u0000'..'\uFFFE'; 
-    caseSensitive = true ;
+    caseSensitive = false ;
     defaultErrorHandler = false ;
 }
 
-protected WHSP : (options{greedy=true;}: ' ' )+ {$setType(Token.SKIP);} ;
+protected WHSP
+    :
+    ( options {greedy=true;} :
+    ' '
+    |
+    '\t'
+    |
+    '\r' (options {greedy=true;} : '\n')? { newline(); } 
+    |
+    '\n' { newline(); }
+    )+
+    { $setType(Token.SKIP); } //ignore this token
+    ;
+
 protected QUOTE : '\'' ;
 //protected ESC : '\\' ;
 
 XKEY : xstring:XSTRING { setText(xstring.getText().trim()); }; 
 XVALUES : values:VALUES { setText(values.getText().trim()); };
 
-protected XSTRING : ( "X-" ( 'a'..'z' | 'A'..'Z' | '-' | '_' )+ WHSP ) ; 
+protected XSTRING : ( "x-" ( 'a'..'z' | '-' | '_' )+ (WHSP)? ) ; 
 protected VALUES : ( VALUE | '('  VALUE ( ('$')? VALUE )* ')' ) ;
 protected VALUE : (WHSP)? ( QUOTED_STRING ) (options {greedy=true;}: WHSP)? ;
 protected QUOTED_STRING : ( QUOTE (~'\'')* QUOTE ) ;
@@ -90,7 +103,7 @@
     {
         try 
         {
-    	    AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
+            AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
             AntlrSchemaQdstringParser parser = new AntlrSchemaQdstringParser(lexer);
             qdstrings = parser.qdstrings();
         }
diff --git a/ldap/src/main/antlr/schema-qdstring.g b/ldap/src/main/antlr/schema-qdstring.g
index 306aa56..ccb1921 100644
--- a/ldap/src/main/antlr/schema-qdstring.g
+++ b/ldap/src/main/antlr/schema-qdstring.g
@@ -23,6 +23,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitor;
+
 }
 
    
@@ -38,20 +40,30 @@
     k = 2 ;
     exportVocab=AntlrSchemaQdstring ;
     charVocabulary = '\u0000'..'\uFFFE'; 
-    caseSensitive = true ;
+    caseSensitive = false ;
     defaultErrorHandler = false ;
 }
 
-WHSP : ( ' ' ) {$setType(Token.SKIP);} ;
+WHSP
+    :
+    ( options {greedy=true;} :
+    ' '
+    |
+    '\t'
+    |
+    '\r' (options {greedy=true;} : '\n')? { newline(); } 
+    |
+    '\n' { newline(); }
+    )+
+    { $setType(Token.SKIP); } //ignore this token
+    ;
+
 LPAR : '(' ;
 RPAR : ')' ;
 QUOTE : '\'' ;
 QDSTRING : ( QUOTE (~'\'')* QUOTE ) ;
 
 
-
-
-
 /**
  * An antlr generated schema parser. This is a sub-parser used to parse
  * qdstring and qdstrings according to RFC4512.
@@ -66,29 +78,48 @@
     //buildAST=true ;
 }
 
+{
+    private ParserMonitor monitor = null;
+    public void setParserMonitor( ParserMonitor monitor )
+    {
+        this.monitor = monitor;
+    }
+    private void matchedProduction( String msg )
+    {
+        if ( null != monitor )
+        {
+            monitor.matchedProduction( msg );
+        }
+    }
+}
+
     /**
      * qdstrings = qdstring / ( LPAREN WSP qdstringlist WSP RPAREN )
      * qdstringlist = [ qdstring *( SP qdstring ) ]
      */
 qdstrings returns [List<String> qdstrings]
     {
-    	qdstrings = new ArrayList<String>();
+        matchedProduction( "AntlrSchemaQdstringParser.qdstrings()" );
+        qdstrings = new ArrayList<String>();
         String qdstring = null;
     }
     :
     (
         ( 
-	        q:QDSTRING 
-	        { 
-	            qdstring = q.getText(); 
-	            if(qdstring.startsWith("'")) {
-	    			qdstring = qdstring.substring(1, qdstring.length());
-	    		}
-	    		if(qdstring.endsWith("'")) {
-	    			qdstring = qdstring.substring(0, qdstring.length()-1);
-	    		}
-	    		qdstrings.add(qdstring);
-	        } 
+            q:QDSTRING 
+            { 
+                qdstring = q.getText(); 
+                if(qdstring.startsWith("'")) {
+                    qdstring = qdstring.substring(1, qdstring.length());
+                }
+                if(qdstring.endsWith("'")) {
+                    qdstring = qdstring.substring(0, qdstring.length()-1);
+                }
+                qdstring = qdstring.replaceAll("\\\\5C", "\\\\");
+                qdstring = qdstring.replaceAll("\\\\5c", "\\\\");
+                qdstring = qdstring.replaceAll("\\\\27", "'");
+                qdstrings.add(qdstring);
+            } 
         )
     |
         ( LPAR qdstring=qdstring { qdstrings.add(qdstring); } ( qdstring=qdstring { qdstrings.add(qdstring); } )* RPAR )
@@ -110,20 +141,23 @@
      * QUTF1    = %x00-26 / %x28-5B / %x5D-7F
      */    
 qdstring returns [String qdstring=null]
+    {
+        matchedProduction( "AntlrSchemaQdstringParser.qdstring()" );
+    }
     : 
     ( 
         q:QDSTRING 
         { 
             qdstring = q.getText(); 
             if(qdstring.startsWith("'")) {
-    			qdstring = qdstring.substring(1, qdstring.length());
-    		}
-    		if(qdstring.endsWith("'")) {
-    			qdstring = qdstring.substring(0, qdstring.length()-1);
-    		}
-    		qdstring = qdstring.replaceAll("\\\\5C", "\\\\");
-    		qdstring = qdstring.replaceAll("\\\\5c", "\\\\");
-    		qdstring = qdstring.replaceAll("\\\\27", "'");
+                qdstring = qdstring.substring(1, qdstring.length());
+            }
+            if(qdstring.endsWith("'")) {
+                qdstring = qdstring.substring(0, qdstring.length()-1);
+            }
+            qdstring = qdstring.replaceAll("\\\\5C", "\\\\");
+            qdstring = qdstring.replaceAll("\\\\5c", "\\\\");
+            qdstring = qdstring.replaceAll("\\\\27", "'");
         } 
     )
     ; 
diff --git a/ldap/src/main/antlr/schema-value.g b/ldap/src/main/antlr/schema-value.g
index 776d63e..6239870 100644
--- a/ldap/src/main/antlr/schema-value.g
+++ b/ldap/src/main/antlr/schema-value.g
@@ -23,6 +23,8 @@
 import java.util.List;
 import java.util.ArrayList;
 
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitor;
+
 }
 
 
@@ -38,33 +40,66 @@
     k = 3 ;
     exportVocab=AntlrSchemaValue ;
     charVocabulary = '\3'..'\377' ;
-    caseSensitive = true ;
+    caseSensitive = false ;
     defaultErrorHandler = false ;
 }
 
-//WHSP : (' ') {$setType(Token.SKIP);} ;
-SP : ( ' ' )+ { setText(" "); };
+WHSP
+    :
+    ( options {greedy=true;} :
+    ' '
+    |
+    '\t'
+    |
+    '\r' (options {greedy=true;} : '\n')? { newline(); } 
+    |
+    '\n' { newline(); }
+    |
+    '#' (~'\n')* '\n' { newline(); }
+    )+
+    { setText(" "); }
+    //{$setType(Token.SKIP);} //ignore this token
+    ;
 
 LPAR : '(' ;
 RPAR : ')' ;
+protected CHAR : 'a'..'z' ;
 protected LDIGIT : '1'..'9' ;
 protected DIGIT : '0'..'9' ; 
 protected NUMBER : DIGIT | ( LDIGIT (DIGIT)+ ) ;
+protected NUMBER2 : (DIGIT)+ ;
 protected NUMERICOID : NUMBER ( '.' NUMBER )+ ;
+protected HYPEN : '-';
+protected OTHER : '_' | ';' | '.' | ':' ;
+protected DESCR: CHAR ( CHAR | DIGIT | HYPEN )* ;
+protected QUIRKS_DESCR: ( CHAR | DIGIT | HYPEN | OTHER )+ ;
 
 QUOTE : '\'' ;
 DOLLAR : '$' ;
 LCURLY : '{' ;
 RCURLY : '}' ;
-DESCR : ( 'a'..'z' | 'A'..'Z' ) ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' )* ;
-LEN : LCURLY n:NUMBER RCURLY { setText(n.getText()); } ;
+LEN : LCURLY n:NUMBER2 RCURLY { setText(n.getText()); } ;
 
-NUMBER_OR_NUMERICOID :
+
+DESCR_OR_QUIRKS_DESCR :
+    ( NUMERICOID QUIRKS_DESCR ) => QUIRKS_DESCR { $setType( QUIRKS_DESCR ); }
+    |
+    ( NUMBER QUIRKS_DESCR ) => QUIRKS_DESCR { $setType( QUIRKS_DESCR ); }
+    |
+    ( HYPEN QUIRKS_DESCR ) => QUIRKS_DESCR { $setType( QUIRKS_DESCR ); }
+    |
+    ( OTHER QUIRKS_DESCR ) => QUIRKS_DESCR { $setType( QUIRKS_DESCR ); }
+    |
+    ( DESCR QUIRKS_DESCR ) => QUIRKS_DESCR { $setType( QUIRKS_DESCR ); }
+    |
+    ( DESCR ) { $setType( DESCR ); }
+    |
     ( NUMBER '.' ) => NUMERICOID { $setType( NUMERICOID ); }
     |
     ( NUMBER ) { $setType( NUMBER ); }
     ;
 
+
 /**
  * An antlr generated schema parser. This is a sub-parser used to parse
  * numericoid, oid, oids, qdescr, qdescrs according to RFC4512.
@@ -79,18 +114,81 @@
     //buildAST=true ;
 }
 
+{
+    private ParserMonitor monitor = null;
+    public void setParserMonitor( ParserMonitor monitor )
+    {
+        this.monitor = monitor;
+    }
+    private void matchedProduction( String msg )
+    {
+        if ( null != monitor )
+        {
+            monitor.matchedProduction( msg );
+        }
+    }
+}
 
     /**
      * noidlen = numericoid [ LCURLY len RCURLY ]
      * len = number
      */
 noidlen returns [AntlrSchemaParser.NoidLen noidlen = new AntlrSchemaParser.NoidLen()]
+    {
+        matchedProduction( "AntlrSchemaValueParser.noidlen()" );
+    }
     :
     ( 
-      o:NUMERICOID { noidlen.noid = o.getText(); } 
-      (
-        l:LEN { noidlen.len = Integer.parseInt(l.getText()); } 
-      )?
+        (LPAR)?
+        (WHSP)?
+        (QUOTE)?
+        (
+            ( d4:DESCR { noidlen.noid = d4.getText(); } )
+            |
+            ( n2:NUMERICOID { noidlen.noid = n2.getText(); } )
+        )
+        (QUOTE)?
+        (WHSP)?
+        (RPAR)?
+        (
+            l:LEN { noidlen.len = Integer.parseInt(l.getText()); }
+            (QUOTE)?
+            (WHSP)?
+            (RPAR)?
+        )?
+    )
+    ;
+
+
+    /**
+     * noidlen = numericoid [ LCURLY len RCURLY ]
+     * len = number
+     */
+quirksNoidlen returns [AntlrSchemaParser.NoidLen noidlen = new AntlrSchemaParser.NoidLen()]
+    {
+        matchedProduction( "AntlrSchemaValueParser.quirksNoidlen()" );
+    }
+    :
+    (
+        (LPAR)?
+        (WHSP)?
+        (QUOTE)?
+        (
+            ( q2:QUIRKS_DESCR { noidlen.noid = q2.getText(); } )
+            |
+            ( d4:DESCR { noidlen.noid = d4.getText(); } )
+            |
+            ( n2:NUMERICOID { noidlen.noid = n2.getText(); } )
+        )
+        (QUOTE)?
+        (WHSP)?
+        (RPAR)?
+        (
+            l:LEN { noidlen.len = Integer.parseInt(l.getText()); }
+            (QUOTE)?
+            (WHSP)?
+            (RPAR)?
+        )?    
     )
     ;
 
@@ -99,9 +197,22 @@
      * numericoid = number 1*( DOT number )
      */
 numericoid returns [String numericoid=null]
+    {
+        matchedProduction( "AntlrSchemaValueParser.numericoid()" );
+    }
     : 
     (
-        (SP)? n:NUMERICOID (SP)? { numericoid = n.getText(); } 
+        (WHSP)?
+        (LPAR (WHSP)? )?
+        (
+            ( QUOTE n1:NUMERICOID { numericoid = n1.getText(); } QUOTE )
+            |
+            ( n2:NUMERICOID { numericoid = n2.getText(); } )
+        )
+        (
+        (WHSP)?
+        (RPAR)?
+        )
     )
     ;
 
@@ -117,15 +228,22 @@
      *
      */
 oid returns [String oid=null]
+    {
+        matchedProduction( "AntlrSchemaValueParser.oid()" );
+    }
     : 
     (
-        (SP)? 
-	    (
-	        n:NUMERICOID { oid = n.getText(); }
-	    | 
-	        d:DESCR { oid = d.getText(); }
-	    )
-        (SP)?
+        (WHSP)?
+        (
+            ( QUOTE n1:NUMERICOID { oid = n1.getText(); } QUOTE  )
+            |
+            ( n2:NUMERICOID { oid = n2.getText(); } )
+            |
+            ( QUOTE d1:DESCR { oid = d1.getText(); } QUOTE )
+            |
+            ( d2:DESCR { oid = d2.getText(); } )
+        )
+        (options {greedy=true;} : WHSP)?
     )
     ;
 
@@ -136,23 +254,24 @@
      */
 oids returns [List<String> oids]
     {
+        matchedProduction( "AntlrSchemaValueParser.oids()" );
         oids = new ArrayList<String>();
         String oid = null;
     }
     :
     (
         ( 
-        	oid=oid { oids.add(oid); } 
-    	)
+            oid=oid { oids.add(oid); } 
+        )
     |
-        ( 
-        	LPAR 
-        	oid=oid { oids.add(oid); } 
-        	( 
-        		DOLLAR 
-        		oid=oid { oids.add(oid); } 
-        	)* 
-        	RPAR 
+        (
+            LPAR
+            oid=oid { oids.add(oid); } 
+            ( 
+                (DOLLAR)? 
+                oid=oid { oids.add(oid); } 
+            )* 
+            RPAR
         )
     )
     ;
@@ -162,12 +281,17 @@
      * qdescr = SQUOTE descr SQUOTE
      */
 qdescr returns [String qdescr=null]
+    {
+        matchedProduction( "AntlrSchemaValueParser.qdescr()" );
+    }
     : 
     ( 
-		(SP)?
-        QUOTE 
-        d:DESCR { qdescr = d.getText(); } 
-        QUOTE
+        (WHSP)?
+        (
+            ( QUOTE d1:DESCR { qdescr = d1.getText(); } QUOTE )
+            |
+            ( d2:DESCR { qdescr = d2.getText(); } )
+        )
     )
     ; 
 
@@ -178,37 +302,112 @@
      */
 qdescrs returns [List<String> qdescrs]
     {
-    	qdescrs = new ArrayList<String>();
+        matchedProduction( "AntlrSchemaValueParser.qdescrs()" );
+        qdescrs = new ArrayList<String>();
         String qdescr = null;
     }
     :
     (
         ( 
-        	qdescr=qdescr { qdescrs.add(qdescr); } 
-    	)
+            qdescr=qdescr { qdescrs.add(qdescr); } 
+        )
     |
-        ( 
-        	LPAR 
-        	qdescr=qdescr { qdescrs.add(qdescr); } 
-        	(
-        		SP
-        		qdescr=qdescr { qdescrs.add(qdescr); } 
-    		)* 
-    		(SP)?
-    		RPAR 
-		)
+        (             
+        
+            LPAR 
+            qdescr=qdescr { qdescrs.add(qdescr); } 
+            (options {greedy=true;} : WHSP)?
+            (DOLLAR)?
+            (options {greedy=true;} : WHSP)?
+            (
+                qdescr=qdescr { qdescrs.add(qdescr); } 
+                (options {greedy=true;} : WHSP)?
+                (DOLLAR)?
+                (options {greedy=true;} : WHSP)?
+            )*
+            RPAR 
+        )
     )
     ;
     
+    
+    
+    /**
+     * qdescr = SQUOTE descr SQUOTE
+     */
+quirksQdescr returns [String qdescr=null]
+    {
+        matchedProduction( "AntlrSchemaValueParser.qdescr()" );
+    }
+    : 
+    ( 
+        (WHSP)?
+        (
+            ( QUOTE d1:QUIRKS_DESCR { qdescr = d1.getText(); } QUOTE )
+            |
+            ( d2:QUIRKS_DESCR { qdescr = d2.getText(); } )
+            |
+            ( QUOTE d3:DESCR { qdescr = d3.getText(); } QUOTE )
+            |
+            ( d4:DESCR { qdescr = d4.getText(); } )
+            |
+            ( QUOTE n1:NUMERICOID { qdescr = n1.getText(); } QUOTE  )
+            |
+            ( n2:NUMERICOID { qdescr = n2.getText(); } )
+        )
+        (options {greedy=true;} : WHSP)?
+    )
+    ; 
+
+
+    /**
+     * qdescrs = qdescr / ( LPAREN WSP qdescrlist WSP RPAREN )
+     * qdescrlist = [ qdescr *( SP qdescr ) ]
+     */
+quirksQdescrs returns [List<String> qdescrs]
+    {
+        matchedProduction( "AntlrSchemaValueParser.qdescrs()" );
+        qdescrs = new ArrayList<String>();
+        String qdescr = null;
+    }
+    :
+    (
+        ( 
+            qdescr=quirksQdescr { qdescrs.add(qdescr); } 
+        )
+    |
+        ( 
+            LPAR 
+            qdescr=quirksQdescr { qdescrs.add(qdescr); } 
+            (options {greedy=true;} : WHSP)?
+            (DOLLAR)?
+            (options {greedy=true;} : WHSP)?
+            (
+                qdescr=quirksQdescr { qdescrs.add(qdescr); } 
+                (options {greedy=true;} : WHSP)?
+                (DOLLAR)?
+                (options {greedy=true;} : WHSP)?
+            )*
+            RPAR 
+        )
+    )
+    ;
+    
+    
+    
+    
     /**
      * ruleid = number
      * number  = DIGIT / ( LDIGIT 1*DIGIT )
      *
      */
 ruleid returns [Integer ruleid=null]
+    {
+        matchedProduction( "AntlrSchemaValueParser.ruleid()" );
+    }
     : 
     (
-        (SP)? 
+        (WHSP)? 
         n:NUMBER { ruleid = Integer.parseInt(n.getText()); }
     )
     ;
@@ -220,24 +419,25 @@
      */
 ruleids returns [List<Integer> ruleids]
     {
+        matchedProduction( "AntlrSchemaValueParser.ruleids()" );
         ruleids = new ArrayList<Integer>();
         Integer ruleid = null;
     }
     :
     (
         ( 
-        	ruleid=ruleid { ruleids.add(ruleid); } 
-    	)
+            ruleid=ruleid { ruleids.add(ruleid); } 
+        )
     |
         ( 
-        	LPAR 
-        	ruleid=ruleid { ruleids.add(ruleid); } 
-        	( 
-        		SP
-        		ruleid=ruleid { ruleids.add(ruleid); } 
-        	)* 
-        	(SP)?
-        	RPAR 
+            LPAR 
+            ruleid=ruleid { ruleids.add(ruleid); } 
+            ( 
+                WHSP
+                ruleid=ruleid { ruleids.add(ruleid); } 
+            )* 
+            (WHSP)?
+            RPAR 
         )
     )
     ;
diff --git a/ldap/src/main/antlr/schema.g b/ldap/src/main/antlr/schema.g
index bc4a56a..a06ddf5 100644
--- a/ldap/src/main/antlr/schema.g
+++ b/ldap/src/main/antlr/schema.g
@@ -26,6 +26,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitor;
 import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
 import org.apache.directory.shared.ldap.schema.UsageEnum;
 
@@ -40,14 +41,28 @@
 class AntlrSchemaLexer extends Lexer;
 
 options    {
-    k = 5 ;
+    k = 8 ;
     exportVocab=AntlrSchema ;
-    charVocabulary = '\u0000'..'\uFFFE'; 
-    caseSensitive = true ;
+    charVocabulary = '\u0000'..'\uFFFE';
+    caseSensitive = false ;
     defaultErrorHandler = false ;
 }
 
-WHSP : (options{greedy=true;}: ' ' )+ {$setType(Token.SKIP);} ;
+WHSP
+    :
+    ( options {greedy=true;} :
+    ' '
+    |
+    '\t'
+    |
+    '\r' (options {greedy=true;} : '\n')? { newline(); } 
+    |
+    '\n' { newline(); }
+    |
+    '#' (~'\n')* '\n' { newline(); }
+    )+
+    {$setType(Token.SKIP);} //ignore this token
+    ;
 
 LPAR : '(' ;
 RPAR : ')' ;
@@ -58,43 +73,61 @@
 
 LEN : LBRACKET ('0'..'9')+ RBRACKET ;
 
-SINGLE_VALUE : ( "SINGLE-VALUE" (WHSP)? ) ;
-COLLECTIVE : ( "COLLECTIVE" (WHSP)? ) ;
-NO_USER_MODIFICATION : ( "NO-USER-MODIFICATION" (WHSP)? ) ;
+SINGLE_VALUE : ( "single-value" (WHSP)? ) ;
+COLLECTIVE : ( "collective" (WHSP)? ) ;
+NO_USER_MODIFICATION : ( "no-user-modification" (WHSP)? ) ;
 
-OBSOLETE : ( "OBSOLETE" (WHSP)? ) ;
-ABSTRACT : ( "ABSTRACT" (WHSP)? ) ;
-STRUCTURAL : ( "STRUCTURAL" (WHSP)? ) ;
-AUXILIARY : ( "AUXILIARY" (WHSP)? ) ;
+OBSOLETE : ( "obsolete" (WHSP)? ) ;
+ABSTRACT : ( "abstract" (WHSP)? ) ;
+STRUCTURAL : ( "structural" (WHSP)? ) ;
+protected AUXILIARY : ( "auxiliary" (WHSP)? ) ;
 
-STARTNUMERICOID : ( LPAR ( numericoid:VALUE ) ) { setText(numericoid.getText().trim()); } ;
-NAME : ( "NAME" WHSP qdstrings:VALUES ) { setText(qdstrings.getText().trim()); } ;
-DESC : ( "DESC" WHSP qdstring:VALUES ) { setText(qdstring.getText().trim()); } ;
-SUP : ( "SUP" WHSP sup:VALUES ) { setText(sup.getText().trim()); } ;
-MUST : ( "MUST" WHSP must:VALUES ) { setText(must.getText().trim()); } ;
-MAY : ( "MAY" WHSP may:VALUES ) { setText(may.getText()); } ;
-AUX : ( "AUX" WHSP aux:VALUES ) { setText(aux.getText()); } ;
-NOT : ( "NOT" WHSP not:VALUES ) { setText(not.getText()); } ;
-FORM : ( "FORM" WHSP form:VALUES ) { setText(form.getText()); } ;
-OC : ( "OC" WHSP oc:VALUES ) { setText(oc.getText()); } ;
-EQUALITY : ( "EQUALITY" WHSP equality:VALUES ) { setText(equality.getText().trim()); } ;
-ORDERING : ( "ORDERING" WHSP ordering:VALUES ) { setText(ordering.getText().trim()); } ;
-SUBSTR : ( "SUBSTR" WHSP substr:VALUES ) { setText(substr.getText().trim()); } ;
-SYNTAX : ( "SYNTAX" WHSP syntax:VALUES (len:LEN)? ) { setText(syntax.getText().trim() + (len!=null?len.getText().trim():"")); } ;
-APPLIES : ( "APPLIES" WHSP applies:VALUES ) { setText(applies.getText().trim()); } ;
-EXTENSION : x:( "X-" ( 'a'..'z' | 'A'..'Z' | '-' | '_' )+ WHSP VALUES ) ; 
-FQCN : ( "FQCN" WHSP fqcn:FQCN_VALUE ) { setText(fqcn.getText().trim()); } ;
-BYTECODE : ( "BYTECODE" WHSP bytecode:BYTECODE_VALUE ) { setText(bytecode.getText().trim()); } ;
+OBJECTIDENTIFIER : 
+    ( "objectidentifier" 
+      WHSP
+      ( oiName:UNQUOTED_STRING ) 
+      WHSP
+      ( oiValue:UNQUOTED_STRING ) 
+    ) 
+    { setText( oiName.getText() + " " + oiValue.getText() ); }
+    ;
+
+OBJECTCLASS : ( "objectclass" (WHSP)? ) ;
+ATTRIBUTETYPE : ( "attributetype" (WHSP)? ) ;
+
+STARTNUMERICOID : ( LPAR (options {greedy=true;} : WHSP)? ( numericoid:VALUES ) ) { setText(numericoid.getText()); } ;
+NAME : ( "name" (options {greedy=true;} : WHSP)? qdstrings:VALUES ) { setText(qdstrings.getText().trim()); } ;
+DESC : ( "desc" (options {greedy=true;} : WHSP)? qdstring:VALUES ) { setText(qdstring.getText().trim()); } ;
+SUP : ( "sup" (options {greedy=true;} : WHSP)? sup:VALUES ) { setText(sup.getText().trim()); } ;
+MUST : ( "must" (options {greedy=true;} : WHSP)? must:VALUES ) { setText(must.getText().trim()); } ;
+MAY : ( "may" (options {greedy=true;} : WHSP)? may:VALUES ) { setText(may.getText()); } ;
+protected AUX : ( "aux" (options {greedy=true;} : WHSP)? aux:VALUES ) { setText(aux.getText()); } ;
+NOT : ( "not" (options {greedy=true;} : WHSP)? not:VALUES ) { setText(not.getText()); } ;
+FORM : ( "form" (options {greedy=true;} : WHSP)? form:VALUES ) { setText(form.getText()); } ;
+OC : ( "oc" (options {greedy=true;} : WHSP)? oc:VALUES ) { setText(oc.getText()); } ;
+EQUALITY : ( "equality" (options {greedy=true;} : WHSP)? equality:VALUES ) { setText(equality.getText().trim()); } ;
+ORDERING : ( "ordering" (options {greedy=true;} : WHSP)? ordering:VALUES ) { setText(ordering.getText().trim()); } ;
+SUBSTR : ( "substr" (options {greedy=true;} : WHSP)? substr:VALUES ) { setText(substr.getText().trim()); } ;
+SYNTAX : ( "syntax" (options {greedy=true;} : WHSP)? syntax:VALUES (len:LEN)? ) { setText(syntax.getText().trim() + (len!=null?len.getText().trim():"")); } ;
+APPLIES : ( "applies" (options {greedy=true;} : WHSP)? applies:VALUES ) { setText(applies.getText().trim()); } ;
+EXTENSION : x:( "x-" ( options {greedy=true;} : 'a'..'z' | '-' | '_' )+ (options {greedy=true;} : WHSP)? VALUES ) ; 
+FQCN : ( "fqcn" (options {greedy=true;} : WHSP)? fqcn:FQCN_VALUE ) { setText(fqcn.getText().trim()); } ;
+BYTECODE : ( "bytecode" (options {greedy=true;} : WHSP)? bytecode:BYTECODE_VALUE ) { setText(bytecode.getText().trim()); } ;
+
+AUX_OR_AUXILIARY :
+    ( AUXILIARY ) => AUXILIARY { $setType( AUXILIARY ); }
+    |
+    ( AUX ) { $setType( AUX ); }
+    ;
 
 protected VALUES : ( VALUE | LPAR  VALUE ( (DOLLAR)? VALUE )* RPAR ) ;
 protected VALUE : (WHSP)? ( QUOTED_STRING | UNQUOTED_STRING ) (options {greedy=true;}: WHSP)? ;
-protected UNQUOTED_STRING : (options{greedy=true;}: 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | ';' | '.' )+ ;
+protected UNQUOTED_STRING : (options{greedy=true;}: 'a'..'z' | '0'..'9' | '-' | '_' | ';' | '.' | ':' )+ ;
 protected QUOTED_STRING : ( QUOTE (~'\'')* QUOTE ) ;
 protected FQCN_VALUE : ( FQCN_IDENTIFIER ( '.' FQCN_IDENTIFIER )* ) ;
 protected FQCN_IDENTIFIER : ( FQCN_LETTER ( FQCN_LETTERORDIGIT )* ) ;
 protected FQCN_LETTER : 
        '\u0024' |
-       '\u0041'..'\u005a' |
        '\u005f' |
        '\u0061'..'\u007a' |
        '\u00c0'..'\u00d6' |
@@ -108,7 +141,6 @@
        '\uf900'..'\ufaff' ;
 protected FQCN_LETTERORDIGIT : 
        '\u0024' |
-       '\u0041'..'\u005a' |
        '\u005f' |
        '\u0061'..'\u007a' |
        '\u00c0'..'\u00d6' |
@@ -121,14 +153,14 @@
        '\u4e00'..'\u9fff' |
        '\uf900'..'\ufaff' |
        '\u0030'..'\u0039' ;
-protected BYTECODE_VALUE : ( 'a'..'z' | 'A'..'Z' | '0'..'9' | '+' | '/' | '=' )+ ;
+protected BYTECODE_VALUE : ( 'a'..'z' | '0'..'9' | '+' | '/' | '=' )+ ;
 
 
-USAGE : ( "USAGE" (WHSP)? ) ;
-USER_APPLICATIONS : ( "userApplications" (WHSP)? ) ;
-DIRECTORY_OPERATION : ( "directoryOperation" (WHSP)? ) ;
-DISTRIBUTED_OPERATION : ( "distributedOperation" (WHSP)? ) ;
-DSA_OPERATION : ( "dSAOperation" (WHSP)? ) ;
+USAGE : ( "usage" (WHSP)? ) ;
+USER_APPLICATIONS : ( "userapplications" (WHSP)? ) ;
+DIRECTORY_OPERATION : ( "directoryoperation" (WHSP)? ) ;
+DISTRIBUTED_OPERATION : ( "distributedoperation" (WHSP)? ) ;
+DSA_OPERATION : ( "dsaoperation" (WHSP)? ) ;
 
 /**
  * An antlr generated schema main parser.
@@ -144,40 +176,117 @@
 }
 
 {
-	static class Extension
-	{
-	    String key = "";
-	    List<String> values = new ArrayList<String>();
-	    
-	    public void addValue( String value )
-	    {
-	        this.values.add( value );
-	    }
-	}
-	static class NoidLen
-	{
-	    String noid = "";
-	    int len = 0;
-	}
+    private ParserMonitor monitor = null;
+    private boolean isQuirksModeEnabled = false;
+    public void setParserMonitor( ParserMonitor monitor )
+    {
+        this.monitor = monitor;
+    }
+    private void matchedProduction( String msg )
+    {
+        if ( null != monitor )
+        {
+            monitor.matchedProduction( msg );
+        }
+    }
+    public void setQuirksMode( boolean enabled )
+    {
+        this.isQuirksModeEnabled = enabled;
+    }
+    public boolean isQuirksMode()
+    {
+        return this.isQuirksModeEnabled;
+    }
+    static class Extension
+    {
+        String key = "";
+        List<String> values = new ArrayList<String>();
+        
+        public void addValue( String value )
+        {
+            this.values.add( value );
+        }
+    }
+    static class NoidLen
+    {
+        String noid = "";
+        int len = 0;
+    }
     static class ElementTracker
-	{
-	    Map<String, Integer> elementMap = new HashMap<String, Integer>();
-	    void track(String element, Token token) throws SemanticException 
-	    {
-	        if(elementMap.containsKey(element))
-	        {
-	            throw new SemanticException( element + " appears twice.", token.getFilename(), token.getLine() , token.getColumn() );
-	        }
-	        elementMap.put(element, new Integer(1));
-	    }
-	    boolean contains(String element) 
-	    {
-	        return elementMap.containsKey(element);
-	    }
-	}
+    {
+        Map<String, Integer> elementMap = new HashMap<String, Integer>();
+        void track(String element, Token token) throws SemanticException 
+        {
+            if(elementMap.containsKey(element))
+            {
+                throw new SemanticException( element + " appears twice.", token.getFilename(), token.getLine() , token.getColumn() );
+            }
+            elementMap.put(element, new Integer(1));
+        }
+        boolean contains(String element) 
+        {
+            return elementMap.containsKey(element);
+        }
+    }
 
 }
 
+openLdapSchema returns [List<Object> list = new ArrayList<Object>()]
+    {
+        AttributeTypeDescription atd = null;
+        ObjectClassDescription ocd = null;
+        OpenLdapObjectIdentifierMacro oloid = null;
+    }
+    :
+    (
+        oloid = openLdapObjectIdentifier { list.add( oloid ); }
+        |
+        atd = openLdapAttributeType { list.add( atd ); }
+        |
+        ocd = openLdapObjectClass { list.add( ocd ); }
+    )*
+    ;
+
+openLdapObjectIdentifier returns [OpenLdapObjectIdentifierMacro oloid]
+    {
+        matchedProduction( "openLdapObjectIdentifier()" );
+    }
+    :
+    (
+        oi:OBJECTIDENTIFIER 
+        {
+            String[] nameAndValue = oi.getText().split( " " );
+            oloid = new OpenLdapObjectIdentifierMacro();
+            oloid.setName( nameAndValue[0] );
+            oloid.setRawOidOrNameSuffix( nameAndValue[1] );
+        }
+    )
+    ;
+    
+
+openLdapObjectClass returns [ObjectClassDescription ocd]
+    {
+        matchedProduction( "openLdapObjectClass()" );
+    }
+    :
+    (
+        OBJECTCLASS
+        ( ocd=objectClassDescription )
+    )
+    ;
+    
+    
+openLdapAttributeType returns [AttributeTypeDescription atd]
+    {
+        matchedProduction( "openLdapAttributeType()" );
+    }
+    :
+    (
+        ATTRIBUTETYPE
+        ( atd=attributeTypeDescription )
+    )
+    ;
+
 
     /**
      * Production for matching object class descriptions. It is fault-tolerant
@@ -203,36 +312,37 @@
     */
 objectClassDescription returns [ObjectClassDescription ocd = new ObjectClassDescription()]
     {
+        matchedProduction( "objectClassDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { ocd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); ocd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); ocd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); ocd.setObsolete( true ); } )
-	    |
-	    ( sup:SUP { et.track("SUP", sup); ocd.setSuperiorObjectClasses(oids(sup.getText())); } )
-	    |
-	    ( kind1:ABSTRACT { et.track("KIND", kind1); ocd.setKind( ObjectClassTypeEnum.ABSTRACT ); }
-	      |
-	      kind2:STRUCTURAL { et.track("KIND", kind2); ocd.setKind( ObjectClassTypeEnum.STRUCTURAL ); }
-	      |
-	      kind3:AUXILIARY { et.track("KIND", kind3); ocd.setKind( ObjectClassTypeEnum.AUXILIARY ); } 
-	    )
-	    |
-	    ( must:MUST { et.track("MUST", must); ocd.setMustAttributeTypes(oids(must.getText())); } )
-	    |
-	    ( may:MAY { et.track("MAY", may); ocd.setMayAttributeTypes(oids(may.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        ocd.addExtension(ex.key, ex.values); 
-	     } )
-	)*    
+        ( name:NAME { et.track("NAME", name); ocd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); ocd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); ocd.setObsolete( true ); } )
+        |
+        ( sup:SUP { et.track("SUP", sup); ocd.setSuperiorObjectClasses(oids(sup.getText())); } )
+        |
+        ( kind1:ABSTRACT { et.track("KIND", kind1); ocd.setKind( ObjectClassTypeEnum.ABSTRACT ); }
+          |
+          kind2:STRUCTURAL { et.track("KIND", kind2); ocd.setKind( ObjectClassTypeEnum.STRUCTURAL ); }
+          |
+          kind3:AUXILIARY { et.track("KIND", kind3); ocd.setKind( ObjectClassTypeEnum.AUXILIARY ); } 
+        )
+        |
+        ( must:MUST { et.track("MUST", must); ocd.setMustAttributeTypes(oids(must.getText())); } )
+        |
+        ( may:MAY { et.track("MAY", may); ocd.setMayAttributeTypes(oids(may.getText())); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            ocd.addExtension(ex.key, ex.values); 
+         } )
+    )*    
     RPAR
     ;
 
@@ -269,19 +379,20 @@
     */
 attributeTypeDescription returns [AttributeTypeDescription atd = new AttributeTypeDescription()]
     {
+        matchedProduction( "attributeTypeDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { atd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); atd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); atd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); atd.setObsolete( true ); } )
-	    |
-	    ( sup:SUP { et.track("SUP", sup); atd.setSuperType(oid(sup.getText())); } )
-	    |
+        ( name:NAME { et.track("NAME", name); atd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); atd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); atd.setObsolete( true ); } )
+        |
+        ( sup:SUP { et.track("SUP", sup); atd.setSuperType(oid(sup.getText())); } )
+        |
         ( equality:EQUALITY { et.track("EQUALITY", equality); atd.setEqualityMatchingRule(oid(equality.getText())); } )
         |
         ( ordering:ORDERING { et.track("ORDERING", ordering); atd.setOrderingMatchingRule(oid(ordering.getText())); } )
@@ -301,39 +412,42 @@
         |
         ( noUserModification:NO_USER_MODIFICATION { et.track("NO_USER_MODIFICATION", noUserModification); atd.setUserModifiable( false ); } )
         |
-	    ( usage1:USAGE (WHSP)* USER_APPLICATIONS { et.track("USAGE", usage1); atd.setUsage( UsageEnum.USER_APPLICATIONS ); }
-	      |
-	      usage2:USAGE DIRECTORY_OPERATION { et.track("USAGE", usage2); atd.setUsage( UsageEnum.DIRECTORY_OPERATION ); }
-	      |
-	      usage3:USAGE DISTRIBUTED_OPERATION { et.track("USAGE", usage3); atd.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } 
-	      |
-	      usage4:USAGE DSA_OPERATION { et.track("USAGE", usage4); atd.setUsage( UsageEnum.DSA_OPERATION ); } 
-	    )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        atd.addExtension(ex.key, ex.values); 
-	     } )
-	)*    
+        ( usage1:USAGE (WHSP)* USER_APPLICATIONS { et.track("USAGE", usage1); atd.setUsage( UsageEnum.USER_APPLICATIONS ); }
+          |
+          usage2:USAGE DIRECTORY_OPERATION { et.track("USAGE", usage2); atd.setUsage( UsageEnum.DIRECTORY_OPERATION ); }
+          |
+          usage3:USAGE DISTRIBUTED_OPERATION { et.track("USAGE", usage3); atd.setUsage( UsageEnum.DISTRIBUTED_OPERATION ); } 
+          |
+          usage4:USAGE DSA_OPERATION { et.track("USAGE", usage4); atd.setUsage( UsageEnum.DSA_OPERATION ); } 
+        )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            atd.addExtension(ex.key, ex.values); 
+         } )
+    )*    
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("SYNTAX") && !et.contains("SUP") ) 
+        if( !isQuirksModeEnabled )
         {
-            throw new SemanticException( "One of SYNTAX or SUP is required", null, 0, 0 );
-        }
+            // semantic check: required elements
+            if( !et.contains("SYNTAX") && !et.contains("SUP") ) 
+            {
+                throw new SemanticException( "One of SYNTAX or SUP is required", null, 0, 0 );
+            }
         
-        // COLLECTIVE requires USAGE userApplications
-        if ( atd.isCollective() && ( atd.getUsage() != UsageEnum.USER_APPLICATIONS ) )
-        {
-            throw new SemanticException( "COLLECTIVE requires USAGE userApplications", null, 0, 0 );
-        }
+            // COLLECTIVE requires USAGE userApplications
+            if ( atd.isCollective() && ( atd.getUsage() != UsageEnum.USER_APPLICATIONS ) )
+            {
+                throw new SemanticException( "COLLECTIVE requires USAGE userApplications", null, 0, 0 );
+            }
         
-        // NO-USER-MODIFICATION requires an operational USAGE.
-        if ( !atd.isUserModifiable() && ( atd.getUsage() == UsageEnum.USER_APPLICATIONS ) )
-        {
-            throw new SemanticException( "NO-USER-MODIFICATION requires an operational USAGE", null, 0, 0 );
+            // NO-USER-MODIFICATION requires an operational USAGE.
+            if ( !atd.isUserModifiable() && ( atd.getUsage() == UsageEnum.USER_APPLICATIONS ) )
+            {
+                throw new SemanticException( "NO-USER-MODIFICATION requires an operational USAGE", null, 0, 0 );
+            }
         }
     }
     ;
@@ -352,18 +466,21 @@
     */
 ldapSyntaxDescription returns [LdapSyntaxDescription lsd = new LdapSyntaxDescription()]
     {
+        matchedProduction( "ldapSyntaxDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { lsd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( desc:DESC { et.track("DESC", desc); lsd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        lsd.addExtension(ex.key, ex.values); 
-	     } )
+        ( name:NAME { et.track("NAME", name); lsd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); lsd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            lsd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     ;
@@ -386,30 +503,34 @@
     */
 matchingRuleDescription returns [MatchingRuleDescription mrd = new MatchingRuleDescription()]
     {
+        matchedProduction( "matchingRuleDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { mrd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); mrd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); mrd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrd.setObsolete( true ); } )
-	    |
+        ( name:NAME { et.track("NAME", name); mrd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); mrd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrd.setObsolete( true ); } )
+        |
         ( syntax:SYNTAX { et.track("SYNTAX", syntax); mrd.setSyntax(numericoid(syntax.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        mrd.addExtension(ex.key, ex.values); 
-	     } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            mrd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("SYNTAX") ) {
-            throw new SemanticException( "SYNTAX is required", null, 0, 0 );
+        if( !isQuirksModeEnabled )
+        {    
+            // semantic check: required elements
+            if( !et.contains("SYNTAX") ) {
+                throw new SemanticException( "SYNTAX is required", null, 0, 0 );
+            }
         }
     }
     ;
@@ -431,30 +552,34 @@
     */
 matchingRuleUseDescription returns [MatchingRuleUseDescription mrud = new MatchingRuleUseDescription()]
     {
+        matchedProduction( "matchingRuleUseDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { mrud.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); mrud.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); mrud.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrud.setObsolete( true ); } )
-	    |
+        ( name:NAME { et.track("NAME", name); mrud.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); mrud.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); mrud.setObsolete( true ); } )
+        |
         ( applies:APPLIES { et.track("APPLIES", applies); mrud.setApplicableAttributes(oids(applies.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        mrud.addExtension(ex.key, ex.values); 
-	     } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            mrud.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("APPLIES") ) {
-            throw new SemanticException( "APPLIES is required", null, 0, 0 );
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("APPLIES") ) {
+                throw new SemanticException( "APPLIES is required", null, 0, 0 );
+            }
         }
     }
     ;
@@ -479,30 +604,31 @@
     */
 ditContentRuleDescription returns [DITContentRuleDescription dcrd = new DITContentRuleDescription()]
     {
+        matchedProduction( "ditContentRuleDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { dcrd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); dcrd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); dcrd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dcrd.setObsolete( true ); } )
-	    |
-	    ( aux:AUX { et.track("AUX", aux); dcrd.setAuxiliaryObjectClasses(oids(aux.getText())); } )
-	    |
-	    ( must:MUST { et.track("MUST", must); dcrd.setMustAttributeTypes(oids(must.getText())); } )
-	    |
-	    ( may:MAY { et.track("MAY", may); dcrd.setMayAttributeTypes(oids(may.getText())); } )
-	    |
-	    ( not:NOT { et.track("NOT", not); dcrd.setNotAttributeTypes(oids(not.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        dcrd.addExtension(ex.key, ex.values); 
-	     } )
+        ( name:NAME { et.track("NAME", name); dcrd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); dcrd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dcrd.setObsolete( true ); } )
+        |
+        ( aux:AUX { et.track("AUX", aux); dcrd.setAuxiliaryObjectClasses(oids(aux.getText())); } )
+        |
+        ( must:MUST { et.track("MUST", must); dcrd.setMustAttributeTypes(oids(must.getText())); } )
+        |
+        ( may:MAY { et.track("MAY", may); dcrd.setMayAttributeTypes(oids(may.getText())); } )
+        |
+        ( not:NOT { et.track("NOT", not); dcrd.setNotAttributeTypes(oids(not.getText())); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            dcrd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     ;
@@ -529,32 +655,36 @@
     */
 ditStructureRuleDescription returns [DITStructureRuleDescription dsrd = new DITStructureRuleDescription()]
     {
+        matchedProduction( "ditStructureRuleDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( ruleid:STARTNUMERICOID { dsrd.setRuleId(ruleid(ruleid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); dsrd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); dsrd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dsrd.setObsolete( true ); } )
-	    |
-	    ( form:FORM { et.track("FORM", form); dsrd.setForm(oid(form.getText())); } )
-	    |
-	    ( sup:SUP { et.track("SUP", sup); dsrd.setSuperRules(ruleids(sup.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        dsrd.addExtension(ex.key, ex.values); 
-	     } )
+        ( name:NAME { et.track("NAME", name); dsrd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); dsrd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); dsrd.setObsolete( true ); } )
+        |
+        ( form:FORM { et.track("FORM", form); dsrd.setForm(oid(form.getText())); } )
+        |
+        ( sup:SUP { et.track("SUP", sup); dsrd.setSuperRules(ruleids(sup.getText())); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            dsrd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("FORM") ) {
-            throw new SemanticException( "FORM is required", null, 0, 0 );
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("FORM") ) {
+                throw new SemanticException( "FORM is required", null, 0, 0 );
+            }
         }
     }
     ;
@@ -578,46 +708,50 @@
     */
 nameFormDescription returns [NameFormDescription nfd = new NameFormDescription()]
     {
+        matchedProduction( "nameFormDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { nfd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( name:NAME { et.track("NAME", name); nfd.setNames(qdescrs(name.getText())); } )
-	    |
-	    ( desc:DESC { et.track("DESC", desc); nfd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); nfd.setObsolete( true ); } )
-	    |
-	    ( oc:OC { et.track("OC", oc); nfd.setStructuralObjectClass(oid(oc.getText())); } )
-	    |
-	    ( must:MUST { et.track("MUST", must); nfd.setMustAttributeTypes(oids(must.getText())); } )
-	    |
-	    ( may:MAY { et.track("MAY", may); nfd.setMayAttributeTypes(oids(may.getText())); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        nfd.addExtension(ex.key, ex.values); 
-	     } )
+        ( name:NAME { et.track("NAME", name); nfd.setNames(qdescrs(name.getText())); } )
+        |
+        ( desc:DESC { et.track("DESC", desc); nfd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( obsolete:OBSOLETE { et.track("OBSOLETE", obsolete); nfd.setObsolete( true ); } )
+        |
+        ( oc:OC { et.track("OC", oc); nfd.setStructuralObjectClass(oid(oc.getText())); } )
+        |
+        ( must:MUST { et.track("MUST", must); nfd.setMustAttributeTypes(oids(must.getText())); } )
+        |
+        ( may:MAY { et.track("MAY", may); nfd.setMayAttributeTypes(oids(may.getText())); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            nfd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("MUST") ) {
-            throw new SemanticException( "MUST is required", null, 0, 0 );
-        }
-        if( !et.contains("OC") ) {
-            throw new SemanticException( "OC is required", null, 0, 0 );
-        }
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("MUST") ) {
+                throw new SemanticException( "MUST is required", null, 0, 0 );
+            }
+            if( !et.contains("OC") ) {
+                throw new SemanticException( "OC is required", null, 0, 0 );
+            }
         
-        // semantic check: MUST and MAY must be disjoint
-        //List<String> aList = new ArrayList<String>( nfd.getMustAttributeTypes() );
-        //aList.retainAll( nfd.getMayAttributeTypes() );
-        //if( !aList.isEmpty() ) 
-        //{
-        //    throw new SemanticException( "MUST and MAY must be disjoint, "+aList.get( 0 )+" appears in both", null, 0, 0 );
-        //}
+            // semantic check: MUST and MAY must be disjoint
+            //List<String> aList = new ArrayList<String>( nfd.getMustAttributeTypes() );
+            //aList.retainAll( nfd.getMayAttributeTypes() );
+            //if( !aList.isEmpty() ) 
+            //{
+            //    throw new SemanticException( "MUST and MAY must be disjoint, "+aList.get( 0 )+" appears in both", null, 0, 0 );
+            //}
+        }
     }
     ;
     
@@ -642,33 +776,37 @@
     */
 comparatorDescription returns [ComparatorDescription cd = new ComparatorDescription()]
     {
+        matchedProduction( "comparatorDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { cd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( desc:DESC { et.track("DESC", desc); cd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( fqcn:FQCN { et.track("FQCN", fqcn); cd.setFqcn(fqcn.getText()); } )
-	    |
-	    ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); cd.setBytecode(bytecode.getText()); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        cd.addExtension(ex.key, ex.values); 
-	     } )
+        ( desc:DESC { et.track("DESC", desc); cd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( fqcn:FQCN { et.track("FQCN", fqcn); cd.setFqcn(fqcn.getText()); } )
+        |
+        ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); cd.setBytecode(bytecode.getText()); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            cd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("FQCN") ) {
-            throw new SemanticException( "FQCN is required", null, 0, 0 );
-        }
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("FQCN") ) {
+                throw new SemanticException( "FQCN is required", null, 0, 0 );
+            }
         
-        // semantic check: length should be divisible by 4
-        if( cd.getBytecode() != null && ( cd.getBytecode().length() % 4 != 0 ) ) {
-            throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
+            // semantic check: length should be divisible by 4
+            if( cd.getBytecode() != null && ( cd.getBytecode().length() % 4 != 0 ) ) {
+                throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
+            }
         }
     }
     ;
@@ -694,34 +832,38 @@
     */
 normalizerDescription returns [NormalizerDescription nd = new NormalizerDescription()]
     {
+        matchedProduction( "normalizerDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { nd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( desc:DESC { et.track("DESC", desc); nd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( fqcn:FQCN { et.track("FQCN", fqcn); nd.setFqcn(fqcn.getText()); } )
-	    |
-	    ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); nd.setBytecode(bytecode.getText()); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        nd.addExtension(ex.key, ex.values); 
-	     } )
+        ( desc:DESC { et.track("DESC", desc); nd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( fqcn:FQCN { et.track("FQCN", fqcn); nd.setFqcn(fqcn.getText()); } )
+        |
+        ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); nd.setBytecode(bytecode.getText()); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            nd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("FQCN") ) {
-            throw new SemanticException( "FQCN is required", null, 0, 0 );
-        }
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("FQCN") ) {
+                throw new SemanticException( "FQCN is required", null, 0, 0 );
+            }
         
-        // semantic check: length should be divisible by 4
-        if( nd.getBytecode() != null && ( nd.getBytecode().length() % 4 != 0 ) ) {
-            throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
-        }        
+            // semantic check: length should be divisible by 4
+            if( nd.getBytecode() != null && ( nd.getBytecode().length() % 4 != 0 ) ) {
+                throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
+            }     
+        }   
     }
     ;
     
@@ -746,34 +888,38 @@
     */
 syntaxCheckerDescription returns [SyntaxCheckerDescription scd = new SyntaxCheckerDescription()]
     {
+        matchedProduction( "syntaxCheckerDescription()" );
         ElementTracker et = new ElementTracker();
     }
     :
     ( oid:STARTNUMERICOID { scd.setNumericOid(numericoid(oid.getText())); } )
     (
-	    ( desc:DESC { et.track("DESC", desc); scd.setDescription(qdstring(desc.getText())); } )
-	    |
-	    ( fqcn:FQCN { et.track("FQCN", fqcn); scd.setFqcn(fqcn.getText()); } )
-	    |
-	    ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); scd.setBytecode(bytecode.getText()); } )
-	    |
-	    ( extension:EXTENSION { 
-	        Extension ex = extension(extension.getText());
-	        et.track(ex.key, extension); 
-	        scd.addExtension(ex.key, ex.values); 
-	     } )
+        ( desc:DESC { et.track("DESC", desc); scd.setDescription(qdstring(desc.getText())); } )
+        |
+        ( fqcn:FQCN { et.track("FQCN", fqcn); scd.setFqcn(fqcn.getText()); } )
+        |
+        ( bytecode:BYTECODE { et.track("BYTECODE", bytecode); scd.setBytecode(bytecode.getText()); } )
+        |
+        ( extension:EXTENSION { 
+            Extension ex = extension(extension.getText());
+            et.track(ex.key, extension); 
+            scd.addExtension(ex.key, ex.values); 
+         } )
     )*
     RPAR
     {
-        // semantic check: required elements
-        if( !et.contains("FQCN") ) {
-            throw new SemanticException( "FQCN is required", null, 0, 0 );
-        }
+        if( !isQuirksModeEnabled )
+        {
+            // semantic check: required elements
+            if( !et.contains("FQCN") ) {
+                throw new SemanticException( "FQCN is required", null, 0, 0 );
+            }
         
-        // semantic check: length should be divisible by 4
-        if( scd.getBytecode() != null && ( scd.getBytecode().length() % 4 != 0 ) ) {
-            throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
-        }        
+            // semantic check: length should be divisible by 4
+            if( scd.getBytecode() != null && ( scd.getBytecode().length() % 4 != 0 ) ) {
+                throw new SemanticException( "BYTECODE must be divisible by 4", null, 0, 0 );
+            }  
+        }      
     }
     ;
     
@@ -782,9 +928,11 @@
 
 noidlen [String s] returns [NoidLen noidlen]
     {
+        matchedProduction( "noidlen()" );
         AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
         AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        noidlen = parser.noidlen();
+        parser.setParserMonitor(monitor);
+        noidlen = isQuirksModeEnabled ? parser.quirksNoidlen() : parser.noidlen();
     }
     :
     ;
@@ -792,6 +940,7 @@
 
 extension [String s] returns [Extension extension]
     {
+        matchedProduction( "extension()" );
         AntlrSchemaExtensionLexer lexer = new AntlrSchemaExtensionLexer(new StringReader(s));
         AntlrSchemaExtensionParser parser = new AntlrSchemaExtensionParser(lexer);
         extension = parser.extension();
@@ -802,62 +951,96 @@
 
 numericoid [String s] returns [String numericoid]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
-        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        numericoid = parser.numericoid();
+        matchedProduction( "numericoid()");
+        if(isQuirksModeEnabled)
+        {
+             numericoid = oid(s);
+        }
+        else
+        {
+	        AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+	        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+	        parser.setParserMonitor(monitor);
+	        numericoid = parser.numericoid();
+        }
     }
     :
     ;
 
 oid [String s] returns [String oid]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
-        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        oid = parser.oid();
+        matchedProduction( "oid()" );
+        List<String> oids = oids(s);
+        if( oids.size() != 1 ) 
+        {
+            throw new SemanticException( "Exactly one OID expected", null, 0, 0 );
+        }
+        oid = oids.get(0);
     }
     :
     ;
 
 oids [String s] returns [List<String> oids]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
-        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        oids = parser.oids();
+        matchedProduction( "oids()" );
+        if(isQuirksModeEnabled)
+        {
+             oids = qdescrs(s);
+        }
+        else
+        {
+	        AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+	        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+	        parser.setParserMonitor(monitor);
+	        oids = parser.oids();
+	    }
     }
     :
     ;
 
 qdescr [String s] returns [String qdescr]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
-        AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        qdescr = parser.qdescr();
+        matchedProduction( "qdescr()" );
+        List<String> qdescrs = qdescrs(s);
+        if( qdescrs.size() != 1 ) 
+        {
+            throw new SemanticException( "Exactly one qdescrs expected", null, 0, 0 );
+        }
+        qdescr = qdescrs.get(0);
     }
     :
     ;
 
 qdescrs [String s] returns [List<String> qdescrs]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+        matchedProduction( "qdescrs()" );
+        AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
         AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
-        qdescrs = parser.qdescrs();
+        parser.setParserMonitor(monitor);
+        qdescrs = isQuirksModeEnabled ? parser.quirksQdescrs() : parser.qdescrs();
     }
     :
     ;
 
 qdstring [String s] returns [String qdstring]
     {
-    	AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
-        AntlrSchemaQdstringParser parser = new AntlrSchemaQdstringParser(lexer);
-        qdstring = parser.qdstring();
+        matchedProduction( "qdstring()" );
+        List<String> qdstrings = qdstrings(s);
+        if( qdstrings.size() != 1 ) 
+        {
+            throw new SemanticException( "Exactly one qdstrings expected", null, 0, 0 );
+        }
+        qdstring = qdstrings.get(0);
     }
     :
     ;
 
 qdstrings [String s] returns [List<String> qdstrings]
     {
-    	AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
+        matchedProduction( "qdstrings()" );
+        AntlrSchemaQdstringLexer lexer = new AntlrSchemaQdstringLexer(new StringReader(s));
         AntlrSchemaQdstringParser parser = new AntlrSchemaQdstringParser(lexer);
+        parser.setParserMonitor(monitor);
         qdstrings = parser.qdstrings();
     }
     :
@@ -865,8 +1048,10 @@
 
 ruleid [String s] returns [Integer ruleid]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+        matchedProduction( "ruleid()" );
+        AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
         AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+        parser.setParserMonitor(monitor);
         ruleid = parser.ruleid();
     }
     :
@@ -874,8 +1059,10 @@
 
 ruleids [String s] returns [List<Integer> ruleids]
     {
-    	AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
+        matchedProduction( "ruleids()" );
+        AntlrSchemaValueLexer lexer = new AntlrSchemaValueLexer(new StringReader(s));
         AntlrSchemaValueParser parser = new AntlrSchemaValueParser(lexer);
+        parser.setParserMonitor(monitor);
         ruleids = parser.ruleids();
     }
     :
diff --git a/ldap/src/main/antlr/subtree-specification.g b/ldap/src/main/antlr/subtree-specification.g
index 07965fd..e0b2af6 100644
--- a/ldap/src/main/antlr/subtree-specification.g
+++ b/ldap/src/main/antlr/subtree-specification.g
@@ -45,6 +45,7 @@
 import org.apache.directory.shared.ldap.util.ComponentsMonitor;
 import org.apache.directory.shared.ldap.util.OptionalComponentsMonitor;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -99,19 +100,19 @@
      */
     public void init( Map<String, OidNormalizer> oidsMap )
     {
-    	this.oidsMap = oidsMap;
+        this.oidsMap = oidsMap;
     }
     
     
     public void setNormalizerMappingResolver( NormalizerMappingResolver resolver )
     {
-    	this.resolver = resolver;
+        this.resolver = resolver;
     }
     
     
     public boolean isNormalizing()
     {
-    	return this.resolver != null;
+        return this.resolver != null;
     }
     
 
@@ -318,12 +319,12 @@
     
 filter returns [ ExprNode filterExpr = null ]
 {
-	log.debug( "entered filter()" );
+    log.debug( "entered filter()" );
 }
-	:
-	( filterToken:FILTER { filterExpr=FilterParser.parse( filterToken.getText() ); } )
-	;
-	exception
+    :
+    ( filterToken:FILTER { filterExpr=FilterParser.parse( filterToken.getText() ); } )
+    ;
+    exception
     catch [Exception e]
     {
         throw new RecognitionException( "filterParser failed. " + e.getMessage() );
@@ -341,7 +342,7 @@
         
         if ( isNormalizing() )
         {
-        	name.normalize( oidsMap );
+            name.normalize( oidsMap );
         }
         
         log.debug( "recognized a DistinguishedName: " + token.getText() );
@@ -398,7 +399,7 @@
     :
     ID_item ( SP )* COLON ( SP )* oid=oid
     {
-        node = new EqualityNode( SchemaConstants.OBJECT_CLASS_AT, oid );
+        node = new EqualityNode( SchemaConstants.OBJECT_CLASS_AT, new ClientStringValue( oid ) );
     }
     ;
 
diff --git a/ldap/src/main/appended-resources/META-INF/LICENSE b/ldap/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..857d336
--- /dev/null
+++ b/ldap/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,21 @@
+--------------------------------------------------------------
+                            ANTLR 2 License
+
+ANTLR 2 License
+
+We reserve no legal rights to the ANTLR--it is fully in the public domain. An 
+individual or company may do whatever they wish with source code distributed 
+with ANTLR or the code generated by ANTLR, including the incorporation of 
+ANTLR, or its output, into commerical software.
+
+We encourage users to develop software with ANTLR. However, we do ask that 
+credit is given to us for developing ANTLR. By "credit", we mean that if you 
+use ANTLR or incorporate any source code into one of your programs (commercial 
+product, research project, or otherwise) that you acknowledge this fact 
+somewhere in the documentation, research report, etc... If you like ANTLR 
+and have developed a nice tool with the output, please mention that you 
+developed it using ANTLR. In addition, we ask that the headers remain intact 
+in our source code. As long as these guidelines are kept, we expect to 
+continue enhancing this system and expect to make other tools available as 
+they are completed. 
+
diff --git a/ldap/src/main/appended-resources/META-INF/NOTICE b/ldap/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..c4d94e5
--- /dev/null
+++ b/ldap/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+
+This software includes code generated by ANTLR 2.
+
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/MultiException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/MultiException.java
index 3422f39..3a3261a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/MultiException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/MultiException.java
@@ -20,12 +20,12 @@
 package org.apache.directory.shared.ldap;
 
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Collection;
-
-import java.io.PrintWriter;
 import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 
 
 /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/RuntimeMultiException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/RuntimeMultiException.java
index bdd8873..0c80e2c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/RuntimeMultiException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/RuntimeMultiException.java
@@ -21,12 +21,12 @@
 package org.apache.directory.shared.ldap;
 
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Collection;
-
-import java.io.PrintWriter;
 import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 
 
 /**
@@ -37,7 +37,7 @@
  */
 public class RuntimeMultiException extends RuntimeException
 {
-    static final long serialVersionUID = 8582253398936366771L;
+    private static final long serialVersionUID = 8582253398936366771L;
 
     /** Collection of nested exceptions. */
     private Collection<Throwable> nestedExceptions = new ArrayList<Throwable>();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java
index 9d35e84..1105a60 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACIItem.java
@@ -25,6 +25,8 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
 
 /**
  * An abstract class that provides common properties and operations for
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java
index 866bee9..97f71b2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ACITuple.java
@@ -27,6 +27,8 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
 
 /**
  * A flatten entity which is converted from an {@link ACIItem}. The tuples are
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/AuthenticationLevel.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/AuthenticationLevel.java
deleted file mode 100644
index b0b2bdf..0000000
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/AuthenticationLevel.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.shared.ldap.aci;
-
-
-import java.io.Serializable;
-
-
-/**
- * An enumeration that represents the level of authentication.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
- */
-public class AuthenticationLevel implements Comparable, Serializable
-{
-    private static final long serialVersionUID = -6757937682267073130L;
-
-    /**
-     * No authentication (anonymous access)
-     */
-    public static final AuthenticationLevel NONE = new AuthenticationLevel( 0, "none" );
-
-    /**
-     * Simple authentication (bound with plain-text credentials)
-     */
-    public static final AuthenticationLevel SIMPLE = new AuthenticationLevel( 1, "simple" );
-
-    /**
-     * Strong authentication (bound with encrypted cerdentials)
-     */
-    public static final AuthenticationLevel STRONG = new AuthenticationLevel( 2, "strong" );
-
-    private final int level;
-
-    private final String name;
-
-
-    private AuthenticationLevel(int level, String name)
-    {
-        this.level = level;
-        this.name = name;
-    }
-
-
-    /**
-     * Returns the integet value of this level (greater value, stronger level).
-     */
-    public int getLevel()
-    {
-        return level;
-    }
-
-
-    /**
-     * Returns the name of this level.
-     */
-    public String getName()
-    {
-        return name;
-    }
-
-
-    public String toString()
-    {
-        return name;
-    }
-
-
-    public boolean equals( Object o )
-    {
-        if ( this == o )
-        {
-            return true;
-        }
-
-        if ( o instanceof AuthenticationLevel )
-        {
-            AuthenticationLevel that = ( AuthenticationLevel ) o;
-            return this.level == that.level;
-        }
-
-        return false;
-    }
-
-
-    public int compareTo( Object o )
-    {
-        AuthenticationLevel that = ( AuthenticationLevel ) o;
-        return this.level - that.level;
-    }
-}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java
index 3b71879..1439c2a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/GrantAndDenial.java
@@ -170,18 +170,6 @@
 
     public String toString()
     {
-        return "[" + code + "] " + name;
-    }
-    
-    
-    /**
-     * Converts this item into its string representation as stored
-     * in directory.
-     *
-     * @param buffer the string buffer
-     */
-    public void printToBuffer( StringBuilder buffer )
-    {
-        buffer.append( getName() );
+        return name;
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java
index 6a1d02b..b021f3a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemFirstACIItem.java
@@ -25,6 +25,8 @@
 import java.util.Collections;
 import java.util.Set;
 
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
 
 /**
  * An {@link ACIItem} which specifies {@link ProtectedItem}s first and then
@@ -87,8 +89,8 @@
 
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         // identificationTag
         buf.append( "{ identificationTag \"" );
         buf.append( getIdentificationTag() );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java
index 2551e87..700b927 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ItemPermission.java
@@ -69,18 +69,8 @@
 
     public String toString()
     {
-        return "itemPermission: precedence=" + getPrecedence() + ", " + "userClasses=" + userClasses + ", "
-            + "grantsAndDenials=" + getGrantsAndDenials();
-    }
-    
-    /**
-     * Converts this item into its string representation as stored
-     * in directory.
-     *
-     * @param buffer the string buffer
-     */
-    public void printToBuffer( StringBuilder buffer )
-    {
+        StringBuilder buffer = new StringBuilder();
+        
         buffer.append( "{ " );
 
         if ( getPrecedence() >= 0 && getPrecedence() <= 255 )
@@ -105,7 +95,7 @@
                 buffer.append( ", " );
             }
 
-            userClass.printToBuffer( buffer );
+            buffer.append( userClass.toString() );
         }
         
         buffer.append( " }, grantsAndDenials { " );
@@ -123,9 +113,11 @@
                 buffer.append( ", " );
             }
 
-            grantAndDenial.printToBuffer( buffer );
+            buffer.append( grantAndDenial.toString() );
         }
         
         buffer.append( " } }" );
+        
+        return buffer.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ProtectedItem.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ProtectedItem.java
index c1b0ba3..19269b5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ProtectedItem.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/ProtectedItem.java
@@ -126,12 +126,12 @@
          */
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-        	
-        	buf.append( "classes " );
-        	classes.printRefinementToBuffer( buf );
-        	
-        	return buf.toString();
+            StringBuilder buf = new StringBuilder();
+            
+            buf.append( "classes " );
+            classes.printRefinementToBuffer( buf );
+            
+            return buf.toString();
         }
     }
 
@@ -249,36 +249,13 @@
         }
         
         
-        public void printToBuffer( StringBuilder buffer )
-        {
-            buffer.append( "{ " );
-            boolean isFirst = true;
-            
-            for ( String attributeType:attributeTypes )
-            {
-                if ( isFirst ) 
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    buffer.append( ", " );
-                }
-
-                buffer.append( attributeType );
-            }
-            
-            buffer.append( " }" );
-        }
-
-        
         /**
          * @see Object#toString()
          */
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-        	
+            StringBuilder buf = new StringBuilder();
+            
             buf.append( "{ " );
             boolean isFirst = true;
             
@@ -297,8 +274,8 @@
             }
             
             buf.append( " }" );
-        	
-        	return buf.toString();
+            
+            return buf.toString();
         }
     }
 
@@ -325,7 +302,7 @@
 
         public String toString()
         {
-            return "attributeType: " + attributeTypes;
+            return "attributeType " + super.toString();
         }
     }
 
@@ -351,7 +328,7 @@
 
         public String toString()
         {
-            return "allAttributeValues: " + attributeTypes;
+            return "allAttributeValues " + super.toString();
         }
     }
 
@@ -381,7 +358,7 @@
 
         public String toString()
         {
-            return "selfValue: " + attributeTypes;
+            return "selfValue " + super.toString();
         }
     }
 
@@ -434,8 +411,8 @@
 
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-        	
+            StringBuilder buf = new StringBuilder();
+            
             buf.append( "attributeValue {" );
             
             for ( Iterator<Attribute> it = attributes.iterator(); it.hasNext(); )
@@ -461,7 +438,7 @@
             
             buf.append( " }" );
 
-            return "attributeValue: " + attributes;
+            return buf.toString();
         }
     }
 
@@ -521,23 +498,23 @@
 
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-        	
-        	buf.append( "maxValueCount {" );
+            StringBuilder buf = new StringBuilder();
+            
+            buf.append( "maxValueCount {" );
 
-        	boolean isFirst = true;
-        	
+            boolean isFirst = true;
+            
             for ( MaxValueCountItem item:items )
             {
-            	if ( isFirst )
-            	{
-            		isFirst = false;
-            	}
-            	else
-            	{
-            		buf.append( ", " );
-            	}
-            	
+                if ( isFirst )
+                {
+                    isFirst = false;
+                }
+                else
+                {
+                    buf.append( ", " );
+                }
+                
                 buf.append( item.toString() );
             }
             
@@ -603,8 +580,9 @@
 
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-            buf.append( "rangeOfValues: " );
+            StringBuilder buf = new StringBuilder();
+            
+            buf.append( "rangeOfValues " );
             buf.append( filter.toString() );
             
             return buf.toString();
@@ -668,7 +646,7 @@
 
         public String toString()
         {
-            return "maxImmSub: " + value;
+            return "maxImmSub " + value;
         }
     }
 
@@ -727,23 +705,23 @@
 
         public String toString()
         {
-        	StringBuilder buf = new StringBuilder();
-        	
+            StringBuilder buf = new StringBuilder();
+            
             buf.append( "restrictedBy {" );
 
             boolean isFirst = true;
             
             for ( RestrictedByItem item:items )
             {
-            	if ( isFirst )
-            	{
-            		isFirst = false;
-            	}
-            	else
-            	{
-            		buf.append( ", " );
-            	}
-            	
+                if ( isFirst )
+                {
+                    isFirst = false;
+                }
+                else
+                {
+                    buf.append( ", " );
+                }
+                
                 buf.append( item.toString() );
             }
             
@@ -801,7 +779,7 @@
 
         public String toString()
         {
-            return "attributeType=" + attributeType + ", maxCount=" + maxCount;
+            return "{ type " + attributeType + ", maxCount " + maxCount + " }";
         }
     }
 
@@ -854,7 +832,7 @@
 
         public String toString()
         {
-            return "{attributeType=" + attributeType + ", valuesIn=" + valuesIn + "}";
+            return "{ type " + attributeType + ", valuesIn " + valuesIn + " }";
         }
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserClass.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserClass.java
index 87d80b9..84173b2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserClass.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserClass.java
@@ -27,6 +27,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.subtree.SubtreeSpecification;
 
 
@@ -59,15 +60,6 @@
     {
     }
     
-    
-    /**
-     * Converts this item into its string representation as stored
-     * in directory.
-     *
-     * @param buffer the string buffer
-     */
-    public abstract void printToBuffer( StringBuilder buffer );
-    
 
     /**
      * Every directory user (with possible requirements for
@@ -87,12 +79,6 @@
         {
             return "allUsers";
         }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
-            buffer.append( "allUsers" );
-        }
     }
 
     /**
@@ -114,12 +100,6 @@
         {
             return "thisEntry";
         }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
-            buffer.append( "thisEntry" );
-        }
     }
 
     /**
@@ -127,7 +107,7 @@
      */
     private static abstract class NamedUserClass extends UserClass
     {
-        protected final Set<javax.naming.Name> names;
+        protected final Set<LdapDN> names;
 
 
         /**
@@ -135,16 +115,16 @@
          * 
          * @param names a set of names
          */
-        protected NamedUserClass( Set<javax.naming.Name> names )
+        protected NamedUserClass( Set<LdapDN> names )
         {
-            this.names = Collections.unmodifiableSet( new HashSet<javax.naming.Name>( names ) );
+            this.names = Collections.unmodifiableSet( new HashSet<LdapDN>( names ) );
         }
 
 
         /**
          * Returns the set of all names.
          */
-        public Set<javax.naming.Name> getNames()
+        public Set<LdapDN> getNames()
         {
             return names;
         }
@@ -174,12 +154,8 @@
 
         public String toString()
         {
-            return names.toString();
-        }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
+            StringBuilder buffer = new StringBuilder();
+            
             boolean isFirst = true;
             buffer.append( "{ " );
             
@@ -200,6 +176,8 @@
             }
             
             buffer.append( " }" );
+            
+            return buffer.toString();
         }
     }
 
@@ -217,7 +195,7 @@
          * @param usernames
          *            the set of user DNs.
          */
-        public Name( Set<javax.naming.Name> usernames )
+        public Name( Set<LdapDN> usernames )
         {
             super( usernames );
         }
@@ -225,14 +203,7 @@
 
         public String toString()
         {
-            return "name: " + super.toString();
-        }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
-            buffer.append( "name " );
-            super.printToBuffer( buffer );
+            return "name " + super.toString();
         }
     }
 
@@ -253,7 +224,7 @@
          * @param groupNames
          *            the set of group DNs.
          */
-        public UserGroup( Set<javax.naming.Name> groupNames )
+        public UserGroup( Set<LdapDN> groupNames )
         {
             super( groupNames );
         }
@@ -261,14 +232,7 @@
 
         public String toString()
         {
-            return "userGroup: " + super.toString();
-        }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
-            buffer.append( "userGroup " );
-            super.printToBuffer( buffer );
+            return "userGroup " + super.toString();
         }
     }
 
@@ -323,12 +287,8 @@
 
         public String toString()
         {
-            return "subtree: " + subtreeSpecifications;
-        }
-        
-        
-        public void printToBuffer( StringBuilder buffer )
-        {
+            StringBuilder buffer = new StringBuilder();
+            
             boolean isFirst = true;
             buffer.append( "subtree { " );
             
@@ -347,6 +307,8 @@
             }
             
             buffer.append( " }" );
+            
+            return buffer.toString();
         }
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserFirstACIItem.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserFirstACIItem.java
index 58c4f72..2165642 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserFirstACIItem.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserFirstACIItem.java
@@ -25,6 +25,8 @@
 import java.util.Collections;
 import java.util.Set;
 
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+
 
 /**
  * An {@link ACIItem} which specifies {@link UserClass}es first and then
@@ -87,8 +89,8 @@
 
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         // identificationTag
         buf.append( "{ identificationTag \"" );
         buf.append( getIdentificationTag() );
@@ -114,15 +116,15 @@
         
         for ( UserClass userClass:userClasses )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             buf.append( userClass.toString() );
         }
 
@@ -135,15 +137,15 @@
         
         for ( UserPermission permission:userPermissions )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             buf.append( permission.toString() );
         }
         
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserPermission.java b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserPermission.java
index b7cf04e..648923b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserPermission.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/UserPermission.java
@@ -68,8 +68,8 @@
 
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         buf.append( "{ " );
 
         if ( getPrecedence() >= 0 && getPrecedence() <= 255 )
@@ -85,15 +85,15 @@
         
         for ( ProtectedItem item:protectedItems )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             buf.append( item.toString() );
         }
         
@@ -103,16 +103,16 @@
         
         for ( GrantAndDenial grantAndDenial:getGrantsAndDenials() )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
 
-        	buf.append( grantAndDenial.toString() );
+            buf.append( grantAndDenial.toString() );
         }
         
         buf.append( " } }" );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/package.html b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/package.html
index 8fc6eb9..ea6fdde 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/aci/package.html
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/aci/package.html
@@ -1,4 +1,23 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
 <html>
 <head>
 </head>
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/AttributeValueAssertion.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/AttributeValueAssertion.java
index ff3ed18..0ac532d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/AttributeValueAssertion.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/AttributeValueAssertion.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.shared.ldap.codec;
 
+import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.util.StringTools;
 
 
@@ -35,6 +36,7 @@
  * AssertionValue ::= OCTET STRING
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AttributeValueAssertion
 {
@@ -45,7 +47,7 @@
     private String attributeDesc;
 
     /** The assertion value */
-    private Object assertionValue;
+    private Value<?> assertionValue;
 
 
     // ~ Methods
@@ -56,7 +58,7 @@
      * 
      * @return Returns the assertionValue.
      */
-    public Object getAssertionValue()
+    public Value<?> getAssertionValue()
     {
         return assertionValue;
     }
@@ -67,7 +69,7 @@
      * 
      * @param assertionValue The assertionValue to set.
      */
-    public void setAssertionValue( Object assertionValue )
+    public void setAssertionValue( Value<?> assertionValue )
     {
         this.assertionValue = assertionValue;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/Control.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/Control.java
index 1cc889e..7652a34 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/Control.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/Control.java
@@ -36,6 +36,7 @@
  * A Asn1Object to store a Control.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class Control extends AbstractAsn1Object
 {
@@ -119,7 +120,13 @@
      */
     public void setEncodedValue( byte[] encodedValue )
     {
-        this.encodedValue = encodedValue;
+        if ( encodedValue != null )
+        {
+            this.encodedValue = new byte[ encodedValue.length ];
+            System.arraycopy( encodedValue, 0, this.encodedValue, 0, encodedValue.length );
+        } else {
+            this.encodedValue = null;
+        }
     }
 
 
@@ -135,7 +142,9 @@
             return StringTools.EMPTY_BYTES;
         }
 
-        return encodedValue;
+        final byte[] copy = new byte[ encodedValue.length ];
+        System.arraycopy( encodedValue, 0, copy, 0, encodedValue.length );
+        return copy;
     }
 
 
@@ -257,7 +266,7 @@
         }
 
         // The control type
-        Value.encode( buffer, controlType.getBytes() );
+        Value.encode( buffer, getControlType().getBytes() );
 
         // The control criticality, if true
         if ( criticality )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ControlDecoder.java
index 0e5f871..c187596 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ControlDecoder.java
@@ -28,6 +28,7 @@
  * An interface for decoders of controls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public interface ControlDecoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapConstants.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapConstants.java
index b1b2ef5..ccba027 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapConstants.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapConstants.java
@@ -22,6 +22,7 @@
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapConstants
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapDecoder.java
index b23309f..37b1959 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapDecoder.java
@@ -27,6 +27,7 @@
  * The Ldap decoder.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapDecoder extends Asn1Decoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessage.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessage.java
index 5860c8b..0f05292 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessage.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessage.java
@@ -20,6 +20,12 @@
 package org.apache.directory.shared.ldap.codec;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.directory.shared.asn1.AbstractAsn1Object;
 import org.apache.directory.shared.asn1.Asn1Object;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -47,18 +53,13 @@
 import org.apache.directory.shared.ldap.codec.search.SearchResultReference;
 import org.apache.directory.shared.ldap.codec.unbind.UnBindRequest;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-
-import java.util.ArrayList;
-import java.util.List;
-
 
 /**
  * The main ldapObject : every Ldap Message are encapsulated in it. It contains
  * a message Id, a operation (protocolOp) and one ore more Controls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapMessage extends AbstractAsn1Object
 {
@@ -111,7 +112,14 @@
      */
     public Control getControls( int i )
     {
-        return controls.get( i );
+        if ( controls != null )
+        {
+            return controls.get( i );
+        }
+        else
+        {
+            return null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageContainer.java
index 5b9f358..952c571 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageContainer.java
@@ -20,12 +20,8 @@
 package org.apache.directory.shared.ldap.codec;
 
 
-import java.util.HashSet;
-import java.util.Set;
-
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
-import org.apache.directory.shared.ldap.util.StringTools;
+import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
 
 
 /**
@@ -34,8 +30,9 @@
  * ILdapContainer.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class LdapMessageContainer extends AbstractContainer implements IAsn1Container
+public class LdapMessageContainer extends AbstractContainer
 {
     // ~ Instance fields
     // ----------------------------------------------------------------------------
@@ -43,9 +40,9 @@
     /** The ldap message */
     private LdapMessage ldapMessage;
 
-    /** A HashSet which contaons the binary attributes */
-    private Set binaries;
-    
+    /** checks if attribute is binary */
+    private final BinaryAttributeDetector binaryAttributeDetector;
+
     /** The message ID */
     private int messageId;
     
@@ -61,22 +58,29 @@
      */
     public LdapMessageContainer()
     {
-        this( new HashSet() );
+        this( new BinaryAttributeDetector()
+        {
+            public boolean isBinary( String attributeId ) 
+            {
+                return false;
+            }
+        });
     }
 
 
     /**
      * Creates a new LdapMessageContainer object. We will store ten grammars,
      * it's enough ...
+     *
+     * @param binaryAttributeDetector checks if an attribute is binary
      */
-    public LdapMessageContainer( Set binaries )
+    public LdapMessageContainer( BinaryAttributeDetector binaryAttributeDetector )
     {
         super();
-        stateStack = new int[10];
-        grammar = LdapMessageGrammar.getInstance();
-        states = LdapStatesEnum.getInstance();
-
-        this.binaries = binaries;
+        this.stateStack = new int[10];
+        this.grammar = LdapMessageGrammar.getInstance();
+        this.states = LdapStatesEnum.getInstance();
+        this.binaryAttributeDetector = binaryAttributeDetector;
     }
 
 
@@ -115,10 +119,16 @@
 
     /**
      * @return Returns true if the attribute is binary.
+     * @param id checks if an attribute id is binary
      */
     public boolean isBinary( String id )
     {
-        return binaries.contains( StringTools.lowerCaseAscii( StringTools.trim( id ) ) );
+        if ( ( id != null ) && id.endsWith( ";binary" ) )
+        {
+            return true;
+        }
+        
+        return binaryAttributeDetector.isBinary( id );
     }
 
     /**
@@ -131,6 +141,7 @@
 
     /**
      * Set the message ID
+     * @param messageId the id of the message
      */
     public void setMessageId( int messageId )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java
index 3a44a8b..d1308e3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapMessageGrammar.java
@@ -115,8 +115,9 @@
  * an action is to be added or modified, this is where the work is to be done !
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class LdapMessageGrammar extends AbstractGrammar implements IGrammar
+public class LdapMessageGrammar extends AbstractGrammar
 {
     // ~ Static fields/initializers
     // -----------------------------------------------------------------
@@ -126,7 +127,7 @@
 
     /** A speedup for logger */
     static final boolean IS_DEBUG = log.isDebugEnabled();
-    
+
     /** The instance of grammar. LdapMessageGrammar is a singleton */
     private static IGrammar instance = new LdapMessageGrammar();
 
@@ -157,9 +158,9 @@
         // The next state will be LDAP_MESSAGE_STATE
         //
         // We will just check that the length is not null
-        super.transitions[LdapStatesEnum.START_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.START_STATE, LdapStatesEnum.LDAP_MESSAGE_STATE, UniversalTag.SEQUENCE_TAG, 
-                new GrammarAction( "LdapMessage initialization" )
+        super.transitions[LdapStatesEnum.START_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.START_STATE, LdapStatesEnum.LDAP_MESSAGE_STATE, UniversalTag.SEQUENCE_TAG,
+            new GrammarAction( "LdapMessage initialization" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -200,9 +201,9 @@
         //
         // The message ID will be temporarely stored in the container, because we can't store it
         // into an object.
-        super.transitions[LdapStatesEnum.LDAP_MESSAGE_STATE][UniversalTag.INTEGER_TAG] = 
-            new GrammarTransition(LdapStatesEnum.LDAP_MESSAGE_STATE, LdapStatesEnum.MESSAGE_ID_STATE, UniversalTag.INTEGER_TAG, 
-                new GrammarAction( "Store MessageId" )
+        super.transitions[LdapStatesEnum.LDAP_MESSAGE_STATE][UniversalTag.INTEGER_TAG] = new GrammarTransition(
+            LdapStatesEnum.LDAP_MESSAGE_STATE, LdapStatesEnum.MESSAGE_ID_STATE, UniversalTag.INTEGER_TAG,
+            new GrammarAction( "Store MessageId" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -218,7 +219,7 @@
                     if ( tlv.getLength() == 0 )
                     {
                         log.error( "The messageId has a zero length. This is not allowed" );
-                        
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( "The messageId should not be null" );
                     }
@@ -282,9 +283,9 @@
         // LdapMessage ::= ... UnBindRequest ...
         // unbindRequest ::= [APPLICATION 2] NULL
         // We have to switch to the UnBindRequest grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.UNBIND_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.UNBIND_REQUEST_STATE, LdapConstants.UNBIND_REQUEST_TAG, 
-                new GrammarAction( "Unbind Request initialization" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.UNBIND_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.UNBIND_REQUEST_STATE, LdapConstants.UNBIND_REQUEST_TAG,
+            new GrammarAction( "Unbind Request initialization" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -298,15 +299,15 @@
                     // The Length should be null
                     if ( expectedLength != 0 )
                     {
-                        log.error( "The length of a UnBindRequest must be null, the actual value is {}", 
-                            Integer.valueOf( expectedLength ) );
-                        
+                        log.error( "The length of a UnBindRequest must be null, the actual value is {}", Integer
+                            .valueOf( expectedLength ) );
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( "The length of a UnBindRequest must be null" );
                     }
-                    
+
                     UnBindRequest unBindRequest = new UnBindRequest();
-                    
+
                     unBindRequest.setParent( ldapMessage );
 
                     // And we associate it to the ldapMessage Object
@@ -326,9 +327,9 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.UNBIND_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.UNBIND_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.UNBIND_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.UNBIND_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Message ID to DelRequest Message.
@@ -337,9 +338,9 @@
         // delRequest ::= [APPLICATION 10] LDAPDN
         //
         // We store the DN to bve deleted into the DelRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.DEL_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.DEL_REQUEST_STATE, LdapConstants.DEL_REQUEST_TAG, 
-                new GrammarAction( "Init del Request" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.DEL_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.DEL_REQUEST_STATE, LdapConstants.DEL_REQUEST_TAG,
+            new GrammarAction( "Init del Request" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -366,20 +367,20 @@
                     else
                     {
                         byte[] dnBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             entry = new LdapDN( dnBytes );
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "The DN to delete : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes )
-                                + ") is invalid";
+                            String msg = "The DN to delete : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-                            
+
                             DeleteResponseImpl response = new DeleteResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
 
                         delRequest.setEntry( entry );
@@ -405,9 +406,9 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.DEL_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DEL_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.DEL_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.DEL_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Message ID to AbandonRequest Message.
@@ -416,9 +417,9 @@
         // AbandonRequest ::= [APPLICATION 16] MessageID
         //
         // Create the AbandonRequest object, and store the ID in it
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ABANDON_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ABANDON_REQUEST_STATE, LdapConstants.ABANDON_REQUEST_TAG, 
-                new GrammarAction( "Init Abandon Request" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ABANDON_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ABANDON_REQUEST_STATE, LdapConstants.ABANDON_REQUEST_TAG,
+            new GrammarAction( "Init Abandon Request" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -453,7 +454,9 @@
 
                         if ( IS_DEBUG )
                         {
-                            log.debug( "AbandonMessage Id has been decoded : {}", Integer.valueOf( abandonnedMessageId ) );
+                            log
+                                .debug( "AbandonMessage Id has been decoded : {}", Integer
+                                    .valueOf( abandonnedMessageId ) );
                         }
 
                         ldapMessageContainer.grammarEndAllowed( true );
@@ -461,8 +464,9 @@
                     }
                     catch ( IntegerDecoderException ide )
                     {
-                        log.error( "The Abandonned Message Id {} is invalid : {}. The message ID must be between (0 .. 2 147 483 647)",
-                                StringTools.dumpBytes( value.getData() ), ide.getMessage() );
+                        log.error( "The Abandonned Message Id {} is invalid : {}."
+                            + " The message ID must be between (0 .. 2 147 483 647)", StringTools.dumpBytes( value
+                            .getData() ), ide.getMessage() );
 
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( ide.getMessage() );
@@ -477,10 +481,10 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.ABANDON_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ABANDON_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ABANDON_REQUEST_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ABANDON_REQUEST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Message ID to BindRequest Message.
         // --------------------------------------------------------------------------------------------
@@ -488,10 +492,9 @@
         // BindRequest ::= [APPLICATION 0] SEQUENCE { ...
         //
         // We have to allocate a BindRequest
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_REQUEST_STATE, LdapConstants.BIND_REQUEST_TAG, 
-                new GrammarAction(
-                "Init BindRequest" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_REQUEST_STATE, LdapConstants.BIND_REQUEST_TAG,
+            new GrammarAction( "Init BindRequest" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -505,7 +508,7 @@
                     {
                         String msg = "The BindRequest must not be null";
                         log.error( msg );
-                     
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( msg );
                     }
@@ -523,9 +526,9 @@
         //     ....
         //
         // The Ldap version is parsed and stored into the BindRequest object
-        super.transitions[LdapStatesEnum.BIND_REQUEST_STATE][UniversalTag.INTEGER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.BIND_REQUEST_STATE, LdapStatesEnum.VERSION_STATE, UniversalTag.INTEGER_TAG, 
-                new GrammarAction( "Store version" )
+        super.transitions[LdapStatesEnum.BIND_REQUEST_STATE][UniversalTag.INTEGER_TAG] = new GrammarTransition(
+            LdapStatesEnum.BIND_REQUEST_STATE, LdapStatesEnum.VERSION_STATE, UniversalTag.INTEGER_TAG,
+            new GrammarAction( "Store version" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -562,7 +565,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from version to name
         // --------------------------------------------------------------------------------------------
@@ -572,9 +575,9 @@
         //     ....
         //
         // The Ldap version is parsed and stored into the BindRequest object
-        super.transitions[LdapStatesEnum.VERSION_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VERSION_STATE, LdapStatesEnum.NAME_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store Bind Name value" )
+        super.transitions[LdapStatesEnum.VERSION_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.VERSION_STATE, LdapStatesEnum.NAME_STATE, UniversalTag.OCTET_STRING_TAG, new GrammarAction(
+                "Store Bind Name value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -592,26 +595,24 @@
                     }
                     else
                     {
-                        LdapDN dn = LdapDN.EMPTY_LDAPDN;
                         byte[] dnBytes = tlv.getValue().getData();
 
                         try
                         {
-                            dn = new LdapDN( dnBytes );
+                            LdapDN dn = new LdapDN( dnBytes );
+                            bindRequestMessage.setName( dn );
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Incorrect DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes )
-                                + ") is invalid";
+                            String msg = "Incorrect DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-                        
-                            BindResponseImpl response = new BindResponseImpl( ldapMessage.getMessageId() );
-                        
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
-                        }
 
-                        bindRequestMessage.setName( dn );
+                            BindResponseImpl response = new BindResponseImpl( ldapMessage.getMessageId() );
+
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
+                        }
                     }
 
                     if ( IS_DEBUG )
@@ -622,7 +623,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from name to Simple Authentication
         // --------------------------------------------------------------------------------------------
@@ -635,9 +636,9 @@
         //     ...
         //
         // We have to create an Authentication Object to store the credentials.
-        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SIMPLE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NAME_STATE, LdapStatesEnum.SIMPLE_STATE, LdapConstants.BIND_REQUEST_SIMPLE_TAG, 
-                new GrammarAction( "Store Bind Simple Authentication value" )
+        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SIMPLE_TAG] = new GrammarTransition(
+            LdapStatesEnum.NAME_STATE, LdapStatesEnum.SIMPLE_STATE, LdapConstants.BIND_REQUEST_SIMPLE_TAG,
+            new GrammarAction( "Store Bind Simple Authentication value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -682,10 +683,10 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.SIMPLE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SIMPLE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.SIMPLE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.SIMPLE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from name to SASL Authentication
         // --------------------------------------------------------------------------------------------
@@ -699,9 +700,9 @@
         //     ...
         //
         // We have to create an Authentication Object to store the credentials.
-        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SASL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NAME_STATE, LdapStatesEnum.SASL_STATE, LdapConstants.BIND_REQUEST_SASL_TAG, 
-                new GrammarAction( "Initialize Bind SASL Authentication" )
+        super.transitions[LdapStatesEnum.NAME_STATE][LdapConstants.BIND_REQUEST_SASL_TAG] = new GrammarTransition(
+            LdapStatesEnum.NAME_STATE, LdapStatesEnum.SASL_STATE, LdapConstants.BIND_REQUEST_SASL_TAG,
+            new GrammarAction( "Initialize Bind SASL Authentication" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -715,10 +716,10 @@
                     {
                         String msg = "The SaslCredential must not be null";
                         log.error( msg );
-                        
+
                         BindResponseImpl response = new BindResponseImpl( ldapMessage.getMessageId() );
-                    
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_CREDENTIALS, 
+
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_CREDENTIALS,
                             bindRequestMessage.getName(), null );
                     }
 
@@ -729,7 +730,7 @@
 
                     bindRequestMessage.setAuthentication( authentication );
 
-                    if ( IS_DEBUG ) 
+                    if ( IS_DEBUG )
                     {
                         log.debug( "The SaslCredential has been created" );
                     }
@@ -746,9 +747,9 @@
         //     ...
         //
         // We have to store the mechanism.
-        super.transitions[LdapStatesEnum.SASL_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SASL_STATE, LdapStatesEnum.MECHANISM_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store SASL mechanism" )
+        super.transitions[LdapStatesEnum.SASL_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.SASL_STATE, LdapStatesEnum.MECHANISM_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store SASL mechanism" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -782,7 +783,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from Mechanism to Credentials
         // --------------------------------------------------------------------------------------------
@@ -791,21 +792,21 @@
         //     credentials OCTET STRING OPTIONAL }
         //
         // We have to store the mechanism.
-        super.transitions[LdapStatesEnum.MECHANISM_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CREDENTIALS_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store SASL credentials" )
+        super.transitions[LdapStatesEnum.MECHANISM_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CREDENTIALS_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store SASL credentials" )
             {
                 public void action( IAsn1Container container )
                 {
                     LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
-    
+
                     BindRequest bindRequestMessage = ldapMessageContainer.getLdapMessage().getBindRequest();
-    
+
                     // Get the Value and store it in the BindRequest
                     TLV tlv = ldapMessageContainer.getCurrentTLV();
-    
+
                     SaslCredentials credentials = bindRequestMessage.getSaslAuthentication();
-    
+
                     // We have to handle the special case of a 0 length
                     // credentials
                     if ( tlv.getLength() == 0 )
@@ -816,18 +817,18 @@
                     {
                         credentials.setCredentials( tlv.getValue().getData() );
                     }
-    
+
                     // We can have an END transition
                     ldapMessageContainer.grammarEndAllowed( true );
                     if ( IS_DEBUG )
                     {
                         log.debug( "The credentials are : {}", credentials.getCredentials() );
                     }
-    
+
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // transition from from Mechanism to Controls.
         // --------------------------------------------------------------------------------------------
@@ -835,10 +836,10 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.MECHANISM_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.MECHANISM_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.MECHANISM_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // transition from credentials to Controls.
         // --------------------------------------------------------------------------------------------
@@ -846,19 +847,19 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from MessageId to BindResponse message 
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... BindResponse ...
         // BindResponse ::= [APPLICATION 1] SEQUENCE { ...
         // We have to switch to the BindResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_RESPONSE_STATE, LdapConstants.BIND_RESPONSE_TAG, 
-                new GrammarAction( "Init BindReponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.BIND_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.BIND_RESPONSE_STATE, LdapConstants.BIND_RESPONSE_TAG,
+            new GrammarAction( "Init BindReponse" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -890,9 +891,9 @@
         //         ...
         // 
         // Stores the result code into the Bind Response object
-        super.transitions[LdapStatesEnum.BIND_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.BIND_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_BR_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
+        super.transitions[LdapStatesEnum.BIND_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.BIND_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_BR_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Result Code BR to Matched DN BR 
@@ -903,9 +904,9 @@
         //     ...
         //
         // Stores the matched DN
-        super.transitions[LdapStatesEnum.RESULT_CODE_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESULT_CODE_BR_STATE, LdapStatesEnum.MATCHED_DN_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new MatchedDNAction() );
+        super.transitions[LdapStatesEnum.RESULT_CODE_BR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESULT_CODE_BR_STATE, LdapStatesEnum.MATCHED_DN_BR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new MatchedDNAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Matched DN BR to Error Message BR 
@@ -916,9 +917,9 @@
         //     ...
         //
         // Stores the error message
-        super.transitions[LdapStatesEnum.MATCHED_DN_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCHED_DN_BR_STATE, LdapStatesEnum.ERROR_MESSAGE_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ErrorMessageAction() );
+        super.transitions[LdapStatesEnum.MATCHED_DN_BR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCHED_DN_BR_STATE, LdapStatesEnum.ERROR_MESSAGE_BR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ErrorMessageAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message BR to Server SASL credentials 
@@ -928,9 +929,9 @@
         //     serverSaslCreds [7] OCTET STRING OPTIONAL }
         //
         // Stores the sasl credentials 
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapConstants.SERVER_SASL_CREDENTIAL_TAG, 
-                new ServerSASLCredsAction() );
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE,
+            LdapConstants.SERVER_SASL_CREDENTIAL_TAG, new ServerSASLCredsAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message BR to Referrals BR 
@@ -941,9 +942,10 @@
         //
         // Initialiaze the referrals list 
         super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.REFERRALS_BR_STATE, LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, 
-                new InitReferralsAction() );
-        
+            new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.REFERRALS_BR_STATE,
+            LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, new InitReferralsAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Referrals BR to Referral BR 
         // --------------------------------------------------------------------------------------------
@@ -951,10 +953,10 @@
         // URI ::= LDAPString
         //
         // Add a first Referral
-        super.transitions[LdapStatesEnum.REFERRALS_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRALS_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
-        
+        super.transitions[LdapStatesEnum.REFERRALS_BR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRALS_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Referral BR to Referral BR 
         // --------------------------------------------------------------------------------------------
@@ -962,9 +964,9 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.REFERRAL_BR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral BR to Server SASL Credentials 
@@ -973,9 +975,9 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapConstants.SERVER_SASL_CREDENTIAL_TAG, 
-                new ServerSASLCredsAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.SERVER_SASL_CREDENTIAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE,
+            LdapConstants.SERVER_SASL_CREDENTIAL_TAG, new ServerSASLCredsAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral BR to Controls 
@@ -985,9 +987,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_BR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message BR to controls 
@@ -997,10 +999,10 @@
         //     controls       [0] Controls OPTIONAL }
         //
         //  
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_BR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_BR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Server SASL credentials to Controls 
         // --------------------------------------------------------------------------------------------
@@ -1008,9 +1010,9 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.SERVER_SASL_CREDENTIALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Result Code to Matched DN 
@@ -1021,9 +1023,9 @@
         //     ...
         //
         // Stores the matched DN
-        super.transitions[LdapStatesEnum.RESULT_CODE_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESULT_CODE_STATE, LdapStatesEnum.MATCHED_DN_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new MatchedDNAction() );
+        super.transitions[LdapStatesEnum.RESULT_CODE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESULT_CODE_STATE, LdapStatesEnum.MATCHED_DN_STATE, UniversalTag.OCTET_STRING_TAG,
+            new MatchedDNAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Matched DN to Error Message 
@@ -1034,9 +1036,9 @@
         //     ...
         //
         // Stores the error message
-        super.transitions[LdapStatesEnum.MATCHED_DN_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCHED_DN_STATE, LdapStatesEnum.ERROR_MESSAGE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ErrorMessageAction() );
+        super.transitions[LdapStatesEnum.MATCHED_DN_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCHED_DN_STATE, LdapStatesEnum.ERROR_MESSAGE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ErrorMessageAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message to Referrals
@@ -1047,9 +1049,9 @@
         //
         // Initialiaze the referrals list 
         super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.REFERRALS_STATE, LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, 
-                new GrammarAction(
-                "Init referrals list" )
+            new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.REFERRALS_STATE,
+            LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, new GrammarAction( "Init referrals list" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1057,7 +1059,7 @@
                     LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
                     LdapResponse response = ldapMessage.getLdapResponse();
                     LdapResult ldapResult = response.getLdapResult();
-                    
+
                     TLV tlv = ldapMessageContainer.getCurrentTLV();
 
                     // If we hae a Referrals sequence, then it should not be empty
@@ -1066,7 +1068,7 @@
                     {
                         String msg = "The Referrals must not be null";
                         log.error( msg );
-                     
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( msg );
                     }
@@ -1074,7 +1076,7 @@
                     ldapResult.initReferrals();
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from Referrals to Referral 
         // --------------------------------------------------------------------------------------------
@@ -1082,10 +1084,10 @@
         // URI ::= LDAPString
         //
         // Add a first Referral
-        super.transitions[LdapStatesEnum.REFERRALS_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRALS_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
-        
+        super.transitions[LdapStatesEnum.REFERRALS_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRALS_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Referral to Referral 
         // --------------------------------------------------------------------------------------------
@@ -1093,9 +1095,9 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.REFERRAL_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral to Controls 
@@ -1105,9 +1107,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message to controls 
@@ -1117,10 +1119,10 @@
         //     controls       [0] Controls OPTIONAL }
         //
         //  
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from MessageId to SearchResultEntry Message.
         // --------------------------------------------------------------------------------------------
@@ -1128,9 +1130,9 @@
         // SearchResultEntry ::= [APPLICATION 4] SEQUENCE { ...
         //
         // Initialize the searchResultEntry object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_ENTRY_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE, LdapConstants.SEARCH_RESULT_ENTRY_TAG, 
-                new GrammarAction( "Init SearchResultEntry" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_ENTRY_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE,
+            LdapConstants.SEARCH_RESULT_ENTRY_TAG, new GrammarAction( "Init SearchResultEntry" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1152,9 +1154,9 @@
         // ...
         //
         // Store the object name.
-        super.transitions[LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE, LdapStatesEnum.OBJECT_NAME_STATE, UniversalTag.OCTET_STRING_TAG,
-                new GrammarAction( "Store search result entry object name Value" )
+        super.transitions[LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.SEARCH_RESULT_ENTRY_STATE, LdapStatesEnum.OBJECT_NAME_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store search result entry object name Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1183,8 +1185,8 @@
                         catch ( InvalidNameException ine )
                         {
                             // This is for the client side. We will never decode LdapResult on the server
-                            String msg = "The DN " + StringTools.dumpBytes( dnBytes )
-                                + "is invalid : " + ine.getMessage();
+                            String msg = "The DN " + StringTools.dumpBytes( dnBytes ) + "is invalid : "
+                                + ine.getMessage();
                             log.error( "{} : {}", msg, ine.getMessage() );
                             throw new DecoderException( msg, ine );
                         }
@@ -1198,7 +1200,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from ObjectName to AttributesSR
         // --------------------------------------------------------------------------------------------
@@ -1210,16 +1212,16 @@
         // ...
         //
         // We may have no attributes. Just allows the grammar to end
-        super.transitions[LdapStatesEnum.OBJECT_NAME_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OBJECT_NAME_STATE, LdapStatesEnum.ATTRIBUTES_SR_STATE, UniversalTag.SEQUENCE_TAG,
-                new GrammarAction( "Pop and end allowed" )
+        super.transitions[LdapStatesEnum.OBJECT_NAME_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.OBJECT_NAME_STATE, LdapStatesEnum.ATTRIBUTES_SR_STATE, UniversalTag.SEQUENCE_TAG,
+            new GrammarAction( "Pop and end allowed" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
                     container.grammarEndAllowed( true );
                 }
-            } );               
-        
+            } );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributesSR to PartialAttributesList
         // --------------------------------------------------------------------------------------------
@@ -1231,9 +1233,10 @@
         // ...
         //
         // nothing to do
-        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE,
+            UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributesSR to Controls
         // --------------------------------------------------------------------------------------------
@@ -1242,10 +1245,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTES_SR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTES_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from PartialAttributesList to typeSR
         // --------------------------------------------------------------------------------------------
@@ -1258,9 +1261,9 @@
         //     ...
         //
         // Store the attribute's name.
-        super.transitions[LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, LdapStatesEnum.TYPE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store search result entry object name Value" )
+        super.transitions[LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, LdapStatesEnum.TYPE_SR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store search result entry object name Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1302,9 +1305,9 @@
         //     vals SET OF AttributeValue }
         //
         // We may have no value. Just allows the grammar to end
-        super.transitions[LdapStatesEnum.TYPE_SR_STATE][UniversalTag.SET_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPE_SR_STATE, LdapStatesEnum.VALS_SR_STATE, UniversalTag.SET_TAG, 
-                new GrammarAction( "Grammar end allowed" )
+        super.transitions[LdapStatesEnum.TYPE_SR_STATE][UniversalTag.SET_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPE_SR_STATE, LdapStatesEnum.VALS_SR_STATE, UniversalTag.SET_TAG, new GrammarAction(
+                "Grammar end allowed" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1322,10 +1325,10 @@
         // AttributeValue ::= OCTET STRING
         // 
         // Store the attribute value
-        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new SearchResultAttributeValueAction() );
-        
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, UniversalTag.OCTET_STRING_TAG,
+            new SearchResultAttributeValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from ValsSR to PartialAttributesList
         // --------------------------------------------------------------------------------------------
@@ -1334,9 +1337,9 @@
         //     vals SET OF AttributeValue }
         // 
         // Loop when we don't have any attribute value. Nothing to do
-        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from ValsSR to Controls
         // --------------------------------------------------------------------------------------------
@@ -1345,10 +1348,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.VALS_SR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.VALS_SR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributeValueSR to AttributeValueSR 
         // --------------------------------------------------------------------------------------------
@@ -1359,10 +1362,10 @@
         // AttributeValue ::= OCTET STRING
         // 
         // Store the attribute value
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new SearchResultAttributeValueAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE,
+            UniversalTag.OCTET_STRING_TAG, new SearchResultAttributeValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributeValueSR to PartialAttributesList
         // --------------------------------------------------------------------------------------------
@@ -1371,9 +1374,10 @@
         //     vals SET OF AttributeValue }
         // 
         // Loop when we don't have any attribute value. Nothing to do
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.PARTIAL_ATTRIBUTES_LIST_STATE,
+            UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributeValueSR to Controls
         // --------------------------------------------------------------------------------------------
@@ -1382,19 +1386,19 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_SR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // SearchResultDone Message.
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... SearchResultDone ...
         // SearchResultDone ::= [APPLICATION 5] SEQUENCE { ...
         // 
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_DONE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_DONE_STATE, LdapConstants.SEARCH_RESULT_DONE_TAG, 
-                new GrammarAction( "Init search Result Done" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_DONE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_DONE_STATE,
+            LdapConstants.SEARCH_RESULT_DONE_TAG, new GrammarAction( "Init search Result Done" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1420,10 +1424,10 @@
         //         ...
         // 
         // Stores the result code
-        super.transitions[LdapStatesEnum.SEARCH_RESULT_DONE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SEARCH_RESULT_DONE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.SEARCH_RESULT_DONE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.SEARCH_RESULT_DONE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Message ID to ModifyRequest Message
         // --------------------------------------------------------------------------------------------
@@ -1431,9 +1435,9 @@
         // ModifyRequest ::= [APPLICATION 6] SEQUENCE { ...
         //
         // Creates the Modify Request object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_REQUEST_STATE, LdapConstants.MODIFY_REQUEST_TAG, 
-                new GrammarAction( "Init ModifyRequest" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_REQUEST_STATE, LdapConstants.MODIFY_REQUEST_TAG,
+            new GrammarAction( "Init ModifyRequest" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1455,9 +1459,9 @@
         //     ...
         //
         // Stores the object DN
-        super.transitions[LdapStatesEnum.MODIFY_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFY_REQUEST_STATE, LdapStatesEnum.OBJECT_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store Modify request object Value" )
+        super.transitions[LdapStatesEnum.MODIFY_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFY_REQUEST_STATE, LdapStatesEnum.OBJECT_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store Modify request object Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1485,13 +1489,13 @@
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-                    
+
                             ModifyResponseImpl response = new ModifyResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
 
                         modifyRequest.setObject( object );
@@ -1513,9 +1517,9 @@
         //     ...
         //
         // Initialize the modifications list
-        super.transitions[LdapStatesEnum.OBJECT_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OBJECT_STATE, LdapStatesEnum.MODIFICATIONS_STATE, UniversalTag.SEQUENCE_TAG, 
-                new GrammarAction( "Init modifications array list" )
+        super.transitions[LdapStatesEnum.OBJECT_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.OBJECT_STATE, LdapStatesEnum.MODIFICATIONS_STATE, UniversalTag.SEQUENCE_TAG,
+            new GrammarAction( "Init modifications array list" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1526,7 +1530,7 @@
 
                     modifyRequest.initModifications();
                 }
-            } );                
+            } );
 
         // --------------------------------------------------------------------------------------------
         // Transition from modifications to modification sequence
@@ -1537,8 +1541,8 @@
         //     ...
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.MODIFICATIONS_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFICATIONS_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG, null );
+        super.transitions[LdapStatesEnum.MODIFICATIONS_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFICATIONS_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG, null );
 
         // --------------------------------------------------------------------------------------------
         // Transition from modification sequence to operation
@@ -1550,9 +1554,9 @@
         //             ...
         //
         // Store operation type
-        super.transitions[LdapStatesEnum.MODIFICATIONS_SEQ_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFICATIONS_SEQ_STATE, LdapStatesEnum.OPERATION_STATE, UniversalTag.ENUMERATED_TAG, 
-                new GrammarAction( "Store operation type" )
+        super.transitions[LdapStatesEnum.MODIFICATIONS_SEQ_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFICATIONS_SEQ_STATE, LdapStatesEnum.OPERATION_STATE, UniversalTag.ENUMERATED_TAG,
+            new GrammarAction( "Store operation type" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1575,7 +1579,7 @@
                         String msg = "Invalid operation ( " + StringTools.dumpBytes( tlv.getValue().getData() )
                             + "), it should be 0, 1 or 2";
                         log.error( msg );
-                        
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( msg );
                     }
@@ -1617,9 +1621,9 @@
         //     ...
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.OPERATION_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OPERATION_STATE, LdapStatesEnum.MODIFICATION_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.OPERATION_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.OPERATION_STATE, LdapStatesEnum.MODIFICATION_STATE, UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from modification to TypeMod
         // --------------------------------------------------------------------------------------------
@@ -1634,9 +1638,9 @@
         //     ...
         //
         // Stores the type
-        super.transitions[LdapStatesEnum.MODIFICATION_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFICATION_STATE, LdapStatesEnum.TYPE_MOD_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store type" )
+        super.transitions[LdapStatesEnum.MODIFICATION_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFICATION_STATE, LdapStatesEnum.TYPE_MOD_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store type" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1654,9 +1658,10 @@
                     {
                         String msg = "The type can't be null";
                         log.error( msg );
-                        
+
                         ModifyResponseImpl response = new ModifyResponseImpl( ldapMessage.getMessageId() );
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, modifyRequest.getObject(), null );
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
+                            modifyRequest.getObject(), null );
                     }
                     else
                     {
@@ -1670,7 +1675,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypeMod to vals
         // --------------------------------------------------------------------------------------------
@@ -1685,9 +1690,9 @@
         //     vals SET OF AttributeValue }
         //
         // Initialize the list of values
-        super.transitions[LdapStatesEnum.TYPE_MOD_STATE][UniversalTag.SET_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPE_MOD_STATE, LdapStatesEnum.VALS_STATE, UniversalTag.SET_TAG, 
-                new GrammarAction( "Init Attribute vals" )
+        super.transitions[LdapStatesEnum.TYPE_MOD_STATE][UniversalTag.SET_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPE_MOD_STATE, LdapStatesEnum.VALS_STATE, UniversalTag.SET_TAG, new GrammarAction(
+                "Init Attribute vals" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1707,8 +1712,8 @@
 
                     log.debug( "Some vals are to be decoded" );
                 }
-            } );                
-        
+            } );
+
         // --------------------------------------------------------------------------------------------
         // Transition from vals to Attribute Value
         // --------------------------------------------------------------------------------------------
@@ -1725,10 +1730,10 @@
         // AttributeValue ::= OCTET STRING
         //
         // Stores a value
-        super.transitions[LdapStatesEnum.VALS_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ModifyAttributeValueAction() );       
-        
+        super.transitions[LdapStatesEnum.VALS_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ModifyAttributeValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from vals to ModificationsSeq
         // --------------------------------------------------------------------------------------------
@@ -1745,9 +1750,9 @@
         // AttributeValue ::= OCTET STRING
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.VALS_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.VALS_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from vals to Controls
         // --------------------------------------------------------------------------------------------
@@ -1756,10 +1761,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.VALS_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.VALS_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALS_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Value to Attribute Value
         // --------------------------------------------------------------------------------------------
@@ -1776,10 +1781,10 @@
         // AttributeValue ::= OCTET STRING
         //
         // Stores a value
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ModifyAttributeValueAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.ATTRIBUTE_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ModifyAttributeValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Value to ModificationsSeq
         // --------------------------------------------------------------------------------------------
@@ -1796,9 +1801,10 @@
         // AttributeValue ::= OCTET STRING
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.MODIFICATIONS_SEQ_STATE, UniversalTag.SEQUENCE_TAG,
+            null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Value to Controls
         // --------------------------------------------------------------------------------------------
@@ -1807,32 +1813,32 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Nothing to do
-        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_VALUE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // ModifyResponse Message.
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... ModifyResponse ...
         // ModifyResponse ::= [APPLICATION 7] SEQUENCE { ...
         // We have to switch to the ModifyResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_RESPONSE_STATE, LdapConstants.MODIFY_RESPONSE_TAG, 
-                new GrammarAction( "Init ModifyResponse" )
-        {
-            public void action( IAsn1Container container )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_RESPONSE_STATE, LdapConstants.MODIFY_RESPONSE_TAG,
+            new GrammarAction( "Init ModifyResponse" )
             {
+                public void action( IAsn1Container container )
+                {
 
-                LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
-                LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
+                    LdapMessageContainer ldapMessageContainer = ( LdapMessageContainer ) container;
+                    LdapMessage ldapMessage = ldapMessageContainer.getLdapMessage();
 
-                // We associate it to the ldapMessage Object
-                ldapMessage.setProtocolOP( new ModifyResponse() );
+                    // We associate it to the ldapMessage Object
+                    ldapMessage.setProtocolOP( new ModifyResponse() );
 
-                log.debug( "Modify response" );
-            }
-        } );
+                    log.debug( "Modify response" );
+                }
+            } );
 
         // --------------------------------------------------------------------------------------------
         // ModifyResponse Message.
@@ -1845,10 +1851,10 @@
         //         ...
         // 
         // Stores the result code
-        super.transitions[LdapStatesEnum.MODIFY_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFY_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.MODIFY_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFY_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // AddRequest Message.
         // --------------------------------------------------------------------------------------------
@@ -1856,9 +1862,9 @@
         // AddRequest ::= [APPLICATION 8] SEQUENCE { ...
         //
         // Initialize the AddRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ADD_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ADD_REQUEST_STATE, LdapConstants.ADD_REQUEST_TAG, 
-                new GrammarAction( "Init addRequest" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ADD_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ADD_REQUEST_STATE, LdapConstants.ADD_REQUEST_TAG,
+            new GrammarAction( "Init addRequest" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1873,7 +1879,7 @@
                     {
                         String msg = "The AddRequest must not be null";
                         log.error( msg );
-                        
+
                         // Will generate a PROTOCOL_ERROR
                         throw new DecoderException( msg );
                     }
@@ -1892,9 +1898,9 @@
         //     ...
         //
         // Stores the DN
-        super.transitions[LdapStatesEnum.ADD_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ADD_REQUEST_STATE, LdapStatesEnum.ENTRY_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store add request object Value" )
+        super.transitions[LdapStatesEnum.ADD_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ADD_REQUEST_STATE, LdapStatesEnum.ENTRY_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store add request object Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -1910,12 +1916,13 @@
                     {
                         String msg = "Empty entry DN given";
                         log.error( msg );
-                
+
                         AddResponseImpl response = new AddResponseImpl( ldapMessage.getMessageId() );
-                
+
                         // I guess that trying to add an entry which DN is empty is a naming violation...
                         // Not 100% sure though ...
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.NAMING_VIOLATION, LdapDN.EMPTY_LDAPDN, null );
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.NAMING_VIOLATION,
+                            LdapDN.EMPTY_LDAPDN, null );
                     }
                     else
                     {
@@ -1928,13 +1935,13 @@
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-                
+
                             AddResponseImpl response = new AddResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
 
                         addRequest.setEntry( entry );
@@ -1954,9 +1961,9 @@
         // AttributeList ::= SEQUENCE OF ... 
         //
         // Initialize the attribute list
-        super.transitions[LdapStatesEnum.ENTRY_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ENTRY_STATE, LdapStatesEnum.ATTRIBUTES_STATE, UniversalTag.SEQUENCE_TAG, 
-                new GrammarAction( "Init attributes array list" )
+        super.transitions[LdapStatesEnum.ENTRY_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ENTRY_STATE, LdapStatesEnum.ATTRIBUTES_STATE, UniversalTag.SEQUENCE_TAG, new GrammarAction(
+                "Init attributes array list" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -1968,15 +1975,15 @@
                     addRequest.initAttributes();
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from Attributes to Attribute
         // --------------------------------------------------------------------------------------------
         // AttributeList ::= SEQUENCE OF SEQUENCE {
         //
         // We don't do anything in this transition. The attribute will be created when we met the type
-        super.transitions[LdapStatesEnum.ATTRIBUTES_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTES_STATE, LdapStatesEnum.ATTRIBUTE_STATE, UniversalTag.SEQUENCE_TAG, null );
+        super.transitions[LdapStatesEnum.ATTRIBUTES_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTES_STATE, LdapStatesEnum.ATTRIBUTE_STATE, UniversalTag.SEQUENCE_TAG, null );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute to type
@@ -1988,9 +1995,9 @@
         // AttributeDescription LDAPString
         //
         // We store the type in the current attribute
-        super.transitions[LdapStatesEnum.ATTRIBUTE_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_STATE, LdapStatesEnum.TYPE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store attribute type" )
+        super.transitions[LdapStatesEnum.ATTRIBUTE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_STATE, LdapStatesEnum.TYPE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store attribute type" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2005,12 +2012,13 @@
 
                     if ( tlv.getLength() == 0 )
                     {
-                        String msg = "Null or empty types are not allowed"; 
+                        String msg = "Null or empty types are not allowed";
                         log.error( msg );
 
                         AddResponseImpl response = new AddResponseImpl( ldapMessage.getMessageId() );
-                        
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, addRequest.getEntry(), null );
+
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
+                            addRequest.getEntry(), null );
                     }
 
                     String type = StringTools.getType( tlv.getValue().getData() );
@@ -2023,7 +2031,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from type to vals
         // --------------------------------------------------------------------------------------------
@@ -2032,9 +2040,9 @@
         //     vals SET OF AttributeValue }
         //
         // Nothing to do here.
-        super.transitions[LdapStatesEnum.TYPE_STATE][UniversalTag.SET_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPE_STATE, LdapStatesEnum.VALUES_STATE, UniversalTag.SET_TAG, null );
-        
+        super.transitions[LdapStatesEnum.TYPE_STATE][UniversalTag.SET_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPE_STATE, LdapStatesEnum.VALUES_STATE, UniversalTag.SET_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from vals to Value
         // --------------------------------------------------------------------------------------------
@@ -2045,10 +2053,9 @@
         // AttributeValue OCTET STRING
         //
         // Store the value into the current attribute
-        super.transitions[LdapStatesEnum.VALUES_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALUES_STATE, LdapStatesEnum.VALUE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ValueAction() );
-        
+        super.transitions[LdapStatesEnum.VALUES_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALUES_STATE, LdapStatesEnum.VALUE_STATE, UniversalTag.OCTET_STRING_TAG, new ValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Value to Value
         // --------------------------------------------------------------------------------------------
@@ -2059,9 +2066,8 @@
         // AttributeValue OCTET STRING
         //
         // Store the value into the current attribute
-        super.transitions[LdapStatesEnum.VALUE_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALUE_STATE, LdapStatesEnum.VALUE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ValueAction() );
+        super.transitions[LdapStatesEnum.VALUE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALUE_STATE, LdapStatesEnum.VALUE_STATE, UniversalTag.OCTET_STRING_TAG, new ValueAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Value to Attribute
@@ -2069,8 +2075,8 @@
         // AttributeList ::= SEQUENCE OF SEQUENCE {
         //
         // Nothing to do here.
-        super.transitions[LdapStatesEnum.VALUE_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALUE_STATE, LdapStatesEnum.ATTRIBUTE_STATE, UniversalTag.SEQUENCE_TAG, null );
+        super.transitions[LdapStatesEnum.VALUE_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALUE_STATE, LdapStatesEnum.ATTRIBUTE_STATE, UniversalTag.SEQUENCE_TAG, null );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Value to Controls
@@ -2078,9 +2084,9 @@
         // AttributeList ::= SEQUENCE OF SEQUENCE {
         //
         // Initialize the controls
-        super.transitions[LdapStatesEnum.VALUE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.VALUE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // AddResponse Message.
@@ -2088,9 +2094,9 @@
         // LdapMessage ::= ... AddResponse ...
         // AddResponse ::= [APPLICATION 9] LDAPResult
         // 
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ADD_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ADD_RESPONSE_STATE, LdapConstants.ADD_RESPONSE_TAG, 
-                new GrammarAction( "Init AddResponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.ADD_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.ADD_RESPONSE_STATE, LdapConstants.ADD_RESPONSE_TAG,
+            new GrammarAction( "Init AddResponse" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2137,19 +2143,19 @@
         //         ...
         // 
         // Stores the result code
-        super.transitions[LdapStatesEnum.ADD_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ADD_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.ADD_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.ADD_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // DelResponse Message.
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... DelResponse ...
         // DelResponse ::= [APPLICATION 11] LDAPResult
         // We have to switch to the DelResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.DEL_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.DEL_RESPONSE_STATE, LdapConstants.DEL_RESPONSE_TAG, 
-                new GrammarAction( "Init DelResponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.DEL_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.DEL_RESPONSE_STATE, LdapConstants.DEL_RESPONSE_TAG,
+            new GrammarAction( "Init DelResponse" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -2177,10 +2183,10 @@
         //         ...
         // 
         // Stores the result code
-        super.transitions[LdapStatesEnum.DEL_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DEL_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.DEL_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.DEL_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from MessageID to ModifydDNRequest Message.
         // --------------------------------------------------------------------------------------------
@@ -2188,10 +2194,9 @@
         // ModifyDNRequest ::= [APPLICATION 12] SEQUENCE { ...
         //
         // Create the ModifyDNRequest Object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_DN_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_DN_REQUEST_STATE, LdapConstants.MODIFY_DN_REQUEST_TAG, 
-                new GrammarAction(
-                "Init Modify DN Request" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_DN_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_DN_REQUEST_STATE,
+            LdapConstants.MODIFY_DN_REQUEST_TAG, new GrammarAction( "Init Modify DN Request" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -2214,9 +2219,9 @@
         //     ...
         //
         // Stores the entry DN
-        super.transitions[LdapStatesEnum.MODIFY_DN_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFY_DN_REQUEST_STATE, LdapStatesEnum.ENTRY_MOD_DN_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store entry" )
+        super.transitions[LdapStatesEnum.MODIFY_DN_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFY_DN_REQUEST_STATE, LdapStatesEnum.ENTRY_MOD_DN_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store entry" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2241,20 +2246,20 @@
                     else
                     {
                         byte[] dnBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             entry = new LdapDN( dnBytes );
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-        
+
                             ModifyDnResponseImpl response = new ModifyDnResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
 
                         modifyDNRequest.setEntry( entry );
@@ -2268,7 +2273,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from EntryModDN to NewRDN
         // --------------------------------------------------------------------------------------------
@@ -2280,9 +2285,9 @@
         // RelativeRDN :: LDAPString
         //
         // Stores the new RDN
-        super.transitions[LdapStatesEnum.ENTRY_MOD_DN_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ENTRY_MOD_DN_STATE, LdapStatesEnum.NEW_RDN_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store new RDN" )
+        super.transitions[LdapStatesEnum.ENTRY_MOD_DN_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ENTRY_MOD_DN_STATE, LdapStatesEnum.NEW_RDN_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store new RDN" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2302,15 +2307,16 @@
                     if ( tlv.getLength() == 0 )
                     {
                         String msg = "The newrdn must not be null";
-                        log.error(  msg  );
-                        
+                        log.error( msg );
+
                         ModifyDnResponseImpl response = new ModifyDnResponseImpl( ldapMessage.getMessageId() );
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, modifyDNRequest.getEntry(), null );
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                            modifyDNRequest.getEntry(), null );
                     }
                     else
                     {
                         byte[] dnBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             LdapDN dn = new LdapDN( dnBytes );
@@ -2318,13 +2324,13 @@
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid new RDN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid new RDN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-    
+
                             ModifyDnResponseImpl response = new ModifyDnResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, modifyDNRequest.getEntry(), ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                modifyDNRequest.getEntry(), ine );
                         }
 
                         modifyDNRequest.setNewRDN( newRdn );
@@ -2336,7 +2342,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from NewRDN to DeleteOldRDN
         // --------------------------------------------------------------------------------------------
@@ -2346,9 +2352,9 @@
         //     ...
         //
         // Stores the deleteOldRDN flag
-        super.transitions[LdapStatesEnum.NEW_RDN_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NEW_RDN_STATE, LdapStatesEnum.DELETE_OLD_RDN_STATE, UniversalTag.BOOLEAN_TAG, 
-                new GrammarAction( "Store matching dnAttributes Value" )
+        super.transitions[LdapStatesEnum.NEW_RDN_STATE][UniversalTag.BOOLEAN_TAG] = new GrammarTransition(
+            LdapStatesEnum.NEW_RDN_STATE, LdapStatesEnum.DELETE_OLD_RDN_STATE, UniversalTag.BOOLEAN_TAG,
+            new GrammarAction( "Store matching dnAttributes Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2398,7 +2404,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from DeleteOldRDN to NewSuperior
         // --------------------------------------------------------------------------------------------
@@ -2408,8 +2414,9 @@
         //
         // Stores the new superior
         super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE][LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DELETE_OLD_RDN_STATE, LdapStatesEnum.NEW_SUPERIOR_STATE, LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG,
-                new GrammarAction( "Store new superior" )
+            new GrammarTransition(
+            LdapStatesEnum.DELETE_OLD_RDN_STATE, LdapStatesEnum.NEW_SUPERIOR_STATE,
+            LdapConstants.MODIFY_DN_REQUEST_NEW_SUPERIOR_TAG, new GrammarAction( "Store new superior" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2445,20 +2452,20 @@
                     else
                     {
                         byte[] dnBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             newSuperior = new LdapDN( dnBytes );
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid new superior DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid new superior DN given : " + StringTools.utf8ToString( dnBytes )
+                                + " (" + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-    
+
                             ModifyDnResponseImpl response = new ModifyDnResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, modifyDNRequest.getEntry(), ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                modifyDNRequest.getEntry(), ine );
                         }
 
                         modifyDNRequest.setNewSuperior( newSuperior );
@@ -2475,7 +2482,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from DeleteOldRDN to Controls
         // --------------------------------------------------------------------------------------------
@@ -2484,10 +2491,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Stores the new superior
-        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DELETE_OLD_RDN_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.DELETE_OLD_RDN_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.DELETE_OLD_RDN_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from DeleteOldRDN to Controls
         // --------------------------------------------------------------------------------------------
@@ -2496,10 +2503,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Stores the new superior
-        super.transitions[LdapStatesEnum.NEW_SUPERIOR_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NEW_SUPERIOR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.NEW_SUPERIOR_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.NEW_SUPERIOR_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from MessageID to ModifyDNResponse Message.
         // --------------------------------------------------------------------------------------------
@@ -2507,9 +2514,9 @@
         //     ...
         //
         // Creates the ModifyDNResponse
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_DN_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_DN_RESPONSE_STATE, LdapConstants.MODIFY_DN_RESPONSE_TAG, 
-                new GrammarAction( "Init ModifyDNResponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.MODIFY_DN_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.MODIFY_DN_RESPONSE_STATE,
+            LdapConstants.MODIFY_DN_RESPONSE_TAG, new GrammarAction( "Init ModifyDNResponse" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -2537,10 +2544,10 @@
         // Stores the result co        //     modifyDNRequest ModifyDNRequest,
         //     ... },
         // controls   [0] Controls OPTIONAL }
-        super.transitions[LdapStatesEnum.MODIFY_DN_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MODIFY_DN_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.MODIFY_DN_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.MODIFY_DN_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Message ID to CompareResquest
         // --------------------------------------------------------------------------------------------
@@ -2550,9 +2557,9 @@
         // ...
         //
         // Initialize the Compare Request object 
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.COMPARE_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.COMPARE_REQUEST_STATE, LdapConstants.COMPARE_REQUEST_TAG, 
-                new GrammarAction( "Init Compare Request" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.COMPARE_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.COMPARE_REQUEST_STATE, LdapConstants.COMPARE_REQUEST_TAG,
+            new GrammarAction( "Init Compare Request" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -2573,9 +2580,9 @@
         //     ...
         //
         // Stores the compared DN
-        super.transitions[LdapStatesEnum.COMPARE_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.COMPARE_REQUEST_STATE, LdapStatesEnum.ENTRY_COMP_STATE, UniversalTag.OCTET_STRING_TAG,
-                new GrammarAction( "Store entry" )
+        super.transitions[LdapStatesEnum.COMPARE_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.COMPARE_REQUEST_STATE, LdapStatesEnum.ENTRY_COMP_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store entry" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2600,20 +2607,20 @@
                     else
                     {
                         byte[] dnBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             entry = new LdapDN( dnBytes );
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) + 
-                                ") is invalid";
+                            String msg = "Invalid DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-            
+
                             CompareResponseImpl response = new CompareResponseImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
 
                         compareRequest.setEntry( entry );
@@ -2624,7 +2631,7 @@
                         log.debug( "Comparing DN {}", entry );
                     }
                 }
-            } );           
+            } );
 
         // --------------------------------------------------------------------------------------------
         // Transition from entryComp to ava
@@ -2636,9 +2643,9 @@
         // AttributeValueAssertion ::= SEQUENCE {
         // 
         // Nothing to do
-        super.transitions[LdapStatesEnum.ENTRY_COMP_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ENTRY_COMP_STATE, LdapStatesEnum.AVA_STATE, UniversalTag.SEQUENCE_TAG, null );
-        
+        super.transitions[LdapStatesEnum.ENTRY_COMP_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ENTRY_COMP_STATE, LdapStatesEnum.AVA_STATE, UniversalTag.SEQUENCE_TAG, null );
+
         // --------------------------------------------------------------------------------------------
         // Transition from ava to AttributeDesc
         // --------------------------------------------------------------------------------------------
@@ -2649,9 +2656,9 @@
         // AttributeDescription LDAPString
         // 
         // Stores the attribute description
-        super.transitions[LdapStatesEnum.AVA_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AVA_STATE, LdapStatesEnum.ATTRIBUTE_DESC_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store attribute desc" )
+        super.transitions[LdapStatesEnum.AVA_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.AVA_STATE, LdapStatesEnum.ATTRIBUTE_DESC_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store attribute desc" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2672,8 +2679,9 @@
                         String msg = "The attribute description must not be null";
                         log.error( msg );
                         CompareResponseImpl response = new CompareResponseImpl( ldapMessage.getMessageId() );
-                        
-                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, compareRequest.getEntry(), null );
+
+                        throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX,
+                            compareRequest.getEntry(), null );
                     }
 
                     String type = StringTools.getType( tlv.getValue().getData() );
@@ -2685,7 +2693,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from AttributeDesc to Assertion Value
         // --------------------------------------------------------------------------------------------
@@ -2696,9 +2704,9 @@
         // AssertionValue OCTET STRING
         // 
         // Stores the attribute value
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESC_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESC_STATE, LdapStatesEnum.ASSERTION_VALUE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Store assertion value" )
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESC_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESC_STATE, LdapStatesEnum.ASSERTION_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store assertion value" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -2744,7 +2752,7 @@
                     ldapMessageContainer.grammarEndAllowed( true );
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value to Controls
         // --------------------------------------------------------------------------------------------
@@ -2755,19 +2763,19 @@
         // AssertionValue OCTET STRING
         // 
         // Stores the attribute value
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // CompareResponse Message.
         // --------------------------------------------------------------------------------------------
         // LdapMessage ::= ... CompareResponse ...
         // CompareResponse ::= [APPLICATION 15] LDAPResult
         // We have to switch to the CompareResponse grammar
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.COMPARE_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.COMPARE_RESPONSE_STATE, LdapConstants.COMPARE_RESPONSE_TAG, 
-                new GrammarAction( "Init CompareResponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.COMPARE_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.COMPARE_RESPONSE_STATE, LdapConstants.COMPARE_RESPONSE_TAG,
+            new GrammarAction( "Init CompareResponse" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2804,10 +2812,10 @@
         //         ...
         // 
         // Stores the result code
-        super.transitions[LdapStatesEnum.COMPARE_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.COMPARE_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
-        
+        super.transitions[LdapStatesEnum.COMPARE_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.COMPARE_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from MessageID to SearchResultReference Message.
         // --------------------------------------------------------------------------------------------
@@ -2815,9 +2823,9 @@
         // SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
         //
         // Initialization of SearchResultReference object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_REFERENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE, LdapConstants.SEARCH_RESULT_REFERENCE_TAG, 
-                new GrammarAction( "Init SearchResultReference" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_RESULT_REFERENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE,
+            LdapConstants.SEARCH_RESULT_REFERENCE_TAG, new GrammarAction( "Init SearchResultReference" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2844,10 +2852,10 @@
         // SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
         //
         // Initialization of SearchResultReference object
-        super.transitions[LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE][UniversalTag.OCTET_STRING] = 
-            new GrammarTransition( LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE, LdapStatesEnum.REFERENCE_STATE, UniversalTag.OCTET_STRING,
-                new StoreReferenceAction() );
-        
+        super.transitions[LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
+            LdapStatesEnum.SEARCH_RESULT_REFERENCE_STATE, LdapStatesEnum.REFERENCE_STATE, UniversalTag.OCTET_STRING,
+            new StoreReferenceAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Reference to Reference
         // --------------------------------------------------------------------------------------------
@@ -2855,10 +2863,10 @@
         // SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
         //
         // Initialization of SearchResultReference object
-        super.transitions[LdapStatesEnum.REFERENCE_STATE][UniversalTag.OCTET_STRING] = 
-            new GrammarTransition( LdapStatesEnum.REFERENCE_STATE, LdapStatesEnum.REFERENCE_STATE, UniversalTag.OCTET_STRING,
-                new StoreReferenceAction() );
-                
+        super.transitions[LdapStatesEnum.REFERENCE_STATE][UniversalTag.OCTET_STRING] = new GrammarTransition(
+            LdapStatesEnum.REFERENCE_STATE, LdapStatesEnum.REFERENCE_STATE, UniversalTag.OCTET_STRING,
+            new StoreReferenceAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Reference to Controls
         // --------------------------------------------------------------------------------------------
@@ -2867,10 +2875,10 @@
         // controls   [0] Controls OPTIONAL }
         //
         // Initialization the controls
-        super.transitions[LdapStatesEnum.REFERENCE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERENCE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
-                
+        super.transitions[LdapStatesEnum.REFERENCE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERENCE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Message Id to ExtendedRequest Message
         // --------------------------------------------------------------------------------------------
@@ -2878,9 +2886,9 @@
         // ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
         //
         // Creates the ExtendedRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.EXTENDED_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.EXTENDED_REQUEST_STATE, LdapConstants.EXTENDED_REQUEST_TAG, 
-                new GrammarAction( "Init Extended Request" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.EXTENDED_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.EXTENDED_REQUEST_STATE, LdapConstants.EXTENDED_REQUEST_TAG,
+            new GrammarAction( "Init Extended Request" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2901,9 +2909,9 @@
         //     ...
         //
         // Stores the name
-        super.transitions[LdapStatesEnum.EXTENDED_REQUEST_STATE][LdapConstants.EXTENDED_REQUEST_NAME_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EXTENDED_REQUEST_STATE, LdapStatesEnum.REQUEST_NAME_STATE, LdapConstants.EXTENDED_REQUEST_NAME_TAG, 
-                new GrammarAction( "Store name" )
+        super.transitions[LdapStatesEnum.EXTENDED_REQUEST_STATE][LdapConstants.EXTENDED_REQUEST_NAME_TAG] = new GrammarTransition(
+            LdapStatesEnum.EXTENDED_REQUEST_STATE, LdapStatesEnum.REQUEST_NAME_STATE,
+            LdapConstants.EXTENDED_REQUEST_NAME_TAG, new GrammarAction( "Store name" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -2928,7 +2936,7 @@
                     else
                     {
                         byte[] requestNameBytes = tlv.getValue().getData();
-                        
+
                         try
                         {
                             OID oid = new OID( StringTools.utf8ToString( requestNameBytes ) );
@@ -2936,9 +2944,9 @@
                         }
                         catch ( DecoderException de )
                         {
-                            String msg = "The Request name is not a valid OID : " + StringTools.utf8ToString( requestNameBytes ) + 
-                            " (" + StringTools.dumpBytes( requestNameBytes )
-                            + ") is invalid";
+                            String msg = "The Request name is not a valid OID : "
+                                + StringTools.utf8ToString( requestNameBytes ) + " ("
+                                + StringTools.dumpBytes( requestNameBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, de.getMessage() );
 
                             // Rethrow the exception, we will get a PROTOCOL_ERROR
@@ -2955,7 +2963,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from RequestName to RequestValue
         // --------------------------------------------------------------------------------------------
@@ -2964,9 +2972,9 @@
         //     requestValue  [1] OCTET STRING OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE][LdapConstants.EXTENDED_REQUEST_VALUE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REQUEST_NAME_STATE, LdapStatesEnum.REQUEST_VALUE_STATE, LdapConstants.EXTENDED_REQUEST_VALUE_TAG, 
-                new GrammarAction( "Store value" )
+        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE][LdapConstants.EXTENDED_REQUEST_VALUE_TAG] = new GrammarTransition(
+            LdapStatesEnum.REQUEST_NAME_STATE, LdapStatesEnum.REQUEST_VALUE_STATE,
+            LdapConstants.EXTENDED_REQUEST_VALUE_TAG, new GrammarAction( "Store value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3000,7 +3008,7 @@
                     }
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from RequestName to Controls
         // --------------------------------------------------------------------------------------------
@@ -3009,9 +3017,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REQUEST_NAME_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.REQUEST_NAME_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REQUEST_NAME_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from RequestValue to Controls
@@ -3021,9 +3029,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Stores the value
-        super.transitions[LdapStatesEnum.REQUEST_VALUE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REQUEST_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.REQUEST_VALUE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REQUEST_VALUE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from MessageId to ExtendedRequest Message.
@@ -3032,9 +3040,9 @@
         // ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
         //
         // Creates the ExtendeResponse object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.EXTENDED_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE,LdapStatesEnum.EXTENDED_RESPONSE_STATE, LdapConstants.EXTENDED_RESPONSE_TAG, 
-                new GrammarAction( "Init Extended Reponse" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.EXTENDED_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.EXTENDED_RESPONSE_STATE,
+            LdapConstants.EXTENDED_RESPONSE_TAG, new GrammarAction( "Init Extended Reponse" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3056,9 +3064,9 @@
         //     ...
         //
         // Stores the result code
-        super.transitions[LdapStatesEnum.EXTENDED_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EXTENDED_RESPONSE_STATE,LdapStatesEnum.RESULT_CODE_ER_STATE, UniversalTag.ENUMERATED_TAG, 
-                new ResultCodeAction() );
+        super.transitions[LdapStatesEnum.EXTENDED_RESPONSE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.EXTENDED_RESPONSE_STATE, LdapStatesEnum.RESULT_CODE_ER_STATE, UniversalTag.ENUMERATED_TAG,
+            new ResultCodeAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Result Code ER to Matched DN ER
@@ -3069,9 +3077,9 @@
         //     ...
         //
         // 
-        super.transitions[LdapStatesEnum.RESULT_CODE_ER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESULT_CODE_ER_STATE,LdapStatesEnum.MATCHED_DN_ER_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new MatchedDNAction() );
+        super.transitions[LdapStatesEnum.RESULT_CODE_ER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESULT_CODE_ER_STATE, LdapStatesEnum.MATCHED_DN_ER_STATE, UniversalTag.OCTET_STRING_TAG,
+            new MatchedDNAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Matched DN ER to Error Message ER 
@@ -3082,9 +3090,9 @@
         //     ...
         //
         // 
-        super.transitions[LdapStatesEnum.MATCHED_DN_ER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCHED_DN_ER_STATE,LdapStatesEnum.ERROR_MESSAGE_ER_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ErrorMessageAction() );
+        super.transitions[LdapStatesEnum.MATCHED_DN_ER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCHED_DN_ER_STATE, LdapStatesEnum.ERROR_MESSAGE_ER_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ErrorMessageAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message ER to Referrals ER 
@@ -3096,8 +3104,9 @@
         //
         // 
         super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE][LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_ER_STATE,LdapStatesEnum.REFERRALS_ER_STATE, LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, 
-                new InitReferralsAction() );
+            new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_ER_STATE, LdapStatesEnum.REFERRALS_ER_STATE,
+            LdapConstants.LDAP_RESULT_REFERRAL_SEQUENCE_TAG, new InitReferralsAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referrals ER to Referral ER 
@@ -3106,10 +3115,10 @@
         // URI ::= LDAPString
         //
         // Add a first Referral
-        super.transitions[LdapStatesEnum.REFERRALS_ER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRALS_ER_STATE, LdapStatesEnum.REFERRAL_ER_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
-        
+        super.transitions[LdapStatesEnum.REFERRALS_ER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRALS_ER_STATE, LdapStatesEnum.REFERRAL_ER_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Referral ER to Referral ER 
         // --------------------------------------------------------------------------------------------
@@ -3117,9 +3126,9 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.REFERRAL_ER_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new ReferralAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.REFERRAL_ER_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ReferralAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral ER to ResponseName 
@@ -3129,8 +3138,9 @@
         //
         // Adda new Referral
         super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.RESPONSE_NAME_STATE, LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG, 
-                new ResponseNameAction() );
+            new GrammarTransition(
+            LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.RESPONSE_NAME_STATE,
+            LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG, new ResponseNameAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral ER to Response 
@@ -3139,9 +3149,9 @@
         // URI ::= LDAPString
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.RESPONSE_STATE, LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, 
-                new ResponseAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.RESPONSE_STATE,
+            LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, new ResponseAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Referral ER to Controls 
@@ -3151,9 +3161,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Adda new Referral
-        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.REFERRAL_ER_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.REFERRAL_ER_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message ER to Controls 
@@ -3164,9 +3174,9 @@
         //     ...
         //
         // 
-        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_ER_STATE,LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_ER_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message ER to ResponseName 
@@ -3179,9 +3189,10 @@
         //
         // Stores the response name
         super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_ER_STATE,LdapStatesEnum.RESPONSE_NAME_STATE, LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG, 
-                new ResponseNameAction() );
-        
+            new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_ER_STATE, LdapStatesEnum.RESPONSE_NAME_STATE,
+            LdapConstants.EXTENDED_RESPONSE_RESPONSE_NAME_TAG, new ResponseNameAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Response Name to Response 
         // --------------------------------------------------------------------------------------------
@@ -3192,10 +3203,10 @@
         //     response       [11] OCTET STRING OPTIONAL}
         //
         // Stores the response
-        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESPONSE_NAME_STATE,LdapStatesEnum.RESPONSE_STATE, LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, 
-                new ResponseAction() );
-        
+        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESPONSE_NAME_STATE, LdapStatesEnum.RESPONSE_STATE,
+            LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, new ResponseAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from ResponseName to Controls 
         // --------------------------------------------------------------------------------------------
@@ -3204,10 +3215,10 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Init the controls
-        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESPONSE_NAME_STATE,LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.RESPONSE_NAME_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESPONSE_NAME_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Error Message ER to Response 
         // --------------------------------------------------------------------------------------------
@@ -3219,9 +3230,10 @@
         //
         // Stores the response
         super.transitions[LdapStatesEnum.ERROR_MESSAGE_ER_STATE][LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ERROR_MESSAGE_ER_STATE,LdapStatesEnum.RESPONSE_STATE, LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, 
-                new ResponseAction() );
-        
+            new GrammarTransition(
+            LdapStatesEnum.ERROR_MESSAGE_ER_STATE, LdapStatesEnum.RESPONSE_STATE,
+            LdapConstants.EXTENDED_RESPONSE_RESPONSE_TAG, new ResponseAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Response to Controls 
         // --------------------------------------------------------------------------------------------
@@ -3230,10 +3242,10 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Init the controls
-        super.transitions[LdapStatesEnum.RESPONSE_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.RESPONSE_STATE,LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
-        
+        super.transitions[LdapStatesEnum.RESPONSE_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.RESPONSE_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
+
         // --------------------------------------------------------------------------------------------
         // Controls
         // --------------------------------------------------------------------------------------------
@@ -3251,7 +3263,7 @@
                 if ( expectedLength == 0 )
                 {
                     log.error( "The length of a control must not be null" );
-                    
+
                     // This will generate a PROTOCOL_ERROR
                     throw new DecoderException( "The length of a control must not be null" );
                 }
@@ -3263,7 +3275,7 @@
                 message.addControl( control );
             }
         };
-        
+
         // ============================================================================================
         // Transition from Controls to Control
         // ============================================================================================
@@ -3272,9 +3284,8 @@
         //  ...
         //
         // Initialize the controls 
-        super.transitions[LdapStatesEnum.CONTROLS_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROLS_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG, 
-                addControl );
+        super.transitions[LdapStatesEnum.CONTROLS_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROLS_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG, addControl );
 
         // ============================================================================================
         // Transition from Control to ControlType
@@ -3283,9 +3294,9 @@
         //     ...
         //
         // Create a new Control object, and store it in the message Container
-        super.transitions[LdapStatesEnum.CONTROL_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROL_STATE, LdapStatesEnum.CONTROL_TYPE_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Set Control Type" )
+        super.transitions[LdapStatesEnum.CONTROL_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROL_STATE, LdapStatesEnum.CONTROL_TYPE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Set Control Type" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3302,7 +3313,7 @@
                     if ( tlv.getLength() == 0 )
                     {
                         log.error( "The OID must not be null" );
-                        
+
                         // This will generate a PROTOCOL_ERROR
                         throw new DecoderException( "The OID must not be null" );
                     }
@@ -3310,7 +3321,7 @@
                     {
                         byte[] value = tlv.getValue().getData();
                         String oidValue = StringTools.asciiBytesToString( value );
-                        
+
                         // The OID is encoded as a String, not an Object Id
                         try
                         {
@@ -3318,8 +3329,8 @@
                         }
                         catch ( DecoderException de )
                         {
-                            log.error( "The control type " + StringTools.dumpBytes( value )
-                                + " is not a valid OID : " + de.getMessage() );
+                            log.error( "The control type " + StringTools.dumpBytes( value ) + " is not a valid OID : "
+                                + de.getMessage() );
 
                             // This will generate a PROTOCOL_ERROR
                             throw de;
@@ -3347,9 +3358,9 @@
         //     ...
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CRITICALITY_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "Set Criticality" )
+        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.BOOLEAN_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CRITICALITY_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Set Criticality" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3401,10 +3412,10 @@
         //     controlValue OCTET STRING OPTIONAL }
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CRITICALITY_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CRITICALITY_STATE, LdapStatesEnum.CONTROL_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
-                new ControlValueAction() );
-        
+        super.transitions[LdapStatesEnum.CRITICALITY_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.CRITICALITY_STATE, LdapStatesEnum.CONTROL_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ControlValueAction() );
+
         // ============================================================================================
         // Transition from Control Type to Control Value
         // ============================================================================================
@@ -3413,10 +3424,10 @@
         //     controlValue OCTET STRING OPTIONAL }
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CONTROL_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
-                new ControlValueAction() );
-        
+        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CONTROL_VALUE_STATE, UniversalTag.OCTET_STRING_TAG,
+            new ControlValueAction() );
+
         // ============================================================================================
         // Transition from Control Type to Control
         // ============================================================================================
@@ -3425,10 +3436,8 @@
         //     controlValue OCTET STRING OPTIONAL }
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG,
-                addControl );
-        
+        super.transitions[LdapStatesEnum.CONTROL_TYPE_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROL_TYPE_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG, addControl );
 
         // ============================================================================================
         // Transition from Control Criticality to Control
@@ -3438,10 +3447,9 @@
         //     controlValue OCTET STRING OPTIONAL }
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CRITICALITY_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CRITICALITY_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG,
-                addControl );
-        
+        super.transitions[LdapStatesEnum.CRITICALITY_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.CRITICALITY_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG, addControl );
+
         // ============================================================================================
         // Transition from Control Value to Control
         // ============================================================================================
@@ -3450,11 +3458,9 @@
         //     controlValue OCTET STRING OPTIONAL }
         //
         // Store the value in the control object created before
-        super.transitions[LdapStatesEnum.CONTROL_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.CONTROL_VALUE_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG,
-                addControl );
+        super.transitions[LdapStatesEnum.CONTROL_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.CONTROL_VALUE_STATE, LdapStatesEnum.CONTROL_STATE, UniversalTag.SEQUENCE_TAG, addControl );
 
-    
         // --------------------------------------------------------------------------------------------
         // Transition from message ID to SearchRequest Message
         // --------------------------------------------------------------------------------------------
@@ -3462,9 +3468,9 @@
         // SearchRequest ::= [APPLICATION 3] SEQUENCE { ...
         //
         // Initialize the searchRequest object
-        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_REQUEST_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_REQUEST_STATE, LdapConstants.SEARCH_REQUEST_TAG, 
-                new GrammarAction( "Init SearchRequest" )
+        super.transitions[LdapStatesEnum.MESSAGE_ID_STATE][LdapConstants.SEARCH_REQUEST_TAG] = new GrammarTransition(
+            LdapStatesEnum.MESSAGE_ID_STATE, LdapStatesEnum.SEARCH_REQUEST_STATE, LdapConstants.SEARCH_REQUEST_TAG,
+            new GrammarAction( "Init SearchRequest" )
             {
                 public void action( IAsn1Container container )
                 {
@@ -3486,9 +3492,9 @@
         //     ...
         //
         // We have a value for the base object, we will store it in the message
-        super.transitions[LdapStatesEnum.SEARCH_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SEARCH_REQUEST_STATE, LdapStatesEnum.BASE_OBJECT_STATE, UniversalTag.OCTET_STRING_TAG, 
-                new GrammarAction( "store base object value" )
+        super.transitions[LdapStatesEnum.SEARCH_REQUEST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.SEARCH_REQUEST_STATE, LdapStatesEnum.BASE_OBJECT_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "store base object value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3516,13 +3522,13 @@
                         }
                         catch ( InvalidNameException ine )
                         {
-                            String msg = "Invalid root DN given : " + StringTools.utf8ToString( dnBytes ) + 
-                                " (" + StringTools.dumpBytes( dnBytes ) +
-                                ") is invalid";
+                            String msg = "Invalid root DN given : " + StringTools.utf8ToString( dnBytes ) + " ("
+                                + StringTools.dumpBytes( dnBytes ) + ") is invalid";
                             log.error( "{} : {}", msg, ine.getMessage() );
-                    
+
                             SearchResponseDoneImpl response = new SearchResponseDoneImpl( ldapMessage.getMessageId() );
-                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX, LdapDN.EMPTY_LDAPDN, ine );
+                            throw new ResponseCarryingException( msg, response, ResultCodeEnum.INVALID_DN_SYNTAX,
+                                LdapDN.EMPTY_LDAPDN, ine );
                         }
                     }
 
@@ -3546,9 +3552,9 @@
         //     ...
         //
         // We have a value for the scope, we will store it in the message
-        super.transitions[LdapStatesEnum.BASE_OBJECT_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.BASE_OBJECT_STATE, LdapStatesEnum.SCOPE_STATE, UniversalTag.ENUMERATED_TAG, 
-                new GrammarAction( "store scope value" )
+        super.transitions[LdapStatesEnum.BASE_OBJECT_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.BASE_OBJECT_STATE, LdapStatesEnum.SCOPE_STATE, UniversalTag.ENUMERATED_TAG,
+            new GrammarAction( "store scope value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3597,7 +3603,7 @@
                     return;
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from Scope to DerefAlias
         // --------------------------------------------------------------------------------------------
@@ -3611,9 +3617,9 @@
         //     ...
         //
         // We have a value for the derefAliases, we will store it in the message
-        super.transitions[LdapStatesEnum.SCOPE_STATE][UniversalTag.ENUMERATED_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SCOPE_STATE, LdapStatesEnum.DEREF_ALIAS_STATE, UniversalTag.ENUMERATED_TAG, 
-                new GrammarAction( "store derefAliases value" )
+        super.transitions[LdapStatesEnum.SCOPE_STATE][UniversalTag.ENUMERATED_TAG] = new GrammarTransition(
+            LdapStatesEnum.SCOPE_STATE, LdapStatesEnum.DEREF_ALIAS_STATE, UniversalTag.ENUMERATED_TAG,
+            new GrammarAction( "store derefAliases value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3664,8 +3670,8 @@
                     }
                     return;
                 }
-            } );   
-        
+            } );
+
         // --------------------------------------------------------------------------------------------
         // Transition from DerefAlias to SizeLimit
         // --------------------------------------------------------------------------------------------
@@ -3675,9 +3681,9 @@
         //     ...
         //
         // We have a value for the sizeLimit, we will store it in the message
-        super.transitions[LdapStatesEnum.DEREF_ALIAS_STATE][UniversalTag.INTEGER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DEREF_ALIAS_STATE, LdapStatesEnum.SIZE_LIMIT_STATE, UniversalTag.INTEGER_TAG, 
-                new GrammarAction( "store sizeLimit value" )
+        super.transitions[LdapStatesEnum.DEREF_ALIAS_STATE][UniversalTag.INTEGER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DEREF_ALIAS_STATE, LdapStatesEnum.SIZE_LIMIT_STATE, UniversalTag.INTEGER_TAG,
+            new GrammarAction( "store sizeLimit value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3712,8 +3718,8 @@
 
                     return;
                 }
-            } );                
-        
+            } );
+
         // --------------------------------------------------------------------------------------------
         // Transition from SizeLimit to TimeLimit
         // --------------------------------------------------------------------------------------------
@@ -3723,9 +3729,9 @@
         //     ...
         //
         // We have a value for the timeLimit, we will store it in the message
-        super.transitions[LdapStatesEnum.SIZE_LIMIT_STATE][UniversalTag.INTEGER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SIZE_LIMIT_STATE, LdapStatesEnum.TIME_LIMIT_STATE, UniversalTag.INTEGER_TAG,
-                new GrammarAction( "store timeLimit value" )
+        super.transitions[LdapStatesEnum.SIZE_LIMIT_STATE][UniversalTag.INTEGER_TAG] = new GrammarTransition(
+            LdapStatesEnum.SIZE_LIMIT_STATE, LdapStatesEnum.TIME_LIMIT_STATE, UniversalTag.INTEGER_TAG,
+            new GrammarAction( "store timeLimit value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3761,8 +3767,8 @@
 
                     return;
                 }
-            } );                
-        
+            } );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TimeLimit to TypesOnly
         // --------------------------------------------------------------------------------------------
@@ -3772,9 +3778,9 @@
         //     ...
         //
         // We have a value for the typesOnly, we will store it in the message.
-        super.transitions[LdapStatesEnum.TIME_LIMIT_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TIME_LIMIT_STATE, LdapStatesEnum.TYPES_ONLY_STATE, UniversalTag.BOOLEAN_TAG,
-                new GrammarAction( "store typesOnly value" )
+        super.transitions[LdapStatesEnum.TIME_LIMIT_STATE][UniversalTag.BOOLEAN_TAG] = new GrammarTransition(
+            LdapStatesEnum.TIME_LIMIT_STATE, LdapStatesEnum.TYPES_ONLY_STATE, UniversalTag.BOOLEAN_TAG,
+            new GrammarAction( "store typesOnly value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -3813,7 +3819,7 @@
                     return;
                 }
             } );
-        
+
         //============================================================================================
         // Search Request And Filter
         // This is quite complicated, because we have a tree structure to build,
@@ -3891,10 +3897,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to OR filter
         // --------------------------------------------------------------------------------------------
@@ -3909,10 +3915,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -3927,10 +3933,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -3945,10 +3951,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE,
+            LdapConstants.EQUALITY_MATCH_FILTER_TAG, new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -3963,10 +3969,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE,
+            LdapConstants.SUBSTRINGS_FILTER_TAG, new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -3981,10 +3987,9 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to LessOrEqual filter
@@ -4000,9 +4005,9 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE,
+            LdapConstants.LESS_OR_EQUAL_FILTER_TAG, new InitLessOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to Present filter
@@ -4018,10 +4023,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -4036,9 +4041,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from TypesOnly to Extensible Match filter
@@ -4054,9 +4059,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+        super.transitions[LdapStatesEnum.TYPES_ONLY_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPES_ONLY_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from AND to AND filter
@@ -4071,10 +4076,9 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG, new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to OR filter
         // --------------------------------------------------------------------------------------------
@@ -4089,10 +4093,9 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG, new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -4107,10 +4110,9 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG, new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -4125,10 +4127,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -4143,10 +4145,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -4161,10 +4163,9 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+            new InitGreaterOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from AND to LessOrEqual filter
@@ -4180,9 +4181,9 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from AND to Present filter
@@ -4198,10 +4199,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from AND to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -4216,9 +4217,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from AND to Extensible Match filter
@@ -4234,9 +4235,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.AND_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+        super.transitions[LdapStatesEnum.AND_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.AND_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+            new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from OR to AND filter
@@ -4251,10 +4252,9 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG, new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to OR filter
         // --------------------------------------------------------------------------------------------
@@ -4269,10 +4269,9 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG, new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -4287,10 +4286,9 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG, new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -4305,10 +4303,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -4323,10 +4321,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -4341,10 +4339,9 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+            new InitGreaterOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from OR to LessOrEqual filter
@@ -4360,9 +4357,9 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from OR to Present filter
@@ -4378,10 +4375,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from OR to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -4396,9 +4393,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from OR to Extensible Match filter
@@ -4414,9 +4411,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.OR_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+        super.transitions[LdapStatesEnum.OR_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.OR_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+            new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to AND filter
@@ -4431,10 +4428,9 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG, new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to OR filter
         // --------------------------------------------------------------------------------------------
@@ -4449,10 +4445,9 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG, new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -4467,10 +4462,9 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG, new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -4485,10 +4479,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -4503,10 +4497,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -4521,10 +4515,9 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+            new InitGreaterOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to LessOrEqual filter
@@ -4540,9 +4533,9 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to Present filter
@@ -4558,10 +4551,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -4576,9 +4569,9 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from NOT to Extensible Match filter
@@ -4594,9 +4587,9 @@
         //     ...
         //
         // Init extensible match filter
-        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.NOT_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+        super.transitions[LdapStatesEnum.NOT_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.NOT_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+            new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Equality match to Attribute Desc Filter
@@ -4611,9 +4604,9 @@
         //     ...
         //
         // Init Attribute Desc filter
-        super.transitions[LdapStatesEnum.EQUALITY_MATCH_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EQUALITY_MATCH_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, UniversalTag.OCTET_STRING_TAG,
-                new InitAttributeDescFilterAction() );
+        super.transitions[LdapStatesEnum.EQUALITY_MATCH_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.EQUALITY_MATCH_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE,
+            UniversalTag.OCTET_STRING_TAG, new InitAttributeDescFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Desc Filter to Assertion Value Filter
@@ -4628,10 +4621,10 @@
         //     assertionValue   AssertionValue }
         //
         // Init Assertion Value filter
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, UniversalTag.OCTET_STRING_TAG,
-                new InitAssertionValueFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE,
+            UniversalTag.OCTET_STRING_TAG, new InitAssertionValueFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to AND filter
         // --------------------------------------------------------------------------------------------
@@ -4645,10 +4638,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to OR filter
         // --------------------------------------------------------------------------------------------
@@ -4663,10 +4656,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -4681,10 +4674,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -4700,9 +4693,10 @@
         //
         // Init NOT filter
         super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+            new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE,
+            LdapConstants.EQUALITY_MATCH_FILTER_TAG, new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -4717,10 +4711,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE,
+            LdapConstants.SUBSTRINGS_FILTER_TAG, new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -4736,10 +4730,10 @@
         //
         // Init Greater Or Equal filter
         super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+            new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -4755,9 +4749,10 @@
         //
         // Init Less Or Equal filter
         super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+            new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE,
+            LdapConstants.LESS_OR_EQUAL_FILTER_TAG, new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Present filter
         // --------------------------------------------------------------------------------------------
@@ -4772,10 +4767,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.PRESENT_STATE,
+            LdapConstants.PRESENT_FILTER_TAG, new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -4791,9 +4786,10 @@
         //
         // Init Approx Match filter
         super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+            new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.APPROX_MATCH_STATE,
+            LdapConstants.APPROX_MATCH_FILTER_TAG, new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -4809,8 +4805,9 @@
         //
         // Init Assertion Value Filter filter
         super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+            new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Assertion Value Filter to Attribute Description List
@@ -4824,9 +4821,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ASSERTION_VALUE_FILTER_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE,
+            UniversalTag.SEQUENCE_TAG, new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Description List to AttributeDescription
@@ -4840,9 +4837,9 @@
         //     AttributeDescription
         //
         // Store attribute description
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, UniversalTag.OCTET_STRING_TAG,
-                new AttributeDescAction() );
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE,
+            UniversalTag.OCTET_STRING_TAG, new AttributeDescAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Description List to Controls
@@ -4852,9 +4849,9 @@
         //     controls       [0] Controls OPTIONAL }
         //
         // Empty attribute description list, with controls
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Attribute Description to AttributeDescription
@@ -4868,10 +4865,10 @@
         //     AttributeDescription
         //
         // Store attribute description
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, UniversalTag.OCTET_STRING_TAG,
-                new AttributeDescAction() );
-        
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE,
+            UniversalTag.OCTET_STRING_TAG, new AttributeDescAction() );
+
         // --------------------------------------------------------------------------------------------
         // transition from Attribute Description to Controls.
         // --------------------------------------------------------------------------------------------
@@ -4879,9 +4876,9 @@
         //         ... },
         //     controls       [0] Controls OPTIONAL }
         //
-        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE][LdapConstants.CONTROLS_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG, 
-                new ControlsInitAction() );
+        super.transitions[LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE][LdapConstants.CONTROLS_TAG] = new GrammarTransition(
+            LdapStatesEnum.ATTRIBUTE_DESCRIPTION_STATE, LdapStatesEnum.CONTROLS_STATE, LdapConstants.CONTROLS_TAG,
+            new ControlsInitAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Greater Or Equal to Attribute Desc Filter
@@ -4896,9 +4893,9 @@
         //     ...
         //
         // Init Attribute Desc filter
-        super.transitions[LdapStatesEnum.GREATER_OR_EQUAL_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, UniversalTag.OCTET_STRING_TAG,
-                new InitAttributeDescFilterAction() );
+        super.transitions[LdapStatesEnum.GREATER_OR_EQUAL_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE,
+            UniversalTag.OCTET_STRING_TAG, new InitAttributeDescFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Less Or Equal to Attribute Desc Filter
@@ -4913,9 +4910,9 @@
         //     ...
         //
         // Init Attribute Desc filter
-        super.transitions[LdapStatesEnum.LESS_OR_EQUAL_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, UniversalTag.OCTET_STRING_TAG,
-                new InitAttributeDescFilterAction() );
+        super.transitions[LdapStatesEnum.LESS_OR_EQUAL_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE,
+            UniversalTag.OCTET_STRING_TAG, new InitAttributeDescFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Substrings to typeSubstring
@@ -4930,9 +4927,9 @@
         //     ...
         //
         // Init substring type
-        super.transitions[LdapStatesEnum.SUBSTRING_FILTER_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapStatesEnum.TYPE_SUBSTRING_STATE, UniversalTag.OCTET_STRING_TAG,
-                new GrammarAction( "Store substring filter type" )
+        super.transitions[LdapStatesEnum.SUBSTRING_FILTER_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapStatesEnum.TYPE_SUBSTRING_STATE, UniversalTag.OCTET_STRING_TAG,
+            new GrammarAction( "Store substring filter type" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -4976,9 +4973,9 @@
         //     ...
         //
         // Init substring type
-        super.transitions[LdapStatesEnum.TYPE_SUBSTRING_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPE_SUBSTRING_STATE, LdapStatesEnum.SUBSTRINGS_STATE, UniversalTag.SEQUENCE_TAG,
-                new GrammarAction( "Substring Filter substringsSequence " )
+        super.transitions[LdapStatesEnum.TYPE_SUBSTRING_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPE_SUBSTRING_STATE, LdapStatesEnum.SUBSTRINGS_STATE, UniversalTag.SEQUENCE_TAG,
+            new GrammarAction( "Substring Filter substringsSequence " )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -4992,7 +4989,7 @@
                         throw new DecoderException( "The substring sequence is empty" );
                     }
                 }
-            } );                
+            } );
 
         // --------------------------------------------------------------------------------------------
         // Transition from substrings to Initial
@@ -5004,9 +5001,9 @@
         //         ...
         //
         // Store initial value
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.INITIAL_STATE, LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG,
-                new GrammarAction( "Store substring filter initial Value" )
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.INITIAL_STATE, LdapConstants.SUBSTRINGS_FILTER_INITIAL_TAG,
+            new GrammarAction( "Store substring filter initial Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -5032,7 +5029,7 @@
                     searchRequest.unstackFilters( container );
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from substrings to any
         // --------------------------------------------------------------------------------------------
@@ -5044,10 +5041,10 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
-                new StoreAnyAction() );
-        
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = new GrammarTransition(
+            LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+            new StoreAnyAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from substrings to final
         // --------------------------------------------------------------------------------------------
@@ -5058,9 +5055,9 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
-                new StoreFinalAction() );
+        super.transitions[LdapStatesEnum.SUBSTRINGS_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.SUBSTRINGS_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+            new StoreFinalAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from initial to any
@@ -5073,10 +5070,10 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
-                new StoreAnyAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+            new StoreAnyAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to final
         // --------------------------------------------------------------------------------------------
@@ -5087,10 +5084,10 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
-                new StoreFinalAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+            new StoreFinalAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -5103,9 +5100,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.INITIAL_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.INITIAL_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
+            new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from initial to AND filter
@@ -5120,10 +5117,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to OR filter
         // --------------------------------------------------------------------------------------------
@@ -5138,10 +5135,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -5156,10 +5153,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -5174,10 +5171,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -5192,10 +5189,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5210,11 +5207,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5229,10 +5225,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Present filter
         // --------------------------------------------------------------------------------------------
@@ -5247,10 +5243,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -5265,10 +5261,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from initial to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -5283,9 +5279,9 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
+        super.transitions[LdapStatesEnum.INITIAL_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.INITIAL_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from any to final
@@ -5297,10 +5293,10 @@
         //         final  [2] LDAPSTRING }
         //
         // Store substring final type
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
-                new StoreFinalAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.FINAL_STATE, LdapConstants.SUBSTRINGS_FILTER_FINAL_TAG,
+            new StoreFinalAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to any
         // --------------------------------------------------------------------------------------------
@@ -5312,10 +5308,10 @@
         //         ...
         //
         // Store substring any type
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
-                new StoreAnyAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_ANY_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.ANY_STATE, LdapConstants.SUBSTRINGS_FILTER_ANY_TAG,
+            new StoreAnyAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -5328,9 +5324,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.ANY_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.ANY_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
+            new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from any to AND filter
@@ -5345,10 +5341,9 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG, new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to OR filter
         // --------------------------------------------------------------------------------------------
@@ -5363,10 +5358,9 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG, new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -5381,10 +5375,9 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG, new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -5399,10 +5392,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -5417,10 +5410,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5435,11 +5428,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
+            new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5454,10 +5446,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Present filter
         // --------------------------------------------------------------------------------------------
@@ -5472,10 +5464,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -5490,10 +5482,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from any to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -5508,10 +5500,10 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.ANY_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.ANY_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.ANY_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
+            new InitExtensibleMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -5524,9 +5516,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.FINAL_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.FINAL_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
+            new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from final to AND filter
@@ -5541,10 +5533,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to OR filter
         // --------------------------------------------------------------------------------------------
@@ -5559,10 +5551,9 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG, new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -5577,10 +5568,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -5595,10 +5586,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -5613,10 +5604,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5631,11 +5622,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5650,10 +5640,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Present filter
         // --------------------------------------------------------------------------------------------
@@ -5668,10 +5658,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -5686,10 +5676,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from final to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -5704,10 +5694,10 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.FINAL_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.FINAL_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.FINAL_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to AND filter
         // --------------------------------------------------------------------------------------------
@@ -5721,10 +5711,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to OR filter
         // --------------------------------------------------------------------------------------------
@@ -5739,10 +5729,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -5757,10 +5747,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -5775,10 +5765,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
+            new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -5793,10 +5783,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
+            new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5811,11 +5801,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -5830,10 +5819,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
+            new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Present filter
         // --------------------------------------------------------------------------------------------
@@ -5848,10 +5837,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -5866,10 +5855,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -5884,10 +5873,10 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.PRESENT_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Present Filter to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -5900,9 +5889,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.PRESENT_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.PRESENT_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.PRESENT_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
+            new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Approx Match to Attribute Desc Filter
@@ -5917,9 +5906,9 @@
         //     ...
         //
         // Init Attribute Desc filter
-        super.transitions[LdapStatesEnum.APPROX_MATCH_STATE][UniversalTag.OCTET_STRING_TAG] = 
-            new GrammarTransition( LdapStatesEnum.APPROX_MATCH_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE, UniversalTag.OCTET_STRING_TAG,
-                new InitAttributeDescFilterAction() );
+        super.transitions[LdapStatesEnum.APPROX_MATCH_STATE][UniversalTag.OCTET_STRING_TAG] = new GrammarTransition(
+            LdapStatesEnum.APPROX_MATCH_STATE, LdapStatesEnum.ATTRIBUTE_DESC_FILTER_STATE,
+            UniversalTag.OCTET_STRING_TAG, new InitAttributeDescFilterAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from Extensible Match to MatchingRule
@@ -5933,9 +5922,9 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCHING_RULE_ID_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.MATCHING_RULE_STATE, LdapConstants.MATCHING_RULE_ID_TAG,
-                new GrammarAction( "Store matching rule Value" )
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCHING_RULE_ID_TAG] = new GrammarTransition(
+            LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.MATCHING_RULE_STATE,
+            LdapConstants.MATCHING_RULE_ID_TAG, new GrammarAction( "Store matching rule Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -5952,7 +5941,7 @@
                     if ( tlv.getLength() == 0 )
                     {
                         log.error( "The matching rule is empty" );
-                        
+
                         // It will generate a PROTOCOL_ERROR
                         throw new DecoderException( "Invalid matching rule : it can't be empty" );
                     }
@@ -5976,10 +5965,10 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCHING_RULE_TYPE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.TYPE_MATCHING_RULE_STATE, LdapConstants.MATCHING_RULE_TYPE_TAG,
-                new StoreTypeMatchingRuleAction() );
-        
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCHING_RULE_TYPE_TAG] = new GrammarTransition(
+            LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.TYPE_MATCHING_RULE_STATE,
+            LdapConstants.MATCHING_RULE_TYPE_TAG, new StoreTypeMatchingRuleAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from Extensible Match to match value
         // --------------------------------------------------------------------------------------------
@@ -5993,10 +5982,10 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCH_VALUE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
-                new StoreMatchValueAction() );
-        
+        super.transitions[LdapStatesEnum.EXTENSIBLE_MATCH_STATE][LdapConstants.MATCH_VALUE_TAG] = new GrammarTransition(
+            LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
+            new StoreMatchValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from matching rule to type matching rule
         // --------------------------------------------------------------------------------------------
@@ -6010,10 +5999,10 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE][LdapConstants.MATCHING_RULE_TYPE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCHING_RULE_STATE, LdapStatesEnum.TYPE_MATCHING_RULE_STATE, LdapConstants.MATCHING_RULE_TYPE_TAG,
-                new StoreTypeMatchingRuleAction() );
-        
+        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE][LdapConstants.MATCHING_RULE_TYPE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCHING_RULE_STATE, LdapStatesEnum.TYPE_MATCHING_RULE_STATE,
+            LdapConstants.MATCHING_RULE_TYPE_TAG, new StoreTypeMatchingRuleAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from matching rule to match value
         // --------------------------------------------------------------------------------------------
@@ -6027,10 +6016,10 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE][LdapConstants.MATCH_VALUE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCHING_RULE_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
-                new StoreMatchValueAction() );
-        
+        super.transitions[LdapStatesEnum.MATCHING_RULE_STATE][LdapConstants.MATCH_VALUE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCHING_RULE_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
+            new StoreMatchValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from matching type to match value
         // --------------------------------------------------------------------------------------------
@@ -6044,10 +6033,10 @@
         //     ...
         //
         // Store the matching rule ID 
-        super.transitions[LdapStatesEnum.TYPE_MATCHING_RULE_STATE][LdapConstants.MATCH_VALUE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.TYPE_MATCHING_RULE_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
-                new StoreMatchValueAction() );
-        
+        super.transitions[LdapStatesEnum.TYPE_MATCHING_RULE_STATE][LdapConstants.MATCH_VALUE_TAG] = new GrammarTransition(
+            LdapStatesEnum.TYPE_MATCHING_RULE_STATE, LdapStatesEnum.MATCH_VALUE_STATE, LdapConstants.MATCH_VALUE_TAG,
+            new StoreMatchValueAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to dnAttributes
         // --------------------------------------------------------------------------------------------
@@ -6060,10 +6049,9 @@
         //     dnAttributes [4] BOOLEAN DEFAULT FALSE }
         //
         // Store the dnAttributes flag 
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.DN_ATTRIBUTES_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapConstants.DN_ATTRIBUTES_FILTER_TAG,
-                new GrammarAction(
-                "Store matching dnAttributes Value" )
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.DN_ATTRIBUTES_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.DN_ATTRIBUTES_STATE,
+            LdapConstants.DN_ATTRIBUTES_FILTER_TAG, new GrammarAction( "Store matching dnAttributes Value" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
@@ -6101,12 +6089,12 @@
                     {
                         log.debug( "DN Attributes : {}", Boolean.valueOf( extensibleMatchFilter.isDnAttributes() ) );
                     }
-                    
+
                     // unstack the filters if needed
                     searchRequest.unstackFilters( ldapMessageContainer );
                 }
             } );
-        
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to AND filter
         // --------------------------------------------------------------------------------------------
@@ -6120,10 +6108,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to OR filter
         // --------------------------------------------------------------------------------------------
@@ -6138,10 +6126,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -6156,10 +6144,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -6174,10 +6162,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE,
+            LdapConstants.EQUALITY_MATCH_FILTER_TAG, new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -6192,10 +6180,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE,
+            LdapConstants.SUBSTRINGS_FILTER_TAG, new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -6210,11 +6198,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -6229,10 +6216,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE,
+            LdapConstants.LESS_OR_EQUAL_FILTER_TAG, new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Present filter
         // --------------------------------------------------------------------------------------------
@@ -6247,10 +6234,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -6265,10 +6252,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
+            new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -6283,10 +6270,10 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from match value to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -6299,9 +6286,9 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.MATCH_VALUE_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.MATCH_VALUE_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE,
+            UniversalTag.SEQUENCE_TAG, new InitAttributeDescListAction() );
 
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to AND filter
@@ -6316,10 +6303,10 @@
         //     ...
         //
         // Init AND filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.AND_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
-                new InitAndFilterAction() );
-                
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.AND_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.AND_STATE, LdapConstants.AND_FILTER_TAG,
+            new InitAndFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to OR filter
         // --------------------------------------------------------------------------------------------
@@ -6334,10 +6321,10 @@
         //     ...
         //
         // Init OR filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.OR_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
-                new InitOrFilterAction() );
-        
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.OR_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.OR_STATE, LdapConstants.OR_FILTER_TAG,
+            new InitOrFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to NOT filter
         // --------------------------------------------------------------------------------------------
@@ -6352,10 +6339,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.NOT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
-                new InitNotFilterAction() );
-        
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.NOT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.NOT_STATE, LdapConstants.NOT_FILTER_TAG,
+            new InitNotFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Equality Match filter
         // --------------------------------------------------------------------------------------------
@@ -6370,10 +6357,10 @@
         //     ...
         //
         // Init NOT filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE, LdapConstants.EQUALITY_MATCH_FILTER_TAG,
-                new InitEqualityMatchFilterAction() );
-        
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.EQUALITY_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.EQUALITY_MATCH_STATE,
+            LdapConstants.EQUALITY_MATCH_FILTER_TAG, new InitEqualityMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Substrings filter
         // --------------------------------------------------------------------------------------------
@@ -6388,10 +6375,10 @@
         //     ...
         //
         // Init Substrings filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE, LdapConstants.SUBSTRINGS_FILTER_TAG,
-                new InitSubstringsFilterAction() );
-        
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.SUBSTRINGS_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.SUBSTRING_FILTER_STATE,
+            LdapConstants.SUBSTRINGS_FILTER_TAG, new InitSubstringsFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to GreaterOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -6406,11 +6393,10 @@
         //     ...
         //
         // Init Greater Or Equal filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE, LdapConstants.GREATER_OR_EQUAL_FILTER_TAG,
-                new InitGreaterOrEqualFilterAction() );
-        
-    
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.GREATER_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.GREATER_OR_EQUAL_STATE,
+            LdapConstants.GREATER_OR_EQUAL_FILTER_TAG, new InitGreaterOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to LessOrEqual filter
         // --------------------------------------------------------------------------------------------
@@ -6425,10 +6411,10 @@
         //     ...
         //
         // Init Less Or Equal filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE, LdapConstants.LESS_OR_EQUAL_FILTER_TAG,
-                new InitLessOrEqualFilterAction() );
-    
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.LESS_OR_EQUAL_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.LESS_OR_EQUAL_STATE,
+            LdapConstants.LESS_OR_EQUAL_FILTER_TAG, new InitLessOrEqualFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Present filter
         // --------------------------------------------------------------------------------------------
@@ -6443,10 +6429,10 @@
         //     ...
         //
         // Init present filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.PRESENT_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
-                new InitPresentFilterAction() );
-        
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.PRESENT_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.PRESENT_STATE, LdapConstants.PRESENT_FILTER_TAG,
+            new InitPresentFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Approx Match filter
         // --------------------------------------------------------------------------------------------
@@ -6461,10 +6447,10 @@
         //     ...
         //
         // Init Approx Match filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.APPROX_MATCH_STATE, LdapConstants.APPROX_MATCH_FILTER_TAG,
-                new InitApproxMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.APPROX_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.APPROX_MATCH_STATE,
+            LdapConstants.APPROX_MATCH_FILTER_TAG, new InitApproxMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Extensible Match filter
         // --------------------------------------------------------------------------------------------
@@ -6479,10 +6465,10 @@
         //     ...
         //
         // Init Assertion Value Filter filter
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE, LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG,
-                new InitExtensibleMatchFilterAction() );
-    
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.EXTENSIBLE_MATCH_STATE,
+            LdapConstants.EXTENSIBLE_MATCH_FILTER_TAG, new InitExtensibleMatchFilterAction() );
+
         // --------------------------------------------------------------------------------------------
         // Transition from dnAttributes to Attribute Description List
         // --------------------------------------------------------------------------------------------
@@ -6495,11 +6481,12 @@
         //     AttributeDescription
         //
         // Init attribute description list
-        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE, UniversalTag.SEQUENCE_TAG,
-                new InitAttributeDescListAction() );
+        super.transitions[LdapStatesEnum.DN_ATTRIBUTES_STATE][UniversalTag.SEQUENCE_TAG] = new GrammarTransition(
+            LdapStatesEnum.DN_ATTRIBUTES_STATE, LdapStatesEnum.ATTRIBUTE_DESCRIPTION_LIST_STATE,
+            UniversalTag.SEQUENCE_TAG, new InitAttributeDescListAction() );
     }
 
+
     // ~ Methods
     // ------------------------------------------------------------------------------------
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResponse.java
index 59fd256..c47cca4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResponse.java
@@ -29,6 +29,7 @@
  * A generic LdapResponse Object. It will contain the LdapResult.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapResponse extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResult.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResult.java
index f7a11d4..a7e2f2f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResult.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapResult.java
@@ -20,6 +20,11 @@
 package org.apache.directory.shared.ldap.codec;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.directory.shared.asn1.AbstractAsn1Object;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
@@ -30,17 +35,12 @@
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.util.StringTools;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 
 /**
  * A ldapObject to store the LdapResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapResult extends AbstractAsn1Object
 {
@@ -278,15 +278,11 @@
 
         if ( ( referrals != null ) && ( referrals.size() != 0 ) )
         {
-            Iterator referralIterator = referrals.iterator();
-
             referralsLength = 0;
 
             // Each referral
-            while ( referralIterator.hasNext() )
+            for ( LdapURL referral:referrals )
             {
-                LdapURL referral = ( LdapURL ) referralIterator.next();
-
                 referralsLength += 1 + TLV.getNbBytes( referral.getNbBytes() ) + referral.getNbBytes();
             }
 
@@ -338,14 +334,10 @@
             buffer.put( TLV.getBytes( referralsLength ) );
 
             // Each referral
-            Iterator referralIterator = referrals.iterator();
-
-            while ( referralIterator.hasNext() )
+            for ( LdapURL referral:referrals )
             {
-                LdapURL referral = ( LdapURL ) referralIterator.next();
-
-                // Ecode the current referral
-                Value.encode( buffer, referral.getBytes() );
+                // Encode the current referral
+                Value.encode( buffer, referral.getBytesReference() );
             }
         }
 
@@ -607,6 +599,8 @@
                         sb.append( "Unknown error code : " ).append( resultCode );
                         break;
                 }
+            
+            break;
         }
 
         sb.append( "            Matched DN : '" ).append( matchedDN == null ? "": matchedDN.toString() ).append( "'\n" );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapStatesEnum.java
index 2505556..41a378e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/LdapStatesEnum.java
@@ -29,6 +29,7 @@
  * purpose
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ResponseCarryingException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ResponseCarryingException.java
index 5c29340..4d3937e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ResponseCarryingException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/ResponseCarryingException.java
@@ -31,6 +31,7 @@
  * Thrown when a Decoder has encountered a failure condition during a decode.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ResponseCarryingException extends DecoderException
 {
@@ -63,7 +64,8 @@
      * @param message A message with meaning to a human
      * @param cause The Exception which caused the error
      */
-    public ResponseCarryingException(String message, ResultResponse response, ResultCodeEnum code, LdapDN matchedDn, Throwable cause)
+    public ResponseCarryingException(String message, ResultResponse response, ResultCodeEnum code, 
+        LdapDN matchedDn, Throwable cause)
     {
         super( message, cause );
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixDecoder.java
index 1ad5580..245fad9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixDecoder.java
@@ -22,32 +22,29 @@
 
 import java.io.InputStream;
 import java.nio.ByteBuffer;
-import java.util.Set;
 
 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
 import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum;
 import org.apache.directory.shared.asn1.codec.DecoderException;
 import org.apache.directory.shared.asn1.codec.stateful.DecoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.DecoderMonitor;
+import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
 import org.apache.directory.shared.ldap.message.spi.Provider;
 import org.apache.directory.shared.ldap.message.spi.ProviderDecoder;
 import org.apache.directory.shared.ldap.message.spi.ProviderException;
 import org.apache.directory.shared.ldap.util.StringTools;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  * The TwixDecoder decodes ASN.1 BER encoded PDUs.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class TwixDecoder implements ProviderDecoder
 {
-    //TM private static long cumul = 0L;
-    //TM private static long count = 0L;
-    //TM private Object lock = new Object();
-
     /** The logger */
     private static Logger log = LoggerFactory.getLogger( TwixDecoder.class );
 
@@ -71,13 +68,13 @@
      * Creates an instance of a Twix Decoder implementation.
      * 
      * @param provider the owning provider.
-     * @param binaries The binary attributes set
+     * @param binaryAttributeDetector checks for binary attributes 
      */
-    public TwixDecoder(Provider provider, Set binaries)
+    public TwixDecoder( Provider provider, BinaryAttributeDetector binaryAttributeDetector )
     {
         this.provider = provider;
-        ldapMessageContainer = new LdapMessageContainer( binaries );
-        ldapDecoder = new LdapDecoder();
+        this.ldapMessageContainer = new LdapMessageContainer( binaryAttributeDetector );
+        this.ldapDecoder = new LdapDecoder();
     }
 
 
@@ -85,11 +82,10 @@
      * Decodes a PDU
      * 
      * @param encoded The PDU containing the LdapMessage to decode
-     * @throws DecoderExceptionIf anything went wrong
+     * @throws DecoderException if anything goes wrong
      */
     public void decode( Object encoded ) throws DecoderException
     {
-        //TM long t0 = System.nanoTime();
         ByteBuffer buf;
         int position = 0;
 
@@ -120,12 +116,12 @@
                     int size = buf.position();
                     buf.flip();
                     
-                	byte[] array = new byte[ size - position ];
-                	
-                	for ( int i = position; i < size; i++ )
-                	{
-                		array[ i ] = buf.get();
-                	}
+                    byte[] array = new byte[ size - position ];
+                    
+                    for ( int i = position; i < size; i++ )
+                    {
+                        array[ i ] = buf.get();
+                    }
     
                     position = size;
                     
@@ -141,37 +137,14 @@
                     }
     
                     decoderCallback.decodeOccurred( null, ldapMessageContainer.getLdapMessage() );
-
                     ldapMessageContainer.clean();
-                    //TM long t1 = System.nanoTime();
-                    //TM
-                    //TM synchronized (lock)
-                    //TM {
-                    //TM     cumul += (t1 - t0);
-                    //TM     count++;
-                    //TM    
-                    //TM
-                    //TM     if ( count % 1000L == 0)
-                    //TM     {
-                    //TM         System.out.println( "Decode cost : " + (cumul/count) );
-                    //TM         cumul = 0L;
-                    //TM     }
-                    //TM }
-                    
-                }
-                else
-                {
-                	if ( IS_DEBUG )
-                	{
-                		
-                	}
                 }
             }
             catch ( DecoderException de )
             {
-            	buf.clear();
-            	ldapMessageContainer.clean();
-            	throw de;
+                buf.clear();
+                ldapMessageContainer.clean();
+                throw de;
             }
         }
     }
@@ -241,6 +214,7 @@
             {
                 log.error( "Twix decoder failure, PDU does not contain enough data" );
                 ProviderException pe = new ProviderException( provider, "Twix decoder failure!" );
+                //noinspection ThrowableInstanceNeverThrown
                 pe.addThrowable( new DecoderException( "The input stream does not contain a full PDU" ) );
                 throw pe;
             }
@@ -280,6 +254,7 @@
             {
                 log.error( "Twix decoder failure : The input stream does not contain a full PDU" );
                 ProviderException pe = new ProviderException( provider, "Twix decoder failure!" );
+                //noinspection ThrowableInstanceNeverThrown
                 pe.addThrowable( new DecoderException( "The input stream does not contain a full PDU" ) );
                 throw pe;
             }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixEncoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixEncoder.java
index e564d5a..c289f11 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixEncoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixEncoder.java
@@ -20,6 +20,12 @@
 package org.apache.directory.shared.ldap.codec;
 
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.EncoderMonitor;
@@ -31,12 +37,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.WritableByteChannel;
-
 
 /**
  * Twix LDAP BER provider's encoder.
@@ -68,7 +68,7 @@
      * 
      * @param provider The associated Provider
      */
-    public TwixEncoder(Provider provider)
+    public TwixEncoder( Provider provider )
     {
         this.provider = provider;
         encodeCallback = new OutputCallback();
@@ -92,6 +92,7 @@
                 log.debug( "Encoding this LdapMessage : " + obj );
             }
 
+            ( ( OutputCallback ) encodeCallback ).attach( out );
             encodeCallback.encodeOccurred( null, ( ( LdapMessage ) obj ).encode( null ) );
         }
         catch ( EncoderException e )
@@ -255,6 +256,7 @@
         {
             try
             {
+                ( ( ByteBuffer ) encoded ).flip();
                 channel.write( ( ByteBuffer ) encoded );
             }
             catch ( IOException e )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixProvider.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixProvider.java
index 4494765..985b733 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixProvider.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixProvider.java
@@ -19,11 +19,7 @@
  */
 package org.apache.directory.shared.ldap.codec;
 
-
-import java.util.Set;
-
-import org.apache.directory.shared.ldap.codec.TwixDecoder;
-import org.apache.directory.shared.ldap.codec.TwixEncoder;
+import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
 import org.apache.directory.shared.ldap.message.spi.Provider;
 import org.apache.directory.shared.ldap.message.spi.ProviderDecoder;
 import org.apache.directory.shared.ldap.message.spi.ProviderEncoder;
@@ -31,6 +27,8 @@
 import org.apache.directory.shared.ldap.message.spi.TransformerSpi;
 
 
+
+
 /**
  * The Twix specific BER provider for LDAP.
  * 
@@ -62,7 +60,7 @@
      * 
      * @return the singleton SnaccProvider instance
      */
-    public synchronized static Provider getProvider()
+    public static synchronized Provider getProvider()
     {
         if ( singleton == null )
         {
@@ -93,9 +91,9 @@
      * @throws org.apache.directory.shared.ldap.message.spi.ProviderException
      *             if the provider or its decoder cannot be found
      */
-    public ProviderDecoder getDecoder( Set binaries ) throws ProviderException
+    public ProviderDecoder getDecoder( BinaryAttributeDetector binaryAttributeDetector ) throws ProviderException
     {
-        return new TwixDecoder( this, binaries );
+        return new TwixDecoder( this, binaryAttributeDetector );
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixTransformer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixTransformer.java
index c63ce14..a59f9c8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixTransformer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/TwixTransformer.java
@@ -22,9 +22,9 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 
+import javax.naming.InvalidNameException;
 import javax.naming.NamingEnumeration;
 import javax.naming.directory.Attribute;
 
@@ -61,8 +61,8 @@
 import org.apache.directory.shared.ldap.codec.search.SearchResultEntry;
 import org.apache.directory.shared.ldap.codec.search.SearchResultReference;
 import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
-import org.apache.directory.shared.ldap.codec.search.controls.PSearchControl;
-import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControl;
+import org.apache.directory.shared.ldap.codec.search.controls.PSearchControlCodec;
+import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlCodec;
 import org.apache.directory.shared.ldap.codec.util.LdapURL;
 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
 import org.apache.directory.shared.ldap.filter.AndNode;
@@ -79,18 +79,18 @@
 import org.apache.directory.shared.ldap.filter.PresenceNode;
 import org.apache.directory.shared.ldap.filter.SubstringNode;
 import org.apache.directory.shared.ldap.message.AbandonRequestImpl;
+import org.apache.directory.shared.ldap.message.AbstractMutableControlImpl;
 import org.apache.directory.shared.ldap.message.AddRequestImpl;
 import org.apache.directory.shared.ldap.message.AddResponseImpl;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.BindRequestImpl;
 import org.apache.directory.shared.ldap.message.BindResponseImpl;
 import org.apache.directory.shared.ldap.message.CascadeControl;
 import org.apache.directory.shared.ldap.message.CompareRequestImpl;
 import org.apache.directory.shared.ldap.message.CompareResponseImpl;
-import org.apache.directory.shared.ldap.message.AbstractMutableControlImpl;
 import org.apache.directory.shared.ldap.message.DeleteRequestImpl;
 import org.apache.directory.shared.ldap.message.DeleteResponseImpl;
-import org.apache.directory.shared.ldap.message.DerefAliasesEnum;
 import org.apache.directory.shared.ldap.message.ExtendedRequestImpl;
 import org.apache.directory.shared.ldap.message.ExtendedResponseImpl;
 import org.apache.directory.shared.ldap.message.LdapResultImpl;
@@ -112,6 +112,7 @@
 import org.apache.directory.shared.ldap.message.extended.GracefulShutdownRequest;
 import org.apache.directory.shared.ldap.message.spi.Provider;
 import org.apache.directory.shared.ldap.message.spi.TransformerSpi;
+import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -121,7 +122,7 @@
  * A Twix to Snickers Message transformer.
  * 
  * @author <a href="mailto:dev@directory.apache.org"> Apache Directory Project</a>
- *         $Rev$
+ * @version $Rev$, $Date$, 
  */
 public class TwixTransformer implements TransformerSpi
 {
@@ -240,6 +241,72 @@
 
 
     /**
+     * Transform a BindResponse message from a TwixMessage to a 
+     * SnickersMessage.  This is used by clients which are receiving a 
+     * BindResponse PDU and must decode it to return the Snickers 
+     * representation.
+     * 
+     * @param twixMessage The message to transform
+     * @param messageId The message Id
+     * @return a Snickers BindResponseImpl
+     */
+    private Message transformBindResponse( LdapMessage twixMessage, int messageId )
+    {
+        BindResponseImpl snickersMessage = new BindResponseImpl( messageId );
+        BindResponse bindResponse = twixMessage.getBindResponse();
+
+        // Twix : byte[] serverSaslcreds -> Snickers : byte[] serverSaslCreds
+        snickersMessage.setServerSaslCreds( bindResponse.getServerSaslCreds() );
+        transformControlsTwixToSnickers( twixMessage, snickersMessage );
+        transformLdapResultTwixToSnickers( bindResponse.getLdapResult(), snickersMessage.getLdapResult() );
+        
+        return snickersMessage;
+    }
+
+    
+    /**
+     * Transforms parameters of a Twix LdapResult into a Snickers LdapResult.
+     *
+     * @param twixResult the Twix LdapResult representation
+     * @param snickersResult the Snickers LdapResult representation
+     */
+    private void transformLdapResultTwixToSnickers( LdapResult twixResult, 
+        org.apache.directory.shared.ldap.message.LdapResult snickersResult )
+    {
+        snickersResult.setErrorMessage( twixResult.getErrorMessage() );
+        
+        try
+        {
+            snickersResult.setMatchedDn( new LdapDN( twixResult.getMatchedDN() ) );
+        }
+        catch ( InvalidNameException e )
+        {
+            log.error( "Could not parse matchedDN while transforming twix value to snickers: {}", 
+                twixResult.getMatchedDN() );
+            snickersResult.setMatchedDn( new LdapDN() );
+        }
+        
+        snickersResult.setResultCode( twixResult.getResultCode() );
+
+        if ( twixResult.getReferrals() == null )
+        {
+            
+        }
+        else
+        {
+            ReferralImpl referral = new ReferralImpl();
+            
+            for ( LdapURL url : twixResult.getReferrals() )
+            {
+                referral.addLdapUrl( url.toString() );
+            }
+            
+            snickersResult.setReferral( referral );
+        }
+    }
+    
+
+    /**
      * Transform a CompareRequest message from a TwixMessage to a
      * SnickersMessage
      * 
@@ -302,7 +369,7 @@
     private Message transformExtendedRequest( LdapMessage twixMessage, int messageId )
     {
         ExtendedRequest extendedRequest = twixMessage.getExtendedRequest();
-        ExtendedRequestImpl snickersMessage = null;
+        ExtendedRequestImpl snickersMessage;
 
         if ( extendedRequest.getRequestName().equals( GracefulShutdownRequest.EXTENSION_OID ) )
         {
@@ -370,12 +437,10 @@
         // Twix : ArrayList modifications -> Snickers : ArrayList mods
         if ( modifyRequest.getModifications() != null )
         {
-            Iterator modifications = modifyRequest.getModifications().iterator();
-
             // Loop through the modifications
-            while ( modifications.hasNext() )
+            for ( ModificationItemImpl modification:modifyRequest.getModifications() )
             {
-                snickersMessage.addModification( ( ModificationItemImpl ) modifications.next() );
+                snickersMessage.addModification( modification );
             }
         }
 
@@ -416,11 +481,9 @@
                 // Loop on all AND/OR children
                 if ( filtersSet != null )
                 {
-                    Iterator filters = filtersSet.iterator();
-
-                    while ( filters.hasNext() )
+                    for ( Filter filter:filtersSet )
                     {
-                        branch.addNode( transformFilter( ( Filter ) filters.next() ) );
+                        branch.addNode( transformFilter( filter ) );
                     }
                 }
 
@@ -443,58 +506,26 @@
                     switch ( ( ( AttributeValueAssertionFilter ) twixFilter ).getFilterType() )
                     {
                         case LdapConstants.EQUALITY_MATCH_FILTER:
-                            if ( ava.getAssertionValue() instanceof String )
-                            {
-                                branch = new EqualityNode( ava.getAttributeDesc(), 
-                                    (String)ava.getAssertionValue() );
-                            }
-                            else
-                            {
-                                branch = new EqualityNode( ava.getAttributeDesc(), 
-                                    (byte[])ava.getAssertionValue() );
-                            }
+                            branch = new EqualityNode( ava.getAttributeDesc(), 
+                                ava.getAssertionValue() );
                             
                             break;
 
                         case LdapConstants.GREATER_OR_EQUAL_FILTER:
-                            if ( ava.getAssertionValue() instanceof String )
-                            {
-                                branch = new GreaterEqNode( ava.getAttributeDesc(),
-                                    (String)ava.getAssertionValue() );
-                            }
-                            else
-                            {
-                                branch = new GreaterEqNode( ava.getAttributeDesc(),
-                                    (byte[])ava.getAssertionValue() );
-                            }
+                            branch = new GreaterEqNode( ava.getAttributeDesc(),
+                                ava.getAssertionValue() );
 
                             break;
 
                         case LdapConstants.LESS_OR_EQUAL_FILTER:
-                            if ( ava.getAssertionValue() instanceof String )
-                            {
-                                branch = new LessEqNode( ava.getAttributeDesc(), 
-                                    (String)ava.getAssertionValue() );
-                            }
-                            else
-                            {
-                                branch = new LessEqNode( ava.getAttributeDesc(), 
-                                    (byte[])ava.getAssertionValue() );
-                            }
+                            branch = new LessEqNode( ava.getAttributeDesc(), 
+                                ava.getAssertionValue() );
 
                             break;
 
                         case LdapConstants.APPROX_MATCH_FILTER:
-                            if ( ava.getAssertionValue() instanceof String )
-                            {
-                                branch = new ApproximateNode( ava.getAttributeDesc(), 
-                                    (String)ava.getAssertionValue() );
-                            }
-                            else
-                            {
-                                branch = new ApproximateNode( ava.getAttributeDesc(), 
-                                    (byte[])ava.getAssertionValue() );
-                            }
+                            branch = new ApproximateNode( ava.getAttributeDesc(), 
+                                ava.getAssertionValue() );
 
                             break;
                     }
@@ -595,23 +626,23 @@
         // Twix : int scope -> Snickers : ScopeEnum scope
         snickersMessage.setScope( searchRequest.getScope() );
 
-        // Twix : int derefAliases -> Snickers : DerefAliasesEnum derefAliases
+        // Twix : int derefAliases -> Snickers : AliasDerefMode derefAliases
         switch ( searchRequest.getDerefAliases() )
         {
             case LdapConstants.DEREF_ALWAYS:
-                snickersMessage.setDerefAliases( DerefAliasesEnum.DEREF_ALWAYS );
+                snickersMessage.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
                 break;
 
             case LdapConstants.DEREF_FINDING_BASE_OBJ:
-                snickersMessage.setDerefAliases( DerefAliasesEnum.DEREF_FINDING_BASE_OBJ );
+                snickersMessage.setDerefAliases( AliasDerefMode.DEREF_FINDING_BASE_OBJ );
                 break;
 
             case LdapConstants.DEREF_IN_SEARCHING:
-                snickersMessage.setDerefAliases( DerefAliasesEnum.DEREF_IN_SEARCHING );
+                snickersMessage.setDerefAliases( AliasDerefMode.DEREF_IN_SEARCHING );
                 break;
 
             case LdapConstants.NEVER_DEREF_ALIASES:
-                snickersMessage.setDerefAliases( DerefAliasesEnum.NEVER_DEREF_ALIASES );
+                snickersMessage.setDerefAliases( AliasDerefMode.NEVER_DEREF_ALIASES );
                 break;
         }
 
@@ -632,7 +663,7 @@
         // Twix : ArrayList attributes -> Snickers : ArrayList attributes
         if ( searchRequest.getAttributes() != null )
         {
-            NamingEnumeration attributes = searchRequest.getAttributes().getAll();
+            NamingEnumeration<?> attributes = searchRequest.getAttributes().getAll();
 
             if ( attributes != null )
             {
@@ -730,6 +761,9 @@
                 break;
 
             case ( LdapConstants.BIND_RESPONSE  ):
+                snickersMessage = transformBindResponse( twixMessage, messageId );
+                break;
+
             case ( LdapConstants.SEARCH_RESULT_ENTRY  ):
             case ( LdapConstants.SEARCH_RESULT_DONE  ):
             case ( LdapConstants.SEARCH_RESULT_REFERENCE  ):
@@ -747,38 +781,34 @@
         }
 
         // Transform the controls, too
-        List twixControls = twixMessage.getControls();
+        List<org.apache.directory.shared.ldap.codec.Control> twixControls = twixMessage.getControls();
 
         if ( twixControls != null )
         {
-            Iterator controls = twixControls.iterator();
-
-            while ( controls.hasNext() )
+            for ( final Control twixControl:twixControls )
             {
                 AbstractMutableControlImpl neutralControl = null;
-                final org.apache.directory.shared.ldap.codec.Control twixControl = 
-                    ( org.apache.directory.shared.ldap.codec.Control ) controls.next();
 
                 if ( twixControl.getControlValue() instanceof 
-                    org.apache.directory.shared.ldap.codec.controls.CascadeControl )
+                    org.apache.directory.shared.ldap.codec.controls.CascadeControlCodec )
                 {
                     neutralControl = new CascadeControl();
                     neutralControl.setCritical( twixControl.getCriticality() );
                 }
-                else if ( twixControl.getControlValue() instanceof PSearchControl )
+                else if ( twixControl.getControlValue() instanceof PSearchControlCodec )
                 {
                     PersistentSearchControl neutralPsearch = new PersistentSearchControl();
                     neutralControl = neutralPsearch;
-                    PSearchControl twixPsearch = ( PSearchControl ) twixControl.getControlValue();
+                    PSearchControlCodec twixPsearch = ( PSearchControlCodec ) twixControl.getControlValue();
                     neutralPsearch.setChangeTypes( twixPsearch.getChangeTypes() );
                     neutralPsearch.setChangesOnly( twixPsearch.isChangesOnly() );
                     neutralPsearch.setReturnECs( twixPsearch.isReturnECs() );
                     neutralPsearch.setCritical( twixControl.getCriticality() );
                 }
-                else if ( twixControl.getControlValue() instanceof SubEntryControl )
+                else if ( twixControl.getControlValue() instanceof SubEntryControlCodec )
                 {
                     SubentriesControl neutralSubentriesControl = new SubentriesControl();
-                    SubEntryControl twixSubentriesControl = ( SubEntryControl ) twixControl.getControlValue();
+                    SubEntryControlCodec twixSubentriesControl = ( SubEntryControlCodec ) twixControl.getControlValue();
                     neutralControl = neutralSubentriesControl;
                     neutralSubentriesControl.setVisibility( twixSubentriesControl.isVisible() );
                     neutralSubentriesControl.setCritical( twixControl.getCriticality() );
@@ -787,10 +817,6 @@
                 {
                     neutralControl = new AbstractMutableControlImpl()
                     {
-                        // Just to avoid a compilation warning !!!
-                        public static final long serialVersionUID = 1L;
-
-
                         public byte[] getEncodedValue()
                         {
                             return ( byte[] ) twixControl.getControlValue();
@@ -808,10 +834,6 @@
                 {
                     neutralControl = new AbstractMutableControlImpl()
                     {
-                        // Just to avoid a compilation warning !!!
-                        public static final long serialVersionUID = 1L;
-
-
                         public byte[] getEncodedValue()
                         {
                             return ( byte[] ) twixControl.getControlValue();
@@ -838,7 +860,7 @@
     /**
      * Transform a Ldapresult part of a Snickers Response to a Twix LdapResult
      * 
-     * @param snickersLdapResult The Snickers LdapResult to transform
+     * @param snickersLdapResult the Snickers LdapResult to transform
      * @return A Twix LdapResult
      */
     private LdapResult transformLdapResult( LdapResultImpl snickersLdapResult )
@@ -857,17 +879,14 @@
         twixLdapResult.setMatchedDN( snickersLdapResult.getMatchedDn() );
 
         // Snickers : Referral referral -> Twix : ArrayList referrals
-        ReferralImpl snisckersReferrals = ( ReferralImpl ) snickersLdapResult.getReferral();
+        ReferralImpl snickersReferrals = ( ReferralImpl ) snickersLdapResult.getReferral();
 
-        if ( snisckersReferrals != null )
+        if ( snickersReferrals != null )
         {
-            Iterator referrals = snisckersReferrals.getLdapUrls().iterator();
             twixLdapResult.initReferrals();
 
-            while ( referrals.hasNext() )
+            for ( String referral:snickersReferrals.getLdapUrls() )
             {
-                String referral = ( String ) referrals.next();
-
                 try
                 {
                     LdapURL ldapUrl = new LdapURL( referral.getBytes() );
@@ -935,6 +954,41 @@
 
 
     /**
+     * Transform a Snickers BindRequest to a Twix BindRequest
+     * 
+     * @param twixMessage The Twix BindRequest to produce
+     * @param snickersMessage The incoming Snickers BindRequest
+     */
+    private void transformBindRequest( LdapMessage twixMessage, Message snickersMessage )
+    {
+        BindRequestImpl snickersBindRequest = ( BindRequestImpl ) snickersMessage;
+
+        BindRequest bindRequest = new BindRequest();
+        
+        if ( snickersBindRequest.isSimple() )
+        {
+            SimpleAuthentication simple = new SimpleAuthentication();
+            simple.setSimple( snickersBindRequest.getCredentials() );
+            bindRequest.setAuthentication( simple );
+        }
+        else
+        {
+            SaslCredentials sasl = new SaslCredentials();
+            sasl.setCredentials( snickersBindRequest.getCredentials() );
+            sasl.setMechanism( snickersBindRequest.getSaslMechanism() );
+            bindRequest.setAuthentication( sasl );
+        }
+        
+        bindRequest.setMessageId( snickersBindRequest.getMessageId() );
+        bindRequest.setName( snickersBindRequest.getName() );
+        bindRequest.setVersion( snickersBindRequest.isVersion3() ? 3 : 2 );
+        
+        // Set the operation into the LdapMessage
+        twixMessage.setProtocolOP( bindRequest );
+    }
+
+
+    /**
      * Transform a Snickers CompareResponse to a Twix CompareResponse
      * 
      * @param twixMessage The Twix CompareResponse to produce
@@ -1112,23 +1166,19 @@
         // Loop on all referals
         if ( referrals != null )
         {
-            Collection urls = referrals.getLdapUrls();
+            Collection<String> urls = referrals.getLdapUrls();
 
             if ( urls != null )
             {
-                Iterator url = urls.iterator();
-
-                while ( url.hasNext() )
+                for ( String url:urls)
                 {
-                    String urlValue = ( String ) url.next();
-
                     try
                     {
-                        searchResultReference.addSearchResultReference( new LdapURL( urlValue ) );
+                        searchResultReference.addSearchResultReference( new LdapURL( url ) );
                     }
                     catch ( LdapURLEncodingException luee )
                     {
-                        log.warn( "The LdapURL " + urlValue + " is incorrect : " + luee.getMessage() );
+                        log.warn( "The LdapURL " + url + " is incorrect : " + luee.getMessage() );
                     }
                 }
             }
@@ -1174,6 +1224,10 @@
                 transformBindResponse( twixMessage, msg );
                 break;
                 
+            case BIND_REQUEST :
+                transformBindRequest( twixMessage, msg );
+                break;
+                
             case ADD_RESPONSE :
                 transformAddResponse( twixMessage, msg );
                 break;
@@ -1214,6 +1268,28 @@
         return twixMessage;
     }
 
+
+    /**
+     * TODO finish this implementation.  Takes Twix Controls, transforming 
+     * them to Snickers Controls and populates the Snickers message with them.
+     *
+     * @param twixMessage the Twix message
+     * @param msg the Snickers message
+     */
+    private void transformControlsTwixToSnickers( LdapMessage twixMessage, Message msg )
+    {
+        if ( twixMessage.getControls() == null )
+        {
+            return;
+        }
+        
+        for ( Control control:twixMessage.getControls() )
+        {
+            log.debug( "Not decoding response control: {}", control );
+        }
+    }
+    
+    
     /**
      * Transforms the controls
      * @param twixMessage The Twix SearchResultReference to produce
@@ -1221,11 +1297,8 @@
      */
     private void transformControls( LdapMessage twixMessage, Message msg )
     {
-        Iterator list = msg.getControls().values().iterator();
-        
-        while ( list.hasNext() )
+        for ( javax.naming.ldap.Control control:msg.getControls().values() )
         {
-            javax.naming.ldap.Control control = ( javax.naming.ldap.Control ) list.next();
             org.apache.directory.shared.ldap.codec.Control twixControl = new org.apache.directory.shared.ldap.codec.Control();
             twixMessage.addControl( twixControl );
             twixControl.setCriticality( control.isCritical() );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/abandon/AbandonRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/abandon/AbandonRequest.java
index 37de29d..8cc2fcc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/abandon/AbandonRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/abandon/AbandonRequest.java
@@ -42,6 +42,7 @@
  * maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AbandonRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/AttributeDescAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/AttributeDescAction.java
index 67c1c56..62b2ad2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/AttributeDescAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/AttributeDescAction.java
@@ -36,6 +36,7 @@
  * The action used to store the attribute description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AttributeDescAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlValueAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlValueAction.java
index ba2a4b4..6c2e308 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlValueAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlValueAction.java
@@ -47,6 +47,7 @@
  * hard code controls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ControlValueAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlsInitAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlsInitAction.java
index 62fdc7b..8cfa790 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlsInitAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ControlsInitAction.java
@@ -35,6 +35,7 @@
  * The action used to initialize a control.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ControlsInitAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ErrorMessageAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ErrorMessageAction.java
index 1356bf1..a9232b7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ErrorMessageAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ErrorMessageAction.java
@@ -38,6 +38,7 @@
  * The action used to set the LdapResult error message.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ErrorMessageAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAndFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAndFilterAction.java
index 1ad6a18..9262b44 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAndFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAndFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the AND filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitAndFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitApproxMatchFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitApproxMatchFilterAction.java
index c670757..1d02ba0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitApproxMatchFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitApproxMatchFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Approx Match filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitApproxMatchFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAssertionValueFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAssertionValueFilterAction.java
index 7e32984..f442fae 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAssertionValueFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAssertionValueFilterAction.java
@@ -29,6 +29,9 @@
 import org.apache.directory.shared.ldap.codec.LdapMessageContainer;
 import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
 import org.apache.directory.shared.ldap.codec.search.SearchRequest;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 import org.apache.directory.shared.ldap.util.StringTools;
 
 import org.slf4j.Logger;
@@ -39,6 +42,7 @@
  * The action used to initialize the Assertion Value filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitAssertionValueFilterAction extends GrammarAction
 {
@@ -65,11 +69,15 @@
         TLV tlv = ldapMessageContainer.getCurrentTLV();
 
         // The value can be null.
-        Object assertionValue = StringTools.EMPTY_BYTES;
+        Value<?> assertionValue = null;
 
         if ( tlv.getLength() != 0 )
         {
-            assertionValue = tlv.getValue().getData();
+            assertionValue = new ClientBinaryValue( tlv.getValue().getData() );
+        }
+        else
+        {
+            assertionValue = new ClientBinaryValue( StringTools.EMPTY_BYTES );
         }
 
         AttributeValueAssertionFilter terminalFilter = ( AttributeValueAssertionFilter ) searchRequest
@@ -78,11 +86,29 @@
 
         if ( ldapMessageContainer.isBinary( assertion.getAttributeDesc() ) )
         {
+            if ( tlv.getLength() != 0 )
+            {
+                assertionValue = new ClientBinaryValue( tlv.getValue().getData() );
+            }
+            else
+            {
+                assertionValue = new ClientBinaryValue( StringTools.EMPTY_BYTES );
+            }
+            
             assertion.setAssertionValue( assertionValue );
         }
         else
         {
-            assertion.setAssertionValue( StringTools.utf8ToString( ( byte[] ) assertionValue ) );
+            if ( tlv.getLength() != 0 )
+            {
+                assertionValue = new ClientStringValue( StringTools.utf8ToString( tlv.getValue().getData() ) );
+            }
+            else
+            {
+                assertionValue = new ClientStringValue( "" );
+            }
+            
+            assertion.setAssertionValue(assertionValue );
         }
 
         // We now have to get back to the nearest filter which is
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescFilterAction.java
index 2227277..96ce5be 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescFilterAction.java
@@ -39,6 +39,7 @@
  * The action used to initialize the AttributeDesc filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitAttributeDescFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescListAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescListAction.java
index bd0e2c1..1cb0af2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescListAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitAttributeDescListAction.java
@@ -33,6 +33,7 @@
  * The action used to initialize the AttributeDesc list
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitAttributeDescListAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitEqualityMatchFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitEqualityMatchFilterAction.java
index 8e3eafb..0764d3f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitEqualityMatchFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitEqualityMatchFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Equality Match filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitEqualityMatchFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitExtensibleMatchFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitExtensibleMatchFilterAction.java
index dea88ad..d01aac5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitExtensibleMatchFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitExtensibleMatchFilterAction.java
@@ -37,6 +37,7 @@
  * The action used to initialize the Extensible Match filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitExtensibleMatchFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitGreaterOrEqualFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitGreaterOrEqualFilterAction.java
index 2635e60..e51b8f5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitGreaterOrEqualFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitGreaterOrEqualFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Greater Or Equal filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitGreaterOrEqualFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitLessOrEqualFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitLessOrEqualFilterAction.java
index e8d8f27..8e57621 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitLessOrEqualFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitLessOrEqualFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Less Or Equal filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitLessOrEqualFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitNotFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitNotFilterAction.java
index 0d1ae72..9bcde64 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitNotFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitNotFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the NOT filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitNotFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitOrFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitOrFilterAction.java
index c122e89..536b2dc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitOrFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitOrFilterAction.java
@@ -38,7 +38,8 @@
  * The action used to initialize the OR filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
+  * @version $Rev$, $Date$, 
+*/
 public class InitOrFilterAction extends GrammarAction
 {
     /** The logger */
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitPresentFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitPresentFilterAction.java
index b07f130..a903566 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitPresentFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitPresentFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Present filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitPresentFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitReferralsAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitReferralsAction.java
index 6e111cb..261e3d5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitReferralsAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitReferralsAction.java
@@ -37,6 +37,7 @@
  * The action used to init referrals to a LdapTresult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitReferralsAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitSubstringsFilterAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitSubstringsFilterAction.java
index 818c33f..3aeacbd 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitSubstringsFilterAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/InitSubstringsFilterAction.java
@@ -38,6 +38,7 @@
  * The action used to initialize the Substrings filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class InitSubstringsFilterAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/MatchedDNAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/MatchedDNAction.java
index 5309267..aa889d5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/MatchedDNAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/MatchedDNAction.java
@@ -42,6 +42,7 @@
  * The action used to set the LdapResult matched DN.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class MatchedDNAction extends GrammarAction
 {
@@ -108,8 +109,11 @@
                     break;
                     
                 default :
-                    log.warn( "The matched DN should not be set when the result code is one of NoSuchObject, AliasProblem, InvalidDNSyntax or AliasDreferencingProblem" );
+                    log.warn( "The matched DN should not be set when the result code is one of NoSuchObject," + 
+                        " AliasProblem, InvalidDNSyntax or AliasDreferencingProblem" );
+
                     ldapResult.setMatchedDN( LdapDN.EMPTY_LDAPDN );
+                    break;
             }
         }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ModifyAttributeValueAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ModifyAttributeValueAction.java
index 8a7b62d..b2e31aa 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ModifyAttributeValueAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ModifyAttributeValueAction.java
@@ -36,6 +36,7 @@
  * The action used to store a Value to an modifyRequest
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ModifyAttributeValueAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ReferralAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ReferralAction.java
index 7b5b840..20f90b7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ReferralAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ReferralAction.java
@@ -20,8 +20,6 @@
 package org.apache.directory.shared.ldap.codec.actions;
 
 
-import java.util.Iterator;
-
 import org.apache.directory.shared.asn1.ber.IAsn1Container;
 import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -43,6 +41,7 @@
  * The action used to add a referral to a LdapTresult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ReferralAction extends GrammarAction
 {
@@ -100,12 +99,10 @@
 
         if ( IS_DEBUG )
         {
-            Iterator urls = ldapResult.getReferrals().iterator();
-
             StringBuffer sb = new StringBuffer();
             boolean isFirst = true;
 
-            while ( urls.hasNext() )
+            for ( LdapURL url:ldapResult.getReferrals() )
             {
                 if ( isFirst )
                 {
@@ -116,7 +113,7 @@
                     sb.append( ", " );
                 }
 
-                sb.append( urls.next() );
+                sb.append( url );
             }
 
             log.debug( "The referral error message is set to " + sb.toString() );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseAction.java
index e16bc48..56e03d0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseAction.java
@@ -37,6 +37,7 @@
  * The action used to store a Response to an ExtendedResponse
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ResponseAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseNameAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseNameAction.java
index 0ecc398..ac6af8b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseNameAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResponseNameAction.java
@@ -38,6 +38,7 @@
  * The action used to store a Response Name to an ExtendedResponse
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ResponseNameAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResultCodeAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResultCodeAction.java
index 5df8b9c..a5efac2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResultCodeAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ResultCodeAction.java
@@ -42,6 +42,7 @@
  * The action used to set the LdapResult result code.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ResultCodeAction extends GrammarAction
 {
@@ -134,6 +135,7 @@
             default:
                 log.warn( "The resultCode " + resultCode + " is unknown." );
                 ldapResult.setResultCode( ResultCodeEnum.OTHER );
+                break;
         }
 
         if ( IS_DEBUG )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/SearchResultAttributeValueAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/SearchResultAttributeValueAction.java
index e62977a..673a267 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/SearchResultAttributeValueAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/SearchResultAttributeValueAction.java
@@ -36,6 +36,7 @@
  * The action used to store a Value to an search result entry
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SearchResultAttributeValueAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ServerSASLCredsAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ServerSASLCredsAction.java
index 47365d8..3f91ed1 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ServerSASLCredsAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ServerSASLCredsAction.java
@@ -36,6 +36,7 @@
  * The action used to store a SASL credentials
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ServerSASLCredsAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreAnyAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreAnyAction.java
index 8b1b2c0..5ce62d1 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreAnyAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreAnyAction.java
@@ -38,6 +38,7 @@
  * The action used to store a any value into a substring filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoreAnyAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreFinalAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreFinalAction.java
index 3e685f0..a9277b2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreFinalAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreFinalAction.java
@@ -38,6 +38,7 @@
  * The action used to store a final value into a substring filter
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoreFinalAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreMatchValueAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreMatchValueAction.java
index 13d731d..fda801d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreMatchValueAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreMatchValueAction.java
@@ -38,6 +38,7 @@
  * The action used to store a match value
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoreMatchValueAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreReferenceAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreReferenceAction.java
index 1e80b6a..e4d27e6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreReferenceAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreReferenceAction.java
@@ -38,6 +38,7 @@
  * The action used to store a reference into a searchResultReference
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoreReferenceAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreTypeMatchingRuleAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreTypeMatchingRuleAction.java
index c487ae8..76e60aa 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreTypeMatchingRuleAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/StoreTypeMatchingRuleAction.java
@@ -38,6 +38,7 @@
  * The action used to store a type matching rule
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoreTypeMatchingRuleAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ValueAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ValueAction.java
index a2581fd..075d0bf 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ValueAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/actions/ValueAction.java
@@ -36,6 +36,7 @@
  * The action used to store a Value to an AddRequest
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ValueAction extends GrammarAction
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddRequest.java
index 4ceba7e..d9172e8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddRequest.java
@@ -20,6 +20,17 @@
 package org.apache.directory.shared.ldap.codec.add;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
@@ -35,16 +46,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-
 
 /**
  * An AddRequest Message. Its syntax is : 
@@ -59,6 +60,7 @@
  *   AttributeValue ::= OCTET STRING
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AddRequest extends LdapMessage
 {
@@ -243,14 +245,14 @@
 
         if ( ( attributes != null ) && ( attributes.size() != 0 ) )
         {
-            NamingEnumeration attributeIterator = attributes.getAll();
+            NamingEnumeration<? extends Attribute> attributeIterator = attributes.getAll();
             attributeLength = new LinkedList<Integer>();
             valuesLength = new LinkedList<Integer>();
 
             // Compute the attributes length
             while ( attributeIterator.hasMoreElements() )
             {
-                Attribute attribute = ( Attribute ) attributeIterator.nextElement();
+                Attribute attribute = attributeIterator.nextElement();
                 int localAttributeLength = 0;
                 int localValuesLength = 0;
 
@@ -261,7 +263,7 @@
                 // The values
                 try
                 {
-                    NamingEnumeration values = attribute.getAll();
+                    NamingEnumeration<?> values = attribute.getAll();
 
                     if ( values.hasMoreElements() )
                     {
@@ -362,13 +364,13 @@
             // The partial attribute list
             if ( ( attributes != null ) && ( attributes.size() != 0 ) )
             {
-                NamingEnumeration attributeIterator = attributes.getAll();
+                NamingEnumeration<? extends Attribute> attributeIterator = attributes.getAll();
                 int attributeNumber = 0;
 
                 // Compute the attributes length
                 while ( attributeIterator.hasMoreElements() )
                 {
-                    Attribute attribute = ( Attribute ) attributeIterator.nextElement();
+                    Attribute attribute = attributeIterator.nextElement();
 
                     // The attributes list sequence
                     buffer.put( UniversalTag.SEQUENCE_TAG );
@@ -385,7 +387,7 @@
 
                     try
                     {
-                        NamingEnumeration values = attribute.getAll();
+                        NamingEnumeration<?> values = attribute.getAll();
 
                         if ( values.hasMoreElements() )
                         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddResponse.java
index 8bdcc32..69b656d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/add/AddResponse.java
@@ -35,6 +35,7 @@
  * AddResponse ::= [APPLICATION 9] LDAPResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AddResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindRequest.java
index fd6c676..8d42c3e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindRequest.java
@@ -37,6 +37,7 @@
  * Asn1Object class to be seen as a member of the LdapMessage CHOICE.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class BindRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindResponse.java
index a70119b..95eae0a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/BindResponse.java
@@ -41,6 +41,7 @@
  * LdapResult ::= resultCode matchedDN errorMessage (referrals)*
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class BindResponse extends LdapResponse
 {
@@ -85,7 +86,14 @@
      */
     public byte[] getServerSaslCreds()
     {
-        return serverSaslCreds;
+        if ( serverSaslCreds == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ serverSaslCreds.length ];
+        System.arraycopy( serverSaslCreds, 0, copy, 0, serverSaslCreds.length );
+        return copy;
     }
 
 
@@ -96,7 +104,13 @@
      */
     public void setServerSaslCreds( byte[] serverSaslCreds )
     {
-        this.serverSaslCreds = serverSaslCreds;
+        if ( serverSaslCreds != null )
+        {
+            this.serverSaslCreds = new byte[ serverSaslCreds.length ];
+            System.arraycopy( serverSaslCreds, 0, this.serverSaslCreds, 0, serverSaslCreds.length );
+        } else {
+            this.serverSaslCreds = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/LdapAuthentication.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/LdapAuthentication.java
index 1a2e334..d23593d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/LdapAuthentication.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/LdapAuthentication.java
@@ -29,6 +29,7 @@
  * as authentication type 1 and 2 are reserved actually in LDAP V3
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public abstract class LdapAuthentication extends AbstractAsn1Object
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SaslCredentials.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SaslCredentials.java
index edf0f34..bfd89c9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SaslCredentials.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SaslCredentials.java
@@ -36,6 +36,7 @@
  * A ldapObject which stores the SASL authentication of a BindRequest.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SaslCredentials extends LdapAuthentication
 {
@@ -84,7 +85,14 @@
      */
     public byte[] getCredentials()
     {
-        return credentials;
+        if ( credentials == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ credentials.length ];
+        System.arraycopy( credentials, 0, copy, 0, credentials.length );
+        return copy;
     }
 
 
@@ -95,7 +103,13 @@
      */
     public void setCredentials( byte[] credentials )
     {
-        this.credentials = credentials;
+        if ( credentials != null )
+        {
+            this.credentials = new byte[ credentials.length ];
+            System.arraycopy( credentials, 0, this.credentials, 0, credentials.length );
+        } else {
+            this.credentials = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SimpleAuthentication.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SimpleAuthentication.java
index 350cc81..c67e03e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SimpleAuthentication.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/bind/SimpleAuthentication.java
@@ -35,6 +35,7 @@
  * A ldapObject which stores the Simple authentication for a BindRequest.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SimpleAuthentication extends LdapAuthentication
 {
@@ -69,7 +70,14 @@
      */
     public byte[] getSimple()
     {
-        return simple;
+        if ( simple == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ simple.length ];
+        System.arraycopy( simple, 0, copy, 0, simple.length );
+        return copy;
     }
 
 
@@ -80,7 +88,13 @@
      */
     public void setSimple( byte[] simple )
     {
-        this.simple = simple;
+        if ( simple != null )
+        {
+            this.simple = new byte[ simple.length ];
+            System.arraycopy( simple, 0, this.simple, 0, simple.length );
+        } else {
+            this.simple = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareRequest.java
index db3ce6f..d63769f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareRequest.java
@@ -48,6 +48,7 @@
  * AssertionValue ::= OCTET STRING
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class CompareRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareResponse.java
index 948422d..838d94f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/compare/CompareResponse.java
@@ -35,6 +35,7 @@
  * CompareResponse ::= [APPLICATION 15] LDAPResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class CompareResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlCodec.java
similarity index 94%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControl.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlCodec.java
index 5fe0034..5f245f2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlCodec.java
@@ -31,7 +31,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class CascadeControl extends AbstractAsn1Object
+public class CascadeControlCodec extends AbstractAsn1Object
 {
     private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate( 0 );
 
@@ -39,7 +39,7 @@
      * Default constructor
      *
      */
-    public CascadeControl()
+    public CascadeControlCodec()
     {
         super();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlDecoder.java
index 9a0886b..a3210ae 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/CascadeControlDecoder.java
@@ -29,6 +29,7 @@
  * A decoder for CascadeControls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class CascadeControlDecoder implements ControlDecoder
 {
@@ -40,6 +41,6 @@
 
     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
     {
-        return new org.apache.directory.shared.ldap.codec.controls.CascadeControl();
+        return new org.apache.directory.shared.ldap.codec.controls.CascadeControlCodec();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlCodec.java
similarity index 96%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControl.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlCodec.java
index afb9d67..c1418d8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlCodec.java
@@ -64,7 +64,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class ManageDsaITControl extends AbstractAsn1Object
+public class ManageDsaITControlCodec extends AbstractAsn1Object
 {
     private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate( 0 );
 
@@ -72,7 +72,7 @@
      * Default constructor
      *
      */
-    public ManageDsaITControl()
+    public ManageDsaITControlCodec()
     {
         super();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlDecoder.java
index 077becf..a85fb8a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/controls/ManageDsaITControlDecoder.java
@@ -30,6 +30,7 @@
  * A decoder for EntryChangeControls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ManageDsaITControlDecoder implements ControlDecoder
 {
@@ -41,6 +42,6 @@
 
     public Asn1Object decode( byte[] controlBytes ) throws DecoderException
     {
-        return new org.apache.directory.shared.ldap.codec.controls.ManageDsaITControl();
+        return new org.apache.directory.shared.ldap.codec.controls.ManageDsaITControlCodec();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelRequest.java
index 20e1c3a..d205aa7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelRequest.java
@@ -38,6 +38,7 @@
  * DelRequest ::= [APPLICATION 10] LDAPDN
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class DelRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelResponse.java
index c12cfa1..84293c3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/del/DelResponse.java
@@ -35,6 +35,7 @@
  * DelResponse ::= [APPLICATION 11] LDAPResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class DelResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedRequest.java
index 4d7b3b8..d90abab 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedRequest.java
@@ -38,6 +38,7 @@
  *              requestValue     [1] OCTET STRING OPTIONAL }
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ExtendedRequest extends LdapMessage
 {
@@ -112,7 +113,14 @@
      */
     public byte[] getRequestValue()
     {
-        return requestValue;
+        if ( requestValue == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ requestValue.length ];
+        System.arraycopy( requestValue, 0, copy, 0, requestValue.length );
+        return copy;
     }
 
 
@@ -123,7 +131,13 @@
      */
     public void setRequestValue( byte[] requestValue )
     {
-        this.requestValue = requestValue;
+        if ( requestValue != null )
+        {
+            this.requestValue = new byte[ requestValue.length ];
+            System.arraycopy( requestValue, 0, this.requestValue, 0, requestValue.length );
+        } else {
+            this.requestValue = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedResponse.java
index caef710..acaa4dc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/ExtendedResponse.java
@@ -39,6 +39,7 @@
  *              response         [11] OCTET STRING OPTIONAL }
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ExtendedResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulAction.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulAction.java
index c0e0d91..1d8407a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulAction.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulAction.java
@@ -28,6 +28,7 @@
  * A common class for graceful Disconnect and Shutdown extended operations.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public abstract class GracefulAction extends AbstractAsn1Object
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnect.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnect.java
index 5f93a4d..26a62c3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnect.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnect.java
@@ -22,7 +22,6 @@
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -45,7 +44,7 @@
  * </pre>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$
+ * @version $Rev$, $Date$, 
  */
 public class GracefulDisconnect extends GracefulAction
 {
@@ -132,12 +131,10 @@
         {
             replicatedContextsLength = 0;
 
-            Iterator replicatedContextIterator = replicatedContexts.iterator();
-
             // We may have more than one reference.
-            while ( replicatedContextIterator.hasNext() )
+            for ( LdapURL replicatedContext:replicatedContexts )
             {
-                int ldapUrlLength = ( ( LdapURL ) replicatedContextIterator.next() ).getNbBytes();
+                int ldapUrlLength = replicatedContext.getNbBytes();
                 replicatedContextsLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
             }
 
@@ -181,13 +178,10 @@
             bb.put( UniversalTag.SEQUENCE_TAG );
             bb.put( TLV.getBytes( replicatedContextsLength ) );
 
-            Iterator replicatedContextIterator = replicatedContexts.iterator();
-
             // We may have more than one reference.
-            while ( replicatedContextIterator.hasNext() )
+            for ( LdapURL replicatedContext:replicatedContexts )
             {
-                LdapURL url = ( LdapURL ) replicatedContextIterator.next();
-                Value.encode( bb, url.getBytes() );
+                Value.encode( bb, replicatedContext.getBytesReference() );
             }
         }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectContainer.java
index a2c58c3..94f1b27 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectContainer.java
@@ -21,15 +21,15 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * A container for the GracefulDisconnect codec.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class GracefulDisconnectContainer extends AbstractContainer implements IAsn1Container
+public class GracefulDisconnectContainer extends AbstractContainer
 {
     /** GracefulShutdown */
     private GracefulDisconnect gracefulDisconnect;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectDecoder.java
index e86d4ae..7de157d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectDecoder.java
@@ -31,6 +31,7 @@
  * A decoder for GracefulDisconnects.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class GracefulDisconnectDecoder extends Asn1Decoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectGrammar.java
index 8d0b6f4..5f2b87d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectGrammar.java
@@ -58,8 +58,9 @@
  * </pre>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class GracefulDisconnectGrammar extends AbstractGrammar implements IGrammar
+public class GracefulDisconnectGrammar extends AbstractGrammar
 {
     /** The logger */
     static final Logger log = LoggerFactory.getLogger( GracefulDisconnectGrammar.class );
@@ -157,8 +158,8 @@
             }
             catch ( IntegerDecoderException e )
             {
-                String msg = "failed to decode the timeOffline, the value should be between 0 and 720 minutes, it is '"
-                    + StringTools.dumpBytes( value.getData() ) + "'";
+                String msg = "failed to decode the timeOffline, the value should be between 0 and 720 minutes, " + 
+                "it is '" + StringTools.dumpBytes( value.getData() ) + "'";
                 log.error( msg );
                 throw new DecoderException( msg );
             }
@@ -224,7 +225,8 @@
          *     
          * Set the delay value into the GracefulDisconnect object.    
          */
-        super.transitions[GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE][GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] = 
+        super.transitions[GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE]
+                         [GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] = 
             new GrammarTransition( GracefulDisconnectStatesEnum.GRACEFUL_DISCONNECT_SEQUENCE_STATE,
                                     GracefulDisconnectStatesEnum.DELAY_STATE, 
                                     GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG, 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectStatesEnum.java
index b57768a..e231698 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulDisconnectStatesEnum.java
@@ -29,6 +29,7 @@
  * for debugging purposes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class GracefulDisconnectStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownContainer.java
index 4147628..d8cc883 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownContainer.java
@@ -21,15 +21,15 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * A container for the GracefulShutdown codec.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class GracefulShutdownContainer extends AbstractContainer implements IAsn1Container
+public class GracefulShutdownContainer extends AbstractContainer
 {
     /** GracefulShutdown */
     private GracefulShutdown gracefulShutdown;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownDecoder.java
index 92a7a0e..249ec81 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownDecoder.java
@@ -31,6 +31,7 @@
  * A decoder for GracefulShutdowns.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class GracefulShutdownDecoder extends Asn1Decoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownGrammar.java
index 2fc137b..65ad9fe 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownGrammar.java
@@ -49,8 +49,9 @@
  * </pre>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class GracefulShutdownGrammar extends AbstractGrammar implements IGrammar
+public class GracefulShutdownGrammar extends AbstractGrammar
 {
     /** The logger */
     static final Logger log = LoggerFactory.getLogger( GracefulShutdownGrammar.class );
@@ -82,7 +83,9 @@
          * Creates the GracefulShutdown object
          */
         super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] = 
-            new GrammarTransition( IStates.INIT_GRAMMAR_STATE, GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE, UniversalTag.SEQUENCE_TAG,
+            new GrammarTransition( IStates.INIT_GRAMMAR_STATE, 
+                GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE, 
+                UniversalTag.SEQUENCE_TAG,
                 new GrammarAction( "Init GracefulShutdown" )
             {
                 public void action( IAsn1Container container )
@@ -191,7 +194,8 @@
          * Set the delay value into the GracefulShutdown
          * object.
          */
-        super.transitions[GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE][GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] = 
+        super.transitions[GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE]
+                         [GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG] = 
             new GrammarTransition( GracefulShutdownStatesEnum.GRACEFUL_SHUTDOWN_SEQUENCE_STATE, 
                                     GracefulShutdownStatesEnum.DELAY_STATE, 
                                     GracefulActionConstants.GRACEFUL_ACTION_DELAY_TAG, 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownStatesEnum.java
index 6cd40fd..32cd1c6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/GracefulShutdownStatesEnum.java
@@ -29,6 +29,7 @@
  * for debugging purposes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class GracefulShutdownStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedure.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedure.java
index a2b3645..f0c4cc3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedure.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedure.java
@@ -24,7 +24,6 @@
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -40,6 +39,7 @@
  * Stored Procedure Extended Operation bean
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoredProcedure extends AbstractAsn1Object
 {
@@ -80,13 +80,26 @@
 
     public byte[] getProcedure()
     {
-        return procedure;
+        if ( procedure == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ procedure.length ];
+        System.arraycopy( procedure, 0, copy, 0, procedure.length );
+        return copy;
     }
 
 
     public void setProcedure( byte[] procedure )
     {
-        this.procedure = procedure;
+        if ( procedure != null )
+        {
+            this.procedure = new byte[ procedure.length ];
+            System.arraycopy( procedure, 0, this.procedure, 0, procedure.length );
+        } else {
+            this.procedure = null;
+        }
     }
 
 
@@ -126,25 +139,51 @@
 
         public byte[] getType()
         {
-            return type;
+            if ( type == null )
+            {
+                return null;
+            }
+
+            final byte[] copy = new byte[ type.length ];
+            System.arraycopy( type, 0, copy, 0, type.length );
+            return copy;
         }
 
 
         public void setType( byte[] type )
         {
-            this.type = type;
+            if ( type != null )
+            {
+                this.type = new byte[ type.length ];
+                System.arraycopy( type, 0, this.type, 0, type.length );
+            } else {
+                this.type = null;
+            }
         }
 
 
         public byte[] getValue()
         {
-            return value;
+            if ( value == null )
+            {
+                return null;
+            }
+
+            final byte[] copy = new byte[ value.length ];
+            System.arraycopy( value, 0, copy, 0, value.length );
+            return copy;
         }
 
 
         public void setValue( byte[] value )
         {
-            this.value = value;
+            if ( value != null )
+            {
+                this.value = new byte[ value.length ];
+                System.arraycopy( value, 0, this.value, 0, value.length );
+            } else {
+                this.value = null;
+            }
         }
     }
 
@@ -177,49 +216,45 @@
     public int computeLength()
     {
         // The language
-    	byte[] languageBytes = StringTools.getBytesUtf8( language );
-    	
+        byte[] languageBytes = StringTools.getBytesUtf8( language );
+        
         int languageLength = 1 + TLV.getNbBytes( languageBytes.length )
             + languageBytes.length;
-    	
+        
         // The procedure
         int procedureLength = 1 + TLV.getNbBytes( procedure.length )
             + procedure.length;
-    	
-    	// Compute parameters length value
-    	if ( parameters != null )
-    	{
+        
+        // Compute parameters length value
+        if ( parameters != null )
+        {
             parameterLength = new LinkedList<Integer>();
             paramTypeLength = new LinkedList<Integer>();
             paramValueLength = new LinkedList<Integer>();
             
-    		Iterator params = parameters.iterator();
-    		
-    		while ( params.hasNext() )
-    		{
-    			int localParameterLength = 0;
-    			int localParamTypeLength = 0;
-    			int localParamValueLength = 0;
-    			
-    			StoredProcedureParameter spParam = (StoredProcedureParameter)params.next();
-    			
-    			localParamTypeLength = 1 + TLV.getNbBytes( spParam.type.length ) + spParam.type.length;
-    			localParamValueLength = 1 + TLV.getNbBytes( spParam.value.length ) + spParam.value.length;
-    			
-    			localParameterLength = localParamTypeLength + localParamValueLength;
-    			
-    			parametersLength += 1 + TLV.getNbBytes( localParameterLength ) + localParameterLength;
-    			
-    			parameterLength.add( localParameterLength );
-    			paramTypeLength.add( localParamTypeLength );
-    			paramValueLength.add( localParamValueLength );
-    		}
-    	}
-    	
-    	int localParametersLength = 1 + TLV.getNbBytes( parametersLength ) + parametersLength; 
-    	storedProcedureLength = languageLength + procedureLength + localParametersLength;
+            for ( StoredProcedureParameter spParam:parameters )
+            {
+                int localParameterLength = 0;
+                int localParamTypeLength = 0;
+                int localParamValueLength = 0;
+                
+                localParamTypeLength = 1 + TLV.getNbBytes( spParam.type.length ) + spParam.type.length;
+                localParamValueLength = 1 + TLV.getNbBytes( spParam.value.length ) + spParam.value.length;
+                
+                localParameterLength = localParamTypeLength + localParamValueLength;
+                
+                parametersLength += 1 + TLV.getNbBytes( localParameterLength ) + localParameterLength;
+                
+                parameterLength.add( localParameterLength );
+                paramTypeLength.add( localParamTypeLength );
+                paramValueLength.add( localParamValueLength );
+            }
+        }
+        
+        int localParametersLength = 1 + TLV.getNbBytes( parametersLength ) + parametersLength; 
+        storedProcedureLength = languageLength + procedureLength + localParametersLength;
 
-    	return 1 + TLV.getNbBytes( storedProcedureLength ) + storedProcedureLength; 
+        return 1 + TLV.getNbBytes( storedProcedureLength ) + storedProcedureLength; 
     }
 
     /**
@@ -252,13 +287,10 @@
             // The parameters list
             if ( ( parameters != null ) && ( parameters.size() != 0 ) )
             {
-            	int parameterNumber = 0;
-        		Iterator params = parameters.iterator();
-        		
-        		while ( params.hasNext() )
-        		{
-        			StoredProcedureParameter spParam = (StoredProcedureParameter)params.next();
+                int parameterNumber = 0;
 
+                for ( StoredProcedureParameter spParam:parameters )
+                {
                     // The parameter sequence
                     bb.put( UniversalTag.SEQUENCE_TAG );
                     int localParameterLength = parameterLength.get( parameterNumber );
@@ -306,18 +338,15 @@
         {
             sb.append( "        Parameters\n" );
 
-            Iterator params = parameters.iterator();
             int i = 1;
-    		
-    		while ( params.hasNext() )
-    		{
-    			StoredProcedureParameter spParam = (StoredProcedureParameter)params.next();
-    			
-    			sb.append( "            type[" ).append( i ) .append( "] : '" ).
+            
+            for ( StoredProcedureParameter spParam:parameters )
+            {
+                sb.append( "            type[" ).append( i ) .append( "] : '" ).
                     append( StringTools.utf8ToString( spParam.type ) ).append( "'\n" );
-    			sb.append( "            value[" ).append( i ) .append( "] : '" ).
-    				append( StringTools.dumpBytes( spParam.value ) ).append( "'\n" );
-    		}
+                sb.append( "            value[" ).append( i ) .append( "] : '" ).
+                    append( StringTools.dumpBytes( spParam.value ) ).append( "'\n" );
+            }
         }
 
         return sb.toString();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureContainer.java
index a6d50c1..5a01184 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureContainer.java
@@ -22,15 +22,15 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * A container for the StoredProcedure codec
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class StoredProcedureContainer extends AbstractContainer implements IAsn1Container
+public class StoredProcedureContainer extends AbstractContainer
 {
     // ~ Instance fields
     // ----------------------------------------------------------------------------
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureDecoder.java
index 7f17f7d..d1f2a36 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureDecoder.java
@@ -28,6 +28,7 @@
  * StoredProcedure Decoder
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoredProcedureDecoder extends Asn1Decoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureGrammar.java
index c2679bf..af12648 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureGrammar.java
@@ -29,8 +29,8 @@
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.codec.extended.operations.StoredProcedure.StoredProcedureParameter;
+import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,8 +39,9 @@
  * ASN.1 BER Grammar for Stored Procedure Extended Operation
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class StoredProcedureGrammar extends AbstractGrammar implements IGrammar
+public class StoredProcedureGrammar extends AbstractGrammar
 {
     //~ Static fields/initializers -----------------------------------------------------------------
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureStatesEnum.java
index 344ffa1..b5d45ca 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/extended/operations/StoredProcedureStatesEnum.java
@@ -29,6 +29,7 @@
  * Constants for StoredProcedureGrammar
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class StoredProcedureStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyRequest.java
index a3931c3..9a6e2a4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyRequest.java
@@ -20,6 +20,17 @@
 package org.apache.directory.shared.ldap.codec.modify;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.DirContext;
+
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
@@ -33,18 +44,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.DirContext;
-
 
 /**
  * A ModifyRequest Message. 
@@ -71,6 +70,7 @@
  * AttributeValue ::= OCTET STRING
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ModifyRequest extends LdapMessage
 {
@@ -319,19 +319,16 @@
 
         if ( ( modifications != null ) && ( modifications.size() != 0 ) )
         {
-            Iterator modificationsIterator = modifications.iterator();
             modificationSequenceLength = new LinkedList<Integer>();
             modificationLength = new LinkedList<Integer>();
             valuesLength = new LinkedList<Integer>();
 
-            while ( modificationsIterator.hasNext() )
+            for ( ModificationItemImpl modification:modifications )
             {
                 // Modification sequence length initialized with the operation
                 int localModificationSequenceLength = 1 + 1 + 1;
                 int localValuesLength = 0;
 
-                ModificationItemImpl modification = ( ModificationItemImpl ) modificationsIterator.next();
-
                 // Modification length initialized with the type
                 int typeLength = modification.getAttribute().getID().length();
                 int localModificationLength = 1 + TLV.getNbBytes( typeLength ) + typeLength;
@@ -339,7 +336,7 @@
                 try
                 {
 
-                    NamingEnumeration values = modification.getAttribute().getAll();
+                    NamingEnumeration<?> values = modification.getAttribute().getAll();
 
                     // Get all the values
                     if ( values.hasMoreElements() )
@@ -442,14 +439,11 @@
             // The modifications list
             if ( ( modifications != null ) && ( modifications.size() != 0 ) )
             {
-                Iterator modificationIterator = modifications.iterator();
                 int modificationNumber = 0;
 
                 // Compute the modifications length
-                while ( modificationIterator.hasNext() )
+                for ( ModificationItemImpl modification:modifications )
                 {
-                    ModificationItemImpl modification = ( ModificationItemImpl ) modificationIterator.next();
-
                     // The modification sequence
                     buffer.put( UniversalTag.SEQUENCE_TAG );
                     int localModificationSequenceLength = modificationSequenceLength
@@ -492,7 +486,7 @@
 
                     try
                     {
-                        NamingEnumeration values = modification.getAttribute().getAll();
+                        NamingEnumeration<?> values = modification.getAttribute().getAll();
 
                         if ( values.hasMoreElements() )
                         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyResponse.java
index 3dd5a32..057c555 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modify/ModifyResponse.java
@@ -35,6 +35,7 @@
  * ModifyResponse ::= [APPLICATION 7] LDAPResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ModifyResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNRequest.java
index 159974d..525b3e6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNRequest.java
@@ -42,6 +42,7 @@
  *                 newSuperior     [0] LDAPDN OPTIONAL }
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ModifyDNRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNResponse.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNResponse.java
index 0fc0898..194dc54 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNResponse.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/modifyDn/ModifyDNResponse.java
@@ -35,6 +35,7 @@
  * ModifyDNResponse ::= [APPLICATION 13] LDAPResult
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ModifyDNResponse extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AndFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AndFilter.java
index 155375a..f0ed485 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AndFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AndFilter.java
@@ -33,6 +33,7 @@
  * And Filter Object to store the And filter.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AndFilter extends ConnectorFilter
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AttributeValueAssertionFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AttributeValueAssertionFilter.java
index 02a6a45..4bd6b9d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AttributeValueAssertionFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/AttributeValueAssertionFilter.java
@@ -28,6 +28,8 @@
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.ldap.codec.AttributeValueAssertion;
 import org.apache.directory.shared.ldap.codec.LdapConstants;
+import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 import org.apache.directory.shared.ldap.util.StringTools;
 
 
@@ -35,6 +37,7 @@
  * Object to store the filter. A filter is seen as a tree with a root.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class AttributeValueAssertionFilter extends Filter
 {
@@ -152,17 +155,17 @@
 
         avaLength = 1 + TLV.getNbBytes( attributeDescLength ) + attributeDescLength;
 
-        Object assertionValue = assertion.getAssertionValue();
+        org.apache.directory.shared.ldap.entry.Value<?> assertionValue = assertion.getAssertionValue();
 
         int assertionValueLength = 0;
 
-        if ( assertionValue instanceof String )
+        if ( assertionValue instanceof ClientStringValue )
         {
-            assertionValueLength = StringTools.getBytesUtf8( ( String ) assertionValue ).length;
+            assertionValueLength = StringTools.getBytesUtf8( ((ClientStringValue)assertionValue).get() ).length;
         }
         else
         {
-            assertionValueLength = ( ( byte[] ) assertionValue ).length;
+            assertionValueLength = ((ClientBinaryValue)assertionValue).get().length;
         }
 
         avaLength += 1 + TLV.getNbBytes( assertionValueLength ) + assertionValueLength;
@@ -228,13 +231,13 @@
         Value.encode( buffer, assertion.getAttributeDesc() );
 
         // The assertion desc
-        if ( assertion.getAssertionValue() instanceof String )
+        if ( assertion.getAssertionValue().get() instanceof String )
         {
-            Value.encode( buffer, ( String ) assertion.getAssertionValue() );
+            Value.encode( buffer, ( String ) assertion.getAssertionValue().get() );
         }
         else
         {
-            Value.encode( buffer, ( byte[] ) assertion.getAssertionValue() );
+            Value.encode( buffer, ( byte[] ) assertion.getAssertionValue().get() );
         }
 
         return buffer;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ConnectorFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ConnectorFilter.java
index b1eee5f..ba9e704 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ConnectorFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ConnectorFilter.java
@@ -20,20 +20,20 @@
 package org.apache.directory.shared.ldap.codec.search;
 
 
-import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.asn1.codec.EncoderException;
-
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
+import org.apache.directory.shared.asn1.codec.DecoderException;
+import org.apache.directory.shared.asn1.codec.EncoderException;
+
 
 /**
  * This Filter abstract class is used to store a set of filters used by
  * OR/AND/NOT filters.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public abstract class ConnectorFilter extends Filter
 {
@@ -109,12 +109,8 @@
 
         if ( ( filterSet != null ) && ( filterSet.size() != 0 ) )
         {
-            Iterator filterIterator = filterSet.iterator();
-
-            while ( filterIterator.hasNext() )
+            for ( Filter filter:filterSet )
             {
-                Filter filter = ( Filter ) filterIterator.next();
-
                 connectorFilterLength += filter.computeLength();
             }
         }
@@ -142,12 +138,8 @@
         // encode each filter
         if ( ( filterSet != null ) && ( filterSet.size() != 0 ) )
         {
-            Iterator filterIterator = filterSet.iterator();
-
-            while ( filterIterator.hasNext() )
+            for ( Filter filter:filterSet )
             {
-                Filter filter = ( Filter ) filterIterator.next();
-
                 filter.encode( buffer );
             }
         }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ExtensibleMatchFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ExtensibleMatchFilter.java
index 23f2679..a178caf 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ExtensibleMatchFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/ExtensibleMatchFilter.java
@@ -34,6 +34,7 @@
  * The search request filter Matching Rule assertion
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class ExtensibleMatchFilter extends Filter
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/Filter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/Filter.java
index c6a9af2..11b8bcc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/Filter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/Filter.java
@@ -29,6 +29,7 @@
  * filters.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public abstract class Filter extends AbstractAsn1Object
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/NotFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/NotFilter.java
index 0deb96a..7ce8e9b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/NotFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/NotFilter.java
@@ -33,6 +33,7 @@
  * Not Filter Object to store the Not filter.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class NotFilter extends ConnectorFilter
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/OrFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/OrFilter.java
index 43480d8..b7e6122 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/OrFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/OrFilter.java
@@ -33,6 +33,7 @@
  * Or Filter Object to store the Or filter.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class OrFilter extends ConnectorFilter
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/PresentFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/PresentFilter.java
index 83975ca..113df1c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/PresentFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/PresentFilter.java
@@ -33,6 +33,7 @@
  * Object to store the filter. A filter is seen as a tree with a root.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class PresentFilter extends Filter
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchRequest.java
index 9079a10..09b9a54 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchRequest.java
@@ -20,6 +20,14 @@
 package org.apache.directory.shared.ldap.codec.search;
 
 
+import java.io.UnsupportedEncodingException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
 import org.apache.directory.shared.asn1.Asn1Object;
 import org.apache.directory.shared.asn1.ber.IAsn1Container;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -35,20 +43,13 @@
 import org.apache.directory.shared.ldap.message.ScopeEnum;
 import org.apache.directory.shared.ldap.name.LdapDN;
 
-import java.io.UnsupportedEncodingException;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-
 
 /**
  * A SearchRequest ldapObject. It's a sub-class of Asn1Object, and it implements
  * the ldapObject class to be seen as a member of the LdapMessage CHOICE.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SearchRequest extends LdapMessage
 {
@@ -492,12 +493,12 @@
 
         if ( ( attributes != null ) && ( attributes.size() != 0 ) )
         {
-            NamingEnumeration attributeIterator = attributes.getAll();
+            NamingEnumeration<? extends Attribute> attributeIterator = attributes.getAll();
 
             // Compute the attributes length
             while ( attributeIterator.hasMoreElements() )
             {
-                Attribute attribute = ( AttributeImpl ) attributeIterator.nextElement();
+                Attribute attribute = attributeIterator.nextElement();
 
                 // add the attribute length to the attributes length
                 try
@@ -586,7 +587,7 @@
 
             if ( ( attributes != null ) && ( attributes.size() != 0 ) )
             {
-                NamingEnumeration attributeIterator = attributes.getAll();
+                NamingEnumeration<? extends Attribute> attributeIterator = attributes.getAll();
 
                 // encode each attribute
                 while ( attributeIterator.hasMoreElements() )
@@ -633,14 +634,14 @@
 
         if ( attributes != null )
         {
-            NamingEnumeration attrs = attributes.getAll();
+            NamingEnumeration<? extends Attribute> attrs = attributes.getAll();
             boolean isFirst = true;
     
             if ( attrs != null )
             {
                 while ( attrs.hasMoreElements() )
                 {
-                    Attribute attr = ( AttributeImpl ) attrs.nextElement();
+                    Attribute attr = attrs.nextElement();
         
                     if ( isFirst )
                     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultDone.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultDone.java
index cdd5857..da41737 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultDone.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultDone.java
@@ -37,6 +37,7 @@
  * LDAPResult It's a Response, so it inherites from LdapResponse.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SearchResultDone extends LdapResponse
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultEntry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultEntry.java
index 4aa7efc..437e33e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultEntry.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultEntry.java
@@ -20,6 +20,16 @@
 package org.apache.directory.shared.ldap.codec.search;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
@@ -33,16 +43,6 @@
 import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.apache.directory.shared.ldap.util.StringTools;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-
 
 /**
  * A SearchResultEntry Message. Its syntax is :
@@ -63,6 +63,7 @@
  * by one, followed by a searchResultDone message.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SearchResultEntry extends LdapMessage
 {
@@ -228,8 +229,8 @@
      */
     public int computeLength()
     {
-    	objectNameBytes = StringTools.getBytesUtf8( objectName.getUpName() );
-    	
+        objectNameBytes = StringTools.getBytesUtf8( objectName.getUpName() );
+        
         // The entry
         searchResultEntryLength = 1 + TLV.getNbBytes( objectNameBytes.length ) + objectNameBytes.length;
 
@@ -238,7 +239,7 @@
 
         if ( ( partialAttributeList != null ) && ( partialAttributeList.size() != 0 ) )
         {
-            NamingEnumeration attributes = partialAttributeList.getAll();
+            NamingEnumeration<? extends Attribute> attributes = partialAttributeList.getAll();
             attributeLength = new LinkedList<Integer>();
             valsLength = new LinkedList<Integer>();
 
@@ -259,7 +260,7 @@
                     // The values
                     try
                     {
-                        NamingEnumeration values = attribute.getAll();
+                        NamingEnumeration<?> values = attribute.getAll();
 
                         if ( values.hasMoreElements() )
                         {
@@ -372,7 +373,7 @@
             // The partial attribute list
             if ( ( partialAttributeList != null ) && ( partialAttributeList.size() != 0 ) )
             {
-                NamingEnumeration attributes = partialAttributeList.getAll();
+                NamingEnumeration<? extends Attribute> attributes = partialAttributeList.getAll();
                 int attributeNumber = 0;
 
                 // Compute the attributes length
@@ -397,7 +398,7 @@
                     {
                         try
                         {
-                            NamingEnumeration values = attribute.getAll();
+                            NamingEnumeration<?> values = attribute.getAll();
 
                             if ( values.hasMoreElements() )
                             {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultReference.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultReference.java
index b80843e..0742cc0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultReference.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SearchResultReference.java
@@ -20,6 +20,11 @@
 package org.apache.directory.shared.ldap.codec.search;
 
 
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
 import org.apache.directory.shared.asn1.codec.EncoderException;
@@ -27,12 +32,6 @@
 import org.apache.directory.shared.ldap.codec.LdapMessage;
 import org.apache.directory.shared.ldap.codec.util.LdapURL;
 
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 
 /**
  * A SearchResultReference Message. Its syntax is : 
@@ -40,6 +39,7 @@
  * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SearchResultReference extends LdapMessage
 {
@@ -123,12 +123,10 @@
     {
         searchResultReferenceLength = 0;
 
-        Iterator referencesIterator = searchResultReferences.iterator();
-
         // We may have more than one reference.
-        while ( referencesIterator.hasNext() )
+        for ( LdapURL url:searchResultReferences )
         {
-            int ldapUrlLength = ( ( LdapURL ) referencesIterator.next() ).getNbBytes();
+            int ldapUrlLength = url.getNbBytes();
             searchResultReferenceLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
         }
 
@@ -162,13 +160,8 @@
             buffer.put( TLV.getBytes( searchResultReferenceLength ) );
 
             // The references. We must at least have one reference
-            Iterator referencesIterator = searchResultReferences.iterator();
-
-            // We may have more than one reference.
-            while ( referencesIterator.hasNext() )
+            for ( LdapURL reference:searchResultReferences )
             {
-                LdapURL reference = ( ( LdapURL ) referencesIterator.next() );
-
                 // Encode the reference
                 Value.encode( buffer, reference.getString() );
             }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SubstringFilter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SubstringFilter.java
index f33a119..bb2e782 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SubstringFilter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/SubstringFilter.java
@@ -23,7 +23,6 @@
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
@@ -49,6 +48,7 @@
  * final = value
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SubstringFilter extends Filter
 {
@@ -247,11 +247,8 @@
 
         if ( anySubstrings != null )
         {
-            Iterator anyIterator = anySubstrings.iterator();
-
-            while ( anyIterator.hasNext() )
+            for ( String any:anySubstrings )
             {
-                String any = ( String ) anyIterator.next();
                 int anyLength = StringTools.getBytesUtf8( any ).length; 
                 substringsFilterSequenceLength += 1 + TLV.getNbBytes( anyLength ) + anyLength;
             }
@@ -329,11 +326,8 @@
             // The any substrings
             if ( anySubstrings != null )
             {
-                Iterator anyIterator = anySubstrings.iterator();
-
-                while ( anyIterator.hasNext() )
+                for ( String any:anySubstrings )
                 {
-                    String any = ( String ) anyIterator.next();
                     byte[] anyBytes = StringTools.getBytesUtf8( any );
                     buffer.put( ( byte ) LdapConstants.SUBSTRINGS_FILTER_ANY_TAG );
                     buffer.put( TLV.getBytes( anyBytes.length ) );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlCodec.java
similarity index 97%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControl.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlCodec.java
index 31a5249..f1dbb0d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlCodec.java
@@ -77,8 +77,9 @@
  * </pre>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class EntryChangeControl extends AbstractAsn1Object
+public class EntryChangeControlCodec extends AbstractAsn1Object
 {
     public static final int UNDEFINED_CHANGE_NUMBER = -1;
 
@@ -99,7 +100,7 @@
     /**
      * @see Asn1Object#Asn1Object
      */
-    public EntryChangeControl()
+    public EntryChangeControlCodec()
     {
         super();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlContainer.java
index e4adfcd..0642b18 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlContainer.java
@@ -21,16 +21,16 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class EntryChangeControlContainer extends AbstractContainer implements IAsn1Container
+public class EntryChangeControlContainer extends AbstractContainer
 {
     /** EntryChangeControl */
-    private EntryChangeControl control;
+    private EntryChangeControlCodec control;
 
 
     /**
@@ -49,7 +49,7 @@
     /**
      * @return Returns the EntryChangeControl.
      */
-    public EntryChangeControl getEntryChangeControl()
+    public EntryChangeControlCodec getEntryChangeControl()
     {
         return control;
     }
@@ -61,7 +61,7 @@
      * 
      * @param control the EntryChangeControl to set.
      */
-    public void setEntryChangeControl( EntryChangeControl control )
+    public void setEntryChangeControl( EntryChangeControlCodec control )
     {
         this.control = control;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlDecoder.java
index 500f746..4d64963 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlDecoder.java
@@ -32,6 +32,7 @@
  * A decoder for EntryChangeControls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class EntryChangeControlDecoder extends Asn1Decoder implements ControlDecoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlGrammar.java
index d6c8e64..8201e25 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlGrammar.java
@@ -43,8 +43,9 @@
  * this class. As it is a singleton, these declaration are only done once.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class EntryChangeControlGrammar extends AbstractGrammar implements IGrammar
+public class EntryChangeControlGrammar extends AbstractGrammar
 {
     /** The logger */
     static final Logger log = LoggerFactory.getLogger( EntryChangeControlGrammar.class );
@@ -83,7 +84,7 @@
                 public void action( IAsn1Container container )
                 {
                     EntryChangeControlContainer entryChangeContainer = ( EntryChangeControlContainer ) container;
-                    EntryChangeControl control = new EntryChangeControl();
+                    EntryChangeControlCodec control = new EntryChangeControlCodec();
                     entryChangeContainer.setEntryChangeControl( control );
                 }
             } );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlStatesEnum.java
index b5b89da..0358323 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlStatesEnum.java
@@ -29,6 +29,7 @@
  * for debugging purposes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class EntryChangeControlStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlCodec.java
similarity index 97%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControl.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlCodec.java
index db530a7..bdf3bce 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlCodec.java
@@ -33,8 +33,9 @@
  * A persistence search object
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class PSearchControl extends AbstractAsn1Object
+public class PSearchControlCodec extends AbstractAsn1Object
 {
     /**
      * If changesOnly is TRUE, the server MUST NOT return any existing entries
@@ -78,7 +79,7 @@
      * Default constructor
      *
      */
-    public PSearchControl()
+    public PSearchControlCodec()
     {
         super();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlContainer.java
index e28ef64..bfb1675 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlContainer.java
@@ -21,16 +21,16 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class PSearchControlContainer extends AbstractContainer implements IAsn1Container
+public class PSearchControlContainer extends AbstractContainer
 {
     /** PSearchControl */
-    private PSearchControl control;
+    private PSearchControlCodec control;
 
 
     /**
@@ -49,7 +49,7 @@
     /**
      * @return Returns the persistent search control.
      */
-    public PSearchControl getPSearchControl()
+    public PSearchControlCodec getPSearchControl()
     {
 
         return control;
@@ -62,7 +62,7 @@
      * 
      * @param control the PSearchControl to set.
      */
-    public void setPSearchControl( PSearchControl control )
+    public void setPSearchControl( PSearchControlCodec control )
     {
         this.control = control;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlDecoder.java
index 974208d..7cce351 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlDecoder.java
@@ -32,6 +32,7 @@
  * A decoder for PSearchControls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class PSearchControlDecoder extends Asn1Decoder implements ControlDecoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlGrammar.java
index 0c1ea23..f1dd8bd 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlGrammar.java
@@ -56,8 +56,9 @@
  * modDN  (8).
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class PSearchControlGrammar extends AbstractGrammar implements IGrammar
+public class PSearchControlGrammar extends AbstractGrammar
 {
     /** The logger */
     static final Logger log = LoggerFactory.getLogger( PSearchControlGrammar.class );
@@ -96,7 +97,7 @@
                 public void action( IAsn1Container container )
                 {
                     PSearchControlContainer psearchContainer = ( PSearchControlContainer ) container;
-                    PSearchControl control = new PSearchControl();
+                    PSearchControlCodec control = new PSearchControlCodec();
                     psearchContainer.setPSearchControl( control );
                 }
             } );
@@ -111,7 +112,9 @@
          * Stores the change types value
          */
         super.transitions[PSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE][UniversalTag.INTEGER_TAG] = 
-            new GrammarTransition( PSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE, PSearchControlStatesEnum.CHANGE_TYPES_STATE, UniversalTag.INTEGER_TAG,
+            new GrammarTransition( PSearchControlStatesEnum.PSEARCH_SEQUENCE_STATE, 
+                PSearchControlStatesEnum.CHANGE_TYPES_STATE, 
+                UniversalTag.INTEGER_TAG,
                 new GrammarAction( "Set PSearchControl changeTypes" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
@@ -122,7 +125,9 @@
                     try
                     {
                         // Check that the value is into the allowed interval
-                        int changeTypes = IntegerDecoder.parse( value, PSearchControl.CHANGE_TYPES_MIN, PSearchControl.CHANGE_TYPES_MAX );
+                        int changeTypes = IntegerDecoder.parse( value, 
+                            PSearchControlCodec.CHANGE_TYPES_MIN, 
+                            PSearchControlCodec.CHANGE_TYPES_MAX );
                         
                         if ( IS_DEBUG )
                         {
@@ -150,7 +155,8 @@
          * Stores the change only flag
          */
         super.transitions[PSearchControlStatesEnum.CHANGE_TYPES_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( PSearchControlStatesEnum.CHANGE_TYPES_STATE, PSearchControlStatesEnum.CHANGES_ONLY_STATE, UniversalTag.BOOLEAN_TAG,
+            new GrammarTransition( PSearchControlStatesEnum.CHANGE_TYPES_STATE,
+                                    PSearchControlStatesEnum.CHANGES_ONLY_STATE, UniversalTag.BOOLEAN_TAG,
                 new GrammarAction( "Set PSearchControl changesOnly" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
@@ -188,7 +194,8 @@
          * Stores the return ECs flag 
          */
         super.transitions[PSearchControlStatesEnum.CHANGES_ONLY_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( PSearchControlStatesEnum.CHANGES_ONLY_STATE, PSearchControlStatesEnum.RETURN_ECS_STATE, UniversalTag.BOOLEAN_TAG,
+            new GrammarTransition( PSearchControlStatesEnum.CHANGES_ONLY_STATE, 
+                                    PSearchControlStatesEnum.RETURN_ECS_STATE, UniversalTag.BOOLEAN_TAG,
                 new GrammarAction( "Set PSearchControl returnECs" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlStatesEnum.java
index a03f370..67bd457 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlStatesEnum.java
@@ -29,6 +29,7 @@
  * debugging purposes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class PSearchControlStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlCodec.java
similarity index 96%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControl.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlCodec.java
index 27dacc7..7b61441 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlCodec.java
@@ -33,7 +33,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class SubEntryControl extends AbstractAsn1Object
+public class SubEntryControlCodec extends AbstractAsn1Object
 {
     private boolean visibility = false;
 
@@ -41,7 +41,7 @@
      * Default constructor
      *
      */
-    public SubEntryControl()
+    public SubEntryControlCodec()
     {
         super();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlContainer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlContainer.java
index 72e48c2..141bca9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlContainer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlContainer.java
@@ -21,16 +21,16 @@
 
 
 import org.apache.directory.shared.asn1.ber.AbstractContainer;
-import org.apache.directory.shared.asn1.ber.IAsn1Container;
 
 
 /**
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class SubEntryControlContainer extends AbstractContainer implements IAsn1Container
+public class SubEntryControlContainer extends AbstractContainer
 {
     /** PSearchControl */
-    private SubEntryControl control;
+    private SubEntryControlCodec control;
 
 
     /**
@@ -48,7 +48,7 @@
     /**
      * @return Returns the persistent search control.
      */
-    public SubEntryControl getSubEntryControl()
+    public SubEntryControlCodec getSubEntryControl()
     {
         return control;
     }
@@ -60,7 +60,7 @@
      * 
      * @param control the SubEntryControl to set.
      */
-    public void setSubEntryControl( SubEntryControl control )
+    public void setSubEntryControl( SubEntryControlCodec control )
     {
         this.control = control;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlDecoder.java
index 99b96f2..346ef09 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlDecoder.java
@@ -32,6 +32,7 @@
  * A decoder for SubEntryControls.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SubEntryControlDecoder extends Asn1Decoder implements ControlDecoder
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlGrammar.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlGrammar.java
index 3d84bb7..604d9b7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlGrammar.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlGrammar.java
@@ -41,8 +41,9 @@
  * this class. As it is a singleton, these declaration are only done once.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class SubEntryControlGrammar extends AbstractGrammar implements IGrammar
+public class SubEntryControlGrammar extends AbstractGrammar
 {
     /** The logger */
     static final Logger log = LoggerFactory.getLogger( SubEntryControlGrammar.class );
@@ -63,13 +64,14 @@
         super.transitions = new GrammarTransition[SubEntryControlStatesEnum.LAST_SUB_ENTRY_STATE][256];
 
         super.transitions[SubEntryControlStatesEnum.START_STATE][UniversalTag.BOOLEAN_TAG] = 
-            new GrammarTransition( SubEntryControlStatesEnum.START_STATE, SubEntryControlStatesEnum.SUB_ENTRY_VISIBILITY_STATE, UniversalTag.BOOLEAN_TAG, 
+            new GrammarTransition( SubEntryControlStatesEnum.START_STATE, 
+                                    SubEntryControlStatesEnum.SUB_ENTRY_VISIBILITY_STATE, UniversalTag.BOOLEAN_TAG, 
                 new GrammarAction( "SubEntryControl visibility" )
             {
                 public void action( IAsn1Container container ) throws DecoderException
                 {
                     SubEntryControlContainer subEntryContainer = ( SubEntryControlContainer ) container;
-                    SubEntryControl control = new SubEntryControl();
+                    SubEntryControlCodec control = new SubEntryControlCodec();
                     subEntryContainer.setSubEntryControl( control );
 
                     TLV tlv = subEntryContainer.getCurrentTLV();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlStatesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlStatesEnum.java
index 7059368..99a6e6a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlStatesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlStatesEnum.java
@@ -29,6 +29,7 @@
  * debugging purposes.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class SubEntryControlStatesEnum implements IStates
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/unbind/UnBindRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/unbind/UnBindRequest.java
index 78ad342..e0a2ddb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/unbind/UnBindRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/unbind/UnBindRequest.java
@@ -37,6 +37,7 @@
  * This ldapObject is empty.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class UnBindRequest extends LdapMessage
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/HttpClientError.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/HttpClientError.java
index 402927b..659c029 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/HttpClientError.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/HttpClientError.java
@@ -31,7 +31,7 @@
  */
 public class HttpClientError extends Error
 {
-    final static long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapResultEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapResultEnum.java
index e09df77..f752990 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapResultEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapResultEnum.java
@@ -24,6 +24,7 @@
  * This typesafe-enum represent the different resultCode of a LdapResult.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapResultEnum
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURL.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURL.java
index 0b809b5..04707e8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURL.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURL.java
@@ -20,11 +20,6 @@
 package org.apache.directory.shared.ldap.codec.util;
 
 
-import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.ldap.filter.FilterParser;
-import org.apache.directory.shared.ldap.name.LdapDN;
-import org.apache.directory.shared.ldap.util.StringTools;
-
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
 
@@ -40,6 +35,10 @@
 import javax.naming.InvalidNameException;
 import javax.naming.directory.SearchControls;
 
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.StringTools;
+
 
 /**
  * Decodes a LdapUrl, and checks that it complies with
@@ -62,12 +61,20 @@
  * xtoken     = ("X-" / "x-") token
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapURL
 {
+
     // ~ Static fields/initializers
     // -----------------------------------------------------------------
 
+    /** The constant for "ldaps://" scheme. */
+    public static final String LDAPS_SCHEME = "ldaps://";
+
+    /** The constant for "ldap://" scheme. */
+    public static final String LDAP_SCHEME = "ldap://";
+
     /** A null LdapURL */
     public static final LdapURL EMPTY_URL = new LdapURL();
 
@@ -115,7 +122,7 @@
      */
     public LdapURL()
     {
-        super();
+        scheme = LDAP_SCHEME;
         host = null;
         port = -1;
         dn = null;
@@ -133,6 +140,7 @@
      */
     public void parse( char[] chars ) throws LdapURLEncodingException
     {
+        scheme = LDAP_SCHEME;
         host = null;
         port = -1;
         dn = null;
@@ -156,8 +164,8 @@
         int pos = 0;
 
         // The scheme
-        if ( ( ( pos = StringTools.areEquals( chars, 0, "ldap://" ) ) == StringTools.NOT_EQUAL )
-            && ( ( pos = StringTools.areEquals( chars, 0, "ldaps://" ) ) == StringTools.NOT_EQUAL ) )
+        if ( ( ( pos = StringTools.areEquals( chars, 0, LDAP_SCHEME ) ) == StringTools.NOT_EQUAL )
+            && ( ( pos = StringTools.areEquals( chars, 0, LDAPS_SCHEME ) ) == StringTools.NOT_EQUAL ) )
         {
             throw new LdapURLEncodingException( "A LdapUrl must start with \"ldap://\" or \"ldaps://\"" );
         }
@@ -178,7 +186,7 @@
         }
 
         // An optional '/'
-        if ( StringTools.isCharASCII( chars, pos, '/' ) == false )
+        if ( !StringTools.isCharASCII( chars, pos, '/' ) )
         {
             throw new LdapURLEncodingException( "Bad character, position " + pos + ", '" + chars[pos]
                 + "', '/' expected" );
@@ -203,7 +211,7 @@
         }
 
         // Optionals attributes
-        if ( StringTools.isCharASCII( chars, pos, '?' ) == false )
+        if ( !StringTools.isCharASCII( chars, pos, '?' ) )
         {
             throw new LdapURLEncodingException( "Bad character, position " + pos + ", '" + chars[pos]
                 + "', '?' expected" );
@@ -222,7 +230,7 @@
         }
 
         // Optional scope
-        if ( StringTools.isCharASCII( chars, pos, '?' ) == false )
+        if ( !StringTools.isCharASCII( chars, pos, '?' ) )
         {
             throw new LdapURLEncodingException( "Bad character, position " + pos + ", '" + chars[pos]
                 + "', '?' expected" );
@@ -241,7 +249,7 @@
         }
 
         // Optional filter
-        if ( StringTools.isCharASCII( chars, pos, '?' ) == false )
+        if ( !StringTools.isCharASCII( chars, pos, '?' ) )
         {
             throw new LdapURLEncodingException( "Bad character, position " + pos + ", '" + chars[pos]
                 + "', '?' expected" );
@@ -265,7 +273,7 @@
         }
 
         // Optional extensions
-        if ( StringTools.isCharASCII( chars, pos, '?' ) == false )
+        if ( !StringTools.isCharASCII( chars, pos, '?' ) )
         {
             throw new LdapURLEncodingException( "Bad character, position " + pos + ", '" + chars[pos]
                 + "', '?' expected" );
@@ -329,7 +337,9 @@
         }
 
         string = StringTools.utf8ToString( bytes );
-        this.bytes = bytes;
+
+        this.bytes = new byte[ bytes.length ];
+        System.arraycopy( bytes, 0, this.bytes, 0, bytes.length );
 
         parse( string.toCharArray() );
     }
@@ -515,7 +525,7 @@
     private int parsePort( char[] chars, int pos )
     {
 
-        if ( StringTools.isDigit( chars, pos ) == false )
+        if ( !StringTools.isDigit( chars, pos ) )
         {
             return -1;
         }
@@ -663,13 +673,13 @@
      * 
      * @param bytes array of URL safe characters
      * @return array of original bytes
-     * @throws DecoderException Thrown if URL decoding is unsuccessful
+     * @throws UrlDecoderException Thrown if URL decoding is unsuccessful
      */
     private static final byte[] decodeUrl( byte[] bytes ) throws UrlDecoderException
     {
         if ( bytes == null )
         {
-            return null;
+            return StringTools.EMPTY_BYTES;
         }
 
         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
@@ -814,7 +824,7 @@
 
                         String decodedAttr = decode( attribute );
 
-                        if ( hAttributes.contains( decodedAttr ) == false )
+                        if ( !hAttributes.contains( decodedAttr ) )
                         {
                             attributes.add( decodedAttr );
                             hAttributes.add( decodedAttr );
@@ -861,7 +871,7 @@
 
                 String decodedAttr = decode( attribute );
 
-                if ( hAttributes.contains( decodedAttr ) == false )
+                if ( !hAttributes.contains( decodedAttr ) )
                 {
                     attributes.add( decodedAttr );
                     hAttributes.add( decodedAttr );
@@ -1002,7 +1012,7 @@
      * extensions ::= extension [ ',' extension ]* 
      * extension ::= [ '!' ] ( token | ( 'x-' | 'X-' ) token ) ) [ '=' exvalue ]
      * 
-     * @param char The char array to be checked
+     * @param chars The char array to be checked
      * @param pos the starting position
      * @return -1 if the char array does not contains valid extensions or
      *         critical extensions
@@ -1091,7 +1101,7 @@
                 else if ( StringTools.isCharASCII( chars, i, '!' ) )
                 {
 
-                    if ( isNewExtension == false )
+                    if ( !isNewExtension )
                     {
 
                         // '!' must appears first
@@ -1178,6 +1188,7 @@
 
                 default:
                     sb.append( c );
+                break;
             }
         }
 
@@ -1192,8 +1203,9 @@
      */
     public String toString()
     {
+        StringBuffer sb = new StringBuffer();
 
-        StringBuffer sb = new StringBuffer( "ldap://" );
+        sb.append( scheme );
 
         sb.append( ( host == null ) ? "" : host );
 
@@ -1207,8 +1219,8 @@
             sb.append( '/' ).append( urlEncode( dn.toString(), false ) );
 
             if ( ( attributes.size() != 0 )
-                || ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || ( extensions.size() != 0 ) || ( criticalExtensions
-                    .size() != 0 ) ) )
+                || ( ( scope != SearchControls.OBJECT_SCOPE ) || ( filter != null ) || 
+                    ( extensions.size() != 0 ) || ( criticalExtensions.size() != 0 ) ) )
             {
                 sb.append( '?' );
 
@@ -1249,6 +1261,10 @@
                     case SearchControls.SUBTREE_SCOPE:
                         sb.append( "sub" );
                         break;
+                        
+                        
+                    default :
+                        break;
                 }
 
                 if ( ( filter != null ) || ( ( extensions.size() != 0 ) || ( criticalExtensions.size() != 0 ) ) )
@@ -1271,7 +1287,7 @@
                             for ( String key:extensions.keySet() )
                             {
 
-                                if ( isFirst == false )
+                                if ( !isFirst )
                                 {
                                     sb.append( ',' );
                                 }
@@ -1292,7 +1308,7 @@
                             for ( String key:criticalExtensions.keySet() )
                             {
 
-                                if ( isFirst == false )
+                                if ( !isFirst )
                                 {
                                     sb.append( ",!" );
                                 }
@@ -1383,6 +1399,9 @@
 
 
     /**
+     * Returns the scope, one of {@link SearchControls.OBJECT_SCOPE}, 
+     * {@link SearchControls.ONELEVEL_SCOPE} or {@link SearchControls.SUBTREE_SCOPE}.
+     * 
      * @return Returns the scope.
      */
     public int getScope()
@@ -1408,18 +1427,208 @@
     }
     
     /**
-     * @return the bytes representing this LdapURL
+     * @return a reference on the interned bytes representing this LdapURL
      */
-    public byte[] getBytes()
+    public byte[] getBytesReference()
     {
         return bytes;
     }
     
     /**
+     * @return a copy of the bytes representing this LdapURL
+     */
+    public byte[] getBytesCopy()
+    {
+        if ( bytes != null )
+        {
+            byte[] copy = new byte[bytes.length];
+            System.arraycopy( bytes, 0, copy, 0, bytes.length );
+            return copy;
+        }
+        else
+        {
+            return null;
+        }
+    }
+    
+    /**
      * @return the LdapURL as a String
      */
     public String getString()
     {
         return string;
     }
+
+    /**
+     * Compute the instance's hash code
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        return this.toString().hashCode();
+    }
+
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+        if ( obj == null )
+        {
+            return false;
+        }
+        if ( getClass() != obj.getClass() )
+        {
+            return false;
+        }
+        
+        final LdapURL other = ( LdapURL ) obj;
+        return this.toString().equals( other.toString() );
+    }
+
+    
+    /**
+     * Sets the scheme. Must be "ldap://" or "ldaps://", otherwise "ldap://" is assumed as default.
+     * 
+     * @param scheme the new scheme
+     */
+    public void setScheme( String scheme )
+    {
+        if ( scheme != null && LDAP_SCHEME.equals( scheme ) || LDAPS_SCHEME.equals( scheme ) )
+        {
+            this.scheme = scheme;
+        }
+        else
+        {
+            this.scheme = LDAP_SCHEME;
+        }
+
+    }
+
+
+    /**
+     * Sets the host.
+     * 
+     * @param host the new host
+     */
+    public void setHost( String host )
+    {
+        this.host = host;
+    }
+
+
+    /**
+     * Sets the port. Must be between 1 and 65535, otherwise -1 is assumed as default.
+     * 
+     * @param port the new port
+     */
+    public void setPort( int port )
+    {
+        if ( port < 1 || port > 65535 )
+        {
+            this.port = -1;
+        }
+        else
+        {
+            this.port = port;
+        }
+    }
+
+
+    /**
+     * Sets the dn.
+     * 
+     * @param dn the new dn
+     */
+    public void setDn( LdapDN dn )
+    {
+        this.dn = dn;
+    }
+
+
+    /**
+     * Sets the attributes, null removes all existing attributes.
+     * 
+     * @param attributes the new attributes
+     */
+    public void setAttributes( List<String> attributes )
+    {
+        if ( attributes == null )
+        {
+            this.attributes.clear();
+        }
+        else
+        {
+            this.attributes = attributes;
+        }
+    }
+
+
+    /**
+     * Sets the scope. Must be one of {@link SearchControls.OBJECT_SCOPE}, 
+     * {@link SearchControls.ONELEVEL_SCOPE} or {@link SearchControls.SUBTREE_SCOPE},
+     * otherwise {@link SearchControls.OBJECT_SCOPE} is assumed as default.
+     * 
+     * @param scope the new scope
+     */
+    public void setScope( int scope )
+    {
+        if ( scope == SearchControls.ONELEVEL_SCOPE || scope == SearchControls.SUBTREE_SCOPE )
+        {
+            this.scope = scope;
+        }
+        else
+        {
+            this.scope = SearchControls.OBJECT_SCOPE;
+        }
+    }
+
+
+    /**
+     * Sets the filter.
+     * 
+     * @param filter the new filter
+     */
+    public void setFilter( String filter )
+    {
+        this.filter = filter;
+    }
+
+
+    /**
+     * Sets the extensions, null removes all existing extensions.
+     * 
+     * @param extensions the extensions
+     */
+    public void setExtensions( Map<String, String> extensions )
+    {
+        if ( extensions == null )
+        {
+            this.extensions.clear();
+        }
+        else
+        {
+            this.extensions = extensions;
+        }
+    }
+
+
+    /**
+     * Sets the critical extensions, null removes all existing critical extensions.
+     * 
+     * @param criticalExtensions the critical extensions
+     */
+    public void setCriticalExtensions( Map<String, String> criticalExtensions )
+    {
+        if ( criticalExtensions == null )
+        {
+            this.criticalExtensions.clear();
+        }
+        else
+        {
+            this.criticalExtensions = criticalExtensions;
+        }
+    }
+
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURLEncodingException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURLEncodingException.java
index 6c7337c..beda019 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURLEncodingException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/LdapURLEncodingException.java
@@ -26,6 +26,7 @@
  * during the String creation.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapURLEncodingException extends Exception
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/URIException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/URIException.java
index 4a7cc44..3f5b938 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/URIException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/URIException.java
@@ -29,7 +29,7 @@
  */
 public class URIException extends Exception
 {
-    final static long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
 
     // ----------------------------------------------------------- constructors
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/UrlDecoderException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/UrlDecoderException.java
index 4f25e04..e04ea48 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/UrlDecoderException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/codec/util/UrlDecoderException.java
@@ -29,7 +29,7 @@
  */
 public class UrlDecoderException extends Exception
 {
-    final static long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractEntry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractEntry.java
new file mode 100644
index 0000000..264b03e
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractEntry.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.directory.shared.ldap.name.LdapDN;
+
+
+/**
+ * The Abstract class where all the DefaultClientEntry and DefaultServerEntry 
+ * common fields and methods will be found.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class AbstractEntry<K> implements Entry
+{
+    /** The DN for this entry */
+    protected LdapDN dn;
+    
+    /** A map containing all the attributes for this entry */
+    protected Map<K, EntryAttribute> attributes = new HashMap<K, EntryAttribute>();
+    
+    
+    /**
+     * Get this entry's DN.
+     *
+     * @return The entry's DN
+     */
+    public LdapDN getDn()
+    {
+        return dn;
+    }
+
+
+    /**
+     * Set this entry's DN.
+     *
+     * @param dn The DN associated with this entry
+     */
+    public void setDn( LdapDN dn )
+    {
+        this.dn = dn;
+    }
+    
+    
+    /**
+     * Remove all the attributes for this entry. The DN is not reset
+     */
+    public void clear()
+    {
+        attributes.clear();
+    }
+    
+    
+    /**
+     * Returns an enumeration containing the zero or more attributes in the
+     * collection. The behavior of the enumeration is not specified if the
+     * attribute collection is changed.
+     *
+     * @return an enumeration of all contained attributes
+     */
+    public Iterator<EntryAttribute> iterator()
+    {
+        return Collections.unmodifiableMap( attributes ).values().iterator();
+    }
+    
+
+    /**
+     * Returns the number of attributes.
+     *
+     * @return the number of attributes
+     */
+    public int size()
+    {
+        return attributes.size();
+    }
+    
+    
+    /**
+     * Clone the current entry
+     */
+    public Entry clone()
+    {
+        try
+        {
+            return (Entry)super.clone();
+        }
+        catch ( CloneNotSupportedException cnse )
+        {
+            return null;
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractValue.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractValue.java
new file mode 100644
index 0000000..80371be
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/AbstractValue.java
@@ -0,0 +1,252 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.entry;
+
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A wrapper around byte[] values in entries.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public abstract class AbstractValue<T> implements Value<T>
+{
+    /** logger for reporting errors that might not be handled properly upstream */
+    private static final Logger LOG = LoggerFactory.getLogger( AbstractValue.class );
+
+    
+    /** the wrapped binary value */
+    protected T wrapped;
+    
+    /** the canonical representation of the wrapped value */
+    protected T normalizedValue;
+
+    /** A flag set when the value has been normalized */
+    protected boolean normalized;
+
+    /** cached results of the isValid() method call */
+    protected Boolean valid;
+
+    
+    /**
+     * Reset the value
+     */
+    public void clear()
+    {
+        wrapped = null;
+        normalized = false;
+        normalizedValue = null;
+        valid = null;
+    }
+
+    
+    public Value<T> clone()
+    {
+        try
+        {
+            return (Value<T>)super.clone();
+        }
+        catch ( CloneNotSupportedException cnse )
+        {
+            // Do nothing
+            return null;
+        }
+    }
+    
+    
+    /**
+     * Gets a reference to the wrapped binary value.
+     * 
+     * Warning ! The value is not copied !!!
+     *
+     * @return a direct handle on the binary value that is wrapped
+     */
+    public T getReference()
+    {
+        return wrapped;
+    }
+
+    
+    /**
+     * Gets a copy of the wrapped binary value.
+     * 
+     * @return a copy of the binary value that is wrapped
+     */
+    public T get()
+    {
+        // Just call the specific Client copy method.
+        return getCopy();
+    }
+
+    
+    /**
+     * Gets the normalized (canonical) representation for the wrapped value.
+     * If the wrapped value is null, null is returned, otherwise the normalized
+     * form is returned.  If the normalized Value is null, then the wrapped 
+     * value is returned
+     *
+     * @return gets the normalized value
+     */
+    public T getNormalizedValue()
+    {
+        if ( isNull() )
+        {
+            return null;
+        }
+
+        if ( normalizedValue == null )
+        {
+            return getCopy();
+        }
+
+        return getNormalizedValueCopy();
+    }
+
+
+    /**
+     * Gets a reference to the the normalized (canonical) representation 
+     * for the wrapped value.
+     *
+     * @return gets a reference to the normalized value
+     */
+    public T getNormalizedValueReference()
+    {
+        if ( isNull() )
+        {
+            return null;
+        }
+
+        if ( normalizedValue == null )
+        {
+            return wrapped;
+        }
+
+        return normalizedValue;
+
+    }
+
+    
+    /**
+     * Check if the contained value is null or not
+     * 
+     * @return <code>true</code> if the inner value is null.
+     */
+    public final boolean isNull()
+    {
+        return wrapped == null; 
+    }
+    
+    
+    /**
+     * Check if the Valid flag is set or not. This flag is set by a call
+     * to the isValid( SyntaxChecker ) method for client values. It is overridden
+     * for server values.
+     * 
+     * if the flag is not set, returns <code>false</code>
+     *
+     * @see ServerValue#isValid()
+     */
+    public boolean isValid()
+    {
+        if ( valid != null )
+        {
+            return valid;
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Uses the syntaxChecker associated with the attributeType to check if the
+     * value is valid.  Repeated calls to this method do not attempt to re-check
+     * the syntax of the wrapped value every time if the wrapped value does not
+     * change. Syntax checks only result on the first check, and when the wrapped
+     * value changes.
+     *
+     * @see ServerValue#isValid()
+     */
+    public final boolean isValid( SyntaxChecker syntaxChecker ) throws NamingException
+    {
+        if ( valid != null )
+        {
+            return valid;
+        }
+        
+        if ( syntaxChecker == null )
+        {
+            String message = "Cannot validate " + toString() + " with a null SyntaxChecker";
+            LOG.error( message );
+            throw new NamingException( message );
+        }
+        
+        valid = syntaxChecker.isValidSyntax( getReference() );
+        return valid;
+    }
+
+
+    /**
+     * Normalize the value. In order to use this method, the Value
+     * must be schema aware.
+     * 
+     * @exception NamingException If the value cannot be normalized
+     */
+    public void normalize() throws NamingException
+    {
+        normalized = true;
+        normalizedValue = wrapped;
+    }
+
+
+    /**
+     * Sets this value's wrapped value to a copy of the src array.
+     *
+     * @param wrapped the byte array to use as the wrapped value
+     */
+    public abstract void set( T wrapped );
+
+    
+    /**
+     * Tells if the value has already be normalized or not.
+     *
+     * @return <code>true</code> if the value has already been normalized.
+     */
+    public final boolean isNormalized()
+    {
+        return normalized;
+    }
+
+    
+    /**
+     * Set the normalized flag.
+     * 
+     * @param the value : true or false
+     */
+    public final void setNormalized( boolean normalized )
+    {
+        this.normalized = normalized;
+    }
+}
\ No newline at end of file
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Entry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Entry.java
new file mode 100644
index 0000000..d3b0be7
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Entry.java
@@ -0,0 +1,401 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry;

+

+

+import java.util.Iterator;

+import java.util.List;

+

+import javax.naming.NamingException;

+

+import org.apache.directory.shared.ldap.name.LdapDN;

+

+

+/**

+ * <p>

+ * This interface represent a LDAP entry. An LDAP entry contains :

+ * <li> A distinguished name (DN)</li>

+ * <li> A list of attributes</li>

+ * </p>

+ * <p>

+ * The available methods on this object are described in this interface.

+ * </p>

+ * <p>

+ * This interface is used by the serverEntry and clientEntry interfaces.

+ *</p>

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface Entry extends Cloneable, Iterable<EntryAttribute>

+{

+    /**

+     * Remove all the attributes for this entry. The DN is not reset

+     */

+    void clear();

+

+

+    /**

+     * Clone the current entry

+     */

+    Entry clone();

+

+

+    /**

+     * Get this entry's DN.

+     *

+     * @return The entry's DN

+     */

+    LdapDN getDn();

+

+

+    /**

+     * Tells if an entry as a specific ObjectClass value

+     * 

+     * @param objectClass The ObjectClassw we want to check

+     * @return <code>true</code> if the ObjectClass value is present 

+     * in the ObjectClass attribute

+     */

+    boolean hasObjectClass( String objectClass );

+

+

+    /**

+     * <p>

+     * Returns the attribute with the specified alias. The return value

+     * is <code>null</code> if no match is found.  

+     * </p>

+     * <p>An Attribute with an id different from the supplied alias may 

+     * be returned: for example a call with 'cn' may in some implementations 

+     * return an Attribute whose getId() field returns 'commonName'.

+     * </p>

+     *

+     * @param alias an aliased name of the attribute identifier

+     * @return the attribute associated with the alias

+     */

+    EntryAttribute get( String alias );

+

+

+    /**

+     * <p>

+     * Put some new ClientAttribute using the User Provided ID. 

+     * No value is inserted. 

+     * </p>

+     * <p>

+     * If an existing Attribute is found, it will be replaced by an

+     * empty attribute, and returned to the caller.

+     * </p>

+     * 

+     * @param upIds The user provided IDs of the AttributeTypes to add.

+     * @return A list of replaced Attributes.

+     */

+    List<EntryAttribute> set( String... upIds );

+

+

+    /**

+     * Set this entry's DN.

+     *

+     * @param dn The DN associated with this entry

+     */

+    void setDn( LdapDN dn );

+

+

+    /**

+     * Returns an enumeration containing the zero or more attributes in the

+     * collection. The behavior of the enumeration is not specified if the

+     * attribute collection is changed.

+     *

+     * @return an enumeration of all contained attributes

+     */

+    Iterator<EntryAttribute> iterator();

+

+

+    /**

+     * Add some Attributes to the current Entry.

+     *

+     * @param attributes The attributes to add

+     * @throws NamingException If we can't add any of the attributes

+     */

+    void add( EntryAttribute... attributes ) throws NamingException;

+

+

+    /**

+     * Add some String values to the current Entry.

+     *

+     * @param upId The user provided ID of the attribute we want to add 

+     * some values to

+     * @param values The list of String values to add

+     * @throws NamingException If we can't add any of the values

+     */

+    void add( String upId, String... values ) throws NamingException;

+

+

+    /**

+     * Add some binary values to the current Entry.

+     *

+     * @param upId The user provided ID of the attribute we want to add 

+     * some values to

+     * @param values The list of binary values to add

+     * @throws NamingException If we can't add any of the values

+     */

+    void add( String upId, byte[]... values ) throws NamingException;

+

+

+    /**

+     * Add some Values to the current Entry.

+     *

+     * @param upId The user provided ID of the attribute we want to add 

+     * some values to

+     * @param values The list of Values to add

+     * @throws NamingException If we can't add any of the values

+     */

+    void add( String upId, Value<?>... values ) throws NamingException;

+

+

+    /**

+     * <p>

+     * Places attributes in the attribute collection. 

+     * </p>

+     * <p>If there is already an attribute with the same ID as any of the 

+     * new attributes, the old ones are removed from the collection and 

+     * are returned by this method. If there was no attribute with the 

+     * same ID the return value is <code>null</code>.

+     *</p>

+     *

+     * @param attributes the attributes to be put

+     * @return the old attributes with the same OID, if exist; otherwise

+     *         <code>null</code>

+     * @exception NamingException if the operation fails

+     */

+    List<EntryAttribute> put( EntryAttribute... attributes ) throws NamingException;

+

+

+    /**

+     * <p>

+     * Put an attribute (represented by its ID and some binary values) into an entry. 

+     * </p>

+     * <p> 

+     * If the attribute already exists, the previous attribute will be 

+     * replaced and returned.

+     * </p>

+     *

+     * @param upId The attribute ID

+     * @param values The list of binary values to put. It can be empty.

+     * @return The replaced attribute

+     */

+    EntryAttribute put( String upId, byte[]... values );

+

+

+    /**

+     * <p>

+     * Put an attribute (represented by its ID and some String values) into an entry. 

+     * </p>

+     * <p> 

+     * If the attribute already exists, the previous attribute will be 

+     * replaced and returned.

+     * </p>

+     *

+     * @param upId The attribute ID

+     * @param values The list of String values to put. It can be empty.

+     * @return The replaced attribute

+     */

+    EntryAttribute put( String upId, String... values );

+

+

+    /**

+     * <p>

+     * Put an attribute (represented by its ID and some values) into an entry. 

+     * </p>

+     * <p> 

+     * If the attribute already exists, the previous attribute will be 

+     * replaced and returned.

+     * </p>

+     *

+     * @param upId The attribute ID

+     * @param values The list of values to put. It can be empty.

+     * @return The replaced attribute

+     */

+    EntryAttribute put( String upId, Value<?>... values );

+

+

+    /**

+      * Removes the specified attributes. The removed attributes are

+      * returned by this method. If there were no attribute the return value

+      * is <code>null</code>.

+      *

+      * @param attributes the attributes to be removed

+      * @return the removed attribute, if exists; otherwise <code>null</code>

+      */

+    List<EntryAttribute> remove( EntryAttribute... attributes ) throws NamingException;

+

+

+    /**

+     * <p>

+     * Removes the specified binary values from an attribute.

+     * </p>

+     * <p>

+     * If at least one value is removed, this method returns <code>true</code>.

+     * </p>

+     * <p>

+     * If there is no more value after having removed the values, the attribute

+     * will be removed too.

+     * </p>

+     * <p>

+     * If the attribute does not exist, nothing is done and the method returns 

+     * <code>false</code>

+     * </p> 

+     *

+     * @param upId The attribute ID  

+     * @param attributes the attributes to be removed

+     * @return <code>true</code> if at least a value is removed, <code>false</code>

+     * if not all the values have been removed or if the attribute does not exist. 

+     */

+    boolean remove( String upId, byte[]... values ) throws NamingException;

+

+

+    /**

+     * <p>

+     * Removes the specified String values from an attribute.

+     * </p>

+     * <p>

+     * If at least one value is removed, this method returns <code>true</code>.

+     * </p>

+     * <p>

+     * If there is no more value after havong removed the values, the attribute

+     * will be removed too.

+     * </p>

+     * <p>

+     * If the attribute does not exist, nothing is done and the method returns 

+     * <code>false</code>

+     * </p> 

+     *

+     * @param upId The attribute ID  

+     * @param attributes the attributes to be removed

+     * @return <code>true</code> if at least a value is removed, <code>false</code>

+     * if no values have been removed or if the attribute does not exist. 

+     */

+    boolean remove( String upId, String... values ) throws NamingException;

+

+

+    /**

+     * <p>

+     * Removes the specified values from an attribute.

+     * </p>

+     * <p>

+     * If at least one value is removed, this method returns <code>true</code>.

+     * </p>

+     * <p>

+     * If there is no more value after having removed the values, the attribute

+     * will be removed too.

+     * </p>

+     * <p>

+     * If the attribute does not exist, nothing is done and the method returns 

+     * <code>false</code>

+     * </p> 

+     *

+     * @param upId The attribute ID  

+     * @param attributes the attributes to be removed

+     * @return <code>true</code> if at least a value is removed, <code>false</code>

+     * if not all the values have been removed or if the attribute does not exist. 

+     */

+    boolean remove( String upId, Value<?>... values ) throws NamingException;

+

+

+    /**

+      * <p>

+      * Removes the attribute with the specified alias. 

+      * </p>

+      * <p>

+      * The removed attribute are returned by this method. 

+      * </p>

+      * <p>

+      * If there is no attribute with the specified alias,

+      * the return value is <code>null</code>.

+      * </p>

+      *

+      * @param attributes an aliased name of the attribute to be removed

+      * @return the removed attributes, if any, as a list; otherwise <code>null</code>

+      */

+    List<EntryAttribute> removeAttributes( String... attributes );

+

+

+    /**

+     * <p>

+     * Checks if an entry contains a list of attributes.

+     * </p>

+     * <p>

+     * If the list is null or empty, this method will return <code>true</code>

+     * if the entry has no attribute, <code>false</code> otherwise.

+     * </p>

+     *

+     * @param attributes The Attributes to look for

+     * @return <code>true</code> if all the attributes are found within 

+     * the entry, <code>false</code> if at least one of them is not present.

+     * @throws NamingException If the attribute does not exist

+     */

+    boolean contains( EntryAttribute... attributes ) throws NamingException;

+

+

+    /**

+     * Checks if an entry contains an attribute with some binary values.

+     *

+     * @param id The Attribute we are looking for.

+     * @param values The searched values.

+     * @return <code>true</code> if all the values are found within the attribute,

+     * false if at least one value is not present or if the ID is not valid. 

+     */

+    boolean contains( String upId, byte[]... values );

+

+

+    /**

+     * Checks if an entry contains an attribute with some String values.

+     *

+     * @param id The Attribute we are looking for.

+     * @param values The searched values.

+     * @return <code>true</code> if all the values are found within the attribute,

+     * false if at least one value is not present or if the ID is not valid. 

+     */

+    boolean contains( String upId, String... values );

+

+

+    /**

+     * Checks if an entry contains an attribute with some values.

+     *

+     * @param id The Attribute we are looking for.

+     * @param values The searched values.

+     * @return <code>true</code> if all the values are found within the attribute,

+     * false if at least one value is not present or if the ID is not valid. 

+     */

+    boolean contains( String upId, Value<?>... values );

+

+

+    /**

+     * Checks if an entry contains some specific attributes.

+     *

+     * @param attributes The Attributes to look for.

+     * @return <code>true</code> if the attributes are all found within the entry.

+     */

+    boolean containsAttribute( String... attributes );

+

+    

+    /**

+     * Returns the number of attributes.

+     *

+     * @return the number of attributes

+     */

+    int size();

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/EntryAttribute.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/EntryAttribute.java
new file mode 100644
index 0000000..b2b80d0
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/EntryAttribute.java
@@ -0,0 +1,453 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry;

+

+import java.util.Iterator;

+import java.util.List;

+

+import javax.naming.directory.InvalidAttributeValueException;

+

+/**

+ * A generic interface mocking the Attribute JNDI interface. This interface

+ * will be the base interface for the ServerAttribute and ClientAttribute.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface EntryAttribute extends Iterable<Value<?>>, Cloneable

+{

+    /**

+     * Adds some values to this attribute. If the new values are already present in

+     * the attribute values, the method has no effect.

+     * <p>

+     * The new values are added at the end of list of values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were added.

+     * </p>

+     * <p>

+     * If the value's type is different from the attribute's type,

+     * a conversion is done. For instance, if we try to set some String

+     * into a Binary attribute, we just store the UTF-8 byte array 

+     * encoding for this String.

+     * </p>

+     * <p>

+     * If we try to store some byte[] in a HR attribute, we try to 

+     * convert those byte[] assuming they represent an UTF-8 encoded

+     * String. Of course, if it's not the case, the stored value will

+     * be incorrect.

+     * </p>

+     * <p>

+     * It's the responsibility of the caller to check if the stored

+     * values are consistent with the attribute's type.

+     * </p>

+     * <p>

+     * The caller can set the HR flag in order to enforce a type for 

+     * the current attribute, otherwise this type will be set while

+     * adding the first value, using the value's type to set the flag.

+     * </p>

+     *

+     * @param val some new values to be added which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int add( String... vals );

+

+

+    /**

+     * Adds some values to this attribute. If the new values are already present in

+     * the attribute values, the method has no effect.

+     * <p>

+     * The new values are added at the end of list of values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were added.

+     * </p>

+     * If the value's type is different from the attribute's type,

+     * a conversion is done. For instance, if we try to set some String

+     * into a Binary attribute, we just store the UTF-8 byte array 

+     * encoding for this String.

+     * If we try to store some byte[] in a HR attribute, we try to 

+     * convert those byte[] assuming they represent an UTF-8 encoded

+     * String. Of course, if it's not the case, the stored value will

+     * be incorrect.

+     * <br>

+     * It's the responsibility of the caller to check if the stored

+     * values are consistent with the attribute's type.

+     * <br>

+     * The caller can set the HR flag in order to enforce a type for 

+     * the current attribute, otherwise this type will be set while

+     * adding the first value, using the value's type to set the flag.

+     *

+     * @param val some new values to be added which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int add( byte[]... vals );

+

+

+    /**

+     * Adds some values to this attribute. If the new values are already present in

+     * the attribute values, the method has no effect.

+     * <p>

+     * The new values are added at the end of list of values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were added.

+     * </p>

+     * <p>

+     * If the value's type is different from the attribute's type,

+     * a conversion is done. For instance, if we try to set some 

+     * StringValue into a Binary attribute, we just store the UTF-8 

+     * byte array encoding for this StringValue.

+     * </p>

+     * <p>

+     * If we try to store some BinaryValue in a HR attribute, we try to 

+     * convert those BinaryValue assuming they represent an UTF-8 encoded

+     * String. Of course, if it's not the case, the stored value will

+     * be incorrect.

+     * </p>

+     * <p>

+     * It's the responsibility of the caller to check if the stored

+     * values are consistent with the attribute's type.

+     * </p>

+     * <p>

+     * The caller can set the HR flag in order to enforce a type for 

+     * the current attribute, otherwise this type will be set while

+     * adding the first value, using the value's type to set the flag.

+     * </p>

+     * <p>

+     * <b>Note : </b>If the entry contains no value, and the unique added value

+     * is a null length value, then this value will be considered as

+     * a binary value.

+     * </p>

+     * @param val some new values to be added which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int add( Value<?>... val );

+    

+    

+    /**

+     * Remove all the values from this attribute.

+     */

+    void clear();

+    

+    

+    /**

+     * @return A clone of the current object

+     */

+    EntryAttribute clone();

+

+

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is not HR, the values will be converted to byte[]

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    boolean contains( String... vals );

+

+

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is HR, the values will be converted to String

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    boolean contains( byte[]... vals );

+

+

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is HR, the binary values will be converted to String before

+     * being checked.

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    boolean contains( Value<?>... vals );

+

+

+    /**

+     * <p>

+     * Get the first value of this attribute. If there is none, 

+     * null is returned.

+     * </p>

+     * <p>

+     * Note : even if we are storing values into a Set, one can assume

+     * the values are ordered following the insertion order.

+     * </p>

+     * <p> 

+     * This method is meant to be used if the attribute hold only one value.

+     * </p>

+     * 

+     *  @return The first value for this attribute.

+     */

+    Value<?> get();

+

+

+    /**

+     * Returns an iterator over all the attribute's values.

+     * <p>

+     * The effect on the returned enumeration of adding or removing values of

+     * the attribute is not specified.

+     * </p>

+     * <p>

+     * This method will throw any <code>NamingException</code> that occurs.

+     * </p>

+     *

+     * @return an enumeration of all values of the attribute

+     */

+    Iterator<Value<?>> getAll();

+

+

+    /**

+     * <p>

+     * Get the byte[] value, if and only if the value is known to be Binary,

+     * otherwise a InvalidAttributeValueException will be thrown

+     * </p>

+     * <p>

+     * Note that this method returns the first value only.

+     * </p>

+     *

+     * @return The value as a byte[]

+     * @throws InvalidAttributeValueException If the value is a String

+     */

+    byte[] getBytes() throws InvalidAttributeValueException;

+    

+    

+    /**

+     * Get's the attribute identifier for this entry.  This is the value

+     * that will be used as the identifier for the attribute within the

+     * entry.  

+     *

+     * @return the identifier for this attribute

+     */

+    String getId();

+

+    

+    /**

+     * Get's the user provided identifier for this entry.  This is the value

+     * that will be used as the identifier for the attribute within the

+     * entry.  If this is a commonName attribute for example and the user

+     * provides "COMMONname" instead when adding the entry then this is

+     * the format the user will have that entry returned by the directory

+     * server.  To do so we store this value as it was given and track it

+     * in the attribute using this property.

+     *

+     * @return the user provided identifier for this attribute

+     */

+    String getUpId();

+    

+    

+    /**

+     * <p>

+     * Tells if the attribute is Human Readable. 

+     * </p>

+     * <p>This flag is set by the caller, or implicitly when adding String 

+     * values into an attribute which is not yet declared as Binary.

+     * </p> 

+     * @return

+     */

+    boolean isHR();

+

+    

+    /**

+     * <p>

+     * Get the String value, if and only if the value is known to be a String,

+     * otherwise a InvalidAttributeValueException will be thrown

+     * </p>

+     * <p>

+     * Note that this method returns the first value only.

+     * </p>

+     *

+     * @return The value as a String

+     * @throws InvalidAttributeValueException If the value is a byte[]

+     */

+    String getString() throws InvalidAttributeValueException;

+

+    

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int put( String... vals );

+

+

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int put( byte[]... vals );

+

+    

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values are replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    int put( Value<?>... vals );

+

+

+    /**

+     * <p>

+     * Puts a list of values into this attribute.

+     * </p>

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param vals the values to be put

+     * @return the number of added values, or 0 if none has been added

+     */

+    int put( List<Value<?>> vals );

+

+

+    /**

+     * <p>

+     * Removes all the  values that are equal to the given values.

+     * </p>

+     * <p>

+     * Returns true if all the values are removed.

+     * </p>

+     * <p>

+     * If the attribute type is not HR, then the values will be first converted

+     * to byte[]

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    boolean remove( String... vals );

+    

+    

+    /**

+     * <p>

+     * Removes all the  values that are equal to the given values.

+     * </p>

+     * <p>

+     * Returns true if all the values are removed. 

+     * </p>

+     * <p>

+     * If the attribute type is HR, then the values will be first converted

+     * to String

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    boolean remove( byte[]... val );

+

+

+    /**

+     * <p>

+     * Removes all the  values that are equal to the given values.

+     * </p>

+     * <p>

+     * Returns true if all the values are removed.

+     * </p>

+     * <p>

+     * If the attribute type is HR and some value which are not String, we

+     * will convert the values first (same thing for a non-HR attribute).

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    boolean remove( Value<?>... vals );

+

+    

+    /**

+     * <p>

+     * Set the attribute to Human Readable or to Binary. 

+     * </p>

+     * @param isHR <code>true</code> for a Human Readable attribute, 

+     * <code>false</code> for a Binary attribute.

+     */

+    void setHR( boolean isHR );

+

+    

+    /**

+     * Set the normalized ID. The ID will be lowercased, and spaces

+     * will be trimmed. 

+     *

+     * @param id The attribute ID

+     * @throws IllegalArgumentException If the ID is empty or null or

+     * resolve to an empty value after being trimmed

+     */

+    public void setId( String id );

+

+    

+    /**

+     * Set the user provided ID. It will also set the ID, normalizing

+     * the upId (removing spaces before and after, and lowercasing it)

+     *

+     * @param upId The attribute ID

+     * @throws IllegalArgumentException If the ID is empty or null or

+     * resolve to an empty value after being trimmed

+     */

+    public void setUpId( String upId );

+

+    

+    /**

+      * Retrieves the number of values in this attribute.

+      *

+      * @return the number of values in this attribute, including any values

+      * wrapping a null value if there is one

+      */

+    int size();

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Modification.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Modification.java
new file mode 100644
index 0000000..d4c1e50
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Modification.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.entry;
+
+
+/**
+ * An internal interface for a ModificationItem. The name has been
+ * chosen so that it does not conflict with @see ModificationItem
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface Modification extends Cloneable
+{
+    /**
+     *  @return the operation
+     */
+    ModificationOperation getOperation();
+    
+    
+    /**
+     * Store the modification operation
+     *
+     * @param operation The DirContext value to assign
+     */
+    void setOperation( int operation );
+
+    
+    /**
+     * Store the modification operation
+     *
+     * @param operation The ModificationOperation value to assign
+     */
+    void setOperation( ModificationOperation operation );
+
+    
+    /**
+     * @return the attribute containing the modifications
+     */
+    EntryAttribute getAttribute();
+    
+    
+    /**
+     * Set the attribute's modification
+     *
+     * @param attribute The modified attribute 
+     */
+    void setAttribute( EntryAttribute attribute );
+    
+    
+    /**
+     * The clone operation
+     * TODO clone.
+     *
+     * @return
+     */
+    Modification clone();
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/ModificationOperation.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/ModificationOperation.java
new file mode 100644
index 0000000..00c1c63
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/ModificationOperation.java
@@ -0,0 +1,76 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.entry;
+
+/**
+ * An enum storing the different modification operation which can be used
+ * in a Modification. There is a one to one mapping with the DirContext.ADD_ATTRIBUTE,
+ * DirContext.REMOVE_ATTRIBUTE, DirContext.REPLACE_ATTRIBUTE
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public enum ModificationOperation
+{
+    ADD_ATTRIBUTE( 1 ),
+    REPLACE_ATTRIBUTE( 2 ),
+    REMOVE_ATTRIBUTE( 3 );
+
+    /** Internal value */
+    private int value;
+    
+    
+    /**
+     * Creates a new instance of ModificationOperation.
+     */
+    private ModificationOperation( int value )
+    {
+        this.value = value;
+    }
+    
+    
+    /**
+     * @return The integer value associated with the element. This value
+     * is equivalent to the one found in DirContext.
+     */
+    public int getValue()
+    {
+        return value;
+    }
+    
+    
+    public String toString()
+    {
+        switch ( this )
+        {
+            case ADD_ATTRIBUTE :
+                return "add";
+                
+            case REPLACE_ATTRIBUTE :
+                return "replace";
+                
+            case REMOVE_ATTRIBUTE :
+                return "remove";
+                
+            default :
+                return "";
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Value.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Value.java
new file mode 100644
index 0000000..5c21279
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Value.java
@@ -0,0 +1,182 @@
+/*

+ *  Licensed to the Apache Software Foundation (ASF) under one

+ *  or more contributor license agreements.  See the NOTICE file

+ *  distributed with this work for additional information

+ *  regarding copyright ownership.  The ASF licenses this file

+ *  to you under the Apache License, Version 2.0 (the

+ *  "License"); you may not use this file except in compliance

+ *  with the License.  You may obtain a copy of the License at

+ *

+ *    http://www.apache.org/licenses/LICENSE-2.0

+ *

+ *  Unless required by applicable law or agreed to in writing,

+ *  software distributed under the License is distributed on an

+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ *  KIND, either express or implied.  See the License for the

+ *  specific language governing permissions and limitations

+ *  under the License.

+ *

+ */

+package org.apache.directory.shared.ldap.entry;

+

+import java.io.Externalizable;

+

+import javax.naming.NamingException;

+

+import org.apache.directory.shared.ldap.schema.Normalizer;

+import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;

+

+

+/**

+ * A interface for wrapping attribute values stored into an EntryAttribute. These

+ * values can be a String or a byte[].

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface Value<T> extends Cloneable, Externalizable, Comparable<Value<T>>

+{

+    

+    Value<T> clone();

+    

+    

+    /**

+     * Check if the contained value is null or not

+     * 

+     * @return <code>true</code> if the inner value is null.

+     */

+    boolean isNull();

+    

+    

+    /**

+     * Sets the wrapped value.

+     *

+     * @param wrapped the value to set. Should be either a String, URI, or a byte[]

+     */

+    void set( T wrapped );

+    

+

+    /**

+     * Get the stored value.

+     *

+     * @return The stored value

+     */

+    T get();

+    

+    

+    /**

+     * Get a reference on the stored value.

+     *

+     * @return A reference on the stored value.

+     */

+    T getReference();

+    

+    

+    /**

+     * Get a copy of the stored value.

+     *

+     * @return A copy of the stored value.

+     */

+    T getCopy();

+    

+    

+    /**

+     * Reset the value

+     */

+    void clear();

+    

+    

+    /**

+     * Tells if the value has already be normalized or not.

+     *

+     * @return <code>true</code> if the value has already been normalized.

+     */

+    boolean isNormalized();

+    

+    

+    /**

+     * Tells if the value is valid. The value must have already been

+     * validated at least once through a call to isValid( SyntaxChecker ).  

+     * 

+     * @return <code>true</code> if the value is valid

+     */

+    boolean isValid();

+

+    

+    /**

+     * Tells if the value is valid wrt a Syntax checker

+     * 

+     * @param SyntaxChecker the Syntax checker to use to validate the value

+     * @return <code>true</code> if the value is valid

+     * @exception NamingException if the value cannot be validated

+     */

+    boolean isValid( SyntaxChecker checker ) throws NamingException;

+

+    

+    /**

+     * Set the normalized flag.

+     * 

+     * @param the value : true or false

+     */

+    void setNormalized( boolean normalized );

+

+    

+    /**

+     * Gets the normalized (canonical) representation for the wrapped string.

+     * If the wrapped String is null, null is returned, otherwise the normalized

+     * form is returned.  If the normalizedValue is null, then this method

+     * will attempt to generate it from the wrapped value: repeated calls to

+     * this method do not unnecessarily normalize the wrapped value.  Only changes

+     * to the wrapped value result in attempts to normalize the wrapped value.

+     *

+     * @return gets the normalized value

+     */

+    T getNormalizedValue();

+    

+    

+    /**

+     * Gets a reference to the the normalized (canonical) representation 

+     * for the wrapped value.

+     *

+     * @return gets a reference to the normalized value

+     */

+    T getNormalizedValueReference();

+

+    

+    /**

+     * Gets a copy of the the normalized (canonical) representation 

+     * for the wrapped value.

+     *

+     * @return gets a copy of the normalized value

+     */

+    T getNormalizedValueCopy();

+

+    

+    /**

+     * Normalize the value. In order to use this method, the Value

+     * must be schema aware.

+     * 

+     * @exception NamingException If the value cannot be normalized

+     */

+    void normalize() throws NamingException;

+

+    

+    /**

+     * Normalize the value. For a client String value, applies the given normalizer.

+     * 

+     * It supposes that the client has access to the schema in order to select the

+     * appropriate normalizer.

+     * 

+     * @param Normalizer The normalizer to apply to the value

+     * @exception NamingException If the value cannot be normalized

+     */

+    void normalize( Normalizer normalizer ) throws NamingException;

+    

+    

+    /**

+     * Tells if the current value is Binary or String

+     * 

+     * @return <code>true</code> if the value is Binary, <code>false</code> otherwise

+     */

+    boolean isBinary();

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientAttribute.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientAttribute.java
new file mode 100644
index 0000000..32c9580
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientAttribute.java
@@ -0,0 +1,45 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+import javax.naming.NamingException;

+

+import org.apache.directory.shared.ldap.entry.EntryAttribute;

+import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;

+

+

+/**

+ * The server specific interface extending the EntryAttribute interface. It adds

+ * three more methods which are Server side.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface ClientAttribute extends EntryAttribute

+{

+    /**

+     * Checks to see if this attribute is valid along with the values it contains.

+     *

+     * @param checker The syntax checker

+     * @return true if the attribute and it's values are valid, false otherwise

+     * @throws NamingException if there is a failure to check syntaxes of values

+     */

+    boolean isValid( SyntaxChecker checker) throws NamingException;

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValue.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValue.java
new file mode 100644
index 0000000..93b227d
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValue.java
@@ -0,0 +1,397 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+import java.io.Externalizable;

+import java.io.IOException;

+import java.io.ObjectInput;

+import java.io.ObjectOutput;

+import java.util.Arrays;

+

+import javax.naming.NamingException;

+

+import org.apache.directory.shared.ldap.NotImplementedException;

+import org.apache.directory.shared.ldap.entry.AbstractValue;

+import org.apache.directory.shared.ldap.entry.Value;

+import org.apache.directory.shared.ldap.schema.ByteArrayComparator;

+import org.apache.directory.shared.ldap.schema.Normalizer;

+import org.apache.directory.shared.ldap.util.StringTools;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+

+

+/**

+ * A server side schema aware wrapper around a binary attribute value.

+ * This value wrapper uses schema information to syntax check values,

+ * and to compare them for equality and ordering.  It caches results

+ * and invalidates them when the wrapped value changes.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public class ClientBinaryValue extends AbstractValue<byte[]>

+{

+    /** Used for serialization */

+    private static final long serialVersionUID = 2L;

+    

+    /** logger for reporting errors that might not be handled properly upstream */

+    private static final Logger LOG = LoggerFactory.getLogger( ClientBinaryValue.class );

+

+

+    /**

+     * Creates a ServerBinaryValue without an initial wrapped value.

+     *

+     * @param attributeType the schema type associated with this ServerBinaryValue

+     */

+    public ClientBinaryValue()

+    {

+        wrapped = null;

+        normalized = false;

+        valid = null;

+        normalizedValue = null;

+    }

+

+

+    /**

+     * Creates a ServerBinaryValue with an initial wrapped binary value.

+     *

+     * @param attributeType the schema type associated with this ServerBinaryValue

+     * @param wrapped the binary value to wrap which may be null, or a zero length byte array

+     */

+    public ClientBinaryValue( byte[] wrapped )

+    {

+        if ( wrapped != null )

+        {

+            this.wrapped = new byte[ wrapped.length ];

+            System.arraycopy( wrapped, 0, this.wrapped, 0, wrapped.length );

+        }

+        else

+        {

+            this.wrapped = null;

+        }

+        

+        normalized = false;

+        valid = null;

+        normalizedValue = null;

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Value<String> Methods

+    // -----------------------------------------------------------------------

+    /**

+     * Reset the value

+     */

+    public void clear()

+    {

+        wrapped = null;

+        normalized = false;

+        normalizedValue = null;

+        valid = null;

+    }

+

+

+

+

+    /*

+     * Sets the wrapped binary value.  Has the side effect of setting the

+     * normalizedValue and the valid flags to null if the wrapped value is

+     * different than what is already set.  These cached values must be

+     * recomputed to be correct with different values.

+     *

+     * @see ServerValue#set(Object)

+     */

+    public final void set( byte[] wrapped )

+    {

+        // Why should we invalidate the normalized value if it's we're setting the

+        // wrapper to it's current value?

+        byte[] value = getReference();

+        

+        if ( value != null )

+        {

+            if ( Arrays.equals( wrapped, value ) )

+            {

+                return;

+            }

+        }

+

+        normalizedValue = null;

+        normalized = false;

+        valid = null;

+        

+        if ( wrapped == null )

+        {

+            this.wrapped = null;

+        }

+        else

+        {

+            this.wrapped = new byte[ wrapped.length ];

+            System.arraycopy( wrapped, 0, this.wrapped, 0, wrapped.length );

+        }

+    }

+

+

+    // -----------------------------------------------------------------------

+    // ServerValue<String> Methods

+    // -----------------------------------------------------------------------

+    /**

+     * Gets a direct reference to the normalized representation for the

+     * wrapped value of this ServerValue wrapper. Implementations will most

+     * likely leverage the attributeType this value is associated with to

+     * determine how to properly normalize the wrapped value.

+     *

+     * @return the normalized version of the wrapped value

+     * @throws NamingException if schema entity resolution fails or normalization fails

+     */

+    public byte[] getNormalizedValueCopy()

+    {

+        if ( normalizedValue == null )

+        {

+            return null;

+        }

+

+        byte[] copy = new byte[ normalizedValue.length ];

+        System.arraycopy( normalizedValue, 0, copy, 0, normalizedValue.length );

+        return copy;

+    }

+

+

+    /**

+     * Normalize the value. For a client String value, applies the given normalizer.

+     * 

+     * It supposes that the client has access to the schema in order to select the

+     * appropriate normalizer.

+     * 

+     * @param Normalizer The normalizer to apply to the value

+     * @exception NamingException If the value cannot be normalized

+     */

+    public final void normalize( Normalizer normalizer ) throws NamingException

+    {

+        if ( normalizer != null )

+        {

+            if ( wrapped == null )

+            {

+                normalized = true;

+            }

+            else

+            {

+                normalizedValue = (byte[])normalizer.normalize( wrapped );

+                normalized = true;

+            }

+        }

+    }

+

+    

+    /**

+     *

+     * @see ServerValue#compareTo(ServerValue)

+     * @throws IllegalStateException on failures to extract the comparator, or the

+     * normalizers needed to perform the required comparisons based on the schema

+     */

+    public int compareTo( Value<byte[]> value )

+    {

+        if ( isNull() )

+        {

+            if ( ( value == null ) || value.isNull() )

+            {

+                return 0;

+            }

+            else

+            {

+                return -1;

+            }

+        }

+        else

+        {

+            if ( ( value == null ) || value.isNull() ) 

+            {

+                return 1;

+            }

+        }

+

+        if ( value instanceof ClientBinaryValue )

+        {

+            ClientBinaryValue binaryValue = ( ClientBinaryValue ) value;

+

+            return ByteArrayComparator.INSTANCE.compare( getNormalizedValue(), binaryValue.getNormalizedValue() );

+        }

+        

+        String message = "I don't really know how to compare anything other " +

+            "than ServerBinaryValues at this point in time."; 

+        LOG.error( message );

+        throw new NotImplementedException( message );

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Object Methods

+    // -----------------------------------------------------------------------

+

+

+    /**

+     * @see Object#hashCode()

+     * @return the instance's hashcode 

+     */

+    public int hashCode()

+    {

+        // return zero if the value is null so only one null value can be

+        // stored in an attribute - the string version does the same

+        if ( isNull() )

+        {

+            return 0;

+        }

+

+        return Arrays.hashCode( getNormalizedValueReference() );

+    }

+

+

+    /**

+     * Checks to see if this ServerBinaryValue equals the supplied object.

+     *

+     * This equals implementation overrides the BinaryValue implementation which

+     * is not schema aware.

+     * @throws IllegalStateException on failures to extract the comparator, or the

+     * normalizers needed to perform the required comparisons based on the schema

+     */

+    public boolean equals( Object obj )

+    {

+        if ( this == obj )

+        {

+            return true;

+        }

+        

+        if ( ! ( obj instanceof ClientBinaryValue ) )

+        {

+            return false;

+        }

+

+        ClientBinaryValue other = ( ClientBinaryValue ) obj;

+        

+        if ( isNull() )

+        {

+            return other.isNull();

+        }

+

+        // now unlike regular values we have to compare the normalized values

+        return Arrays.equals( getNormalizedValueReference(), other.getNormalizedValueReference() );

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Private Helper Methods (might be put into abstract base class)

+    // -----------------------------------------------------------------------

+    /**

+     * @return a copy of the current value

+     */

+    public ClientBinaryValue clone()

+    {

+        ClientBinaryValue clone = (ClientBinaryValue)super.clone();

+        

+        if ( normalizedValue != null )

+        {

+            clone.normalizedValue = new byte[ normalizedValue.length ];

+            System.arraycopy( normalizedValue, 0, clone.normalizedValue, 0, normalizedValue.length );

+        }

+        

+        if ( wrapped != null )

+        {

+            clone.wrapped = new byte[ wrapped.length ];

+            System.arraycopy( wrapped, 0, clone.wrapped, 0, wrapped.length );

+        }

+        

+        return clone;

+    }

+

+

+    /**

+     * Gets a copy of the binary value.

+     *

+     * @return a copy of the binary value

+     */

+    public byte[] getCopy()

+    {

+        if ( wrapped == null )

+        {

+            return null;

+        }

+

+        

+        final byte[] copy = new byte[ wrapped.length ];

+        System.arraycopy( wrapped, 0, copy, 0, wrapped.length );

+        return copy;

+    }

+    

+    

+    /**

+     * Tells if the current value is Binary or String

+     * 

+     * @return <code>true</code> if the value is Binary, <code>false</code> otherwise

+     */

+    public boolean isBinary()

+    {

+        return true;

+    }

+

+

+    /**

+     * @see Externalizable#readExternal(ObjectInput)

+     */

+    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException

+    {

+        // TODO implement this method

+        return;

+    }

+

+    

+    /**

+     * @see Externalizable#writeExternal(ObjectOutput)

+     */

+    public void writeExternal( ObjectOutput out ) throws IOException

+    {

+        // TODO Implement this method

+    }

+    

+    

+    /**

+     * Dumps binary in hex with label.

+     *

+     * @see Object#toString()

+     */

+    public String toString()

+    {

+        if ( wrapped == null )

+        {

+            return "null";

+        }

+        else if ( wrapped.length > 16 )

+        {

+            // Just dump the first 16 bytes...

+            byte[] copy = new byte[16];

+            

+            System.arraycopy( wrapped, 0, copy, 0, 16 );

+            

+            return "'" + StringTools.dumpBytes( copy ) + "...'";

+        }

+        else

+        {

+            return "'" + StringTools.dumpBytes( wrapped ) + "'";

+        }

+    }

+}
\ No newline at end of file
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntry.java
new file mode 100644
index 0000000..a64806e
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntry.java
@@ -0,0 +1,36 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+import org.apache.directory.shared.ldap.entry.Entry;

+

+

+/**

+ * An entry implementation intended for use by clients. Implementations of

+ * this interface may treat attributes with different aliases of the same

+ * attributeType as the same attribute or may treat them as separate

+ * attributes.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface ClientEntry extends Entry

+{

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntryFactory.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntryFactory.java
new file mode 100644
index 0000000..0b1012e
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientEntryFactory.java
@@ -0,0 +1,31 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+/**

+ * Document me!

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public interface ClientEntryFactory

+{

+    ClientEntry newEntry();

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientStringValue.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientStringValue.java
new file mode 100644
index 0000000..94a6b97
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientStringValue.java
@@ -0,0 +1,333 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+import java.io.Externalizable;

+import java.io.IOException;

+import java.io.ObjectInput;

+import java.io.ObjectOutput;

+

+import javax.naming.NamingException;

+

+import org.apache.directory.shared.ldap.NotImplementedException;

+import org.apache.directory.shared.ldap.entry.AbstractValue;

+import org.apache.directory.shared.ldap.entry.Value;

+import org.apache.directory.shared.ldap.schema.Normalizer;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+

+

+/**

+ * A server side schema aware wrapper around a String attribute value.

+ * This value wrapper uses schema information to syntax check values,

+ * and to compare them for equality and ordering.  It caches results

+ * and invalidates them when the wrapped value changes.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public class ClientStringValue extends AbstractValue<String>

+{

+    /** Used for serialization */

+    private static final long serialVersionUID = 2L;

+    

+    

+    /** logger for reporting errors that might not be handled properly upstream */

+    private static final Logger LOG = LoggerFactory.getLogger( ClientStringValue.class );

+

+    

+    // -----------------------------------------------------------------------

+    // Constructors

+    // -----------------------------------------------------------------------

+    /**

+     * Creates a ServerStringValue without an initial wrapped value.

+     */

+    public ClientStringValue()

+    {

+        normalized = false;

+        valid = null;

+    }

+

+

+    /**

+     * Creates a ServerStringValue with an initial wrapped String value.

+     *

+     * @param wrapped the value to wrap which can be null

+     */

+    public ClientStringValue( String wrapped )

+    {

+        this.wrapped = wrapped;

+        normalized = false;

+        valid = null;

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Value<String> Methods

+    // -----------------------------------------------------------------------

+    /**

+     * Get the stored value.

+     *

+     * @return The stored value

+     */

+    public String get()

+    {

+        return wrapped;

+    }

+

+

+    /**

+     * Get a copy of the stored value.

+     *

+     * @return A copy of the stored value.

+     */

+    public String getCopy()

+    {

+        // The String is immutable, we can safely return the internal

+        // object without copying it.

+        return wrapped;

+    }

+    

+    

+    /**

+     * Sets the wrapped String value.  Has the side effect of setting the

+     * normalizedValue and the valid flags to null if the wrapped value is

+     * different than what is already set.  These cached values must be

+     * recomputed to be correct with different values.

+     *

+     * @see ServerValue#set(Object)

+     */

+    public final void set( String wrapped )

+    {

+        // Why should we invalidate the normalized value if it's we're setting the

+        // wrapper to it's current value?

+        if ( ( wrapped != null ) && wrapped.equals( get() ) )

+        {

+            return;

+        }

+

+        normalizedValue = null;

+        normalized = false;

+        valid = null;

+        this.wrapped = wrapped;

+    }

+

+

+    /**

+     * Gets the normalized (canonical) representation for the wrapped string.

+     * If the wrapped String is null, null is returned, otherwise the normalized

+     * form is returned.  If the normalizedValue is null, then this method

+     * will attempt to generate it from the wrapped value: repeated calls to

+     * this method do not unnecessarily normalize the wrapped value.  Only changes

+     * to the wrapped value result in attempts to normalize the wrapped value.

+     *

+     * @return gets the normalized value

+     */

+    public String getNormalizedValue()

+    {

+        if ( isNull() )

+        {

+            return null;

+        }

+

+        if ( normalizedValue == null )

+        {

+            return wrapped;

+        }

+

+        return normalizedValue;

+    }

+

+

+    /**

+     * Gets a copy of the the normalized (canonical) representation 

+     * for the wrapped value.

+     *

+     * @return gets a copy of the normalized value

+     */

+    public String getNormalizedValueCopy()

+    {

+        return getNormalizedValue();

+    }

+

+

+    /**

+     * Normalize the value. For a client String value, applies the given normalizer.

+     * 

+     * It supposes that the client has access to the schema in order to select the

+     * appropriate normalizer.

+     * 

+     * @param Normalizer The normalizer to apply to the value

+     * @exception NamingException If the value cannot be normalized

+     */

+    public final void normalize( Normalizer normalizer ) throws NamingException

+    {

+        if ( normalizer != null )

+        {

+            normalizedValue = (String)normalizer.normalize( wrapped );

+            normalized = true;

+        }

+    }

+

+    

+    // -----------------------------------------------------------------------

+    // Comparable<String> Methods

+    // -----------------------------------------------------------------------

+    /**

+     * @see ServerValue#compareTo(ServerValue)

+     * @throws IllegalStateException on failures to extract the comparator, or the

+     * normalizers needed to perform the required comparisons based on the schema

+     */

+    public int compareTo( Value<String> value )

+    {

+        if ( isNull() )

+        {

+            if ( ( value == null ) || value.isNull() )

+            {

+                return 0;

+            }

+            else

+            {

+                return -1;

+            }

+        }

+        else if ( ( value == null ) || value.isNull() )

+        {

+            return 1;

+        }

+

+        if ( value instanceof ClientStringValue )

+        {

+            ClientStringValue stringValue = ( ClientStringValue ) value;

+            

+            return getNormalizedValue().compareTo( stringValue.getNormalizedValue() );

+        }

+        else 

+        {

+            String message = "Cannot compare " + toString() + " with the unknown value " + value.getClass();

+            LOG.error( message );

+            throw new NotImplementedException( message );

+        }

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Cloneable methods

+    // -----------------------------------------------------------------------

+    /**

+     * Get a clone of the Client Value

+     * 

+     * @return a copy of the current value

+     */

+    public ClientStringValue clone()

+    {

+        return (ClientStringValue)super.clone();

+    }

+

+

+    // -----------------------------------------------------------------------

+    // Object Methods

+    // -----------------------------------------------------------------------

+    /**

+     * @see Object#hashCode()

+     * @return the instance's hashcode 

+     */

+    public int hashCode()

+    {

+        // return zero if the value is null so only one null value can be

+        // stored in an attribute - the binary version does the same 

+        if ( isNull() )

+        {

+            return 0;

+        }

+

+        // If the normalized value is null, will default to wrapped

+        // which cannot be null at this point.

+        return getNormalizedValue().hashCode();

+    }

+

+

+    /**

+     * @see Object#equals(Object)

+     * 

+     * Two ClientStringValue are equals if their normalized values are equal

+     */

+    public boolean equals( Object obj )

+    {

+        if ( this == obj )

+        {

+            return true;

+        }

+

+        if ( ! ( obj instanceof ClientStringValue ) )

+        {

+            return false;

+        }

+

+        ClientStringValue other = ( ClientStringValue ) obj;

+        

+        if ( this.isNull() )

+        {

+            return other.isNull();

+        }

+        

+        // Test the normalized values

+        return this.getNormalizedValue().equals( other.getNormalizedValue() );

+    }

+    

+    

+    /**

+     * Tells if the current value is Binary or String

+     * 

+     * @return <code>true</code> if the value is Binary, <code>false</code> otherwise

+     */

+    public boolean isBinary()

+    {

+        return false;

+    }

+

+

+    /**

+     * @see Externalizable#readExternal(ObjectInput)

+     */

+    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException

+    {

+        // TODO implement this method

+        return;

+    }

+

+    

+    /**

+     * @see Externalizable#writeExternal(ObjectOutput)

+     */

+    public void writeExternal( ObjectOutput out ) throws IOException

+    {

+        // TODO Implement this method

+    }

+    

+    

+    /**

+     * @see Object#toString()

+     */

+    public String toString()

+    {

+        return wrapped == null ? "null": wrapped;

+    }

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttribute.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttribute.java
new file mode 100644
index 0000000..6ec41ee
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttribute.java
@@ -0,0 +1,1362 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.entry.client;

+

+

+import java.util.Iterator;

+import java.util.LinkedHashSet;

+import java.util.List;

+import java.util.Set;

+

+import javax.naming.NamingException;

+import javax.naming.directory.InvalidAttributeValueException;

+

+import org.apache.directory.shared.ldap.entry.EntryAttribute;

+import org.apache.directory.shared.ldap.entry.Value;

+import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;

+import org.apache.directory.shared.ldap.util.StringTools;

+import org.slf4j.Logger;

+import org.slf4j.LoggerFactory;

+

+

+/**

+ * A client side entry attribute. The client is not aware of the schema,

+ * so we can't tell if the stored value will be String or Binary. We will

+ * default to Binary.<p>

+ * To define the kind of data stored, the client must set the isHR flag.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public class DefaultClientAttribute implements ClientAttribute

+{

+    /** logger for reporting errors that might not be handled properly upstream */

+    private static final Logger LOG = LoggerFactory.getLogger( DefaultClientAttribute.class );

+    

+    

+    /** The set of contained values */

+    protected Set<Value<?>> values = new LinkedHashSet<Value<?>>();

+    

+    /** The User provided ID */

+    protected String upId;

+

+    /** The normalized ID */

+    protected String id;

+

+    /** Tells if the attribute is Human Readable or not. When not set, 

+     * this flag is null. */

+    protected Boolean isHR;

+

+

+    // maybe have some additional convenience constructors which take

+    // an initial value as a string or a byte[]

+    /**

+     * Create a new instance of a EntryAttribute, without ID nor value.

+     */

+    public DefaultClientAttribute()

+    {

+    }

+

+

+    /**

+     * Create a new instance of a EntryAttribute, without value.

+     */

+    public DefaultClientAttribute( String upId )

+    {

+        setUpId( upId );

+    }

+

+

+    /**

+     * If the value does not correspond to the same attributeType, then it's

+     * wrapped value is copied into a new ClientValue which uses the specified

+     * attributeType.

+     * 

+     * Otherwise, the value is stored, but as a reference. It's not a copy.

+     *

+     * @param upId

+     * @param attributeType the attribute type according to the schema

+     * @param vals an initial set of values for this attribute

+     */

+    public DefaultClientAttribute( String upId, Value<?>... vals )

+    {

+        // The value can be null, this is a valid value.

+        if ( vals[0] == null )

+        {

+             add( new ClientStringValue() );

+        }

+        else

+        {

+            for ( Value<?> val:vals )

+            {

+                if ( ( val instanceof ClientStringValue ) || ( val instanceof ClientBinaryValue ) )

+                {

+                    add( val );

+                }

+                else

+                {

+                    String message = "Unknown value type: " + val.getClass().getName();

+                    LOG.error( message );

+                    throw new IllegalStateException( message );

+                }

+            }

+        }

+        

+        setUpId( upId );

+    }

+

+

+    /**

+     * Create a new instance of a EntryAttribute.

+     */

+    public DefaultClientAttribute( String upId, String... vals )

+    {

+        add( vals );

+        setUpId( upId );

+    }

+

+

+    /**

+     * Create a new instance of a EntryAttribute, with some byte[] values.

+     */

+    public DefaultClientAttribute( String upId, byte[]... vals )

+    {

+        add( vals );

+        setUpId( upId );

+    }

+

+

+    /**

+     * <p>

+     * Get the byte[] value, if and only if the value is known to be Binary,

+     * otherwise a InvalidAttributeValueException will be thrown

+     * </p>

+     * <p>

+     * Note that this method returns the first value only.

+     * </p>

+     *

+     * @return The value as a byte[]

+     * @throws InvalidAttributeValueException If the value is a String

+     */

+    public byte[] getBytes() throws InvalidAttributeValueException

+    {

+        Value<?> value = get();

+        

+        if ( value instanceof ClientBinaryValue )

+        {

+            return (byte[])value.get();

+        }

+        else

+        {

+            String message = "The value is expected to be a byte[]";

+            LOG.error( message );

+            throw new InvalidAttributeValueException( message );

+        }

+    }

+

+

+    /**

+     * <p>

+     * Get the String value, if and only if the value is known to be a String,

+     * otherwise a InvalidAttributeValueException will be thrown

+     * </p>

+     * <p>

+     * Note that this method returns the first value only.

+     * </p>

+     *

+     * @return The value as a String

+     * @throws InvalidAttributeValueException If the value is a byte[]

+     */

+    public String getString() throws InvalidAttributeValueException

+    {

+        Value<?> value = get();

+        

+        if ( value instanceof ClientStringValue )

+        {

+            return (String)value.get();

+        }

+        else

+        {

+            String message = "The value is expected to be a String";

+            LOG.error( message );

+            throw new InvalidAttributeValueException( message );

+        }

+    }

+

+

+    /**

+     * Get's the attribute identifier. Its value is the same than the

+     * user provided ID.

+     *

+     * @return the attribute's identifier

+     */

+    public String getId()

+    {

+        return id;

+    }

+

+

+    /**

+     * <p>

+     * Set the attribute to Human Readable or to Binary. 

+     * </p>

+     * @param isHR <code>true</code> for a Human Readable attribute, 

+     * <code>false</code> for a Binary attribute.

+     */

+    public void setHR( boolean isHR )

+    {

+        this.isHR = isHR;

+        //TODO : deal with the values, we may have to convert them.

+    }

+

+    

+    /**

+     * Set the normalized ID. The ID will be lowercased, and spaces

+     * will be trimmed. 

+     *

+     * @param id The attribute ID

+     * @throws IllegalArgumentException If the ID is empty or null or

+     * resolve to an empty value after being trimmed

+     */

+    public void setId( String id )

+    {

+        this.id = StringTools.trim( StringTools.lowerCaseAscii( id ) );

+

+        if ( this.id.length() == 0 )

+        {

+            this.id = null;

+            throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" +

+                " value when trimmed" );

+        }

+    }

+

+    

+    /**

+     * Get's the user provided identifier for this entry.  This is the value

+     * that will be used as the identifier for the attribute within the

+     * entry.  If this is a commonName attribute for example and the user

+     * provides "COMMONname" instead when adding the entry then this is

+     * the format the user will have that entry returned by the directory

+     * server.  To do so we store this value as it was given and track it

+     * in the attribute using this property.

+     *

+     * @return the user provided identifier for this attribute

+     */

+    public String getUpId()

+    {

+        return upId;

+    }

+

+

+    /**

+     * Set the user provided ID. It will also set the ID, normalizing

+     * the upId (removing spaces before and after, and lowercasing it)

+     *

+     * @param upId The attribute ID

+     * @throws IllegalArgumentException If the ID is empty or null or

+     * resolve to an empty value after being trimmed

+     */

+    public void setUpId( String upId )

+    {

+        this.upId = StringTools.trim( upId );

+        

+        if ( this.upId.length() == 0 )

+        {

+            this.upId = null;

+            throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" +

+                " value when trimmed" );

+        }

+

+        this.id = StringTools.lowerCaseAscii( this.upId );

+    }

+

+

+    /**

+     * <p>

+     * Tells if the attribute is Human Readable. 

+     * </p>

+     * <p>This flag is set by the caller, or implicitly when adding String 

+     * values into an attribute which is not yet declared as Binary.

+     * </p> 

+     * @return

+     */

+    public boolean isHR()

+    {

+        return isHR != null ? isHR : false; 

+    }

+

+    

+    /**

+     * Checks to see if this attribute is valid along with the values it contains.

+     *

+     * @return true if the attribute and it's values are valid, false otherwise

+     * @throws NamingException if there is a failure to check syntaxes of values

+     */

+    public boolean isValid() throws NamingException

+    {

+        for ( Value<?> value:values )

+        {

+            if ( !value.isValid() )

+            {

+                return false;

+            }

+        }

+

+        return true;

+    }

+

+

+    /**

+     * Checks to see if this attribute is valid along with the values it contains.

+     *

+     * @return true if the attribute and it's values are valid, false otherwise

+     * @throws NamingException if there is a failure to check syntaxes of values

+     */

+    public boolean isValid( SyntaxChecker checker ) throws NamingException

+    {

+        for ( Value<?> value : values )

+        {

+            if ( !value.isValid( checker ) )

+            {

+                return false;

+            }

+        }

+

+        return true;

+    }

+

+

+    /**

+     * Adds some values to this attribute. If the new values are already present in

+     * the attribute values, the method has no effect.

+     * <p>

+     * The new values are added at the end of list of values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were added.

+     * </p>

+     * <p>

+     * If the value's type is different from the attribute's type,

+     * a conversion is done. For instance, if we try to set some 

+     * StringValue into a Binary attribute, we just store the UTF-8 

+     * byte array encoding for this StringValue.

+     * </p>

+     * <p>

+     * If we try to store some BinaryValue in a HR attribute, we try to 

+     * convert those BinaryValue assuming they represent an UTF-8 encoded

+     * String. Of course, if it's not the case, the stored value will

+     * be incorrect.

+     * </p>

+     * <p>

+     * It's the responsibility of the caller to check if the stored

+     * values are consistent with the attribute's type.

+     * </p>

+     * <p>

+     * The caller can set the HR flag in order to enforce a type for 

+     * the current attribute, otherwise this type will be set while

+     * adding the first value, using the value's type to set the flag.

+     * </p>

+     * <p>

+     * <b>Note : </b>If the entry contains no value, and the unique added value

+     * is a null length value, then this value will be considered as

+     * a binary value.

+     * </p>

+     * @param val some new values to be added which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int add( Value<?>... vals )

+    {

+        int nbAdded = 0;

+        ClientBinaryValue nullBinaryValue = null;

+        ClientStringValue nullStringValue = null;

+        boolean nullValueAdded = false;

+        

+        for ( Value<?> val:vals )

+        {

+            if ( val == null )

+            {

+                // We have a null value. If the HR flag is not set, we will consider 

+                // that the attribute is not HR. We may change this later

+                if ( isHR == null )

+                {

+                    // This is the first value. Add both types, as we 

+                    // don't know yet the attribute type's, but we may

+                    // know later if we add some new value.

+                    // We have to do that because we are using a Set,

+                    // and we can't remove the first element of the Set.

+                    nullBinaryValue = new ClientBinaryValue( null );

+                    nullStringValue = new ClientStringValue( null );

+                    

+                    values.add( nullBinaryValue );

+                    values.add( nullStringValue );

+                    nullValueAdded = true;

+                    nbAdded++;

+                }

+                else if ( !isHR )

+                {

+                    // The attribute type is binary.

+                    nullBinaryValue = new ClientBinaryValue( null );

+                    

+                    // Don't add a value if it already exists. 

+                    if ( !values.contains( nullBinaryValue ) )

+                    {

+                        values.add( nullBinaryValue );

+                        nbAdded++;

+                    }

+                    

+                }

+                else

+                {

+                    // The attribute is HR

+                    nullStringValue = new ClientStringValue( null );

+                    

+                    // Don't add a value if it already exists. 

+                    if ( !values.contains( nullStringValue ) )

+                    {

+                        values.add( nullStringValue );

+                    }

+                }

+            }

+            else

+            {

+                // Let's check the value type. 

+                if ( val instanceof ClientStringValue )

+                {

+                    // We have a String value

+                    if ( isHR == null )

+                    {

+                        // The attribute type will be set to HR

+                        isHR = true;

+                        values.add( val );

+                        nbAdded++;

+                    }

+                    else if ( !isHR )

+                    {

+                        // The attributeType is binary, convert the

+                        // value to a BinaryValue

+                        ClientBinaryValue cbv = new ClientBinaryValue();

+                        cbv.set( StringTools.getBytesUtf8( (String)val.get() ) );

+                        

+                        if ( !contains( cbv ) )

+                        {

+                            values.add( cbv );

+                            nbAdded++;

+                        }

+                    }

+                    else

+                    {

+                        // The attributeType is HR, simply add the value

+                        if ( !contains( val ) )

+                        {

+                            values.add( val );

+                            nbAdded++;

+                        }

+                    }

+                }

+                else

+                {

+                    // We have a Binary value

+                    if ( isHR == null )

+                    {

+                        // The attribute type will be set to binary

+                        isHR = false;

+                        values.add( val );

+                        nbAdded++;

+                    }

+                    else if ( !isHR )

+                    {

+                        // The attributeType is not HR, simply add the value if it does not already exist

+                        if ( !contains( val ) )

+                        {

+                            values.add( val );

+                            nbAdded++;

+                        }

+                    }

+                    else

+                    {

+                        // The attribute Type is HR, convert the

+                        // value to a StringValue

+                        ClientStringValue csv = new ClientStringValue();

+                        csv.set( StringTools.utf8ToString( (byte[])val.get() ) );

+                        

+                        if ( !contains( csv ) )

+                        {

+                            values.add( csv );

+                            nbAdded++;

+                        }

+                    }

+                }

+            }

+        }

+

+        // Last, not least, if a nullValue has been added, and if other 

+        // values are all String, we have to keep the correct nullValue,

+        // and to remove the other

+        if ( nullValueAdded )

+        {

+            if ( isHR ) 

+            {

+                // Remove the Binary value

+                values.remove( nullBinaryValue );

+            }

+            else

+            {

+                // Remove the String value

+                values.remove( nullStringValue );

+            }

+        }

+

+        return nbAdded;

+    }

+

+

+    /**

+     * @see EntryAttribute#add(String...)

+     */

+    public int add( String... vals )

+    {

+        int nbAdded = 0;

+        

+        // First, if the isHR flag is not set, we assume that the

+        // attribute is HR, because we are asked to add some strings.

+        if ( isHR == null )

+        {

+            isHR = true;

+        }

+

+        // Check the attribute type.

+        if ( isHR )

+        {

+            for ( String val:vals )

+            {

+                // Call the add(Value) method, if not already present

+                if ( !contains( val ) )

+                {

+                    if ( add( new ClientStringValue( val ) ) == 1 )

+                    {

+                        nbAdded++;

+                    }

+                }

+            }

+        }

+        else

+        {

+            // The attribute is binary. Transform the String to byte[]

+            for ( String val:vals )

+            {

+                byte[] valBytes = null;

+                

+                if ( val != null )

+                {

+                    valBytes = StringTools.getBytesUtf8( val );

+                }

+                

+                // Now call the add(Value) method

+                if ( add( new ClientBinaryValue( valBytes ) ) == 1 )

+                {

+                    nbAdded++;

+                }

+            }

+        }

+        

+        return nbAdded;

+    }    

+    

+    

+    /**

+     * Adds some values to this attribute. If the new values are already present in

+     * the attribute values, the method has no effect.

+     * <p>

+     * The new values are added at the end of list of values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were added.

+     * </p>

+     * If the value's type is different from the attribute's type,

+     * a conversion is done. For instance, if we try to set some String

+     * into a Binary attribute, we just store the UTF-8 byte array 

+     * encoding for this String.

+     * If we try to store some byte[] in a HR attribute, we try to 

+     * convert those byte[] assuming they represent an UTF-8 encoded

+     * String. Of course, if it's not the case, the stored value will

+     * be incorrect.

+     * <br>

+     * It's the responsibility of the caller to check if the stored

+     * values are consistent with the attribute's type.

+     * <br>

+     * The caller can set the HR flag in order to enforce a type for 

+     * the current attribute, otherwise this type will be set while

+     * adding the first value, using the value's type to set the flag.

+     *

+     * @param val some new values to be added which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int add( byte[]... vals )

+    {

+        int nbAdded = 0;

+        

+        // First, if the isHR flag is not set, we assume that the

+        // attribute is not HR, because we are asked to add some byte[].

+        if ( isHR == null )

+        {

+            isHR = false;

+        }

+

+        // Check the attribute type.

+        if ( isHR )

+        {

+            // The attribute is HR. Transform the byte[] to String

+            for ( byte[] val:vals )

+            {

+                String valString = null;

+                

+                if ( val != null )

+                {

+                    valString = StringTools.utf8ToString( val );

+                }

+                

+                // Now call the add(Value) method, if not already present

+                if ( !contains( val ) )

+                {

+                    if ( add( new ClientStringValue( valString ) ) == 1 )

+                    {

+                        nbAdded++;

+                    }

+                }

+            }

+        }

+        else

+        {

+            for ( byte[] val:vals )

+            {

+                if ( add( new ClientBinaryValue( val ) ) == 1 )

+                {

+                    nbAdded++;

+                }

+            }

+        }

+        

+        return nbAdded;

+    }    

+    

+    

+    /**

+     * Remove all the values from this attribute.

+     */

+    public void clear()

+    {

+        values.clear();

+    }

+

+

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is HR, the binary values will be converted to String before

+     * being checked.

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    public boolean contains( Value<?>... vals )

+    {

+        if ( isHR == null )

+        {

+            // If this flag is null, then there is no values.

+            return false;

+        }

+

+        if ( isHR )

+        {

+            // Iterate through all the values, convert the Binary values

+            // to String values, and quit id any of the values is not

+            // contained in the object

+            for ( Value<?> val:vals )

+            {

+                if ( val instanceof ClientStringValue )

+                {

+                    if ( !values.contains( val ) )

+                    {

+                        return false;

+                    }

+                }

+                else

+                {

+                    byte[] binaryVal = (byte[])val.get();

+                    

+                    // We have to convert the binary value to a String

+                    if ( ! values.contains( new ClientStringValue( StringTools.utf8ToString( binaryVal ) ) ) )

+                    {

+                        return false;

+                    }

+                }

+            }

+        }

+        else

+        {

+            // Iterate through all the values, convert the String values

+            // to binary values, and quit id any of the values is not

+            // contained in the object

+            for ( Value<?> val:vals )

+            {

+                if ( val instanceof ClientBinaryValue )

+                {

+                    if ( !values.contains( val ) )

+                    {

+                        return false;

+                    }

+                }

+                else

+                {

+                    String stringVal = (String)val.get();

+                    

+                    // We have to convert the binary value to a String

+                    if ( ! values.contains( new ClientBinaryValue( StringTools.getBytesUtf8( stringVal ) ) ) )

+                    {

+                        return false;

+                    }

+                }

+            }

+        }

+        

+        return true;

+    }

+

+

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is not HR, the values will be converted to byte[]

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    public boolean contains( String... vals )

+    {

+        if ( isHR == null )

+        {

+            // If this flag is null, then there is no values.

+            return false;

+        }

+

+        if ( isHR )

+        {

+            // Iterate through all the values, and quit if we 

+            // don't find one in the values

+            for ( String val:vals )

+            {

+                if ( !contains( new ClientStringValue( val ) ) )

+                {

+                    return false;

+                }

+            }

+        }

+        else

+        {

+            // As the attribute type is binary, we have to convert 

+            // the values before checking for them in the values

+            // Iterate through all the values, and quit if we 

+            // don't find one in the values

+            for ( String val:vals )

+            {

+                byte[] binaryVal = StringTools.getBytesUtf8( val );

+

+                if ( !contains( new ClientBinaryValue( binaryVal ) ) )

+                {

+                    return false;

+                }

+            }

+        }

+        

+        return true;

+    }

+    

+    

+    /**

+     * <p>

+     * Indicates whether the specified values are some of the attribute's values.

+     * </p>

+     * <p>

+     * If the Attribute is HR, the values will be converted to String

+     * </p>

+     *

+     * @param vals the values

+     * @return true if this attribute contains all the values, otherwise false

+     */

+    public boolean contains( byte[]... vals )

+    {

+        if ( isHR == null )

+        {

+            // If this flag is null, then there is no values.

+            return false;

+        }

+

+        if ( !isHR )

+        {

+            // Iterate through all the values, and quit if we 

+            // don't find one in the values

+            for ( byte[] val:vals )

+            {

+                if ( !contains( new ClientBinaryValue( val ) ) )

+                {

+                    return false;

+                }

+            }

+        }

+        else

+        {

+            // As the attribute type is String, we have to convert 

+            // the values before checking for them in the values

+            // Iterate through all the values, and quit if we 

+            // don't find one in the values

+            for ( byte[] val:vals )

+            {

+                String stringVal = StringTools.utf8ToString( val );

+

+                if ( !contains( new ClientStringValue( stringVal ) ) )

+                {

+                    return false;

+                }

+            }

+        }

+        

+        return true;

+    }

+    

+    

+    /**

+     * @see EntryAttribute#contains(Object...)

+     */

+    public boolean contains( Object... vals )

+    {

+        boolean isHR = true;

+        boolean seen = false;

+        

+        // Iterate through all the values, and quit if we 

+        // don't find one in the values

+        for ( Object val:vals )

+        {

+            if ( ( val instanceof String ) ) 

+            {

+                if ( !seen )

+                {

+                    isHR = true;

+                    seen = true;

+                }

+

+                if ( isHR )

+                {

+                    if ( !contains( (String)val ) )

+                    {

+                        return false;

+                    }

+                }

+                else

+                {

+                    return false;

+                }

+            }

+            else

+            {

+                if ( !seen )

+                {

+                    isHR = false;

+                    seen = true;

+                }

+

+                if ( !isHR )

+                {

+                    if ( !contains( (byte[])val ) )

+                    {

+                        return false;

+                    }

+                }

+                else

+                {

+                    return false;

+                }

+            }

+        }

+        

+        return true;

+    }

+

+    

+    /**

+     * <p>

+     * Get the first value of this attribute. If there is none, 

+     * null is returned.

+     * </p>

+     * <p>

+     * Note : even if we are storing values into a Set, one can assume

+     * the values are ordered following the insertion order.

+     * </p>

+     * <p> 

+     * This method is meant to be used if the attribute hold only one value.

+     * </p>

+     * 

+     *  @return The first value for this attribute.

+     */

+    public Value<?> get()

+    {

+        if ( values.isEmpty() )

+        {

+            return null;

+        }

+        

+        return values.iterator().next();

+    }

+

+

+    /**

+     * Returns an iterator over all the attribute's values.

+     * <p>

+     * The effect on the returned enumeration of adding or removing values of

+     * the attribute is not specified.

+     * </p>

+     * <p>

+     * This method will throw any <code>NamingException</code> that occurs.

+     * </p>

+     *

+     * @return an enumeration of all values of the attribute

+     */

+    public Iterator<Value<?>> getAll()

+    {

+        return iterator();

+    }

+

+

+    /**

+     * Retrieves the number of values in this attribute.

+     *

+     * @return the number of values in this attribute, including any values

+     * wrapping a null value if there is one

+     */

+    public int size()

+    {

+        return values.size();

+    }

+

+

+    /**

+     * <p>

+     * Removes all the  values that are equal to the given values.

+     * </p>

+     * <p>

+     * Returns true if all the values are removed.

+     * </p>

+     * <p>

+     * If the attribute type is HR and some value which are not String, we

+     * will convert the values first (same thing for a non-HR attribute).

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    public boolean remove( Value<?>... vals )

+    {

+        if ( ( isHR == null ) || ( values.size() == 0 ) ) 

+        {

+            // Trying to remove a value from an empty list will fail

+            return false;

+        }

+        

+        boolean removed = true;

+        

+        if ( isHR )

+        {

+            for ( Value<?> val:vals )

+            {

+                if ( val instanceof ClientStringValue )

+                {

+                    removed &= values.remove( val );

+                }

+                else

+                {

+                    // Convert the binary value to a string value

+                    byte[] binaryVal = (byte[])val.get();

+                    removed &= values.remove( new ClientStringValue( StringTools.utf8ToString( binaryVal ) ) );

+                }

+            }

+        }

+        else

+        {

+            for ( Value<?> val:vals )

+            {

+                if ( val instanceof ClientBinaryValue )

+                {

+                    removed &= values.remove( val );

+                }

+                else

+                {

+                    String stringVal = (String)val.get();

+                    removed &= values.remove( new ClientBinaryValue( StringTools.getBytesUtf8( stringVal ) ) );

+                }

+            }

+        }

+        

+        return removed;

+    }

+

+

+    /**

+     * <p>

+     * Removes all the  values that are equal to the given values.

+     * </p>

+     * <p>

+     * Returns true if all the values are removed.

+     * </p>

+     * <p>

+     * If the attribute type is HR, then the values will be first converted

+     * to String

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    public boolean remove( byte[]... vals )

+    {

+        if ( ( isHR == null ) || ( values.size() == 0 ) ) 

+        {

+            // Trying to remove a value from an empty list will fail

+            return false;

+        }

+        

+        boolean removed = true;

+        

+        if ( !isHR )

+        {

+            // The attribute type is not HR, we can directly process the values

+            for ( byte[] val:vals )

+            {

+                ClientBinaryValue value = new ClientBinaryValue( val );

+                removed &= values.remove( value );

+            }

+        }

+        else

+        {

+            // The attribute type is String, we have to convert the values

+            // to String before removing them

+            for ( byte[] val:vals )

+            {

+                ClientStringValue value = new ClientStringValue( StringTools.utf8ToString( val ) );

+                removed &= values.remove( value );

+            }

+        }

+        

+        return removed;

+    }

+

+

+    /**

+     * Removes all the  values that are equal to the given values.

+     * <p>

+     * Returns true if all the values are removed.

+     * </p>

+     * <p>

+     * If the attribute type is not HR, then the values will be first converted

+     * to byte[]

+     * </p>

+     *

+     * @param vals the values to be removed

+     * @return true if all the values are removed, otherwise false

+     */

+    public boolean remove( String... vals )

+    {

+        if ( ( isHR == null ) || ( values.size() == 0 ) ) 

+        {

+            // Trying to remove a value from an empty list will fail

+            return false;

+        }

+        

+        boolean removed = true;

+        

+        if ( isHR )

+        {

+            // The attribute type is HR, we can directly process the values

+            for ( String val:vals )

+            {

+                ClientStringValue value = new ClientStringValue( val );

+                removed &= values.remove( value );

+            }

+        }

+        else

+        {

+            // The attribute type is binary, we have to convert the values

+            // to byte[] before removing them

+            for ( String val:vals )

+            {

+                ClientBinaryValue value = new ClientBinaryValue( StringTools.getBytesUtf8( val ) );

+                removed &= values.remove( value );

+            }

+        }

+        

+        return removed;

+    }

+

+

+    /**

+     * An iterator on top of the stored values.

+     * 

+     * @return an iterator over the stored values.

+     */

+    public Iterator<Value<?>> iterator()

+    {

+        return values.iterator();

+    }

+    

+    

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int put( String... vals )

+    {

+        values.clear();

+        return add( vals );

+    }

+    

+    

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int put( byte[]... vals )

+    {

+        values.clear();

+        return add( vals );

+    }

+

+    

+    /**

+     * Puts some values to this attribute.

+     * <p>

+     * The new values are replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param val some values to be put which may be null

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int put( Value<?>... vals )

+    {

+        values.clear();

+        return add( vals );

+    }

+    

+    

+    /**

+     * <p>

+     * Puts a list of values into this attribute.

+     * </p>

+     * <p>

+     * The new values will replace the previous values.

+     * </p>

+     * <p>

+     * This method returns the number of values that were put.

+     * </p>

+     *

+     * @param vals the values to be put

+     * @return the number of added values, or 0 if none has been added

+     */

+    public int put( List<Value<?>> vals )

+    {

+        values.clear();

+        

+        // Transform the List to an array

+        Value<?>[] valArray = new Value<?>[vals.size()];

+        return add( vals.toArray( valArray ) );

+    }

+    

+    //-------------------------------------------------------------------------

+    // Overloaded Object classes

+    //-------------------------------------------------------------------------

+    /**

+     * The hashCode is based on the id, the isHR flag and 

+     * on the internal values.

+     *  

+     * @see Object#hashCode()

+     * @return the instance's hashcode 

+     */

+    public int hashCode()

+    {

+        int h = 37;

+        

+        if ( isHR != null )

+        {

+            h = h*17 + isHR.hashCode();

+        }

+        

+        if ( id != null )

+        {

+            h = h*17 + id.hashCode();

+        }

+        

+        for ( Value<?> value:values )

+        {

+            h = h*17 + value.hashCode();

+        }

+        

+        return h;

+    }

+    

+    

+    /**

+     * @see Object#equals(Object)

+     */

+    public boolean equals( Object obj )

+    {

+        if ( obj == this )

+        {

+            return true;

+        }

+        

+        if ( ! (obj instanceof EntryAttribute ) )

+        {

+            return false;

+        }

+        

+        EntryAttribute other = (EntryAttribute)obj;

+        

+        if ( id == null )

+        {

+            if ( other.getId() != null )

+            {

+                return false;

+            }

+        }

+        else

+        {

+            if ( other.getId() == null )

+            {

+                return false;

+            }

+            else

+            {

+                if ( !id.equals( other.getId() ) )

+                {

+                    return false;

+                }

+            }

+        }

+        

+        if ( isHR() !=  other.isHR() )

+        {

+            return false;

+        }

+        

+        if ( values.size() != other.size() )

+        {

+            return false;

+        }

+        

+        for ( Value<?> val:values )

+        {

+            if ( ! other.contains( val ) )

+            {

+                return false;

+            }

+        }

+        

+        return true;

+    }

+    

+    

+    /**

+     * @see Cloneable#clone()

+     */

+    public EntryAttribute clone()

+    {

+        try

+        {

+            DefaultClientAttribute attribute = (DefaultClientAttribute)super.clone();

+            

+            attribute.values = new LinkedHashSet<Value<?>>( values.size() );

+            

+            for ( Value<?> value:values )

+            {

+                attribute.values.add( value.clone() );

+            }

+            

+            return attribute;

+        }

+        catch ( CloneNotSupportedException cnse )

+        {

+            return null;

+        }

+    }

+    

+    

+    /**

+     * @see Object#toString() 

+     */

+    public String toString()

+    {

+        StringBuilder sb = new StringBuilder();

+        

+        if ( ( values != null ) && ( values.size() != 0 ) )

+        {

+            for ( Value<?> value:values )

+            {

+                sb.append( "    " ).append( upId ).append( ": " );

+                

+                if ( value.isNull() )

+                {

+                    sb.append( "''" );

+                }

+                else

+                {

+                    sb.append( value );

+                }

+                

+                sb.append( '\n' );

+            }

+        }

+        else

+        {

+            sb.append( "    " ).append( upId ).append( ": (null)\n" );

+        }

+        

+        return sb.toString();

+    }

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntry.java
new file mode 100644
index 0000000..0fd68da
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntry.java
@@ -0,0 +1,1170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry.client;
+
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.entry.AbstractEntry;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A default implementation of a ServerEntry which should suite most
+ * use cases.
+ * 
+ * This class is final, it should not be extended.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public final class DefaultClientEntry extends AbstractEntry<String> implements ClientEntry, Externalizable
+{
+    /** Used for serialization */
+    private static final long serialVersionUID = 2L;
+    
+    /** The logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( DefaultClientEntry.class );
+
+    //-------------------------------------------------------------------------
+    // Constructors
+    //-------------------------------------------------------------------------
+    /**
+     * Creates a new instance of DefaultClientEntry. 
+     * <p>
+     * This entry <b>must</b> be initialized before being used !
+     */
+    public DefaultClientEntry()
+    {
+    }
+
+
+    /**
+     * Creates a new instance of DefaultServerEntry, with a 
+     * DN. 
+     * 
+     * @param dn The DN for this serverEntry. Can be null.
+     */
+    public DefaultClientEntry( LdapDN dn )
+    {
+        this.dn = dn;
+    }
+
+
+    /**
+     * Creates a new instance of DefaultServerEntry, with a 
+     * DN and a list of IDs. 
+     * 
+     * @param dn The DN for this serverEntry. Can be null.
+     * @param upIds The list of attributes to create.
+     */
+    public DefaultClientEntry( LdapDN dn, String... upIds )
+    {
+        this.dn = dn;
+
+        for ( String upId:upIds )
+        {
+            // Add a new AttributeType without value
+            set( upId );
+        }
+    }
+
+    
+    /**
+     * <p>
+     * Creates a new instance of DefaultClientEntry, with a 
+     * DN and a list of EntryAttributes.
+     * </p> 
+     * 
+     * @param dn The DN for this serverEntry. Can be null
+     * @param attributes The list of attributes to create
+     */
+    public DefaultClientEntry( LdapDN dn, EntryAttribute... attributes )
+    {
+        this.dn = dn;
+
+        for ( EntryAttribute attribute:attributes )
+        {
+            if ( attribute == null )
+            {
+                continue;
+            }
+            
+            // Store a new ClientAttribute
+            this.attributes.put( attribute.getId(), attribute );
+        }
+    }
+
+    
+    //-------------------------------------------------------------------------
+    // Helper methods
+    //-------------------------------------------------------------------------
+    private String getId( String upId ) throws IllegalArgumentException
+    {
+        String id = StringTools.trim( StringTools.toLowerCase( upId ) );
+        
+        // If empty, throw an error
+        if ( ( id == null ) || ( id.length() == 0 ) ) 
+        {
+            String message = "The attributeType ID should not be null or empty";
+            LOG.error( message );
+            throw new IllegalArgumentException( message );
+        }
+        
+        return id;
+    }
+
+    
+    //-------------------------------------------------------------------------
+    // Entry methods
+    //-------------------------------------------------------------------------
+    /**
+     * Add some Attributes to the current Entry.
+     *
+     * @param attributes The attributes to add
+     * @throws NamingException If we can't add any of the attributes
+     */
+    public void add( EntryAttribute... attributes ) throws NamingException
+    {
+        // Loop on all the added attributes
+        for ( EntryAttribute attribute:attributes )
+        {
+            // If the attribute already exist, we will add the new values.
+            if ( contains( attribute ) )
+            {
+                EntryAttribute existingAttr = get( attribute.getId() );
+                
+                // Loop on all the values, and add them to the existing attribute
+                for ( Value<?> value:attribute )
+                {
+                    existingAttr.add( value );
+                }
+            }
+            else
+            {
+                // Stores the attribute into the entry
+                this.attributes.put( attribute.getId(), (ClientAttribute)attribute );
+            }
+        }
+    }
+
+    
+    /**
+     * Add an attribute (represented by its ID and binary values) into an entry. 
+     *
+     * @param upId The attribute ID
+     * @param values The list of binary values to inject. It can be empty
+     * @throws NamingException If the attribute does not exist
+     */
+    public void add( String upId, byte[]... values ) throws NamingException
+    {
+        // First, transform the upID to a valid ID
+        String id = getId( upId );
+        
+        // Now, check to see if we already have such an attribute
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute != null )
+        {
+            // This Attribute already exist, we add the values 
+            // into it. (If the values already exists, they will
+            // not be added, but this is done in the add() method)
+            attribute.add( values );
+            attribute.setUpId( upId );
+        }
+        else
+        {
+            // We have to create a new Attribute and set the values
+            // and the upId
+            attributes.put( id, new DefaultClientAttribute( upId, values ) );
+        }
+    }
+
+
+    /**
+     * Add some String values to the current Entry.
+     *
+     * @param upId The user provided ID of the attribute we want to add 
+     * some values to
+     * @param values The list of String values to add
+     * @throws NamingException If we can't add any of the values
+     */
+    public void add( String upId, String... values ) throws NamingException
+    {
+        // First, transform the upID to a valid ID
+        String id = getId( upId );
+
+        // Now, check to see if we already have such an attribute
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute != null )
+        {
+            // This Attribute already exist, we add the values 
+            // into it. (If the values already exists, they will
+            // not be added, but this is done in the add() method)
+            attribute.add( values );
+            attribute.setUpId( upId );
+        }
+        else
+        {
+            // We have to create a new Attribute and set the values
+            // and the upId
+            attributes.put( id, new DefaultClientAttribute( upId, values ) );
+        }
+    }
+
+
+    /**
+     * Add an attribute (represented by its ID and Value values) into an entry. 
+     *
+     * @param upId The attribute ID
+     * @param values The list of Value values to inject. It can be empty
+     * @throws NamingException If the attribute does not exist
+     */
+    public void add( String upId, Value<?>... values ) throws NamingException
+    {
+        // First, transform the upID to a valid ID
+        String id = getId( upId );
+
+        // Now, check to see if we already have such an attribute
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute != null )
+        {
+            // This Attribute already exist, we add the values 
+            // into it. (If the values already exists, they will
+            // not be added, but this is done in the add() method)
+            attribute.add( values );
+            attribute.setUpId( upId );
+        }
+        else
+        {
+            // We have to create a new Attribute and set the values
+            // and the upId
+            attributes.put( id, new DefaultClientAttribute( upId, values ) );
+        }
+    }
+
+
+    /**
+     * Clone an entry. All the element are duplicated, so a modification on
+     * the original object won't affect the cloned object, as a modification
+     * on the cloned object has no impact on the original object
+     */
+    public Entry clone()
+    {
+        // First, clone the structure
+        DefaultClientEntry clone = (DefaultClientEntry)super.clone();
+        
+        // Just in case ... Should *never* happen
+        if ( clone == null )
+        {
+            return null;
+        }
+        
+        // An Entry has a DN and many attributes.
+        // First, clone the DN, if not null.
+        if ( dn != null )
+        {
+            clone.setDn( (LdapDN)dn.clone() );
+        }
+        
+        // then clone the ClientAttribute Map.
+        clone.attributes = (Map<String, EntryAttribute>)(((HashMap<String, EntryAttribute>)attributes).clone());
+        
+        // now clone all the attributes
+        clone.attributes.clear();
+        
+        for ( EntryAttribute attribute:attributes.values() )
+        {
+            clone.attributes.put( attribute.getId(), attribute.clone() );
+        }
+        
+        // We are done !
+        return clone;
+    }
+    
+
+    /**
+     * <p>
+     * Checks if an entry contains a list of attributes.
+     * </p>
+     * <p>
+     * If the list is null or empty, this method will return <code>true</code>
+     * if the entry has no attribute, <code>false</code> otherwise.
+     * </p>
+     *
+     * @param attributes The Attributes to look for
+     * @return <code>true</code> if all the attributes are found within 
+     * the entry, <code>false</code> if at least one of them is not present.
+     * @throws NamingException If the attribute does not exist
+     */
+    public boolean contains( EntryAttribute... attributes ) throws NamingException
+    {
+        for ( EntryAttribute attribute:attributes )
+        {
+            if ( attribute == null )
+            {
+                return this.attributes.size() == 0;
+            }
+            
+            if ( !this.attributes.containsKey( attribute.getId() ) )
+            {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    
+    /**
+     * Checks if an entry contains a specific attribute
+     *
+     * @param attributes The Attributes to look for
+     * @return <code>true</code> if the attributes are found within the entry
+     * @throws NamingException If the attribute does not exist
+     */
+    public boolean contains( String upId ) throws NamingException
+    {
+        String id = getId( upId );
+        
+        return attributes.containsKey( id );
+    }
+
+    
+    /**
+     * Checks if an entry contains an attribute with some binary values.
+     *
+     * @param id The Attribute we are looking for.
+     * @param values The searched values.
+     * @return <code>true</code> if all the values are found within the attribute,
+     * false if at least one value is not present or if the ID is not valid. 
+     */
+    public boolean contains( String upId, byte[]... values )
+    {
+        String id = getId( upId );
+        
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute == null )
+        {
+            return false;
+        }
+        
+        return attribute.contains( values );
+    }
+    
+    
+    /**
+     * Checks if an entry contains an attribute with some String values.
+     *
+     * @param id The Attribute we are looking for.
+     * @param values The searched values.
+     * @return <code>true</code> if all the values are found within the attribute,
+     * false if at least one value is not present or if the ID is not valid. 
+     */
+    public boolean contains( String upId, String... values )
+    {
+        String id = getId( upId );
+        
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute == null )
+        {
+            return false;
+        }
+        
+        return attribute.contains( values );
+    }
+    
+    
+    /**
+     * Checks if an entry contains an attribute with some values.
+     *
+     * @param id The Attribute we are looking for.
+     * @param values The searched values.
+     * @return <code>true</code> if all the values are found within the attribute,
+     * false if at least one value is not present or if the ID is not valid. 
+     */
+    public boolean contains( String upId, Value<?>... values )
+    {
+        String id = getId( upId );
+        
+        EntryAttribute attribute = attributes.get( id );
+        
+        if ( attribute == null )
+        {
+            return false;
+        }
+        
+        return attribute.contains( values );
+    }
+    
+    
+    /**
+     * Checks if an entry contains some specific attributes.
+     *
+     * @param attributes The Attributes to look for.
+     * @return <code>true</code> if the attributes are all found within the entry.
+     */
+    public boolean containsAttribute( String... attributes )
+    {
+        for ( String attribute:attributes )
+        {
+            String id = getId( attribute );
+    
+            if ( !this.attributes.containsKey( id ) )
+            {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    
+    /**
+     * <p>
+     * Returns the attribute with the specified alias. The return value
+     * is <code>null</code> if no match is found.  
+     * </p>
+     * <p>An Attribute with an id different from the supplied alias may 
+     * be returned: for example a call with 'cn' may in some implementations 
+     * return an Attribute whose getId() field returns 'commonName'.
+     * </p>
+     *
+     * @param alias an aliased name of the attribute identifier
+     * @return the attribute associated with the alias
+     */
+    public EntryAttribute get( String alias )
+    {
+        try
+        {
+            String id = getId( alias );
+            
+            return attributes.get( id );
+        }
+        catch( IllegalArgumentException iea )
+        {
+            LOG.error( "An exception has been raised while looking for attribute id {}''", alias );
+            return null;
+        }
+    }
+
+
+    /**
+     * <p>
+     * Put an attribute (represented by its ID and some binary values) into an entry. 
+     * </p>
+     * <p> 
+     * If the attribute already exists, the previous attribute will be 
+     * replaced and returned.
+     * </p>
+     *
+     * @param upId The attribute ID
+     * @param values The list of binary values to put. It can be empty.
+     * @return The replaced attribute
+     */
+    public EntryAttribute put( String upId, byte[]... values )
+    {
+        // Get the normalized form of the ID
+        String id = getId( upId );
+        
+        // Create a new attribute
+        ClientAttribute clientAttribute = new DefaultClientAttribute( upId, values );
+
+        // Replace the previous one, and return it back
+        return attributes.put( id, clientAttribute );
+    }
+
+
+    /**
+     * <p>
+     * Put an attribute (represented by its ID and some String values) into an entry. 
+     * </p>
+     * <p> 
+     * If the attribute already exists, the previous attribute will be 
+     * replaced and returned.
+     * </p>
+     *
+     * @param upId The attribute ID
+     * @param values The list of String values to put. It can be empty.
+     * @return The replaced attribute
+     */
+    public EntryAttribute put( String upId, String... values )
+    {
+        // Get the normalized form of the ID
+        String id = getId( upId );
+        
+        // Create a new attribute
+        ClientAttribute clientAttribute = new DefaultClientAttribute( upId, values );
+
+        // Replace the previous one, and return it back
+        return attributes.put( id, clientAttribute );
+    }
+
+
+    /**
+     * <p>
+     * Put an attribute (represented by its ID and some values) into an entry. 
+     * </p>
+     * <p> 
+     * If the attribute already exists, the previous attribute will be 
+     * replaced and returned.
+     * </p>
+     *
+     * @param upId The attribute ID
+     * @param values The list of values to put. It can be empty.
+     * @return The replaced attribute
+     */
+    public EntryAttribute put( String upId, Value<?>... values )
+    {
+        // Get the normalized form of the ID
+        String id = getId( upId );
+        
+        // Create a new attribute
+        ClientAttribute clientAttribute = new DefaultClientAttribute( upId, values );
+
+        // Replace the previous one, and return it back
+        return attributes.put( id, clientAttribute );
+    }
+
+
+    /**
+     * <p>
+     * Put some new ClientAttribute using the User Provided ID. 
+     * No value is inserted. 
+     * </p>
+     * <p>
+     * If an existing Attribute is found, it will be replaced by an
+     * empty attribute, and returned to the caller.
+     * </p>
+     * 
+     * @param upIds The user provided IDs of the AttributeTypes to add.
+     * @return A list of replaced Attributes.
+     */
+    public List<EntryAttribute> set( String... upIds )
+    {
+        if ( upIds == null )
+        {
+            String message = "The AttributeType list should not be null";
+            LOG.error( message );
+            throw new IllegalArgumentException( message );
+        }
+        
+        List<EntryAttribute> returnedClientAttributes = new ArrayList<EntryAttribute>();
+        
+        // Now, loop on all the attributeType to add
+        for ( String upId:upIds )
+        {
+            String id = StringTools.trim( StringTools.toLowerCase( upId ) );
+            
+            if ( id == null )
+            {
+                String message = "The AttributeType list should not contain null values";
+                LOG.error( message );
+                throw new IllegalArgumentException( message );
+            }
+            
+            if ( attributes.containsKey( id ) )
+            {
+                // Add the removed serverAttribute to the list
+                returnedClientAttributes.add( attributes.remove( id ) );
+            }
+
+            ClientAttribute newAttribute = new DefaultClientAttribute( upId );
+            attributes.put( id, newAttribute );
+        }
+        
+        return returnedClientAttributes;
+    }
+
+    
+    /**
+     * <p>
+     * Places attributes in the attribute collection. 
+     * </p>
+     * <p>If there is already an attribute with the same ID as any of the 
+     * new attributes, the old ones are removed from the collection and 
+     * are returned by this method. If there was no attribute with the 
+     * same ID the return value is <code>null</code>.
+     *</p>
+     *
+     * @param attributes the attributes to be put
+     * @return the old attributes with the same OID, if exist; otherwise
+     *         <code>null</code>
+     * @exception NamingException if the operation fails
+     */
+    public List<EntryAttribute> put( EntryAttribute... attributes ) throws NamingException
+    {
+        // First, get the existing attributes
+        List<EntryAttribute> previous = new ArrayList<EntryAttribute>();
+        
+        for ( EntryAttribute attribute:attributes )
+        {
+            String id = attribute.getId();
+            
+            if ( contains( id ) )
+            {
+                // Store the attribute and remove it from the list
+                previous.add( get( id ) );
+                this.attributes.remove( id );
+            }
+            
+            // add the new one
+            this.attributes.put( id, (ClientAttribute)attribute );            
+        }
+        
+        // return the previous attributes
+        return previous;
+    }
+
+
+    public List<EntryAttribute> remove( EntryAttribute... attributes ) throws NamingException
+    {
+        List<EntryAttribute> removedAttributes = new ArrayList<EntryAttribute>();
+        
+        for ( EntryAttribute attribute:attributes )
+        {
+            if ( contains( attribute.getId() ) )
+            {
+                this.attributes.remove( attribute.getId() );
+                removedAttributes.add( attribute );
+            }
+        }
+        
+        return removedAttributes;
+    }
+
+
+    /**
+     * <p>
+     * Removes the attribute with the specified alias. 
+     * </p>
+     * <p>
+     * The removed attribute are returned by this method. 
+     * </p>
+     * <p>
+     * If there is no attribute with the specified alias,
+     * the return value is <code>null</code>.
+     * </p>
+     *
+     * @param attributes an aliased name of the attribute to be removed
+     * @return the removed attributes, if any, as a list; otherwise <code>null</code>
+     */
+    public List<EntryAttribute> removeAttributes( String... attributes )
+    {
+        if ( attributes.length == 0 )
+        {
+            return null;
+        }
+        
+        List<EntryAttribute> removed = new ArrayList<EntryAttribute>( attributes.length );
+        
+        for ( String attribute:attributes )
+        {
+            EntryAttribute attr = get( attribute );
+            
+            if ( attr != null )
+            {
+                removed.add( this.attributes.remove( attr.getId() ) );
+            }
+            else
+            {
+                String message = "The attribute '" + attribute + "' does not exist in the entry";
+                LOG.warn( message );
+                continue;
+            }
+        }
+        
+        if ( removed.size() == 0 )
+        {
+            return null;
+        }
+        else
+        {
+            return removed;
+        }
+    }
+
+
+    /**
+     * <p>
+     * Removes the specified binary values from an attribute.
+     * </p>
+     * <p>
+     * If at least one value is removed, this method returns <code>true</code>.
+     * </p>
+     * <p>
+     * If there is no more value after having removed the values, the attribute
+     * will be removed too.
+     * </p>
+     * <p>
+     * If the attribute does not exist, nothing is done and the method returns 
+     * <code>false</code>
+     * </p> 
+     *
+     * @param upId The attribute ID  
+     * @param values the values to be removed
+     * @return <code>true</code> if at least a value is removed, <code>false</code>
+     * if not all the values have been removed or if the attribute does not exist. 
+     */
+    public boolean remove( String upId, byte[]... values ) throws NamingException
+    {
+        try
+        {
+            String id = getId( upId );
+            
+            EntryAttribute attribute = get( id );
+            
+            if ( attribute == null )
+            {
+                // Can't remove values from a not existing attribute !
+                return false;
+            }
+            
+            int nbOldValues = attribute.size();
+            
+            // Remove the values
+            attribute.remove( values );
+            
+            if ( attribute.size() == 0 )
+            {
+                // No mare values, remove the attribute
+                attributes.remove( id );
+                
+                return true;
+            }
+            
+            if ( nbOldValues != attribute.size() )
+            {
+                // At least one value have been removed, return true.
+                return true;
+            }
+            else
+            {
+                // No values have been removed, return false.
+                return false;
+            }
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
+            return false;
+        }
+    }
+
+
+    /**
+     * <p>
+     * Removes the specified String values from an attribute.
+     * </p>
+     * <p>
+     * If at least one value is removed, this method returns <code>true</code>.
+     * </p>
+     * <p>
+     * If there is no more value after having removed the values, the attribute
+     * will be removed too.
+     * </p>
+     * <p>
+     * If the attribute does not exist, nothing is done and the method returns 
+     * <code>false</code>
+     * </p> 
+     *
+     * @param upId The attribute ID  
+     * @param attributes the attributes to be removed
+     * @return <code>true</code> if at least a value is removed, <code>false</code>
+     * if not all the values have been removed or if the attribute does not exist. 
+     */
+    public boolean remove( String upId, String... values ) throws NamingException
+    {
+        try
+        {
+            String id = getId( upId );
+            
+            EntryAttribute attribute = get( id );
+            
+            if ( attribute == null )
+            {
+                // Can't remove values from a not existing attribute !
+                return false;
+            }
+            
+            int nbOldValues = attribute.size();
+            
+            // Remove the values
+            attribute.remove( values );
+            
+            if ( attribute.size() == 0 )
+            {
+                // No mare values, remove the attribute
+                attributes.remove( id );
+                
+                return true;
+            }
+            
+            if ( nbOldValues != attribute.size() )
+            {
+                // At least one value have been removed, return true.
+                return true;
+            }
+            else
+            {
+                // No values have been removed, return false.
+                return false;
+            }
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
+            return false;
+        }
+    }
+
+
+    /**
+     * <p>
+     * Removes the specified values from an attribute.
+     * </p>
+     * <p>
+     * If at least one value is removed, this method returns <code>true</code>.
+     * </p>
+     * <p>
+     * If there is no more value after having removed the values, the attribute
+     * will be removed too.
+     * </p>
+     * <p>
+     * If the attribute does not exist, nothing is done and the method returns 
+     * <code>false</code>
+     * </p> 
+     *
+     * @param upId The attribute ID  
+     * @param attributes the attributes to be removed
+     * @return <code>true</code> if at least a value is removed, <code>false</code>
+     * if not all the values have been removed or if the attribute does not exist. 
+     */
+    public boolean remove( String upId, Value<?>... values ) throws NamingException
+    {
+        try
+        {
+            String id = getId( upId );
+            
+            EntryAttribute attribute = get( id );
+            
+            if ( attribute == null )
+            {
+                // Can't remove values from a not existing attribute !
+                return false;
+            }
+            
+            int nbOldValues = attribute.size();
+            
+            // Remove the values
+            attribute.remove( values );
+            
+            if ( attribute.size() == 0 )
+            {
+                // No mare values, remove the attribute
+                attributes.remove( id );
+                
+                return true;
+            }
+            
+            if ( nbOldValues != attribute.size() )
+            {
+                // At least one value have been removed, return true.
+                return true;
+            }
+            else
+            {
+                // No values have been removed, return false.
+                return false;
+            }
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            LOG.error( "The removal of values for the missing '{}' attribute is not possible", upId );
+            return false;
+        }
+    }
+
+
+    public Iterator<EntryAttribute> iterator()
+    {
+        return Collections.unmodifiableMap( attributes ).values().iterator();
+    }
+
+
+    /**
+     * @see Externalizable#writeExternal(ObjectOutput)<p>
+     * 
+     * This is the place where we serialize entries, and all theirs
+     * elements. the reason why we don't call the underlying methods
+     * (<code>ClientAttribute.write(), Value.write()</code>) is that we need
+     * access to the registries to read back the values.
+     * <p>
+     * The structure used to store the entry is the following :
+     * <li><b>[DN length]</b> : can be -1 if we don't have a DN, 0 if the 
+     * DN is empty, otherwise contains the DN's length.<p> 
+     * <b>NOTE :</b>This should be unnecessary, as the DN should always exists
+     * <p>
+     * </li>
+     * <li>
+     * <b>DN</b> : The entry's DN. Can be empty (rootDSE=<p>
+     * </li>
+     * We have to store the UPid, and all the values, if any.
+     */
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        // First, the DN
+        if ( dn == null )
+        {
+            // Write an empty DN
+            LdapDN.EMPTY_LDAPDN.writeExternal( out );
+        }
+        else
+        {
+            // Write the DN
+            out.writeObject( dn );
+        }
+        
+        // Then the attributes. 
+        if ( attributes == null )
+        {
+            // A negative number denotes no attributes
+            out.writeInt( -1 );
+        }
+        else
+        {
+            // Store the attributes' nulber first
+            out.writeInt( attributes.size() );
+            
+            // Iterate through the keys. We store the Attribute
+            // here, to be able to restore it in the readExternal :
+            // we need access to the registries, which are not available
+            // in the ClientAttribute class.
+            for ( EntryAttribute attribute:attributes.values() )
+            {
+                // Store the UP id
+                out.writeUTF( attribute.getUpId() );
+                
+                // The number of values
+                int nbValues = attribute.size();
+                
+                if ( nbValues == 0 ) 
+                {
+                    out.writeInt( 0 );
+                }
+                else 
+                {
+                    out.writeInt( nbValues );
+
+                    for ( Value<?> value:attribute )
+                    {
+                        out.writeObject( value );
+                    }
+                }
+            }
+        }
+        
+        out.flush();
+    }
+
+    
+    /**
+     * @see Externalizable#readExternal(ObjectInput)
+     */
+    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+    {
+        // Read the DN
+        LdapDN dn = (LdapDN)in.readObject();
+        
+        // Read the number of attributes
+        int nbAttributes = in.readInt();
+        
+        attributes = new HashMap<String, EntryAttribute>();
+
+        // Read the attributes
+        for ( int i = 0; i < nbAttributes; i++ )
+        {
+            String upId = in.readUTF();
+            
+            EntryAttribute attribute = new DefaultClientAttribute( upId );
+            
+            // Read the number of values
+            int nbValues = in.readInt();
+            
+            for ( int j = 0; j < nbValues; j++ )
+            {
+                Value<?> value = (Value<?>)in.readObject();
+                attribute.add( value );
+            }
+            
+            attributes.put( attribute.getId(), attribute );
+        }
+    }
+    
+    
+    /**
+     * Get the hash code of this ClientEntry.
+     *
+     * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int result = 37;
+        
+        result = result*17 + dn.hashCode();
+        
+        SortedMap<String, EntryAttribute> sortedMap = new TreeMap<String, EntryAttribute>();
+        
+        for ( String id:attributes.keySet() )
+        {
+            sortedMap.put( id, attributes.get( id ) );
+        }
+        
+        for ( String id:sortedMap.keySet() )
+        {
+            result = result*17 + sortedMap.get( id ).hashCode();
+        }
+        
+        return result;
+    }
+
+    
+    /**
+     * Tells if an entry has a specific ObjectClass value
+     * 
+     * @param objectClass The ObjectClass we want to check
+     * @return <code>true</code> if the ObjectClass value is present 
+     * in the ObjectClass attribute
+     */
+    public boolean hasObjectClass( String objectClass )
+    {
+        return contains( "objectclass", objectClass );
+    }
+
+
+    /**
+     * @see Object#equals(Object)
+     */
+    public boolean equals( Object o )
+    {
+        // Short circuit
+
+        if ( this == o )
+        {
+            return true;
+        }
+        
+        if ( ! ( o instanceof DefaultClientEntry ) )
+        {
+            return false;
+        }
+        
+        DefaultClientEntry other = (DefaultClientEntry)o;
+        
+        // Both DN must be equal
+        if ( dn == null )
+        {
+            if ( other.getDn() != null )
+            {
+                return false;
+            }
+        }
+        else
+        {
+            if ( !dn.equals( other.getDn() ) )
+            {
+                return false;
+            }
+        }
+        
+        // They must have the same number of attributes
+        if ( size() != other.size() )
+        {
+            return false;
+        }
+        
+        // Each attribute must be equal
+        for ( EntryAttribute attribute:other )
+        {
+            if ( !attribute.equals( this.get( attribute.getId() ) ) )
+            {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+        
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        
+        sb.append( "ClientEntry\n" );
+        sb.append( "    dn: " ).append( dn ).append( '\n' );
+        
+        // First dump the ObjectClass attribute
+        if ( containsAttribute( "objectClass" ) )
+        {
+            EntryAttribute objectClass = get( "objectclass" );
+            
+            sb.append( objectClass );
+        }
+        
+        if ( attributes.size() != 0 )
+        {
+            for ( EntryAttribute attribute:attributes.values() )
+            {
+                if ( !attribute.getId().equals( "objectclass" ) )
+                {
+                    sb.append( attribute );
+                }
+            }
+        }
+        
+        return sb.toString();
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapAuthenticationNotSupportedException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapAuthenticationNotSupportedException.java
index 3bbec4e..3f591e7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapAuthenticationNotSupportedException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapAuthenticationNotSupportedException.java
@@ -116,11 +116,7 @@
         switch ( resultCode )
         {
             case INAPPROPRIATE_AUTHENTICATION :
-                break;
-                
             case CONFIDENTIALITY_REQUIRED :
-                break;
-                
             case AUTH_METHOD_NOT_SUPPORTED :
                 break;
                 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapInvalidAttributeValueException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapInvalidAttributeValueException.java
index 6a167ec..5d1b0cb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapInvalidAttributeValueException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapInvalidAttributeValueException.java
@@ -60,8 +60,6 @@
         switch ( resultCode )
         {
             case CONSTRAINT_VIOLATION :
-                break;
-                
             case INVALID_ATTRIBUTE_SYNTAX :
                 break;
                 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapReferralException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapReferralException.java
index 5c6456a..51a0b12 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapReferralException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapReferralException.java
@@ -96,7 +96,7 @@
     }
 
 
-    public Context getReferralContext( Hashtable arg ) throws NamingException
+    public Context getReferralContext( Hashtable<?, ?> arg ) throws NamingException
     {
         throw new NotImplementedException();
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapSchemaViolationException.java b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapSchemaViolationException.java
index d69a2a4..529b2ec 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapSchemaViolationException.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/exception/LdapSchemaViolationException.java
@@ -61,15 +61,8 @@
         switch ( resultCode )
         {
             case OBJECT_CLASS_VIOLATION :
-
-                break;
-
             case NOT_ALLOWED_ON_RDN :
-
-                break;
-
             case OBJECT_CLASS_MODS_PROHIBITED :
-
                 break;
 
             default:
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
index e3f3d4b..7c000fe 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AbstractExprNode.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.filter;
 
 
-import java.util.Map;
 import java.util.HashMap;
+import java.util.Map;
 
 
 /**
@@ -35,16 +35,132 @@
     /** The map of annotations */
     protected Map<String, Object> annotations;
 
+    /** The node type */
+    protected final AssertionType assertionType;
+    
+    
     /**
      * Creates a node by setting abstract node type.
+     * 
+     * @param assertionType The node's type
      */
-    protected AbstractExprNode()
+    protected AbstractExprNode( AssertionType assertionType )
     {
+        this.assertionType = assertionType;
+    }
+
+
+    /**
+     * @see ExprNode#getAssertionType()
+     * 
+     * @return the node's type
+     */
+    public AssertionType getAssertionType()
+    {
+        return assertionType;
+    }
+
+
+    /**
+     * Tests to see if this node is a leaf or branch node.
+     * 
+     * @return true if the node is a leaf,false otherwise
+     */
+    public abstract boolean isLeaf();
+
+    
+    /**
+     * @see Object#equals(Object)
+     *@return <code>true</code> if both objects are equal 
+     */
+    public boolean equals( Object o )
+    {
+        // Shortcut for equals object
+        if ( this == o )
+        {
+            return true;
+        }
+        
+        if ( !( o instanceof AbstractExprNode ) )
+        {
+            return false;
+        }
+        
+        AbstractExprNode that = (AbstractExprNode)o;
+        
+        // Check the node type
+        if ( this.assertionType != that.assertionType )
+        {
+            return false;
+        }
+        
+        if ( annotations == null )
+        {
+            return that.annotations == null;
+        }
+        else if ( that.annotations == null )
+        {
+            return false;
+        }
+        
+        // Check all the annotation
+        for ( String key:annotations.keySet() )
+        {
+            if ( !that.annotations.containsKey( key ) )
+            {
+                return false;
+            }
+            
+            Object thisAnnotation = annotations.get( key ); 
+            Object thatAnnotation = that.annotations.get( key );
+            
+            if ( thisAnnotation == null )
+            {
+                if ( thatAnnotation != null )
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if ( !thisAnnotation.equals( thatAnnotation ) )
+                {
+                    return false;
+                }
+            }
+        }
+        
+        return true;
+    }
+
+
+    /**
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int h = 37;
+        
+        if ( annotations != null )
+        {
+            for ( String key:annotations.keySet() )
+            {
+                Object value = annotations.get( key );
+                
+                h = h*17 + key.hashCode();
+                h = h*17 + ( value == null ? 0 : value.hashCode() );
+            }
+        }
+        
+        return h;
     }
 
 
     /**
      * @see org.apache.directory.shared.ldap.filter.ExprNode#get(java.lang.Object)
+     * 
+     * @return the annotation value.
      */
     public Object get( Object key )
     {
@@ -81,7 +197,21 @@
     {
         return annotations;
     }
-    
+
+
+    /**
+     * Default implementation for this method : just throw an exception.
+     * 
+     * @param buf the buffer to append to.
+     * @return The buffer in which the refinement has been appended
+     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
+     */
+    public StringBuilder printRefinementToBuffer( StringBuilder buf )
+    {
+        throw new UnsupportedOperationException( "ScopeNode can't be part of a refinement" );
+    }
+
+
     public String toString()
     {
         if ( ( null != getAnnotations() ) && getAnnotations().containsKey( "count" ) )
@@ -90,7 +220,7 @@
         }
         else 
         {
-        	return "";
+            return "";
         }
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
index 98c1618..060ccdc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AndNode.java
@@ -36,9 +36,9 @@
      * 
      * @param childList the child nodes under this branch node.
      */
-    public AndNode( List<ExprNode> children)
+    public AndNode( List<ExprNode> childList )
     {
-        super( children );
+        super( childList, AssertionType.AND );
     }
 
 
@@ -56,9 +56,9 @@
      * 
      * @return the operator constant.
      */
-    public AssertionEnum getOperator()
+    public AssertionType getOperator()
     {
-        return AssertionEnum.AND;
+        return AssertionType.AND;
     }
 
 
@@ -97,23 +97,27 @@
     
     /**
      * @see ExprNode#printRefinementToBuffer(StringBuffer)
+     * 
+     * @param buf the buffer to append to.
+     * @return The buffer in which the refinement has been appended
+     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public StringBuilder printRefinementToBuffer( StringBuilder buf )
     {
         buf.append( "and: {" );
         boolean isFirst = true;
         
         for ( ExprNode node:children )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             node.printRefinementToBuffer( buf );
         }
         
@@ -127,6 +131,7 @@
      * down.
      * 
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
@@ -137,7 +142,7 @@
 
         for ( ExprNode child:getChildren() )
         {
-        	buf.append( child );
+            buf.append( child );
         }
         
         buf.append( ')' );
@@ -148,12 +153,13 @@
 
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + AssertionEnum.AND.hashCode();
-        hash = hash*31 + ( annotations == null ? 0 : annotations.hashCode() );
+        int hash = 37;
+        hash = hash*17 + AssertionType.AND.hashCode();
+        hash = hash*17 + ( annotations == null ? 0 : annotations.hashCode() );
         return hash;
     }
 
@@ -186,18 +192,18 @@
 
         if ( children.size() != otherChildren.size() )
         {
-        	return false;
+            return false;
         }
         
         for ( int i = 0; i < children.size(); i++ )
         {
-        	ExprNode child = children.get( i );
-        	ExprNode otherChild = children.get( i );
-        	
-        	if ( !child.equals( otherChild ) )
-        	{
-        		return false;
-        	}
+            ExprNode child = children.get( i );
+            ExprNode otherChild = children.get( i );
+            
+            if ( !child.equals( otherChild ) )
+            {
+                return false;
+            }
         }
         
         return true;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
index 7298677..f6e77eb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ApproximateNode.java
@@ -19,6 +19,7 @@
  */
 package org.apache.directory.shared.ldap.filter;
 
+import org.apache.directory.shared.ldap.entry.Value;
 
 /**
  * A simple assertion value node.
@@ -26,7 +27,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision: 519266 $
  */
-public class ApproximateNode extends SimpleNode
+public class ApproximateNode extends EqualityNode
 {
     /**
      * Creates a new ApproximateNode object.
@@ -34,37 +35,27 @@
      * @param attribute the attribute name
      * @param value the value to test for
      */
-    public ApproximateNode( String attribute, byte[] value )
+    public ApproximateNode( String attribute, Value<?> value )
     {
-        super( attribute, value );
+        super( attribute, value, AssertionType.APPROXIMATE );
     }
 
 
-    /**
-     * Creates a new ApproximateNode object.
-     * 
-     * @param attribute the attribute name
-     * @param value the value to test for
-     */
-    public ApproximateNode( String attribute, String value )
-    {
-        super( attribute, value );
-    }
-
-
+    
     /**
      * @see Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+    
         buf.append( '(' ).append( getAttribute() ).append( "~=" ).append( value );
 
         buf.append( super.toString() );
         
         buf.append( ')' );
         
-    	return buf.toString();
+        return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
index ae0d037..f94b5c8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionNode.java
@@ -32,9 +32,6 @@
  */
 public class AssertionNode extends AbstractExprNode
 {
-    /** Setting scan count to max */
-    private static final Long MAX = Long.MAX_VALUE;
-
     /** The assertion or predicate to apply */
     private final Assertion assertion;
 
@@ -51,7 +48,7 @@
      * 
      * @param assertion the arbitrary selection logic.
      */
-    public AssertionNode(Assertion assertion)
+    public AssertionNode( Assertion assertion )
     {
         this( assertion, "ASSERTION" );
     }
@@ -66,7 +63,7 @@
      */
     public AssertionNode( Assertion assertion, String desc )
     {
-        super();
+        super( AssertionType.ASSERTION );
         this.desc = desc;
         this.assertion = assertion;
 
@@ -75,7 +72,7 @@
          * candidate for use in an enumeration so we set the scan count to the
          * maximum value.
          */
-        set( "count", MAX );
+        set( "count", Long.MAX_VALUE );
     }
 
 
@@ -98,6 +95,7 @@
      * Always returns true since an AssertionNode has no children.
      * 
      * @see org.apache.directory.shared.ldap.filter.ExprNode#isLeaf()
+     * @return true if the node is a leaf,false otherwise
      */
     public boolean isLeaf()
     {
@@ -106,11 +104,18 @@
 
 
     /**
-     * @see ExprNode#printRefinementToBuffer(StringBuffer)
+     * @see Object#hashCode()
+     * @return the instance's hash code 
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public int hashCode()
     {
-        throw new UnsupportedOperationException( "AssertionNode can't be part of a refinement" );
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        h = h*17 + ( assertion != null ? assertion.hashCode() : 0 );
+        h = h*17 + ( desc != null ? desc.hashCode() : 0 );
+        
+        return h;
     }
 
 
@@ -125,16 +130,17 @@
 
     /**
      * @see Object#toString
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
-    	buf.append( "(@" );
-    	buf.append( desc );
-    	buf.append( super.toString() );
-    	buf.append( ')' );
-    	
+        StringBuilder buf = new StringBuilder();
+        
+        buf.append( "(@" );
+        buf.append( desc );
+        buf.append( super.toString() );
+        buf.append( ')' );
+        
         return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionType.java
similarity index 96%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionEnum.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionType.java
index d46490a..61920e9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/AssertionType.java
@@ -26,7 +26,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 470116 $
  */
-public enum AssertionEnum {
+public enum AssertionType {
     /** equality assertion node */
     EQUALITY(0),
 
@@ -72,7 +72,7 @@
      * 
      * @param value the integer value of the enumeration.
      */
-    private AssertionEnum( int value )
+    private AssertionType( int value )
     {
        this.value = value;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
index aefc45c..98ca488 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNode.java
@@ -31,7 +31,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public abstract class BranchNode extends AbstractExprNode
+public class BranchNode extends AbstractExprNode
 {
     /** child node list for this branch node */
     protected List<ExprNode> children = null;
@@ -41,28 +41,31 @@
      * Creates a BranchNode using a logical operator and a list of children.
      * 
      * @param childList the child nodes under this branch node.
+     * @param assertionType the node's type
      */
-    public BranchNode( List<ExprNode> children)
+    protected BranchNode( List<ExprNode> childList, AssertionType assertionType )
     {
-        super();
+        super( assertionType );
 
-        if ( null == children )
+        if ( null == childList )
         {
             this.children = new ArrayList<ExprNode>( 2 );
         }
         else
         {
-            this.children = children;
+            this.children = childList;
         }
     }
 
 
     /**
      * Creates a BranchNode using a logical operator.
+     * 
+     * @param assertionType the node's type
      */
-    public BranchNode()
+    protected BranchNode( AssertionType assertionType )
     {
-        this( null );
+        this( null, assertionType );
     }
 
     /**
@@ -142,12 +145,14 @@
     /**
      * @see org.apache.directory.shared.ldap.filter.ExprNode#accept(
      *      org.apache.directory.shared.ldap.filter.FilterVisitor)
+     *      
+     * @return The modified element
      */
     public final Object accept( FilterVisitor visitor )
     {
         if ( visitor.isPrefix() )
         {
-            List<ExprNode> children = visitor.getOrder( this, this.children );
+            List<ExprNode> childrenList = visitor.getOrder( this, this.children );
             ExprNode result = null;
 
             if ( visitor.canVisit( this ) )
@@ -155,7 +160,7 @@
                 result = (ExprNode)visitor.visit( this );
             }
 
-            for ( ExprNode node:children )
+            for ( ExprNode node:childrenList )
             {
                 node.accept( visitor );
             }
@@ -170,11 +175,35 @@
             }
             else
             {
-            	return null;
+                return null;
             }
         }
     }
     
+    
+    /**
+     * (non-Javadoc)
+     * 
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        
+        if ( children != null )
+        {
+            for ( ExprNode child:children )
+            {
+                h = h*17 + child.hashCode();
+            }
+        }
+        
+        return h;
+    }
+    
     /*
      * (non-Javadoc)
      * 
@@ -194,7 +223,7 @@
         
         if ( other.getClass() != this.getClass() )
         {
-        	return false;
+            return false;
         }
 
         BranchNode otherExprNode = ( BranchNode ) other;
@@ -208,18 +237,18 @@
 
         if ( children.size() != otherChildren.size() )
         {
-        	return false;
+            return false;
         }
         
         for ( int i = 0; i < children.size(); i++ )
         {
-        	ExprNode child = children.get( i );
-        	ExprNode otherChild = children.get( i );
-        	
-        	if ( !child.equals( otherChild ) )
-        	{
-        		return false;
-        	}
+            ExprNode child = children.get( i );
+            ExprNode otherChild = children.get( i );
+            
+            if ( !child.equals( otherChild ) )
+            {
+                return false;
+            }
         }
         
         return true;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
index 12b941b..13100b7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/BranchNormalizedVisitor.java
@@ -20,12 +20,11 @@
 package org.apache.directory.shared.ldap.filter;
 
 
+import java.text.ParseException;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.Comparator;
-import java.io.IOException;
-import java.text.ParseException;
 
 
 /**
@@ -68,16 +67,16 @@
         {
             if ( !child.isLeaf() )
             {
-            	ExprNode newChild = (ExprNode)visit( child );
-            	
-            	if ( newChild != null )
-            	{
-            		set.add( newChild );
-            	}
+                ExprNode newChild = (ExprNode)visit( child );
+                
+                if ( newChild != null )
+                {
+                    set.add( newChild );
+                }
             }
             else
             {
-            	set.add( child );
+                set.add( child );
             }
         }
 
@@ -119,12 +118,10 @@
      * @param filter
      *            the filter to normalize
      * @return the normalized version of the filter
-     * @throws java.io.IOException
-     *             if filter parser cannot be created
      * @throws java.text.ParseException
      *             if the filter is malformed
      */
-    public static String getNormalizedFilter( String filter ) throws IOException, ParseException
+    public static String getNormalizedFilter( String filter ) throws ParseException
     {
         ExprNode originalNode = FilterParser.parse( filter );
 
@@ -153,7 +150,7 @@
     {
         public int compare( ExprNode o1, ExprNode o2 )
         {
-        	StringBuilder buf = new StringBuilder();
+            StringBuilder buf = new StringBuilder();
 
             buf.setLength( 0 );
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
index d139d17..adb0e68 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/EqualityNode.java
@@ -19,6 +19,8 @@
  */
 package org.apache.directory.shared.ldap.filter;
 
+import org.apache.directory.shared.ldap.entry.Value;
+
 
 /**
  * A assertion value node for Equality.
@@ -34,9 +36,9 @@
      * @param attribute the attribute name
      * @param value the value to test for
      */
-    public EqualityNode( String attribute, byte[] value )
+    public EqualityNode( String attribute, Value<?> value )
     {
-        super( attribute, value );
+        super( attribute, value, AssertionType.EQUALITY );
     }
 
 
@@ -45,26 +47,28 @@
      * 
      * @param attribute the attribute name
      * @param value the value to test for
+     * @param assertionType The node's type
      */
-    public EqualityNode( String attribute, String value )
+    protected EqualityNode( String attribute, Value<?> value, AssertionType assertionType )
     {
-        super( attribute, value );
+        super( attribute, value, assertionType );
     }
 
 
     /**
      * @see Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+    
         buf.append( '(' ).append( getAttribute() ).append( "=" ).append( value );
 
         buf.append( super.toString() );
         
         buf.append( ')' );
         
-    	return buf.toString();
+        return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
index 8994563..d77e771 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExprNode.java
@@ -55,15 +55,24 @@
      */
     boolean isLeaf();
 
+    
+    /**
+     * Gets the assertion type of this node. Make it possible to use switch
+     * statements on the node type.
+     * 
+     * @return the assertion type
+     */
+    AssertionType getAssertionType();
 
     /**
      * Recursively appends the refinement string representation of this node and its
-     * descendents in prefix notation to a buffer.
+     * descendants in prefix notation to a buffer.
      * 
      * @param buf the buffer to append to.
+     * @return The buffer in which the refinement has been appended
      * @throws UnsupportedOperationException if this node isn't a part of a refinement.
      */
-    StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException;
+    StringBuilder printRefinementToBuffer( StringBuilder buf );
     
     
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
index a5a5f34..9353d37 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ExtensibleNode.java
@@ -20,6 +20,8 @@
 package org.apache.directory.shared.ldap.filter;
 
 
+import java.util.Arrays;
+
 import org.apache.directory.shared.ldap.util.StringTools;
 
 
@@ -43,10 +45,12 @@
 
     /**
      * Creates a new emptyExtensibleNode object.
+     * 
+     * @param attribute The attribute's ID for this node
      */
     public ExtensibleNode( String attribute )
     {
-        super( attribute );
+        super( attribute, AssertionType.EXTENSIBLE );
         
         dnAttributes = false;
     }
@@ -75,9 +79,16 @@
      */
     public ExtensibleNode( String attribute, byte[] value, String matchingRuleId, boolean dnAttributes )
     {
-        super( attribute );
+        super( attribute, AssertionType.EXTENSIBLE );
 
-        this.value = value;
+        if ( value != null )
+        {
+            this.value = new byte[ value.length ];
+            System.arraycopy( value, 0, this.value, 0, value.length );
+        } else {
+            this.value = null;
+        }
+
         this.matchingRuleId = matchingRuleId;
         this.dnAttributes = dnAttributes;
     }
@@ -118,6 +129,8 @@
 
     /**
      * Sets the matching rule id as an OID string.
+     * 
+     * @param matchingRuleId The maching rule ID
      */
     public void setMatchingRuleId( String matchingRuleId )
     {
@@ -132,12 +145,21 @@
      */
     public final byte[] getValue()
     {
-        return value;
+        if ( value == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ value.length ];
+        System.arraycopy( value, 0, copy, 0, value.length );
+        return copy;
     }
 
 
     /**
      * Sets the value.
+     * 
+     * @param value the value
      */
     public final void setValue( String value)
     {
@@ -146,21 +168,30 @@
 
     
     /**
-     * @see ExprNode#printRefinementToBuffer(StringBuilder)
+     * @see Object#hashCode()
+     * @return the instance's hash code 
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public int hashCode()
     {
-        throw new UnsupportedOperationException( "ExtensibleNode can't be part of a refinement" );
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        h = h*17 + ( dnAttributes ? 1 : 0 );
+        h = h*17 + matchingRuleId.hashCode();
+        h = h*17 + Arrays.hashCode( value );
+        
+        return h;
     }
 
 
     /**
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         buf.append( '(' ).append( getAttribute() );
         buf.append( "-" );
         buf.append( dnAttributes );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterParser.java
index 0a37410..2f251b9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterParser.java
@@ -22,11 +22,18 @@
 
 import java.text.ParseException;
 
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.apache.directory.shared.ldap.util.Position;
 import org.apache.directory.shared.ldap.util.StringTools;
 
 
+/**
+ * This class parse a Ldap filter. The grammar is given in RFC 4515
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
 public class FilterParser
 {
     /**
@@ -35,7 +42,8 @@
     public FilterParser()
     {
     }
-    
+
+
     /**
      * Parse an extensible
      * 
@@ -61,35 +69,35 @@
                 // Push back the ':' 
                 pos.start--;
             }
-            
+
             // Do we have a MatchingRule ?
             if ( StringTools.charAt( filter, pos.start ) == ':' )
             {
                 pos.start++;
                 int start = pos.start;
-                
+
                 if ( StringTools.charAt( filter, pos.start ) == '=' )
                 {
                     pos.start++;
-                    
+
                     // Get the assertionValue
                     node.setValue( parseAssertionValue( filter, pos ) );
-                    
+
                     return node;
                 }
                 else
                 {
                     AttributeUtils.parseAttribute( filter, pos, false );
-                    
+
                     node.setMatchingRuleId( filter.substring( start, pos.start ) );
-                    
+
                     if ( StringTools.areEquals( filter, pos.start, ":=" ) )
                     {
                         pos.start += 2;
-                        
+
                         // Get the assertionValue
                         node.setValue( parseAssertionValue( filter, pos ) );
-                        
+
                         return node;
                     }
                     else
@@ -106,7 +114,7 @@
         else
         {
             boolean oidRequested = false;
-            
+
             // First check if we have a ":dn"
             if ( StringTools.areEquals( filter, pos.start, ":dn" ) )
             {
@@ -118,40 +126,40 @@
             {
                 oidRequested = true;
             }
-            
+
             // Do we have a MatchingRule ?
             if ( StringTools.charAt( filter, pos.start ) == ':' )
             {
                 pos.start++;
                 int start = pos.start;
-                
+
                 if ( StringTools.charAt( filter, pos.start ) == '=' )
                 {
                     if ( oidRequested )
                     {
                         throw new ParseException( "MatchingRule expected", pos.start );
                     }
-                    
+
                     pos.start++;
-                    
+
                     // Get the assertionValue
                     node.setValue( parseAssertionValue( filter, pos ) );
-                    
+
                     return node;
                 }
                 else
                 {
                     AttributeUtils.parseAttribute( filter, pos, false );
-                    
+
                     node.setMatchingRuleId( filter.substring( start, pos.start ) );
-                    
+
                     if ( StringTools.areEquals( filter, pos.start, ":=" ) )
                     {
                         pos.start += 2;
-                        
+
                         // Get the assertionValue
                         node.setValue( parseAssertionValue( filter, pos ) );
-                        
+
                         return node;
                     }
                     else
@@ -166,8 +174,8 @@
             }
         }
     }
-    
-    
+
+
     /**
      * An assertion value : 
      * assertionvalue = valueencoding
@@ -204,9 +212,9 @@
     private static String parseAssertionValue( String filter, Position pos ) throws ParseException
     {
         int start = pos.start;
-        
+
         char c = StringTools.charAt( filter, pos.start );
-        
+
         do
         {
             if ( StringTools.isUnicodeSubset( c ) )
@@ -217,7 +225,7 @@
             {
                 // Maybe an escaped 
                 pos.start++;
-                
+
                 // First hex
                 if ( StringTools.isHex( filter, pos.start ) )
                 {
@@ -243,35 +251,38 @@
                 // not a valid char, so let's get out
                 return filter.substring( start, pos.start );
             }
-        } while ( ( c = StringTools.charAt( filter, pos.start ) ) != '\0' );
-        
+        }
+        while ( ( c = StringTools.charAt( filter, pos.start ) ) != '\0' );
+
         return filter.substring( start, pos.start );
     }
 
+
     /**
      * Parse a substring
      */
-    private static ExprNode parseSubstring( String attr, String initial, String filter, Position pos ) throws ParseException
+    private static ExprNode parseSubstring( String attr, String initial, String filter, Position pos )
+        throws ParseException
     {
         if ( StringTools.isCharASCII( filter, pos.start, '*' ) )
         {
             // We have found a '*' : this is a substring
             SubstringNode node = new SubstringNode( attr );
-            
+
             if ( !StringTools.isEmpty( initial ) )
             {
                 // We have a substring starting with a value : val*...
                 // Set the initial value
                 node.setInitial( initial );
             }
-            
+
             pos.start++;
-            
+
             // 
             while ( true )
             {
                 String assertionValue = parseAssertionValue( filter, pos );
-                
+
                 // Is there anything else but a ')' after the value ?
                 if ( StringTools.isCharASCII( filter, pos.start, ')' ) )
                 {
@@ -293,10 +304,15 @@
                     {
                         node.addAny( assertionValue );
                     }
-                    
+
                     pos.start++;
                 }
-            } 
+                else
+                {
+                    // This is an error
+                    throw new ParseException( "Bad substring", pos.start );
+                }
+            }
         }
         else
         {
@@ -304,7 +320,8 @@
             throw new ParseException( "Bad substring", pos.start );
         }
     }
-    
+
+
     /**
      * Here is the grammar to parse :
      * 
@@ -329,7 +346,8 @@
      * @param pos
      * @return
      */
-    private static ExprNode parsePresenceEqOrSubstring( String attr, String filter, Position pos ) throws ParseException
+    private static ExprNode parsePresenceEqOrSubstring( String attr, String filter, Position pos )
+        throws ParseException
     {
         if ( StringTools.isCharASCII( filter, pos.start, '*' ) )
         {
@@ -353,25 +371,25 @@
         else if ( StringTools.isCharASCII( filter, pos.start, ')' ) )
         {
             // An empty equality Node
-            return new EqualityNode( attr, "" );
+            return new EqualityNode( attr, new ClientStringValue( "" ) );
         }
         else
         {
             // A substring or an equality node
             String value = parseAssertionValue( filter, pos );
-            
+
             // Is there anything else but a ')' after the value ?
             if ( StringTools.isCharASCII( filter, pos.start, ')' ) )
             {
                 // This is an equality node
-                return new EqualityNode( attr, value );
+                return new EqualityNode( attr, new ClientStringValue( value ) );
             }
-            
+
             return parseSubstring( attr, value, filter, pos );
         }
     }
-    
-    
+
+
     /**
      * Parse the following grammar :
      * item           = simple / present / substring / extensible
@@ -389,15 +407,15 @@
     {
         LeafNode node = null;
         String attr = null;
-        
+
         // Relax the grammar a bit : we can have spaces 
         // StringTools.trimLeft( filter, pos );
-        
+
         if ( c == '\0' )
         {
             throw new ParseException( "Bad char", pos.start );
         }
-        
+
         if ( c == ':' )
         {
             // If we have a colon, then the item is an extensible one
@@ -407,24 +425,24 @@
         {
             // We must have an attribute
             attr = AttributeUtils.parseAttribute( filter, pos, true );
-            
+
             // Relax the grammar a bit : we can have spaces 
             // StringTools.trimLeft( filter, pos );
 
             // Now, we may have a present, substring, simple or an extensible
             c = StringTools.charAt( filter, pos.start );
-            
+
             switch ( c )
             {
-                case '=' :
+                case '=':
                     // It can be a presence, an equal or a substring
                     pos.start++;
                     return parsePresenceEqOrSubstring( attr, filter, pos );
-                    
-                case '~' :
+
+                case '~':
                     // Approximate node
                     pos.start++;
-                    
+
                     // Check that we have a '='
                     if ( !StringTools.isCharASCII( filter, pos.start, '=' ) )
                     {
@@ -432,15 +450,15 @@
                     }
 
                     pos.start++;
-                    
+
                     // Parse the value and create the node
-                    node = new ApproximateNode( attr, parseAssertionValue( filter, pos ) );
+                    node = new ApproximateNode( attr, new ClientStringValue( parseAssertionValue( filter, pos ) ) );
                     return node;
-                    
-                case '>' :
+
+                case '>':
                     // Greater or equal node
                     pos.start++;
-                    
+
                     // Check that we have a '='
                     if ( !StringTools.isCharASCII( filter, pos.start, '=' ) )
                     {
@@ -448,15 +466,15 @@
                     }
 
                     pos.start++;
-                    
+
                     // Parse the value and create the node
-                    node = new GreaterEqNode( attr, parseAssertionValue( filter, pos ) );
+                    node = new GreaterEqNode( attr, new ClientStringValue( parseAssertionValue( filter, pos ) ) );
                     return node;
-                    
-                case '<' :
+
+                case '<':
                     // Less or equal node
                     pos.start++;
-                    
+
                     // Check that we have a '='
                     if ( !StringTools.isCharASCII( filter, pos.start, '=' ) )
                     {
@@ -464,23 +482,24 @@
                     }
 
                     pos.start++;
-                    
+
                     // Parse the value and create the node
-                    node = new LessEqNode( attr, parseAssertionValue( filter, pos ) );
+                    node = new LessEqNode( attr, new ClientStringValue( parseAssertionValue( filter, pos ) ) );
                     return node;
-                    
-                case ':' :
+
+                case ':':
                     // An extensible node
                     pos.start++;
                     return parseExtensible( attr, filter, pos );
-                    
-                default :
+
+                default:
                     // This is an error
                     throw new ParseException( "An item is expected", pos.start );
             }
         }
     }
 
+
     /**
      * Parse AND, OR and NOT nodes :
      * 
@@ -493,20 +512,20 @@
      */
     private static ExprNode parseBranchNode( ExprNode node, String filter, Position pos ) throws ParseException
     {
-        BranchNode bNode = (BranchNode)node;
-        
+        BranchNode bNode = ( BranchNode ) node;
+
         // Relax the grammar a bit : we can have spaces 
         // StringTools.trimLeft( filter, pos );
-        
+
         // We must have at least one filter
         ExprNode child = parseFilterInternal( filter, pos );
-        
+
         // Add the child to the node children
         bNode.addNode( child );
 
         // Relax the grammar a bit : we can have spaces 
         // StringTools.trimLeft( filter, pos );
-        
+
         // Now, iterate though all the remaining filters, if any
         while ( ( child = parseFilterInternal( filter, pos ) ) != null )
         {
@@ -516,13 +535,14 @@
             // Relax the grammar a bit : we can have spaces 
             // StringTools.trimLeft( filter, pos );
         }
-        
+
         // Relax the grammar a bit : we can have spaces 
         // StringTools.trimLeft( filter, pos );
 
         return node;
     }
 
+
     /**
      * filtercomp     = and / or / not / item
      * and            = '&' filterlist
@@ -537,53 +557,54 @@
      *                    / ( [dnattrs]
      *                         matchingrule COLON EQUALS assertionvalue )
      */
-    private static ExprNode parseFilterComp( String filter, Position pos )  throws ParseException
+    private static ExprNode parseFilterComp( String filter, Position pos ) throws ParseException
     {
         ExprNode node = null;
 
         // Relax the grammar a bit : we can have spaces 
         // StringTools.trimLeft( filter, pos );
-        
+
         if ( pos.start == pos.length )
         {
             throw new ParseException( "Empty filterComp", pos.start );
         }
-        
+
         char c = StringTools.charAt( filter, pos.start );
-        
+
         switch ( c )
         {
-            case '&' :
+            case '&':
                 // This is a AND node
                 pos.start++;
                 node = new AndNode();
                 parseBranchNode( node, filter, pos );
                 break;
-                
-            case '|' :
+
+            case '|':
                 // This is an OR node
                 pos.start++;
                 node = new OrNode();
                 parseBranchNode( node, filter, pos );
                 break;
-                
-            case '!' :
+
+            case '!':
                 // This is a NOT node
                 pos.start++;
                 node = new NotNode();
                 parseBranchNode( node, filter, pos );
                 break;
-                
-            default :
+
+            default:
                 // This is an item
                 node = parseItem( filter, pos, c );
                 break;
-                    
+
         }
-        
+
         return node;
     }
-    
+
+
     /**
      * Pasre the grammar rule :
      * filter ::= '(' filterComp ')'
@@ -592,9 +613,9 @@
     {
         // relax the grammar by allowing spaces
         // StringTools.trimLeft( filter, pos );
-        
+
         // Check for the left '('
-        if ( StringTools.isCharASCII( filter, pos.start, '(' ) == false )
+        if ( !StringTools.isCharASCII( filter, pos.start, '(' ) )
         {
             // No more node, get out
             if ( ( pos.start == 0 ) && ( pos.length != 0 ) )
@@ -606,34 +627,35 @@
                 return null;
             }
         }
-        
+
         pos.start++;
-        
+
         // relax the grammar by allowing spaces
         // StringTools.trimLeft( filter, pos );
-        
+
         // parse the filter component
         ExprNode node = parseFilterComp( filter, pos );
-        
+
         if ( node == null )
         {
             throw new ParseException( "Bad filter", pos.start );
         }
-        
+
         // relax the grammar by allowing spaces
         // StringTools.trimLeft( filter, pos );
-        
+
         // Check that we have a right ')'
-        if ( StringTools.isCharASCII( filter, pos.start, ')' ) == false )
+        if ( !StringTools.isCharASCII( filter, pos.start, ')' ) )
         {
             throw new ParseException( "The filter has no right parenthese", pos.start );
         }
-        
+
         pos.start++;
-        
+
         return node;
     }
-    
+
+
     /**
      * @see FilterParser#parse(String)
      */
@@ -644,12 +666,12 @@
         {
             throw new ParseException( "Empty filter", 0 );
         }
-        
+
         Position pos = new Position();
         pos.start = 0;
         pos.end = 0;
         pos.length = filter.length();
-        
+
         return parseFilterInternal( filter, pos );
     }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterVisitor.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterVisitor.java
index f8e9a2b..7abd217 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterVisitor.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/FilterVisitor.java
@@ -49,6 +49,7 @@
      * Visits a filter expression AST using a specific visitation order.
      * 
      * @param node the node to visit
+     * @return node the resulting modified node
      */
     Object visit( ExprNode node );
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
index fd38e0a..33bd77e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/GreaterEqNode.java
@@ -20,6 +20,9 @@
 package org.apache.directory.shared.ldap.filter;
 
 
+import org.apache.directory.shared.ldap.entry.Value;
+
+
 /**
  * A assertion value node for GreaterOrEqual.
  * 
@@ -34,37 +37,26 @@
      * @param attribute the attribute name
      * @param value the value to test for
      */
-    public GreaterEqNode( String attribute, byte[] value )
+    public GreaterEqNode( String attribute, Value<?> value )
     {
-        super( attribute, value );
-    }
-
-
-    /**
-     * Creates a new GreaterOrEqual object.
-     * 
-     * @param attribute the attribute name
-     * @param value the value to test for
-     */
-    public GreaterEqNode( String attribute, String value )
-    {
-        super( attribute, value );
+        super( attribute, value, AssertionType.GREATEREQ );
     }
 
 
     /**
      * @see Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+
         buf.append( '(' ).append( getAttribute() ).append( ">=" ).append( value );
 
         buf.append( super.toString() );
-        
+
         buf.append( ')' );
-        
-    	return buf.toString();
+
+        return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
index 92c626f..717887f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LeafNode.java
@@ -26,7 +26,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public abstract class LeafNode extends AbstractExprNode
+public class LeafNode extends AbstractExprNode
 {
     /** attribute on which this leaf is based */
     private String attribute;
@@ -36,11 +36,11 @@
      * Creates a leaf node.
      * 
      * @param attribute the attribute this node is based on
-     * @param type the type of this leaf node
+     * @param assertionType the type of this leaf node
      */
-    protected LeafNode( String attribute )
+    protected LeafNode( String attribute, AssertionType assertionType )
     {
-        super();
+        super( assertionType );
         this.attribute = attribute;
     }
 
@@ -77,6 +77,41 @@
         this.attribute = attribute;
     }
 
+    
+    /**
+     * @see org.apache.directory.shared.ldap.filter.ExprNode#accept(
+     *      org.apache.directory.shared.ldap.filter.FilterVisitor)
+     * 
+     * @param visitor the filter expression tree structure visitor
+     * @return The modified element
+     */
+    public final Object accept( FilterVisitor visitor )
+    {
+        if ( visitor.canVisit( this ) )
+        {
+            return visitor.visit( this );
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        h = h*17 + attribute.hashCode();
+        
+        return h;
+    }
+
 
     /*
      * (non-Javadoc)
@@ -97,26 +132,9 @@
 
         if ( other.getClass() != this.getClass() )
         {
-        	return false;
+            return false;
         }
             
         return attribute.equals( ( ( LeafNode ) other ).getAttribute() );
     }
-
-
-    /**
-     * @see org.apache.directory.shared.ldap.filter.ExprNode#accept(
-     *      org.apache.directory.shared.ldap.filter.FilterVisitor)
-     */
-    public final Object accept( FilterVisitor visitor )
-    {
-        if ( visitor.canVisit( this ) )
-        {
-            return visitor.visit( this );
-        }
-        else
-        {
-        	return null;
-        }
-    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
index 5b651eb..9b20aaa 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/LessEqNode.java
@@ -20,6 +20,9 @@
 package org.apache.directory.shared.ldap.filter;
 
 
+import org.apache.directory.shared.ldap.entry.Value;
+
+
 /**
  * A assertion value node for LessOrEqual.
  * 
@@ -34,37 +37,26 @@
      * @param attribute the attribute name
      * @param value the value to test for
      */
-    public LessEqNode( String attribute, byte[] value )
+    public LessEqNode( String attribute, Value<?> value )
     {
-        super( attribute, value );
-    }
-
-
-    /**
-     * Creates a new LessEqNode object.
-     * 
-     * @param attribute the attribute name
-     * @param value the value to test for
-     */
-    public LessEqNode( String attribute, String value )
-    {
-        super( attribute, value );
+        super( attribute, value, AssertionType.LESSEQ );
     }
 
 
     /**
      * @see Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+
         buf.append( '(' ).append( getAttribute() ).append( "<=" ).append( value );
 
         buf.append( super.toString() );
-        
+
         buf.append( ')' );
-        
-    	return buf.toString();
+
+        return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
index 014fdbc..ba4acfc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/NotNode.java
@@ -38,14 +38,14 @@
      * 
      * @param childList the child nodes under this branch node.
      */
-    public NotNode( List<ExprNode> children)
+    public NotNode( List<ExprNode> childList )
     {
-        super();
-        
-    	if ( this.children.size() > 1 )
-    	{
-    		throw new IllegalStateException( "Cannot add more than one element to a negation node." );    		
-    	}
+        super( AssertionType.NOT );
+
+        if ( childList != null )
+        {
+            setChildren( childList );
+        }
     }
 
 
@@ -64,11 +64,11 @@
      */
     public void addNode( ExprNode node )
     {
-    	if ( children.size() >= 1 )
-    	{
-    		throw new IllegalStateException( "Cannot add more than one element to a negation node." );    		
-    	}
-    	
+        if ( ( children != null ) && ( children.size() >= 1 ) )
+        {
+            throw new IllegalStateException( "Cannot add more than one element to a negation node." );
+        }
+        
         children.add( node );
     }
 
@@ -80,11 +80,11 @@
      */
     public void addNodeToHead( ExprNode node )
     {
-    	if ( children.size() >= 1 )
-    	{
-    		throw new IllegalStateException( "Cannot add more than one element to a negation node." );    		
-    	}
-    	
+        if ( children.size() >= 1 )
+        {
+            throw new IllegalStateException( "Cannot add more than one element to a negation node." );            
+        }
+        
         children.add( node );
     }
 
@@ -92,16 +92,16 @@
     /**
      * Sets the list of children under this node.
      * 
-     * @param list the list of children to set.
+     * @param childList the list of children to set.
      */
-    public void setChildren( List<ExprNode> list )
+    public void setChildren( List<ExprNode> childList )
     {
-    	if ( ( list != null ) && ( list.size() > 1 ) )
-    	{
-    		throw new IllegalStateException( "Cannot add more than one element to a negation node." );    		
-    	}
+        if ( ( childList != null ) && ( childList.size() > 1 ) )
+        {
+            throw new IllegalStateException( "Cannot add more than one element to a negation node." );            
+        }
 
-    	children = list;
+        children = childList;
     }
 
     
@@ -110,9 +110,9 @@
      * 
      * @return the operator constant.
      */
-    public AssertionEnum getOperator()
+    public AssertionType getOperator()
     {
-        return AssertionEnum.NOT;
+        return AssertionType.NOT;
     }
 
 
@@ -151,23 +151,26 @@
 
     /**
      * @see ExprNode#printRefinementToBuffer(StringBuffer)
+     * 
+     * @return The buffer in which the refinement has been appended
+     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public StringBuilder printRefinementToBuffer( StringBuilder buf )
     {
         buf.append( "not: {" );
         boolean isFirst = true;
         
         for ( ExprNode node:children )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             node.printRefinementToBuffer( buf );
         }
         
@@ -181,6 +184,7 @@
      * down.
      * 
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
@@ -194,16 +198,4 @@
         
         return buf.toString();
     }
-
-
-    /**
-     * @see Object#hashCode()
-     */
-    public int hashCode()
-    {
-        int hash = 7;
-        hash = hash*31 + AssertionEnum.NOT.hashCode();
-        hash = hash*31 + ( annotations == null ? 0 : annotations.hashCode() );
-        return hash;
-    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
index 864589d..636bae1 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/OrNode.java
@@ -36,9 +36,9 @@
      * 
      * @param childList the child nodes under this branch node.
      */
-    public OrNode( List<ExprNode> children)
+    public OrNode( List<ExprNode> childList)
     {
-        super( children );
+        super( childList, AssertionType.OR );
     }
 
 
@@ -58,9 +58,9 @@
      * 
      * @return the operator constant.
      */
-    public AssertionEnum getOperator()
+    public AssertionType getOperator()
     {
-        return AssertionEnum.OR;
+        return AssertionType.OR;
     }
 
 
@@ -99,23 +99,26 @@
 
     /**
      * @see ExprNode#printRefinementToBuffer(StringBuffer)
+     * 
+     * @return The buffer in which the refinement has been appended
+     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public StringBuilder printRefinementToBuffer( StringBuilder buf )
     {
         buf.append( "or: {" );
         boolean isFirst = true;
         
         for ( ExprNode node:children )
         {
-        	if ( isFirst )
-        	{
-        		isFirst = false;
-        	}
-        	else
-        	{
-        		buf.append( ", " );
-        	}
-        	
+            if ( isFirst )
+            {
+                isFirst = false;
+            }
+            else
+            {
+                buf.append( ", " );
+            }
+            
             node.printRefinementToBuffer( buf );
         }
         
@@ -129,6 +132,7 @@
      * down.
      * 
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
@@ -139,23 +143,24 @@
 
         for ( ExprNode child:getChildren() )
         {
-        	buf.append( child );
+            buf.append( child );
         }
         
         buf.append( ')' );
-	
+    
         return buf.toString();
     }
 
 
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + AssertionEnum.OR.hashCode();
-        hash = hash*31 + ( annotations == null ? 0 : annotations.hashCode() );
+        int hash = 37;
+        hash = hash*17 + AssertionType.OR.hashCode();
+        hash = hash*17 + ( annotations == null ? 0 : annotations.hashCode() );
         return hash;
     }
 
@@ -188,18 +193,18 @@
 
         if ( children.size() != otherChildren.size() )
         {
-        	return false;
+            return false;
         }
         
         for ( int i = 0; i < children.size(); i++ )
         {
-        	ExprNode child = children.get( i );
-        	ExprNode otherChild = children.get( i );
-        	
-        	if ( !child.equals( otherChild ) )
-        	{
-        		return false;
-        	}
+            ExprNode child = children.get( i );
+            ExprNode otherChild = children.get( i );
+            
+            if ( !child.equals( otherChild ) )
+            {
+                return false;
+            }
         }
         
         return true;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
index c76f60b..12ba060 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/PresenceNode.java
@@ -36,17 +36,18 @@
      */
     public PresenceNode( String attribute )
     {
-        super( attribute );
+        super( attribute, AssertionType.PRESENCE );
     }
 
 
     /**
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         buf.append( '(' ).append( getAttribute() ).append( "=*" );
 
         buf.append( super.toString() );
@@ -55,13 +56,4 @@
         
         return buf.toString();
     }
-
-    
-    /**
-     * @see ExprNode#printRefinementToBuffer(StringBuilder)
-     */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
-    {
-        throw new UnsupportedOperationException( "PresenceNode can't be part of a refinement" );
-    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
index ff9d7e8..f727b79 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/ScopeNode.java
@@ -20,11 +20,9 @@
 package org.apache.directory.shared.ldap.filter;
 
 
-import java.util.Map;
-
 import javax.naming.directory.SearchControls;
 
-import org.apache.directory.shared.ldap.message.DerefAliasesEnum;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
 
 
 /**
@@ -43,39 +41,22 @@
     private final String baseDn;
 
     /** the alias dereferencing mode */
-    private final DerefAliasesEnum derefAliases;
+    private final AliasDerefMode aliasDerefAliases;
 
 
     /**
      * Creates a new ScopeNode object.
      * 
-     * @param derefAliases the alias dereferencing mode
+     * @param aliasDerefAliases the alias dereferencing mode
      * @param baseDn the search base
      * @param scope the search scope
      */
-    public ScopeNode(DerefAliasesEnum derefAliases, String baseDn, int scope)
+    public ScopeNode( AliasDerefMode aliasDerefAliases, String baseDn, int scope )
     {
-        super();
+        super( AssertionType.SCOPE );
         this.scope = scope;
         this.baseDn = baseDn;
-        this.derefAliases = derefAliases;
-    }
-
-
-    /**
-     * Creates a new ScopeNode object.
-     * 
-     * @param env the JNDI environment from which to extract the alias
-     *            dereferencing mode
-     * @param baseDn the search base
-     * @param scope the search scope
-     */
-    public ScopeNode( Map<String, DerefAliasesEnum> env, String baseDn, int scope )
-    {
-        super();
-        this.scope = scope;
-        this.baseDn = baseDn;
-        derefAliases = DerefAliasesEnum.getEnum( env );
+        this.aliasDerefAliases = aliasDerefAliases;
     }
 
 
@@ -83,6 +64,7 @@
      * Always returns true since a scope node has no children.
      * 
      * @see ExprNode#isLeaf()
+     * @return <code>true</code>
      */
     public boolean isLeaf()
     {
@@ -120,24 +102,18 @@
      * 
      * @return the alias dereferencing enumeration constant.
      */
-    public DerefAliasesEnum getDerefAliases()
+    public AliasDerefMode getDerefAliases()
     {
-        return derefAliases;
-    }
-
-
-    /**
-     * @see ExprNode#printRefinementToBuffer(StringBuilder)
-     */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
-    {
-        throw new UnsupportedOperationException( "ScopeNode can't be part of a refinement" );
+        return aliasDerefAliases;
     }
 
 
     /**
      * @see org.apache.directory.shared.ldap.filter.ExprNode#accept(
      *      org.apache.directory.shared.ldap.filter.FilterVisitor)
+     * 
+     * @param visitor the filter expression tree structure visitor
+     * @return The modified element
      */
     public Object accept( FilterVisitor visitor )
     {
@@ -147,18 +123,37 @@
         }
         else
         {
-        	return null;
+            return null;
         }
     }
-    
+
+
+    /**
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        h = h*17 + ( aliasDerefAliases != null ? aliasDerefAliases.hashCode() : 0 );
+        h = h*17 + ( baseDn != null ? baseDn.hashCode() : 0 );
+        h = h*17 + scope;
+        
+        return h;
+    }
+
+
     /**
      * @see Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
-    	buf.append( "(#{" );
+        StringBuilder buf = new StringBuilder();
+        
+        buf.append( "(#{" );
 
         switch ( scope )
         {
@@ -179,16 +174,17 @@
 
             default:
                 buf.append( "UNKNOWN" );
+                break;
         }
-    	
-    	buf.append( ", '" );
-    	buf.append( baseDn );
-    	buf.append( "', " );
-    	buf.append( derefAliases );
-    	buf.append( "}" );
-    	buf.append( super.toString() );
-    	buf.append( ')' );
-    	
-    	return buf.toString();
+        
+        buf.append( ", '" );
+        buf.append( baseDn );
+        buf.append( "', " );
+        buf.append( aliasDerefAliases );
+        buf.append( "}" );
+        buf.append( super.toString() );
+        buf.append( ')' );
+        
+        return buf.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
index 3b3d2d1..f728d66 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SimpleNode.java
@@ -19,7 +19,9 @@
  */
 package org.apache.directory.shared.ldap.filter;
 
+
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.Value;
 
 
 /**
@@ -28,26 +30,16 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
-public abstract class SimpleNode extends LeafNode
+public class SimpleNode extends LeafNode
 {
-	/** the value */
-    protected Object value;
+    /** the value */
+    protected Value<?> value;
 
-    /** Constants for comparisons */
-    public final static boolean EVAL_GREATER = true;
-    public final static boolean EVAL_LESSER = false;
-
-    /**
-     * Creates a new SimpleNode object.
-     * 
-     * @param attribute the attribute name
-     * @param value the value to test for
-     */
-    protected SimpleNode( String attribute, byte[] value )
-    {
-        super( attribute );
-        this.value = value;
-    }
+    /** Constants for comparisons : > */
+    public static final boolean EVAL_GREATER = true;
+    
+    /** Constants for comparisons : < */
+    public static final boolean EVAL_LESSER = false;
 
 
     /**
@@ -55,10 +47,11 @@
      * 
      * @param attribute the attribute name
      * @param value the value to test for
+     * @param assertionType the node's type
      */
-    protected SimpleNode( String attribute, String value )
+    protected SimpleNode( String attribute, Value<?> value, AssertionType assertionType )
     {
-        super( attribute );
+        super( attribute, assertionType );
         this.value = value;
     }
 
@@ -68,7 +61,7 @@
      * 
      * @return the value
      */
-    public final Object getValue()
+    public final Value<?> getValue()
     {
         return value;
     }
@@ -79,35 +72,18 @@
      * 
      * @param value the value for this node
      */
-    public void setValue( Object value )
+    public void setValue( Value<?> value )
     {
         this.value = value;
     }
 
 
     /**
-     * @see org.apache.directory.shared.ldap.filter.ExprNode#printToBuffer(
-     *      java.lang.StringBuilder)
-     */
-    public StringBuilder printToBuffer( StringBuilder buf )
-    {
-        if ( ( null != getAnnotations() ) && getAnnotations().containsKey( "count" ) )
-        {
-            buf.append( ":[" );
-            buf.append( getAnnotations().get( "count" ).toString() );
-            buf.append( "] " );
-        }
-
-        buf.append( ')' );
-
-        return buf;
-    }
-
-    
-    /**
      * @see ExprNode#printRefinementToBuffer(StringBuilder)
+     * @return The buffer in which the refinement has been appended
+     * @throws UnsupportedOperationException if this node isn't a part of a refinement.
      */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
+    public StringBuilder printRefinementToBuffer( StringBuilder buf )
     {
         if ( getAttribute() == null || !SchemaConstants.OBJECT_CLASS_AT.equalsIgnoreCase( getAttribute() ) )
         {
@@ -122,18 +98,19 @@
 
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-    	int h = 31;
-    	h += value.hashCode()*13;
-    	h += getAttribute().hashCode()*13;
-    	h += this.getClass().hashCode()*13;
-    	
-    	return h;
+        int h = 37;
+
+        h = h * 17 + super.hashCode();
+        h = h * 17 + ( value == null ? 0 : value.hashCode() );
+
+        return h;
     }
 
-    
+
     /*
      * (non-Javadoc)
      * 
@@ -150,26 +127,26 @@
         {
             return false;
         }
-        
+
         if ( other.getClass() != this.getClass() )
         {
-        	return false;
-        }
-        
-        if ( !super.equals( other ) )
-        {
-        	return false;
+            return false;
         }
 
-        SimpleNode otherNode = (SimpleNode)other;
+        if ( !super.equals( other ) )
+        {
+            return false;
+        }
+
+        SimpleNode otherNode = ( SimpleNode ) other;
 
         if ( value == null )
         {
-        	return otherNode.value == null;
+            return otherNode.value == null;
         }
         else
         {
-        	return value.equals( otherNode.value );
-    	}
+            return value.equals( otherNode.value );
+        }
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
index fc21aad..63d2273 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/filter/SubstringNode.java
@@ -39,13 +39,13 @@
  */
 public class SubstringNode extends LeafNode
 {
-    /** The initial fragment before any wildcards */
+    /** The initial fragment before any wildcard */
     private String initialPattern;
 
-    /** The end fragment after wildcards */
+    /** The end fragment after wildcard */
     private String finalPattern;
 
-    /** List of fragments between wildcards */
+    /** List of fragments between wildcard */
     private List<String> anyPattern;
 
     /**
@@ -58,7 +58,7 @@
      */
     public SubstringNode( String attribute, String initialPattern, String finalPattern )
     {
-        super( attribute );
+        super( attribute, AssertionType.SUBSTRING );
 
         anyPattern = new ArrayList<String>( 2 );
         this.finalPattern = finalPattern;
@@ -70,12 +70,11 @@
      * Creates a new SubstringNode object without any value
      * 
      * @param attribute the name of the attribute to substring assert
-     * @param initialPattern the initial fragment
-     * @param finalPattern the final fragment
+     * @param attribute The attribute's ID
      */
     public SubstringNode( String attribute )
     {
-        super( attribute );
+        super( attribute, AssertionType.SUBSTRING );
 
         anyPattern = new ArrayList<String>( 2 );
         this.finalPattern = null;
@@ -94,7 +93,7 @@
      */
     public SubstringNode( List<String> anyPattern, String attribute, String initialPattern, String finalPattern )
     {
-        super( attribute );
+        super( attribute, AssertionType.SUBSTRING );
 
         this.anyPattern = anyPattern;
         this.finalPattern = finalPattern;
@@ -116,10 +115,10 @@
      * Set the initial pattern
      * @param initialPattern The initial pattern
      */
-	public void setInitial( String initialPattern ) 
-	{
-		this.initialPattern = initialPattern;
-	}
+    public void setInitial( String initialPattern ) 
+    {
+        this.initialPattern = initialPattern;
+    }
 
     /**
      * Gets the final fragment or suffix.
@@ -136,10 +135,10 @@
      * Set the final pattern
      * @param finalPattern The final pattern
      */
-	public void setFinal( String finalPattern ) 
-	{
-		this.finalPattern = finalPattern;
-	}
+    public void setFinal( String finalPattern ) 
+    {
+        this.finalPattern = finalPattern;
+    }
 
 
     /**
@@ -157,10 +156,10 @@
      * Set the any patterns
      * @param anyPattern The any patterns
      */
-	public void setAny( List<String> anyPattern ) 
-	{
-		this.anyPattern = anyPattern;
-	}
+    public void setAny( List<String> anyPattern ) 
+    {
+        this.anyPattern = anyPattern;
+    }
 
 
     /**
@@ -177,9 +176,11 @@
      * Gets the compiled regular expression for the substring expression.
      * 
      * @return the equivalent compiled regular expression
-     * @throws RESyntaxException if the regular expression is invalid
+     * @param normalizer The normalizer to use for the substring expressions
+     * @exception NamingException If the substring can't be normalized
+     * @exception PatternSyntaxException If the regexp is invalid
      */
-    public final Pattern getRegex( Normalizer normalizer ) throws PatternSyntaxException, NamingException
+    public final Pattern getRegex( Normalizer normalizer ) throws NamingException
     {
         if ( ( anyPattern != null ) && ( anyPattern.size() > 0 ) )
         {
@@ -231,12 +232,38 @@
 
 
     /**
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int h = 37;
+        
+        h = h*17 + super.hashCode();
+        h = h*17 + ( initialPattern != null ? initialPattern.hashCode() : 0 );
+        
+        if ( anyPattern != null )
+        {
+            for ( String pattern:anyPattern )
+            {
+                h = h*17 + pattern.hashCode();
+            }
+        }
+        
+        h = h*17 + ( finalPattern != null ? finalPattern.hashCode() : 0 );
+        
+        return h;
+    }
+
+
+    /**
      * @see java.lang.Object#toString()
+     * @return A string representing the AndNode
      */
     public String toString()
     {
-    	StringBuilder buf = new StringBuilder();
-    	
+        StringBuilder buf = new StringBuilder();
+        
         buf.append( '(' ).append( getAttribute() ).append( '=' );
 
         if ( null != initialPattern )
@@ -250,11 +277,11 @@
 
         if ( null != anyPattern )
         {
-	        for ( String any:anyPattern )
-	        {
-	            buf.append( any );
-	            buf.append( '*' );
-	        }
+            for ( String any:anyPattern )
+            {
+                buf.append( any );
+                buf.append( '*' );
+            }
         }
 
         if ( null != finalPattern )
@@ -268,13 +295,4 @@
         
         return buf.toString();
     }
-
-
-    /**
-     * @see ExprNode#printRefinementToBuffer(StringBuilder)
-     */
-    public StringBuilder printRefinementToBuffer( StringBuilder buf ) throws UnsupportedOperationException
-    {
-        throw new UnsupportedOperationException( "SubstringNode can't be part of a refinement" );
-    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/ChangeType.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/ChangeType.java
index a58fb96..2d9720d 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/ChangeType.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/ChangeType.java
@@ -34,10 +34,19 @@
     ModRdn( 3 ),
     Delete( 4 );
     
+    /** Add ordinal value */
     public static final int ADD_ORDINAL = 0;
+
+    /** Modify ordinal value */
     public static final int MODIFY_ORDINAL = 1;
+
+    /** ModDN ordinal value */
     public static final int MODDN_ORDINAL = 2;
+
+    /** ModRDN ordinal value */
     public static final int MODRDN_ORDINAL = 3;
+
+    /** Delete ordinal value */
     public static final int DELETE_ORDINAL = 4;
 
     /* the ordinal value for a change type */
@@ -60,7 +69,7 @@
      * 
      * @return the changeType
      */
-    public final int getChangeType()
+    public int getChangeType()
     {
         return changeType;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/Entry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/Entry.java
deleted file mode 100644
index 45d875c..0000000
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/Entry.java
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.shared.ldap.ldif;
-
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.ldap.Control;
-
-import org.apache.directory.shared.ldap.message.AttributeImpl;
-import org.apache.directory.shared.ldap.message.AttributesImpl;
-import org.apache.directory.shared.ldap.message.ModificationItemImpl;
-import org.apache.directory.shared.ldap.util.StringTools;
-
-/**
- * A entry to be populated by an ldif parser.
- * 
- * We will have different kind of entries : - added entries - deleted entries -
- * modified entries - RDN modified entries - DN modified entries
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- */
-public class Entry implements Cloneable
-{
-    /** the change type */
-    private ChangeType changeType;
-
-    /** the modification item list */
-    private List<ModificationItemImpl> modificationList;
-
-    private Map<String, ModificationItemImpl> modificationItems;
-
-    /** the dn of the ldif entry */
-    private String dn;
-
-    /** The new superior */
-    private String newSuperior;
-
-    /** The new rdn */
-    private String newRdn;
-
-    /** The delete old rdn flag */
-    private boolean deleteOldRdn;
-
-    /** attributes of the entry */
-    private Attributes attributeList;
-
-    
-    /** The control */
-    private Control control;
-
-    /**
-     * Creates a new Entry object.
-     */
-    public Entry()
-    {
-        changeType = ChangeType.Add; // Default LDIF content
-        modificationList = new LinkedList<ModificationItemImpl>();
-        modificationItems = new HashMap<String, ModificationItemImpl>();
-        dn = null;
-        attributeList = new AttributesImpl( true );
-        control = null;
-    }
-
-    /**
-     * Set the Distinguished Name
-     * 
-     * @param dn
-     *            The Distinguished Name
-     */
-    public void setDn( String dn )
-    {
-        this.dn = dn;
-    }
-
-    /**
-     * Set the modification type
-     * 
-     * @param changeType
-     *            The change type
-     * 
-     */
-    public void setChangeType( ChangeType changeType )
-    {
-        this.changeType = changeType;
-    }
-
-    /**
-     * Set the change type
-     * 
-     * @param changeType
-     *            The change type
-     */
-    public void setChangeType( String changeType )
-    {
-        if ( "add".equals( changeType ) )
-        {
-            this.changeType = ChangeType.Add;
-        }
-        else if ( "modify".equals( changeType ) )
-        {
-            this.changeType = ChangeType.Modify;
-        }
-        else if ( "moddn".equals( changeType ) )
-        {
-            this.changeType = ChangeType.ModDn;
-        }
-        else if ( "modrdn".equals( changeType ) )
-        {
-            this.changeType = ChangeType.ModRdn;
-        }
-        else if ( "delete".equals( changeType ) )
-        {
-            this.changeType = ChangeType.Delete;
-        }
-    }
-
-    /**
-     * Add a modification item (used by modify operations)
-     * 
-     * @param modification The modification to be added
-     */
-    public void addModificationItem( ModificationItemImpl modification )
-    {
-        if ( changeType == ChangeType.Modify )
-        {
-            modificationList.add( modification );
-            modificationItems.put( modification.getAttribute().getID(), modification );
-        }
-    }
-
-    /**
-     * Add a modification item (used by modify operations)
-     * 
-     * @param modOp
-     *            The operation. One of : DirContext.ADD_ATTRIBUTE
-     *            DirContext.REMOVE_ATTRIBUTE DirContext.REPLACE_ATTRIBUTE
-     * 
-     * @param attr
-     *            The attribute to be added
-     */
-    public void addModificationItem( int modOp, Attribute attr ) throws NamingException
-    {
-        if ( changeType == ChangeType.Modify )
-        {
-            if ( modificationItems.containsKey( attr.getID() ) )
-            {
-                ModificationItemImpl item = modificationItems.get( attr.getID() );
-                Attribute attribute = item.getAttribute();
-
-                Enumeration<?> attrs = attr.getAll();
-
-                while ( attrs.hasMoreElements() )
-                {
-                    attribute.add( attrs.nextElement() );
-                }
-            }
-            else
-            {
-                ModificationItemImpl item = new ModificationItemImpl( modOp, attr );
-                modificationList.add( item );
-                modificationItems.put( attr.getID(), item );
-            }
-        }
-    }
-
-    /**
-     * Add a modification item
-     * 
-     * @param modOp
-     *            The operation. One of : DirContext.ADD_ATTRIBUTE
-     *            DirContext.REMOVE_ATTRIBUTE DirContext.REPLACE_ATTRIBUTE
-     * 
-     * @param id
-     *            The attribute's ID
-     * @param value
-     *            The attribute's value
-     */
-    public void addModificationItem( int modOp, String id, Object value ) throws NamingException
-    {
-        if ( changeType == ChangeType.Modify )
-        {
-            Attribute attr = new AttributeImpl( id, value );
-
-            if ( modificationItems.containsKey( id ) )
-            {
-                ModificationItemImpl item = modificationItems.get( id );
-                
-                if ( item.getModificationOp() != modOp )
-                {
-                    // This is an error : we can't have two different 
-                    // modifications of the same attribute for the same entry
-                    
-                    throw new NamingException( "Bad modification" );
-                }
-                
-                Attribute attribute = item.getAttribute();
-
-                attribute.add( value );
-            }
-            else
-            {
-                ModificationItemImpl item = new ModificationItemImpl( modOp, attr );
-                modificationList.add( item );
-                modificationItems.put( id, item );
-            }
-        }
-    }
-
-    /**
-     * Add an attribute to the entry
-     * 
-     * @param attr
-     *            The attribute to be added
-     */
-    public void addAttribute( Attribute attr )
-    {
-        attributeList.put( attr );
-    }
-
-    /**
-     * Add an attribute to the entry
-     * 
-     * @param id
-     *            The attribute ID
-     * 
-     * @param value
-     *            The attribute value
-     * 
-     */
-    public void addAttribute( String id, Object value )
-    {
-        Attribute attr = get( id );
-
-        if ( attr != null )
-        {
-            attr.add( value );
-        }
-        else
-        {
-            attributeList.put( id, value );
-        }
-    }
-
-    /**
-     * Add an attribute value to an existing attribute
-     * 
-     * @param id
-     *            The attribute ID
-     * 
-     * @param value
-     *            The attribute value
-     * 
-     */
-    public void putAttribute( String id, Object value )
-    {
-        Attribute attribute = attributeList.get( id );
-
-        if ( attribute != null )
-        {
-            attribute.add( value );
-        }
-        else
-        {
-            attributeList.put( id, value );
-        }
-    }
-
-    /**
-     * Get the change type
-     * 
-     * @return The change type. One of : ADD = 0; MODIFY = 1; MODDN = 2; MODRDN =
-     *         3; DELETE = 4;
-     */
-    public ChangeType getChangeType()
-    {
-        return changeType;
-    }
-
-    /**
-     * @return The list of modification items
-     */
-    public List<ModificationItemImpl> getModificationItems()
-    {
-        return modificationList;
-    }
-
-    /**
-     * @return The entry Distinguished name
-     */
-    public String getDn()
-    {
-        return dn;
-    }
-
-    /**
-     * @return The number of entry modifications
-     */
-    public int size()
-    {
-        return modificationList.size();
-    }
-
-    /**
-     * Returns a attribute given it's id
-     * 
-     * @param attributeId
-     *            The attribute Id
-     * @return The attribute if it exists
-     */
-    public Attribute get( String attributeId )
-    {
-        if ( "dn".equalsIgnoreCase( attributeId ) )
-        {
-            return new AttributeImpl( "dn", dn );
-        }
-
-        return attributeList.get( attributeId );
-    }
-
-    /**
-     * Get the entry's attributes
-     * 
-     * @return An Attributes
-     */
-    public Attributes getAttributes()
-    {
-        if ( isEntry() )
-        {
-            return attributeList;
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    /**
-     * @return True, if the old RDN should be deleted.
-     */
-    public boolean isDeleteOldRdn()
-    {
-        return deleteOldRdn;
-    }
-
-    /**
-     * Set the flage deleteOldRdn
-     * 
-     * @param deleteOldRdn
-     *            True if the old RDN should be deleted
-     */
-    public void setDeleteOldRdn( boolean deleteOldRdn )
-    {
-        this.deleteOldRdn = deleteOldRdn;
-    }
-
-    /**
-     * @return The new RDN
-     */
-    public String getNewRdn()
-    {
-        return newRdn;
-    }
-
-    /**
-     * Set the new RDN
-     * 
-     * @param newRdn
-     *            The new RDN
-     */
-    public void setNewRdn( String newRdn )
-    {
-        this.newRdn = newRdn;
-    }
-
-    /**
-     * @return The new superior
-     */
-    public String getNewSuperior()
-    {
-        return newSuperior;
-    }
-
-    /**
-     * Set the new superior
-     * 
-     * @param newSuperior
-     *            The new Superior
-     */
-    public void setNewSuperior( String newSuperior )
-    {
-        this.newSuperior = newSuperior;
-    }
-
-    /**
-     * @return True if the entry is an ADD entry
-     */
-    public boolean isChangeAdd()
-    {
-        return changeType == ChangeType.Add;
-    }
-
-    /**
-     * @return True if the entry is a DELETE entry
-     */
-    public boolean isChangeDelete()
-    {
-        return changeType == ChangeType.Delete;
-    }
-
-    /**
-     * @return True if the entry is a MODDN entry
-     */
-    public boolean isChangeModDn()
-    {
-        return changeType == ChangeType.ModDn;
-    }
-
-    /**
-     * @return True if the entry is a MODRDN entry
-     */
-    public boolean isChangeModRdn()
-    {
-        return changeType == ChangeType.ModRdn;
-    }
-
-    /**
-     * @return True if the entry is a MODIFY entry
-     */
-    public boolean isChangeModify()
-    {
-        return changeType == ChangeType.Modify;
-    }
-
-    public boolean isEntry()
-    {
-        return changeType == ChangeType.Add;
-    }
-
-    /**
-     * @return The associated control, if any
-     */
-    public Control getControl()
-    {
-        return control;
-    }
-
-    /**
-     * Add a control to the entry
-     * 
-     * @param control
-     *            The control
-     */
-    public void setControl( Control control )
-    {
-        this.control = control;
-    }
-
-    /**
-     * Clone method
-     */
-    public Entry clone() throws CloneNotSupportedException
-    {
-        Entry clone = (Entry) super.clone();
-
-        if ( modificationList != null )
-        {
-            for ( ModificationItemImpl modif:modificationList )
-            {
-                ModificationItemImpl modifClone = new ModificationItemImpl( modif.getModificationOp(), (Attribute) modif.getAttribute()
-                        .clone() );
-                clone.modificationList.add( modifClone );
-            }
-        }
-
-        if ( modificationItems != null )
-        {
-            for ( String key:modificationItems.keySet() )
-            {
-                ModificationItemImpl modif = modificationItems.get( key );
-                ModificationItemImpl modifClone = new ModificationItemImpl( modif.getModificationOp(), (Attribute) modif.getAttribute()
-                        .clone() );
-                clone.modificationItems.put( key, modifClone );
-            }
-
-        }
-
-        if ( attributeList != null )
-        {
-            clone.attributeList = (Attributes)attributeList.clone();
-        }
-
-        return clone;
-    }
-    
-    /**
-     * Dumps the attributes
-     */
-    private String dumpAttributes()
-    {
-        StringBuffer sb = new StringBuffer();
-        
-        try
-        {
-            for ( NamingEnumeration<? extends Attribute> attrs = attributeList.getAll(); attrs.hasMoreElements(); )
-            {
-                Attribute attribute = attrs.nextElement();
-    
-                sb.append( "        ").append( attribute.getID() ).append( ":\n" );
-    
-                for ( NamingEnumeration<?> values = attribute.getAll(); values.hasMoreElements(); )
-                {
-                    Object value = values.nextElement();
-                    
-                    if ( value instanceof String )
-                    {
-                        sb.append(  "            " ).append( (String)value ).append('\n' );
-                    }
-                    else
-                    {
-                        sb.append(  "            " ).append( StringTools.dumpBytes( (byte[]) value ) ).append('\n' );
-                    }
-                }
-            }
-        }
-        catch ( NamingException ne )
-        {
-            return "";
-        }
-        
-        return sb.toString();
-    }
-    
-    /**
-     * Dumps the modifications
-     */
-    private String dumpModificationItems()
-    {
-        StringBuffer sb = new StringBuffer();
-        
-        for ( ModificationItemImpl modif:modificationList )
-        {
-            sb.append( "            Operation: " );
-            
-            switch ( modif.getModificationOp() )
-            {
-                case DirContext.ADD_ATTRIBUTE :
-                    sb.append( "ADD\n" );
-                    break;
-                    
-                case DirContext.REMOVE_ATTRIBUTE :
-                    sb.append( "REMOVE\n" );
-                    break;
-                    
-                case DirContext.REPLACE_ATTRIBUTE :
-                    sb.append( "REPLACE \n" );
-                    break;
-            }
-            
-            Attribute attribute = modif.getAttribute();
-            
-            sb.append( "                Attribute: " ).append( attribute.getID() ).append( '\n' );
-            
-            if ( attribute.size() != 0 )
-            {
-                try
-                {
-                    for ( NamingEnumeration<?> values = attribute.getAll(); values.hasMoreElements(); )
-                    {
-                        Object value = values.nextElement();
-    
-                        if ( value instanceof String )
-                        {
-                            sb.append(  "                " ).append( (String)value ).append('\n' );
-                        }
-                        else
-                        {
-                            sb.append(  "                " ).append( StringTools.dumpBytes( (byte[]) value ) ).append('\n' );
-                        }
-                    }
-                }
-                catch ( NamingException ne )
-                {
-                    return "";
-                }
-            }
-        }
-        
-        return sb.toString();
-    }
-
-    
-    /**
-     * Return a String representing the Entry
-     */
-    public String toString()
-    {
-        StringBuffer sb = new StringBuffer();
-        sb.append( "Entry : " ).append( dn ).append( '\n' );
-
-        if ( control != null )
-        {
-            sb.append( "    Control : " ).append(  control ).append( '\n' );
-        }
-        
-        switch ( changeType.getChangeType() )
-        {
-            case ChangeType.ADD_ORDINAL :
-                sb.append( "    Change type is ADD\n" );
-                sb.append( "        Attributes : \n" );
-                sb.append( dumpAttributes() );
-                break;
-                
-            case ChangeType.MODIFY_ORDINAL :
-                sb.append( "    Change type is MODIFY\n" );
-                sb.append( "        Modifications : \n" );
-                sb.append( dumpModificationItems() );
-                break;
-                
-            case ChangeType.DELETE_ORDINAL :
-                sb.append( "    Change type is DELETE\n" );
-                break;
-                
-            case ChangeType.MODDN_ORDINAL :
-            case ChangeType.MODRDN_ORDINAL :
-                sb.append( "    Change type is ").append( changeType == ChangeType.ModDn ? "MODDN\n" : "MODRDN\n" );
-                sb.append( "    Delete old RDN : " ).append( deleteOldRdn ? "true\n" : "false\n" );
-                sb.append( "    New RDN : " ).append( newRdn ).append( '\n' );
-                
-                if ( StringTools.isEmpty( newSuperior ) == false )
-                {
-                    sb.append( "    New superior : " ).append( newSuperior ).append( '\n' );
-                }
-
-                break;
-        }
-        
-        return sb.toString();
-    }
-}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java
new file mode 100644
index 0000000..f5a2e99
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java
@@ -0,0 +1,298 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.ldif;
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <pre>
+ *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; 
+ *  &lt;ldif-content-change&gt;
+ *  
+ *  &lt;ldif-content-change&gt; ::= 
+ *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | 
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | 
+ *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
+ *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
+ *                              
+ *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt; 
+ *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | e
+ *                              
+ *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; | e
+ *                              
+ *  &lt;dn-spec&gt; ::= &quot;dn:&quot; &lt;fill&gt; &lt;safe-string&gt; | &quot;dn::&quot; &lt;fill&gt; &lt;base64-string&gt;
+ *                              
+ *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; | e
+ *                              
+ *  &lt;criticality&gt; ::= &quot;true&quot; | &quot;false&quot; | e
+ *                              
+ *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
+ *                              
+ *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
+ *  &lt;attrval-specs-e&gt; | 
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
+ *                              
+ *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
+ *  
+ *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; | 
+ *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; | 
+ *    &quot;:&lt;&quot; &lt;fill&gt; &lt;url&gt;
+ *  
+ *  &lt;attributeType&gt; ::= &lt;number&gt; &lt;oid&gt; | &lt;alpha&gt; &lt;chars-e&gt;
+ *  
+ *  &lt;options-e&gt; ::= ';' &lt;char&gt; &lt;chars-e&gt; &lt;options-e&gt; |e
+ *                              
+ *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
+ *  
+ *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;value-spec&gt; 
+ *  &lt;sep&gt; &lt;attrval-specs-e&gt; | 
+ *    &quot;delete&quot; &lt;sep&gt; | 
+ *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;sep&gt; 
+ *    &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
+ *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; 
+ *    &lt;newsuperior-e&gt; &lt;sep&gt; |
+ *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; 
+ *    &lt;newsuperior-e&gt; &lt;sep&gt;
+ *  
+ *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
+ *  
+ *  &lt;newsuperior-e&gt; ::= &quot;newsuperior&quot; &lt;newrdn&gt; | e
+ *  
+ *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; 
+ *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | e
+ *  
+ *  &lt;mod-type&gt; ::= &quot;add:&quot; | &quot;delete:&quot; | &quot;replace:&quot;
+ *  
+ *  &lt;url&gt; ::= &lt;a Uniform Resource Locator, as defined in [6]&gt;
+ *  
+ *  
+ *  
+ *  LEXICAL
+ *  -------
+ *  
+ *  &lt;fill&gt;           ::= ' ' &lt;fill&gt; | e
+ *  &lt;char&gt;           ::= &lt;alpha&gt; | &lt;digit&gt; | '-'
+ *  &lt;number&gt;         ::= &lt;digit&gt; &lt;digits&gt;
+ *  &lt;0-1&gt;            ::= '0' | '1'
+ *  &lt;digits&gt;         ::= &lt;digit&gt; &lt;digits&gt; | e
+ *  &lt;digit&gt;          ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+ *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt; 
+ *  &lt;seps-e&gt;         ::= &lt;sep&gt; &lt;seps-e&gt; | e
+ *  &lt;sep&gt;            ::= 0x0D 0x0A | 0x0A
+ *  &lt;spaces&gt;         ::= ' ' &lt;spaces-e&gt;
+ *  &lt;spaces-e&gt;       ::= ' ' &lt;spaces-e&gt; | e
+ *  &lt;safe-string-e&gt;  ::= &lt;safe-string&gt; | e
+ *  &lt;safe-string&gt;    ::= &lt;safe-init-char&gt; &lt;safe-chars&gt;
+ *  &lt;safe-init-char&gt; ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x1F] | [0x21-0x39] | 0x3B | [0x3D-0x7F]
+ *  &lt;safe-chars&gt;     ::= &lt;safe-char&gt; &lt;safe-chars&gt; | e
+ *  &lt;safe-char&gt;      ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F]
+ *  &lt;base64-string&gt;  ::= &lt;base64-char&gt; &lt;base64-chars&gt;
+ *  &lt;base64-chars&gt;   ::= &lt;base64-char&gt; &lt;base64-chars&gt; | e
+ *  &lt;base64-char&gt;    ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-9x5A] | [0x61-0x7A]
+ *  &lt;alpha&gt;          ::= [0x41-0x5A] | [0x61-0x7A]
+ *  
+ *  COMMENTS
+ *  --------
+ *  - The ldap-oid VN is not correct in the RFC-2849. It has been changed from 1*DIGIT 0*1(&quot;.&quot; 1*DIGIT) to
+ *  DIGIT+ (&quot;.&quot; DIGIT+)*
+ *  - The mod-spec lacks a sep between *attrval-spec and &quot;-&quot;.
+ *  - The BASE64-UTF8-STRING should be BASE64-CHAR BASE64-STRING
+ *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a 
+ *  single space before the continued value.
+ * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class LdifAttributesReader extends LdifReader
+{
+    /** A logger */
+    private static final Logger LOG = LoggerFactory.getLogger( LdifAttributesReader.class );
+
+    /**
+     * Constructors
+     */
+    public LdifAttributesReader()
+    {
+        lines = new ArrayList<String>();
+        position = new Position();
+        version = DEFAULT_VERSION;
+    }
+
+
+    /**
+     * Parse an AttributeType/AttributeValue
+     * 
+     * @param attributes The entry where to store the value
+     * @param line The line to parse
+     * @param lowerLine The same line, lowercased
+     * @throws NamingException If anything goes wrong
+     */
+    private void parseAttribute( Attributes attributes, String line, String lowerLine ) throws NamingException
+    {
+        int colonIndex = line.indexOf( ':' );
+
+        String attributeType = lowerLine.substring( 0, colonIndex );
+
+        // We should *not* have a DN twice
+        if ( attributeType.equals( "dn" ) )
+        {
+            LOG.error( "An entry must not have two DNs" );
+            throw new NamingException( "A ldif entry should not have two DNs" );
+        }
+
+        Object attributeValue = parseValue( line, colonIndex );
+
+        // Update the entry
+        Attribute attribute = attributes.get( attributeType );
+        
+        if ( attribute == null )
+        {
+            attributes.put( attributeType, attributeValue );
+        }
+        else
+        {
+            attribute.add( attributeValue );
+        }
+    }
+
+    /**
+     * Parse a ldif file. The following rules are processed :
+     * 
+     * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
+     * &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; &lt;ldif-attrval-record&gt; ::=
+     * &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; &lt;ldif-change-record&gt; ::=
+     * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
+     * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
+     * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
+     * 
+     * @return The read entry
+     * @throws NamingException If the entry can't be read or is invalid
+     */
+    private Attributes parseAttributes() throws NamingException
+    {
+        if ( ( lines == null ) || ( lines.size() == 0 ) )
+        {
+            LOG.debug( "The entry is empty : end of ldif file" );
+            return null;
+        }
+
+        Attributes attributes = new BasicAttributes( true );
+
+        // Now, let's iterate through the other lines
+        for ( String line:lines )
+        {
+            // Each line could start either with an OID, an attribute type, with
+            // "control:" or with "changetype:"
+            String lowerLine = line.toLowerCase();
+
+            // We have three cases :
+            // 1) The first line after the DN is a "control:" -> this is an error
+            // 2) The first line after the DN is a "changeType:" -> this is an error
+            // 3) The first line after the DN is anything else
+            if ( lowerLine.startsWith( "control:" ) )
+            {
+                LOG.error( "We cannot have changes when reading a file which already contains entries" );
+                throw new NamingException( "No changes withing entries" );
+            }
+            else if ( lowerLine.startsWith( "changetype:" ) )
+            {
+                LOG.error( "We cannot have changes when reading a file which already contains entries" );
+                throw new NamingException( "No changes withing entries" );
+            }
+            else if ( line.indexOf( ':' ) > 0 )
+            {
+                parseAttribute( attributes, line, lowerLine );
+            }
+            else
+            {
+                // Invalid attribute Value
+                LOG.error( "Expecting an attribute type" );
+                throw new NamingException( "Bad attribute" );
+            }
+        }
+
+        LOG.debug( "Read an attributes : {}", attributes );
+        
+        return attributes;
+    }
+
+
+    /**
+     * A method which parses a ldif string and returns a list of entries.
+     * 
+     * @param ldif The ldif string
+     * @return A list of entries, or an empty List
+     * @throws NamingException
+     *             If something went wrong
+     */
+    public Attributes parseAttributes( String ldif ) throws NamingException
+    {
+        lines = new ArrayList<String>();
+        position = new Position();
+
+        LOG.debug( "Starts parsing ldif buffer" );
+
+        if ( StringTools.isEmpty( ldif ) )
+        {
+            return new BasicAttributes( true );
+        }
+
+        StringReader strIn = new StringReader( ldif );
+        in = new BufferedReader( strIn );
+
+        try
+        {
+            readLines();
+            
+            Attributes attributes = parseAttributes();
+
+            if ( LOG.isDebugEnabled() )
+            {
+                LOG.debug( "Parsed {} entries.", ( attributes == null ? 0 : 1 ) );
+            }
+
+            return attributes;
+        }
+        catch (NamingException ne)
+        {
+            LOG.error( "Cannot parse the ldif buffer : {}", ne.getMessage() );
+            throw new NamingException( "Error while parsing the ldif buffer" );
+        }
+    }
+}
\ No newline at end of file
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposer.java
index 079964f..0ccabe5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposer.java
@@ -42,5 +42,5 @@
      *            the entry to export to ldif
      * @return the ldif of an entry
      */
-    String compose( MultiMap an_entry );
+    String compose( MultiMap<String,?> an_entry );
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposerImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposerImpl.java
index 56b0964..3a8c081 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposerImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifComposerImpl.java
@@ -24,7 +24,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Collection;
-import java.util.Iterator;
 
 import org.apache.directory.shared.ldap.util.Base64;
 import org.apache.directory.shared.ldap.util.MultiMap;
@@ -33,7 +32,109 @@
 /**
  * An LDAP Data Interchange Format (LDIF) composer.
  * 
- * TODO Get the RFC for LDIF syntax in this javadoc.
+ * <pre>
+ *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; 
+ *  &lt;ldif-content-change&gt;
+ *  
+ *  &lt;ldif-content-change&gt; ::= 
+ *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | 
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | 
+ *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
+ *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
+ *                              
+ *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt; 
+ *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *    &lt;ldif-attrval-record-e&gt; | e
+ *                              
+ *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; | e
+ *                              
+ *  &lt;dn-spec&gt; ::= &quot;dn:&quot; &lt;fill&gt; &lt;safe-string&gt; | &quot;dn::&quot; &lt;fill&gt; &lt;base64-string&gt;
+ *                              
+ *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; | e
+ *                              
+ *  &lt;criticality&gt; ::= &quot;true&quot; | &quot;false&quot; | e
+ *                              
+ *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
+ *                              
+ *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
+ *  &lt;attrval-specs-e&gt; | 
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
+ *                              
+ *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
+ *  
+ *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; | 
+ *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; | 
+ *    &quot;:&lt;&quot; &lt;fill&gt; &lt;url&gt;
+ *  
+ *  &lt;attributeType&gt; ::= &lt;number&gt; &lt;oid&gt; | &lt;alpha&gt; &lt;chars-e&gt;
+ *  
+ *  &lt;options-e&gt; ::= ';' &lt;char&gt; &lt;chars-e&gt; &lt;options-e&gt; |e
+ *                              
+ *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
+ *  
+ *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; 
+ *  &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | 
+ *    &quot;delete&quot; &lt;sep&gt; | 
+ *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; 
+ *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
+ *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; 
+ *    &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt; |
+ *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; 
+ *    &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt;
+ *  
+ *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
+ *  
+ *  &lt;newsuperior-e&gt; ::= &quot;newsuperior&quot; &lt;newrdn&gt; | e
+ *  
+ *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; 
+ *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | e
+ *  
+ *  &lt;mod-type&gt; ::= &quot;add:&quot; | &quot;delete:&quot; | &quot;replace:&quot;
+ *  
+ *  &lt;url&gt; ::= &lt;a Uniform Resource Locator, as defined in [6]&gt;
+ *  
+ *  
+ *  
+ *  LEXICAL
+ *  -------
+ *  
+ *  &lt;fill&gt;           ::= ' ' &lt;fill&gt; | e
+ *  &lt;char&gt;           ::= &lt;alpha&gt; | &lt;digit&gt; | '-'
+ *  &lt;number&gt;         ::= &lt;digit&gt; &lt;digits&gt;
+ *  &lt;0-1&gt;            ::= '0' | '1'
+ *  &lt;digits&gt;         ::= &lt;digit&gt; &lt;digits&gt; | e
+ *  &lt;digit&gt;          ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+ *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt; 
+ *  &lt;seps-e&gt;         ::= &lt;sep&gt; &lt;seps-e&gt; | e
+ *  &lt;sep&gt;            ::= 0x0D 0x0A | 0x0A
+ *  &lt;spaces&gt;         ::= ' ' &lt;spaces-e&gt;
+ *  &lt;spaces-e&gt;       ::= ' ' &lt;spaces-e&gt; | e
+ *  &lt;safe-string-e&gt;  ::= &lt;safe-string&gt; | e
+ *  &lt;safe-string&gt;    ::= &lt;safe-init-char&gt; &lt;safe-chars&gt;
+ *  &lt;safe-init-char&gt; ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x1F] | [0x21-0x39] | 0x3B | [0x3D-0x7F]
+ *  &lt;safe-chars&gt;     ::= &lt;safe-char&gt; &lt;safe-chars&gt; | e
+ *  &lt;safe-char&gt;      ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F]
+ *  &lt;base64-string&gt;  ::= &lt;base64-char&gt; &lt;base64-chars&gt;
+ *  &lt;base64-chars&gt;   ::= &lt;base64-char&gt; &lt;base64-chars&gt; | e
+ *  &lt;base64-char&gt;    ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-9x5A] | [0x61-0x7A]
+ *  &lt;alpha&gt;          ::= [0x41-0x5A] | [0x61-0x7A]
+ *  
+ *  COMMENTS
+ *  --------
+ *  - The ldap-oid VN is not correct in the RFC-2849. It has been changed from 1*DIGIT 0*1(&quot;.&quot; 1*DIGIT) to
+ *  DIGIT+ (&quot;.&quot; DIGIT+)*
+ *  - The mod-spec lacks a sep between *attrval-spec and &quot;-&quot;.
+ *  - The BASE64-UTF8-STRING should be BASE64-CHAR BASE64-STRING
+ *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a 
+ *  single space before the continued value.
+ * </pre>
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
@@ -42,25 +143,17 @@
     /**
      * Generates an LDIF from a multi map.
      * 
-     * @param attrHash
-     *            the multi map of single and multivalued attributes.
+     * @param attrHash the multi map of single and multivalued attributes.
      * @return the LDIF as a String.
      */
-    public String compose( MultiMap attrHash )
+    public String compose( MultiMap<String,?> attrHash )
     {
-        Object val = null;
-        String key = null;
-        Iterator keys = attrHash.keySet().iterator();
-        Iterator values = null;
-        Collection valueCol = null;
         StringWriter sw = new StringWriter();
         PrintWriter out = new PrintWriter( sw );
 
-        while ( keys.hasNext() )
+        for ( String key:attrHash.keySet() )
         {
-            key = ( String ) keys.next();
-            valueCol = ( Collection ) attrHash.get( key );
-            values = valueCol.iterator();
+            Collection<?> valueCol = ( Collection<?> ) attrHash.get( key );
 
             if ( valueCol.isEmpty() )
             {
@@ -70,7 +163,7 @@
             {
                 out.print( key );
                 out.print( ':' );
-                val = values.next();
+                Object val = valueCol.iterator().next();
 
                 if ( val.getClass().isArray() )
                 {
@@ -85,11 +178,10 @@
                 continue;
             }
 
-            while ( values.hasNext() )
+            for ( Object val:valueCol )
             {
                 out.print( key );
                 out.print( ':' );
-                val = values.next();
 
                 if ( val.getClass().isArray() )
                 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifControl.java
index 45abce7..3dbad9e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifControl.java
@@ -30,10 +30,11 @@
  * file.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LdifControl implements Control
 {
-    static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
     /** The control OID */
     private OID oid;
@@ -59,6 +60,7 @@
 
     /**
      * Returns the criticality of the current control
+     * @return <code>true</code> if the control is critical
      */
     public boolean isCritical()
     {
@@ -78,6 +80,7 @@
 
     /**
      * Return the control's OID as a String
+     * @return The control's OID
      */
     public String getID()
     {
@@ -87,8 +90,7 @@
     /**
      * Set the control's OID
      * 
-     * @param oid
-     *            The control's OID
+     * @param oid The control's OID
      */
     public void setOid( OID oid )
     {
@@ -97,10 +99,18 @@
 
     /**
      * Returns the BER encoded value of the control
+     * @return the BER encoded value
      */
     public byte[] getEncodedValue()
     {
-        return value;
+        if ( value == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ value.length ];
+        System.arraycopy( value, 0, copy, 0, value.length );
+        return copy;
     }
 
     /**
@@ -111,7 +121,13 @@
      */
     public void setValue( byte[] value )
     {
-        this.value = value;
+        if ( value != null )
+        {
+            this.value = new byte[ value.length ];
+            System.arraycopy( value, 0, this.value, 0, value.length );
+        } else {
+            this.value = null;
+        }
     }
 
     public String toString()
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifEntry.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifEntry.java
new file mode 100644
index 0000000..6c87ee4
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifEntry.java
@@ -0,0 +1,938 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.shared.ldap.ldif;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+import javax.naming.ldap.Control;
+
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+import org.apache.directory.shared.ldap.message.ModificationItemImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.Rdn;
+import org.apache.directory.shared.ldap.util.StringTools;
+
+
+/**
+ * A entry to be populated by an ldif parser.
+ * 
+ * We will have different kind of entries : 
+ * - added entries 
+ * - deleted entries 
+ * - modified entries 
+ * - RDN modified entries 
+ * - DN modified entries
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class LdifEntry implements Cloneable, Serializable
+{
+    private static final long serialVersionUID = 2L;
+    
+    /** Used in toArray() */
+    public static final ModificationItemImpl[] EMPTY_MODS = new ModificationItemImpl[0];
+
+    /** the change type */
+    private ChangeType changeType;
+
+    /** the modification item list */
+    private List<ModificationItemImpl> modificationList;
+
+    private Map<String, ModificationItemImpl> modificationItems;
+
+    /** the dn of the ldif entry */
+    private String dn;
+
+    /** The new superior */
+    private String newSuperior;
+
+    /** The new rdn */
+    private String newRdn;
+
+    /** The delete old rdn flag */
+    private boolean deleteOldRdn;
+
+    /** attributes of the entry */
+    private Attributes attributes;
+
+    
+    /** The control */
+    private Control control;
+
+    /**
+     * Creates a new Entry object.
+     */
+    public LdifEntry()
+    {
+        changeType = ChangeType.Add; // Default LDIF content
+        modificationList = new LinkedList<ModificationItemImpl>();
+        modificationItems = new HashMap<String, ModificationItemImpl>();
+        dn = null;
+        attributes = new AttributesImpl( true );
+        control = null;
+    }
+
+    /**
+     * Set the Distinguished Name
+     * 
+     * @param dn
+     *            The Distinguished Name
+     */
+    public void setDn( String dn )
+    {
+        this.dn = dn;
+    }
+
+    /**
+     * Set the modification type
+     * 
+     * @param changeType
+     *            The change type
+     * 
+     */
+    public void setChangeType( ChangeType changeType )
+    {
+        this.changeType = changeType;
+    }
+
+    /**
+     * Set the change type
+     * 
+     * @param changeType
+     *            The change type
+     */
+    public void setChangeType( String changeType )
+    {
+        if ( "add".equals( changeType ) )
+        {
+            this.changeType = ChangeType.Add;
+        }
+        else if ( "modify".equals( changeType ) )
+        {
+            this.changeType = ChangeType.Modify;
+        }
+        else if ( "moddn".equals( changeType ) )
+        {
+            this.changeType = ChangeType.ModDn;
+        }
+        else if ( "modrdn".equals( changeType ) )
+        {
+            this.changeType = ChangeType.ModRdn;
+        }
+        else if ( "delete".equals( changeType ) )
+        {
+            this.changeType = ChangeType.Delete;
+        }
+    }
+
+    /**
+     * Add a modification item (used by modify operations)
+     * 
+     * @param modification The modification to be added
+     */
+    public void addModificationItem( ModificationItemImpl modification )
+    {
+        if ( changeType == ChangeType.Modify )
+        {
+            modificationList.add( modification );
+            modificationItems.put( modification.getAttribute().getID(), modification );
+        }
+    }
+
+    /**
+     * Add a modification item (used by modify operations)
+     * 
+     * @param modOp The operation. One of : DirContext.ADD_ATTRIBUTE
+     *            DirContext.REMOVE_ATTRIBUTE DirContext.REPLACE_ATTRIBUTE
+     * 
+     * @param attr The attribute to be added
+     */
+    public void addModificationItem( int modOp, Attribute attr )
+    {
+        if ( changeType == ChangeType.Modify )
+        {
+            ModificationItemImpl item = new ModificationItemImpl( modOp, attr );
+            modificationList.add( item );
+            modificationItems.put( attr.getID(), item );
+        }
+    }
+
+    /**
+     * Add a modification item
+     * 
+     * @param modOp
+     *            The operation. One of : DirContext.ADD_ATTRIBUTE
+     *            DirContext.REMOVE_ATTRIBUTE DirContext.REPLACE_ATTRIBUTE
+     * 
+     * @param modOp The modification operation value
+     * @param id The attribute's ID
+     * @param value The attribute's value
+     */
+    public void addModificationItem( int modOp, String id, Object value )
+    {
+        if ( changeType == ChangeType.Modify )
+        {
+            Attribute attr = new AttributeImpl( id, value );
+
+            ModificationItemImpl item = new ModificationItemImpl( modOp, attr );
+            modificationList.add( item );
+            modificationItems.put( id, item );
+        }
+    }
+
+    /**
+     * Add an attribute to the entry
+     * 
+     * @param attr
+     *            The attribute to be added
+     */
+    public void addAttribute( Attribute attr )
+    {
+        attributes.put( attr );
+    }
+
+    /**
+     * Add an attribute to the entry
+     * 
+     * @param id
+     *            The attribute ID
+     * 
+     * @param value
+     *            The attribute value
+     * 
+     */
+    public void addAttribute( String id, Object value )
+    {
+        Attribute attr = get( id );
+
+        if ( attr != null )
+        {
+            attr.add( value );
+        }
+        else
+        {
+            attributes.put( id, value );
+        }
+    }
+
+    /**
+     * Add an attribute value to an existing attribute
+     * 
+     * @param id
+     *            The attribute ID
+     * 
+     * @param value
+     *            The attribute value
+     * 
+     */
+    public void putAttribute( String id, Object value )
+    {
+        Attribute attribute = attributes.get( id );
+
+        if ( attribute != null )
+        {
+            attribute.add( value );
+        }
+        else
+        {
+            attributes.put( id, value );
+        }
+    }
+
+    /**
+     * Get the change type
+     * 
+     * @return The change type. One of : ADD = 0; MODIFY = 1; MODDN = 2; MODRDN =
+     *         3; DELETE = 4;
+     */
+    public ChangeType getChangeType()
+    {
+        return changeType;
+    }
+
+    /**
+     * @return The list of modification items
+     */
+    public List<ModificationItemImpl> getModificationItems()
+    {
+        return modificationList;
+    }
+
+
+    /**
+     * Gets the modification items as an array.
+     *
+     * @return modification items as an array.
+     */
+    public ModificationItemImpl[] getModificationItemsArray()
+    {
+        return modificationList.toArray( EMPTY_MODS );
+    }
+
+
+    /**
+     * @return The entry Distinguished name
+     */
+    public String getDn()
+    {
+        return dn;
+    }
+
+    /**
+     * @return The number of entry modifications
+     */
+    public int size()
+    {
+        return modificationList.size();
+    }
+
+    /**
+     * Returns a attribute given it's id
+     * 
+     * @param attributeId
+     *            The attribute Id
+     * @return The attribute if it exists
+     */
+    public Attribute get( String attributeId )
+    {
+        if ( "dn".equalsIgnoreCase( attributeId ) )
+        {
+            return new AttributeImpl( "dn", dn );
+        }
+
+        return attributes.get( attributeId );
+    }
+
+    /**
+     * Get the entry's attributes
+     * 
+     * @return An Attributes
+     */
+    public Attributes getAttributes()
+    {
+        if ( isEntry() )
+        {
+            return attributes;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    /**
+     * @return True, if the old RDN should be deleted.
+     */
+    public boolean isDeleteOldRdn()
+    {
+        return deleteOldRdn;
+    }
+
+    /**
+     * Set the flage deleteOldRdn
+     * 
+     * @param deleteOldRdn
+     *            True if the old RDN should be deleted
+     */
+    public void setDeleteOldRdn( boolean deleteOldRdn )
+    {
+        this.deleteOldRdn = deleteOldRdn;
+    }
+
+    /**
+     * @return The new RDN
+     */
+    public String getNewRdn()
+    {
+        return newRdn;
+    }
+
+    /**
+     * Set the new RDN
+     * 
+     * @param newRdn
+     *            The new RDN
+     */
+    public void setNewRdn( String newRdn )
+    {
+        this.newRdn = newRdn;
+    }
+
+    /**
+     * @return The new superior
+     */
+    public String getNewSuperior()
+    {
+        return newSuperior;
+    }
+
+    /**
+     * Set the new superior
+     * 
+     * @param newSuperior
+     *            The new Superior
+     */
+    public void setNewSuperior( String newSuperior )
+    {
+        this.newSuperior = newSuperior;
+    }
+
+    /**
+     * @return True if the entry is an ADD entry
+     */
+    public boolean isChangeAdd()
+    {
+        return changeType == ChangeType.Add;
+    }
+
+    /**
+     * @return True if the entry is a DELETE entry
+     */
+    public boolean isChangeDelete()
+    {
+        return changeType == ChangeType.Delete;
+    }
+
+    /**
+     * @return True if the entry is a MODDN entry
+     */
+    public boolean isChangeModDn()
+    {
+        return changeType == ChangeType.ModDn;
+    }
+
+    /**
+     * @return True if the entry is a MODRDN entry
+     */
+    public boolean isChangeModRdn()
+    {
+        return changeType == ChangeType.ModRdn;
+    }
+
+    /**
+     * @return True if the entry is a MODIFY entry
+     */
+    public boolean isChangeModify()
+    {
+        return changeType == ChangeType.Modify;
+    }
+
+    /**
+     * Tells if the current entry is a added one
+     *
+     * @return <code>true</code> if the entry is added
+     */
+    public boolean isEntry()
+    {
+        return changeType == ChangeType.Add;
+    }
+
+    /**
+     * @return The associated control, if any
+     */
+    public Control getControl()
+    {
+        return control;
+    }
+
+    /**
+     * Add a control to the entry
+     * 
+     * @param control
+     *            The control
+     */
+    public void setControl( Control control )
+    {
+        this.control = control;
+    }
+
+    /**
+     * Clone method
+     * @return a clone of the current instance
+     * @exception CloneNotSupportedException If there is some problem while cloning the instance
+     */
+    public LdifEntry clone() throws CloneNotSupportedException
+    {
+        LdifEntry clone = (LdifEntry) super.clone();
+
+        if ( modificationList != null )
+        {
+            for ( ModificationItemImpl modif:modificationList )
+            {
+                ModificationItemImpl modifClone = new ModificationItemImpl( modif.getModificationOp(), 
+                    (Attribute) modif.getAttribute().clone() );
+                clone.modificationList.add( modifClone );
+            }
+        }
+
+        if ( modificationItems != null )
+        {
+            for ( String key:modificationItems.keySet() )
+            {
+                ModificationItemImpl modif = modificationItems.get( key );
+                ModificationItemImpl modifClone = new ModificationItemImpl( modif.getModificationOp(), 
+                    (Attribute) modif.getAttribute().clone() );
+                clone.modificationItems.put( key, modifClone );
+            }
+
+        }
+
+        if ( attributes != null )
+        {
+            clone.attributes = (Attributes)attributes.clone();
+        }
+
+        return clone;
+    }
+    
+    /**
+     * Dumps the attributes
+     * @return A String representing the attributes
+     */
+    private String dumpAttributes()
+    {
+        StringBuffer sb = new StringBuffer();
+        Attribute attribute = null;
+        
+        try
+        {
+            for ( NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); 
+                  attrs.hasMoreElements(); 
+                  attribute = attrs.nextElement())
+            {
+                if ( attribute == null )
+                {
+                    sb.append( "        Null attribute\n" );
+                    continue;
+                }
+                
+                sb.append( "        ").append( attribute.getID() ).append( ":\n" );
+                Object value = null;
+                
+                for ( NamingEnumeration<?> values = attribute.getAll(); 
+                      values.hasMoreElements(); 
+                      value = values.nextElement())
+                {
+                    if ( value instanceof String )
+                    {
+                        sb.append(  "            " ).append( (String)value ).append('\n' );
+                    }
+                    else
+                    {
+                        sb.append(  "            " ).append( StringTools.dumpBytes( (byte[]) value ) ).append('\n' );
+                    }
+                }
+            }
+        }
+        catch ( NamingException ne )
+        {
+            return "";
+        }
+        
+        return sb.toString();
+    }
+    
+    /**
+     * Dumps the modifications
+     * @return A String representing the modifications
+     */
+    private String dumpModificationItems()
+    {
+        StringBuffer sb = new StringBuffer();
+        
+        for ( ModificationItemImpl modif:modificationList )
+        {
+            sb.append( "            Operation: " );
+            
+            switch ( modif.getModificationOp() )
+            {
+                case DirContext.ADD_ATTRIBUTE :
+                    sb.append( "ADD\n" );
+                    break;
+                    
+                case DirContext.REMOVE_ATTRIBUTE :
+                    sb.append( "REMOVE\n" );
+                    break;
+                    
+                case DirContext.REPLACE_ATTRIBUTE :
+                    sb.append( "REPLACE \n" );
+                    break;
+                    
+                default :
+                    break; // Do nothing
+            }
+            
+            Attribute attribute = modif.getAttribute();
+            
+            sb.append( "                Attribute: " ).append( attribute.getID() ).append( '\n' );
+            
+            if ( attribute.size() != 0 )
+            {
+                try
+                {
+                    Object value = null;
+                    for ( NamingEnumeration<?> values = attribute.getAll(); 
+                          values.hasMoreElements(); 
+                          value = values.nextElement() )
+                    {
+                        if ( value instanceof String )
+                        {
+                            sb.append(  "                " ).append( (String)value ).append('\n' );
+                        }
+                        else
+                        {
+                            sb.append(  "                " ).append( StringTools.dumpBytes( (byte[]) value ) ).append('\n' );
+                        }
+                    }
+                }
+                catch ( NamingException ne )
+                {
+                    return "";
+                }
+            }
+        }
+        
+        return sb.toString();
+    }
+
+    
+    /**
+     * @return a String representing the Entry
+     */
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append( "Entry : " ).append( dn ).append( '\n' );
+
+        if ( control != null )
+        {
+            sb.append( "    Control : " ).append(  control ).append( '\n' );
+        }
+        
+        switch ( changeType )
+        {
+            case Add :
+                sb.append( "    Change type is ADD\n" );
+                sb.append( "        Attributes : \n" );
+                sb.append( dumpAttributes() );
+                break;
+                
+            case Modify :
+                sb.append( "    Change type is MODIFY\n" );
+                sb.append( "        Modifications : \n" );
+                sb.append( dumpModificationItems() );
+                break;
+                
+            case Delete :
+                sb.append( "    Change type is DELETE\n" );
+                break;
+                
+            case ModDn :
+            case ModRdn :
+                sb.append( "    Change type is ").append( changeType == ChangeType.ModDn ? "MODDN\n" : "MODRDN\n" );
+                sb.append( "    Delete old RDN : " ).append( deleteOldRdn ? "true\n" : "false\n" );
+                sb.append( "    New RDN : " ).append( newRdn ).append( '\n' );
+                
+                if ( !StringTools.isEmpty( newSuperior ) )
+                {
+                    sb.append( "    New superior : " ).append( newSuperior ).append( '\n' );
+                }
+
+                break;
+                
+            default :
+                break; // Do nothing
+        }
+        
+        return sb.toString();
+    }
+    
+    
+    /**
+     * @see Object#hashCode()
+     * 
+     * @return the instance's hash code
+     */
+    public int hashCode()
+    {
+        int result = 37;
+
+        if ( dn != null )
+        {
+            result = result*17 + dn.hashCode();
+        }
+        
+        if ( changeType != null )
+        {
+            result = result*17 + changeType.hashCode();
+            
+            // Check each different cases
+            switch ( changeType )
+            {
+                case Add :
+                    // Checks the attributes
+                    if ( attributes != null )
+                    {
+                        result = result * 17 + attributes.hashCode();
+                    }
+                    
+                    break;
+
+                case Delete :
+                    // Nothing to compute
+                    break;
+                    
+                case Modify :
+                    if ( modificationList != null )
+                    {
+                        result = result * 17 + modificationList.hashCode();
+                        
+                        for ( ModificationItem modification:modificationList )
+                        {
+                            result = result * 17 + modification.hashCode();
+                        }
+                    }
+                    
+                    break;
+                    
+                case ModDn :
+                case ModRdn :
+                    result = result * 17 + ( deleteOldRdn ? 1 : -1 ); 
+                    
+                    if ( newRdn != null )
+                    {
+                        result = result*17 + newRdn.hashCode();
+                    }
+                    
+                    if ( newSuperior != null )
+                    {
+                        result = result*17 + newSuperior.hashCode();
+                    }
+                    
+                    break;
+                    
+                default :
+                    break; // do nothing
+            }
+        }
+
+        if ( control != null )
+        {
+            result = result * 17 + control.hashCode();
+        }
+
+        return result;
+    }
+    
+    /**
+     * @see Object#equals(Object)
+     * @return <code>true</code> if both values are equal
+     */
+    public boolean equals( Object o )
+    {
+        // Basic equals checks
+        if ( this == o )
+        {
+            return true;
+        }
+        
+        if ( o == null )
+        {
+           return false;
+        }
+        
+        if ( ! (o instanceof LdifEntry ) )
+        {
+            return false;
+        }
+        
+        LdifEntry entry = (LdifEntry)o;
+        
+        // Check the DN
+        try
+        {
+            LdapDN thisDn = new LdapDN( dn );
+            LdapDN dnEntry = new LdapDN( entry.dn );
+            
+            if ( !thisDn.equals( dnEntry ) )
+            {
+                return false;
+            }
+        }
+        catch ( InvalidNameException ine )
+        {
+            return false;
+        }
+        
+        // Check the changeType
+        if ( changeType != entry.changeType )
+        {
+            return false;
+        }
+        
+        // Check each different cases
+        switch ( changeType )
+        {
+            case Add :
+                // Checks the attributes
+                if ( attributes == null )
+                {
+                    if ( entry.attributes != null )
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                
+                if ( entry.attributes == null )
+                {
+                    return false;
+                }
+                
+                if ( attributes.size() != entry.attributes.size() )
+                {
+                    return false;
+                }
+                
+                if ( !attributes.equals( entry.attributes ) )
+                {
+                    return false;
+                }
+                
+                break;
+
+            case Delete :
+                // Nothing to do, is the DNs are equals
+                break;
+                
+            case Modify :
+                // Check the modificationItems list
+
+                // First, deal with special cases
+                if ( modificationList == null )
+                {
+                    if ( entry.modificationList != null )
+                    {
+                        return false;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                
+                if ( entry.modificationList == null )
+                {
+                    return false;
+                }
+                
+                if ( modificationList.size() != entry.modificationList.size() )
+                {
+                    return false;
+                }
+                
+                // Now, compares the contents
+                int i = 0;
+                
+                for ( ModificationItemImpl modification:modificationList )
+                {
+                    if ( ! modification.equals( entry.modificationList.get( i ) ) )
+                    {
+                        return false;
+                    }
+                    
+                    i++;
+                }
+                
+                break;
+                
+            case ModDn :
+            case ModRdn :
+                // Check the deleteOldRdn flag
+                if ( deleteOldRdn != entry.deleteOldRdn )
+                {
+                    return false;
+                }
+                
+                // Check the newRdn value
+                try
+                {
+                    Rdn thisNewRdn = new Rdn( newRdn );
+                    Rdn entryNewRdn = new Rdn( entry.newRdn );
+
+                    if ( !thisNewRdn.equals( entryNewRdn ) )
+                    {
+                        return false;
+                    }
+                }
+                catch ( InvalidNameException ine )
+                {
+                    return false;
+                }
+                
+                // Check the newSuperior value
+                try
+                {
+                    LdapDN thisNewSuperior = new LdapDN( newSuperior );
+                    LdapDN entryNewSuperior = new LdapDN( entry.newSuperior );
+                    
+                    if ( ! thisNewSuperior.equals(  entryNewSuperior ) )
+                    {
+                        return false;
+                    }
+                }
+                catch ( InvalidNameException ine )
+                {
+                    return false;
+                }
+                
+                break;
+                
+            default :
+                break; // do nothing
+        }
+        
+        if ( control != null )
+        {
+            return control.equals(  entry.control );
+        }
+        else 
+        {
+            return entry.control == null;
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java
index 20024bc..7dd0a30 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java
@@ -57,12 +57,16 @@
 
 /**
  * <pre>
- *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;ldif-content-change&gt;
+ *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; 
+ *  &lt;ldif-content-change&gt;
  *  
  *  &lt;ldif-content-change&gt; ::= 
- *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
- *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
- *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
+ *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
+ *    &lt;attrval-specs-e&gt; &lt;ldif-attrval-record-e&gt; | 
+ *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; 
+ *    &lt;criticality&gt; &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
  *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
  *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
  *                              
@@ -82,7 +86,8 @@
  *                              
  *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
  *                              
- *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | 
+ *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; 
+ *  &lt;sep&gt; &lt;attrval-specs-e&gt; | 
  *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
  *                              
  *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
@@ -97,11 +102,15 @@
  *                              
  *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
  *  
- *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | 
+ *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; 
+ *  &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | 
  *    &quot;delete&quot; &lt;sep&gt; | 
- *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
- *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt; |
- *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt;
+ *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; 
+ *    &lt;options-e&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
+ *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; 
+ *    &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt; |
+ *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; 
+ *    &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; &lt;newsuperior-e&gt; &lt;sep&gt;
  *  
  *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
  *  
@@ -149,27 +158,47 @@
  *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a 
  *  single space before the continued value.
  * </pre>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
-public class LdifReader implements Iterator<Entry>
+public class LdifReader implements Iterable<LdifEntry>
 {
     /** A logger */
-    private static final Logger log = LoggerFactory.getLogger( LdifReader.class );
+    private static final Logger LOG = LoggerFactory.getLogger( LdifReader.class );
 
-    /** A private class to track the current position in a line */
-    private class Position
+    /** 
+     * A private class to track the current position in a line 
+     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+     * @version $Rev$, $Date$
+     */
+    public class Position
     {
-        public int pos;
+        /** The current position */
+        private int pos;
 
+        /**
+         * Creates a new instance of Position.
+         */
         public Position()
         {
             pos = 0;
         }
 
+        /**
+         * Increment the current position by one
+         *
+         */
         public void inc()
         {
             pos++;
         }
 
+        /**
+         * Increment the current position by the given value
+         *
+         * @param val The value to add to the current position
+         */
         public void inc( int val )
         {
             pos += val;
@@ -177,54 +206,54 @@
     }
 
     /** A list of read lines */
-    private List<String> lines;
+    protected List<String> lines;
 
     /** The current position */
-    private Position position;
+    protected Position position;
 
     /** The ldif file version default value */
-    private static final int DEFAULT_VERSION = 1;
+    protected static final int DEFAULT_VERSION = 1;
 
     /** The ldif version */
-    private int version;
+    protected int version;
 
     /** Type of element read */
-    private static final int ENTRY = 0;
+    protected static final int LDIF_ENTRY = 0;
 
-    private static final int CHANGE = 1;
+    protected static final int CHANGE = 1;
 
-    private static final int UNKNOWN = 2;
+    protected static final int UNKNOWN = 2;
 
     /** Size limit for file contained values */
-    private long sizeLimit = SIZE_LIMIT_DEFAULT;
+    protected long sizeLimit = SIZE_LIMIT_DEFAULT;
 
     /** The default size limit : 1Mo */
-    private static final long SIZE_LIMIT_DEFAULT = 1024000;
+    protected static final long SIZE_LIMIT_DEFAULT = 1024000;
 
     /** State values for the modify operation */
-    private static final int MOD_SPEC = 0;
+    protected static final int MOD_SPEC = 0;
 
-    private static final int ATTRVAL_SPEC = 1;
+    protected static final int ATTRVAL_SPEC = 1;
 
-    private static final int ATTRVAL_SPEC_OR_SEP = 2;
+    protected static final int ATTRVAL_SPEC_OR_SEP = 2;
 
     /** Iterator prefetched entry */
-    private Entry prefetched;
+    protected LdifEntry prefetched;
 
     /** The ldif Reader */
-    private Reader in;
+    protected Reader in;
 
     /** A flag set if the ldif contains entries */
-    private boolean containsEntries;
+    protected boolean containsEntries;
 
     /** A flag set if the ldif contains changes */
-    private boolean containsChanges;
+    protected boolean containsChanges;
 
     /**
      * An Exception to handle error message, has Iterator.next() can't throw
      * exceptions
      */
-    private Exception error;
+    protected Exception error;
 
     /**
      * Constructors
@@ -261,15 +290,15 @@
     {
         File inf = new File( ldifFileName );
 
-        if ( inf.exists() == false )
+        if ( !inf.exists() )
         {
-            log.error( "File {} cannot be found", inf.getAbsoluteFile() );
+            LOG.error( "File {} cannot be found", inf.getAbsoluteFile() );
             throw new NamingException( "Cannot find file " + inf.getAbsoluteFile() );
         }
 
-        if ( inf.canRead() == false )
+        if ( !inf.canRead() )
         {
-            log.error( "File {} cannot be read", inf.getName() );
+            LOG.error( "File {} cannot be read", inf.getName() );
             throw new NamingException( "Cannot read file " + inf.getName() );
         }
 
@@ -279,7 +308,7 @@
         }
         catch (FileNotFoundException fnfe)
         {
-            log.error( "File {} cannot be found", inf.getAbsoluteFile() );
+            LOG.error( "File {} cannot be found", inf.getAbsoluteFile() );
             throw new NamingException( "Cannot find file " + inf.getAbsoluteFile() );
         }
     }
@@ -333,15 +362,15 @@
      */
     public LdifReader( File in ) throws NamingException
     {
-        if ( in.exists() == false )
+        if ( !in.exists() )
         {
-            log.error( "File {} cannot be found", in.getAbsoluteFile() );
+            LOG.error( "File {} cannot be found", in.getAbsoluteFile() );
             throw new NamingException( "Cannot find file " + in.getAbsoluteFile() );
         }
 
-        if ( in.canRead() == false )
+        if ( !in.canRead() )
         {
-            log.error( "File {} cannot be read", in.getName() );
+            LOG.error( "File {} cannot be read", in.getName() );
             throw new NamingException( "Cannot read file " + in.getName() );
         }
 
@@ -351,7 +380,7 @@
         }
         catch (FileNotFoundException fnfe)
         {
-            log.error( "File {} cannot be found", in.getAbsoluteFile() );
+            LOG.error( "File {} cannot be found", in.getAbsoluteFile() );
             throw new NamingException( "Cannot find file " + in.getAbsoluteFile() );
         }
     }
@@ -400,6 +429,10 @@
      * ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
      * Check that the number is in the interval
+     * 
+     * @param document The document containing the number to parse
+     * @param position The current position in the document
+     * @return a String representing the parsed number
      */
     private static String parseNumber( char[] document, Position position )
     {
@@ -487,7 +520,7 @@
             if ( length == 3 )
             {
                 // The DN is empty : error
-                log.error( "A ldif entry must have a non empty DN" );
+                LOG.error( "A ldif entry must have a non empty DN" );
                 throw new NamingException( "No DN for entry" );
             }
             else if ( line.charAt( 3 ) == ':' )
@@ -504,14 +537,14 @@
                     catch (UnsupportedEncodingException uee)
                     {
                         // The DN is not base 64 encoded
-                        log.error( "The ldif entry is supposed to have a base 64 encoded DN" );
+                        LOG.error( "The ldif entry is supposed to have a base 64 encoded DN" );
                         throw new NamingException( "Invalid base 64 encoded DN" );
                     }
                 }
                 else
                 {
                     // The DN is empty : error
-                    log.error( "A ldif entry must have a non empty DN" );
+                    LOG.error( "A ldif entry must have a non empty DN" );
                     throw new NamingException( "No DN for entry" );
                 }
             }
@@ -522,7 +555,7 @@
         }
         else
         {
-            log.error( "A ldif entry must start with a DN" );
+            LOG.error( "A ldif entry must start with a DN" );
             throw new NamingException( "No DN for entry" );
         }
 
@@ -533,7 +566,7 @@
         }
         catch (InvalidNameException ine)
         {
-            log.error( "The DN {} is not valid" );
+            LOG.error( "The DN {} is not valid" );
             throw ine;
         }
 
@@ -549,7 +582,7 @@
      *            The starting position in the line
      * @return A String or a byte[], depending of the kind of value we get
      */
-    private static Object parseSimpleValue( String line, int pos )
+    protected static Object parseSimpleValue( String line, int pos )
     {
         if ( line.length() > pos + 1 )
         {
@@ -583,7 +616,7 @@
      * @throws NamingException
      *             If something went wrong
      */
-    private Object parseValue( String line, int pos ) throws NamingException
+    protected Object parseValue( String line, int pos ) throws NamingException
     {
         if ( line.length() > pos + 1 )
         {
@@ -609,9 +642,9 @@
 
                         File file = new File( fileName );
 
-                        if ( file.exists() == false )
+                        if ( !file.exists() )
                         {
-                            log.error( "File {} not found", fileName );
+                            LOG.error( "File {} not found", fileName );
                             throw new NamingException( "Bad URL, file not found" );
                         }
                         else
@@ -620,7 +653,7 @@
 
                             if ( length > sizeLimit )
                             {
-                                log.error( "File {} is too big", fileName );
+                                LOG.error( "File {} is too big", fileName );
                                 throw new NamingException( "File too big" );
                             }
                             else
@@ -640,27 +673,24 @@
                                     // We can't reach this point, the file
                                     // existence has already been
                                     // checked
-                                    log.error( "File {} not found", fileName );
+                                    LOG.error( "File {} not found", fileName );
                                     throw new NamingException( "Bad URL, file not found" );
                                 }
                                 catch (IOException ioe)
                                 {
-                                    log.error( "File {} error reading", fileName );
+                                    LOG.error( "File {} error reading", fileName );
                                     throw new NamingException( "Bad URL, file can't be read" );
                                 }
                                 finally
                                 {
-                                    if ( inf != null )
+                                    try
                                     {
-                                        try
-                                        {
-                                            inf.close();
-                                        }
-                                        catch ( IOException ioe )
-                                        {
-                                            log.error( "Error while closing the stream : {}", ioe.getMessage() );
-                                            // Just do nothing ...
-                                        }
+                                        inf.close();
+                                    }
+                                    catch ( IOException ioe )
+                                    {
+                                        LOG.error( "Error while closing the stream : {}", ioe.getMessage() );
+                                        // Just do nothing ...
                                     }
                                 }
                             }
@@ -668,13 +698,13 @@
                     }
                     else
                     {
-                        log.error( "Protocols other than file: are not supported" );
+                        LOG.error( "Protocols other than file: are not supported" );
                         throw new NamingException( "Unsupported URL protocol" );
                     }
                 }
                 catch (MalformedURLException mue)
                 {
-                    log.error( "Bad URL {}", urlName );
+                    LOG.error( "Bad URL {}", urlName );
                     throw new NamingException( "Bad URL" );
                 }
             }
@@ -700,9 +730,10 @@
      * "false") ] [ ":" &lt;fill&gt; &lt;SAFE-STRING-e&gt; | "::" &lt;fill&gt; &lt;BASE64-STRING&gt; | ":<"
      * &lt;fill&gt; &lt;url&gt; ]
      * 
-     * @param line
-     *            The line containing the control
+     * @param line The line containing the control
      * @return A control
+     * @exception NamingException If the control has no OID or if the OID is incorrect,
+     * of if the criticality is not set when it's mandatory.
      */
     private Control parseControl( String line ) throws NamingException
     {
@@ -715,7 +746,7 @@
         if ( pos > length )
         {
             // No OID : error !
-            log.error( "The control does not have an OID" );
+            LOG.error( "The control does not have an OID" );
             throw new NamingException( "Bad control, no oid" );
         }
 
@@ -729,7 +760,7 @@
         if ( pos == initPos )
         {
             // Not a valid OID !
-            log.error( "The control does not have an OID" );
+            LOG.error( "The control does not have an OID" );
             throw new NamingException( "Bad control, no oid" );
         }
 
@@ -744,7 +775,7 @@
         }
         catch (DecoderException de)
         {
-            log.error( "The OID {} is not valid", oidString );
+            LOG.error( "The OID {} is not valid", oidString );
             throw new NamingException( "Bad control oid" );
         }
 
@@ -783,7 +814,7 @@
         {
             // If we have a criticality, it should be either "true" or "false",
             // nothing else
-            log.error( "The control muts have a valid criticality" );
+            LOG.error( "The control muts have a valid criticality" );
             throw new NamingException( "Bad control criticality" );
         }
 
@@ -822,6 +853,7 @@
      * Parse an AttributeType/AttributeValue
      * 
      * @param line The line to parse
+     * @return the parsed Attribute
      */
     public static Attribute parseAttributeValue( String line )
     {
@@ -844,16 +876,12 @@
     /**
      * Parse an AttributeType/AttributeValue
      * 
-     * @param entry
-     *            The entry where to store the value
-     * @param line
-     *            The line to parse
-     * @param lowerLine
-     *            The same line, lowercased
-     * @throws NamingException
-     *             If anything goes wrong
+     * @param entry The entry where to store the value
+     * @param line The line to parse
+     * @param lowerLine The same line, lowercased
+     * @throws NamingException If anything goes wrong
      */
-    public void parseAttributeValue( Entry entry, String line, String lowerLine ) throws NamingException
+    public void parseAttributeValue( LdifEntry entry, String line, String lowerLine ) throws NamingException
     {
         int colonIndex = line.indexOf( ':' );
 
@@ -862,7 +890,7 @@
         // We should *not* have a DN twice
         if ( attributeType.equals( "dn" ) )
         {
-            log.error( "An entry must not have two DNs" );
+            LOG.error( "An entry must not have two DNs" );
             throw new NamingException( "A ldif entry should not have two DN" );
         }
 
@@ -882,7 +910,7 @@
      * @throws NamingException
      *             If anything goes wrong
      */
-    private void parseModRdn( Entry entry, Iterator<String> iter ) throws NamingException
+    private void parseModRdn( LdifEntry entry, Iterator<String> iter ) throws NamingException
     {
         // We must have two lines : one starting with "newrdn:" or "newrdn::",
         // and the second starting with "deleteoldrdn:"
@@ -900,14 +928,14 @@
             }
             else
             {
-                log.error( "A modrdn operation must start with a \"newrdn:\"" );
+                LOG.error( "A modrdn operation must start with a \"newrdn:\"" );
                 throw new NamingException( "Bad modrdn operation" );
             }
 
         }
         else
         {
-            log.error( "A modrdn operation must start with a \"newrdn:\"" );
+            LOG.error( "A modrdn operation must start with a \"newrdn:\"" );
             throw new NamingException( "Bad modrdn operation, no newrdn" );
         }
 
@@ -924,13 +952,13 @@
             }
             else
             {
-                log.error( "A modrdn operation must contains a \"deleteoldrdn:\"" );
+                LOG.error( "A modrdn operation must contains a \"deleteoldrdn:\"" );
                 throw new NamingException( "Bad modrdn operation, no deleteoldrdn" );
             }
         }
         else
         {
-            log.error( "A modrdn operation must contains a \"deleteoldrdn:\"" );
+            LOG.error( "A modrdn operation must contains a \"deleteoldrdn:\"" );
             throw new NamingException( "Bad modrdn operation, no deleteoldrdn" );
         }
 
@@ -948,16 +976,16 @@
      * ATTRIBUTE-DESCRIPTION SEP &lt;attrval-specs-e&gt; "-" SEP &lt;attrval-specs-e&gt; ::=
      * ATTRVAL-SPEC &lt;attrval-specs&gt; | e *
      * 
-     * @param entry
-     *            The entry to feed
-     * @param iter
-     *            The lines
+     * @param entry The entry to feed
+     * @param iter The lines
+     * @exception NamingException If the modify operation is invalid
      */
-    private void parseModify( Entry entry, Iterator<String> iter ) throws NamingException
+    private void parseModify( LdifEntry entry, Iterator<String> iter ) throws NamingException
     {
         int state = MOD_SPEC;
         String modified = null;
-        int modification = 0;
+        int modificationType = 0;
+        Attribute attribute = null;
 
         // The following flag is used to deal with empty modifications
         boolean isEmptyValue = true;
@@ -971,7 +999,7 @@
             {
                 if ( state != ATTRVAL_SPEC_OR_SEP )
                 {
-                    log.error( "Bad state : we should have come from an ATTRVAL_SPEC" );
+                    LOG.error( "Bad state : we should have come from an ATTRVAL_SPEC" );
                     throw new NamingException( "Bad modify separator" );
                 }
                 else
@@ -979,7 +1007,12 @@
                     if ( isEmptyValue )
                     {
                         // Update the entry
-                        entry.addModificationItem( modification, modified, null );
+                        entry.addModificationItem( modificationType, modified, null );
+                    }
+                    else
+                    {
+                        // Update the entry with the attribute
+                        entry.addModificationItem( modificationType, attribute );
                     }
 
                     state = MOD_SPEC;
@@ -991,12 +1024,13 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    log.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
+                    LOG.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
                     throw new NamingException( "Bad modify state" );
                 }
 
                 modified = StringTools.trim( line.substring( "add:".length() ) );
-                modification = DirContext.ADD_ATTRIBUTE;
+                modificationType = DirContext.ADD_ATTRIBUTE;
+                attribute = new AttributeImpl( modified );
 
                 state = ATTRVAL_SPEC;
             }
@@ -1004,12 +1038,13 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    log.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
+                    LOG.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
                     throw new NamingException( "Bad modify state" );
                 }
 
                 modified = StringTools.trim( line.substring( "delete:".length() ) );
-                modification = DirContext.REMOVE_ATTRIBUTE;
+                modificationType = DirContext.REMOVE_ATTRIBUTE;
+                attribute = new AttributeImpl( modified );
 
                 state = ATTRVAL_SPEC_OR_SEP;
             }
@@ -1017,12 +1052,13 @@
             {
                 if ( ( state != MOD_SPEC ) && ( state != ATTRVAL_SPEC ) )
                 {
-                    log.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
+                    LOG.error( "Bad state : we should have come from a MOD_SPEC or an ATTRVAL_SPEC" );
                     throw new NamingException( "Bad modify state" );
                 }
 
                 modified = StringTools.trim( line.substring( "replace:".length() ) );
-                modification = DirContext.REPLACE_ATTRIBUTE;
+                modificationType = DirContext.REPLACE_ATTRIBUTE;
+                attribute = new AttributeImpl( modified );
 
                 state = ATTRVAL_SPEC_OR_SEP;
             }
@@ -1030,7 +1066,7 @@
             {
                 if ( ( state != ATTRVAL_SPEC ) && ( state != ATTRVAL_SPEC_OR_SEP ) )
                 {
-                    log.error( "Bad state : we should have come from an ATTRVAL_SPEC" );
+                    LOG.error( "Bad state : we should have come from an ATTRVAL_SPEC" );
                     throw new NamingException( "Bad modify state" );
                 }
 
@@ -1039,23 +1075,23 @@
 
                 String attributeType = line.substring( 0, colonIndex );
 
-                if ( attributeType.equalsIgnoreCase( modified ) == false )
+                if ( !attributeType.equalsIgnoreCase( modified ) )
                 {
-                    log.error( "The modified attribute and the attribute value spec must be equal" );
+                    LOG.error( "The modified attribute and the attribute value spec must be equal" );
                     throw new NamingException( "Bad modify attribute" );
                 }
 
                 // We should *not* have a DN twice
                 if ( attributeType.equalsIgnoreCase( "dn" ) )
                 {
-                    log.error( "An entry must not have two DNs" );
+                    LOG.error( "An entry must not have two DNs" );
                     throw new NamingException( "A ldif entry should not have two DN" );
                 }
 
                 Object attributeValue = parseValue( line, colonIndex );
 
-                // Update the entry
-                entry.addModificationItem( modification, modified, attributeValue );
+                attribute.add( attributeValue );
+                
                 isEmptyValue = false;
 
                 state = ATTRVAL_SPEC_OR_SEP;
@@ -1084,17 +1120,12 @@
      * ::= FILL ATTRIBUTE-DESCRIPTION SEP ATTRVAL-SPEC &lt;attrval-specs-e&gt; "-" SEP
      * &lt;attrval-specs-e&gt; ::= ATTRVAL-SPEC &lt;attrval-specs&gt; | e
      * 
-     * @param entry
-     *            The entry to feed
-     * @param iter
-     *            The lines iterator
-     * @param operation
-     *            The change operation (add, modify, delete, moddn or modrdn)
-     * @param control
-     *            The associated control, if any
-     * @return A modification entry
+     * @param entry The entry to feed
+     * @param iter The lines iterator
+     * @param operation The change operation (add, modify, delete, moddn or modrdn)
+     * @exception NamingException If the change operation is invalid
      */
-    private void parseChange( Entry entry, Iterator<String> iter, ChangeType operation, Control control ) throws NamingException
+    private void parseChange( LdifEntry entry, Iterator<String> iter, ChangeType operation ) throws NamingException
     {
         // The changetype and operation has already been parsed.
         entry.setChangeType( operation );
@@ -1143,7 +1174,7 @@
                     {
                         if ( operation == ChangeType.ModDn )
                         {
-                            log.error( "A moddn operation must contains a \"newsuperior:\"" );
+                            LOG.error( "A moddn operation must contains a \"newsuperior:\"" );
                             throw new NamingException( "Bad moddn operation, no newsuperior" );
                         }
                     }
@@ -1152,7 +1183,7 @@
                 {
                     if ( operation == ChangeType.ModDn )
                     {
-                        log.error( "A moddn operation must contains a \"newsuperior:\"" );
+                        LOG.error( "A moddn operation must contains a \"newsuperior:\"" );
                         throw new NamingException( "Bad moddn operation, no newsuperior" );
                     }
                 }
@@ -1161,7 +1192,7 @@
 
             default:
                 // This is an error
-                log.error( "Unknown operation" );
+                LOG.error( "Unknown operation" );
                 throw new NamingException( "Bad operation" );
         }
     }
@@ -1175,12 +1206,15 @@
      * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
      * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
      * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
+     * 
+     * @return the parsed ldifEntry
+     * @exception NamingException If the ldif file does not contain a valid entry 
      */
-    private Entry parseEntry() throws NamingException
+    private LdifEntry parseEntry() throws NamingException
     {
         if ( ( lines == null ) || ( lines.size() == 0 ) )
         {
-            log.debug( "The entry is empty : end of ldif file" );
+            LOG.debug( "The entry is empty : end of ldif file" );
             return null;
         }
 
@@ -1190,7 +1224,7 @@
         String dn = parseDn( line );
 
         // Ok, we have found a DN
-        Entry entry = new Entry();
+        LdifEntry entry = new LdifEntry();
         entry.setDn( dn );
 
         // We remove this dn from the lines
@@ -1229,7 +1263,7 @@
             {
                 if ( containsEntries )
                 {
-                    log.error( "We cannot have changes when reading a file which already contains entries" );
+                    LOG.error( "We cannot have changes when reading a file which already contains entries" );
                     throw new NamingException( "No changes withing entries" );
                 }
 
@@ -1237,7 +1271,7 @@
 
                 if ( controlSeen )
                 {
-                    log.error( "We already have had a control" );
+                    LOG.error( "We already have had a control" );
                     throw new NamingException( "Control misplaced" );
                 }
 
@@ -1249,7 +1283,7 @@
             {
                 if ( containsEntries )
                 {
-                    log.error( "We cannot have changes when reading a file which already contains entries" );
+                    LOG.error( "We cannot have changes when reading a file which already contains entries" );
                     throw new NamingException( "No changes withing entries" );
                 }
 
@@ -1257,7 +1291,7 @@
 
                 if ( changeTypeSeen )
                 {
-                    log.error( "We already have had a changeType" );
+                    LOG.error( "We already have had a changeType" );
                     throw new NamingException( "ChangeType misplaced" );
                 }
 
@@ -1268,14 +1302,14 @@
                 operation = parseChangeType( line );
 
                 // Parse the change operation in a separate function
-                parseChange( entry, iter, operation, control );
+                parseChange( entry, iter, operation );
                 changeTypeSeen = true;
             }
             else if ( line.indexOf( ':' ) > 0 )
             {
                 if ( containsChanges )
                 {
-                    log.error( "We cannot have entries when reading a file which already contains changes" );
+                    LOG.error( "We cannot have entries when reading a file which already contains changes" );
                     throw new NamingException( "No entries within changes" );
                 }
 
@@ -1283,33 +1317,33 @@
 
                 if ( controlSeen || changeTypeSeen )
                 {
-                    log.error( "We can't have a Attribute/Value pair after a control or a changeType" );
+                    LOG.error( "We can't have a Attribute/Value pair after a control or a changeType" );
                     throw new NamingException( "AttributeType misplaced" );
                 }
 
                 parseAttributeValue( entry, line, lowerLine );
-                type = ENTRY;
+                type = LDIF_ENTRY;
             }
             else
             {
                 // Invalid attribute Value
-                log.error( "Expecting an attribute type" );
+                LOG.error( "Expecting an attribute type" );
                 throw new NamingException( "Bad attribute" );
             }
         }
 
-        if ( type == ENTRY )
+        if ( type == LDIF_ENTRY )
         {
-            log.debug( "Read an entry : {}", entry );
+            LOG.debug( "Read an entry : {}", entry );
         }
         else if ( type == CHANGE )
         {
             entry.setChangeType( operation );
-            log.debug( "Read a modification : {}", entry );
+            LOG.debug( "Read a modification : {}", entry );
         }
         else
         {
-            log.error( "Unknown entry type" );
+            LOG.error( "Unknown entry type" );
             throw new NamingException( "Unknown entry" );
         }
 
@@ -1319,12 +1353,10 @@
     /**
      * Parse the version from the ldif input.
      * 
-     * @param in
-     *            The input which contains the ldif data
      * @return A number representing the version (default to 1)
      * @throws NamingException
      *             If the version is incorrect
-     * @throws IOException
+     * @throws NamingException
      *             If the input is incorrect
      */
     private int parseVersion() throws NamingException
@@ -1336,7 +1368,7 @@
 
         if ( lines.size() == 0 )
         {
-            log.warn( "The ldif file is empty" );
+            LOG.warn( "The ldif file is empty" );
             return ver;
         }
 
@@ -1358,7 +1390,7 @@
             // We should not have any other chars after the number
             if ( position.pos != document.length )
             {
-                log.error( "The version is not a number" );
+                LOG.error( "The version is not a number" );
                 throw new NamingException( "Ldif parsing error" );
             }
 
@@ -1368,11 +1400,11 @@
             }
             catch (NumberFormatException nfe)
             {
-                log.error( "The version is not a number" );
+                LOG.error( "The version is not a number" );
                 throw new NamingException( "Ldif parsing error" );
             }
 
-            log.debug( "Ldif version : {}", versionNumber );
+            LOG.debug( "Ldif version : {}", versionNumber );
 
             // We have found the version, just discard the line from the list
             lines.remove( 0 );
@@ -1385,7 +1417,7 @@
         }
         else
         {
-            log.warn( "No version information : assuming version: 1" );
+            LOG.warn( "No version information : assuming version: 1" );
         }
 
         return ver;
@@ -1397,12 +1429,9 @@
      * 
      * The lines represent *one* entry.
      * 
-     * @param in
-     *            The buffer
-     * @throws NamingException
-     *             If something went wrong
+     * @throws NamingException If something went wrong
      */
-    private void readLines() throws NamingException
+    protected void readLines() throws NamingException
     {
         String line = null;
         boolean insideComment = true;
@@ -1445,7 +1474,7 @@
                         }
                         else if ( sb.length() == 0 )
                         {
-                            log.error( "Cannot have an empty continuation line" );
+                            LOG.error( "Cannot have an empty continuation line" );
                             throw new NamingException( "Ldif Parsing error" );
                         }
                         else
@@ -1495,7 +1524,7 @@
      * @throws NamingException
      *             If the parsing fails
      */
-    public List<Entry> parseLdifFile( String fileName ) throws NamingException
+    public List<LdifEntry> parseLdifFile( String fileName ) throws NamingException
     {
         return parseLdifFile( fileName, Charset.forName( StringTools.getDefaultCharsetName() ).toString() );
     }
@@ -1511,36 +1540,35 @@
      * @throws NamingException
      *             If the parsing fails
      */
-    public List<Entry> parseLdifFile( String fileName, String encoding ) throws NamingException
+    public List<LdifEntry> parseLdifFile( String fileName, String encoding ) throws NamingException
     {
         if ( StringTools.isEmpty( fileName ) )
         {
-            log.error( "Cannot parse an empty file name !" );
+            LOG.error( "Cannot parse an empty file name !" );
             throw new NamingException( "Empty filename" );
         }
 
         File file = new File( fileName );
 
-        if ( file.exists() == false )
+        if ( !file.exists() )
         {
-            log.error( "Cannot parse the file {}, it does not exist", fileName );
+            LOG.error( "Cannot parse the file {}, it does not exist", fileName );
             throw new NamingException( "Filename " + fileName + " not found." );
         }
 
         // Open the file and then get a channel from the stream
-        BufferedReader inf;
-
         try
         {
-            inf = new BufferedReader( new InputStreamReader( new FileInputStream( file ), Charset.forName( encoding ) ) );
+            BufferedReader inf = new BufferedReader( new InputStreamReader( new FileInputStream( file ), 
+                Charset.forName( encoding ) ) );
+
+            return parseLdif( inf );
         }
         catch (FileNotFoundException fnfe)
         {
-            log.error( "Cannot find file {}", fileName );
+            LOG.error( "Cannot find file {}", fileName );
             throw new NamingException( "Filename " + fileName + " not found." );
         }
-
-        return parseLdif( inf );
     }
 
     /**
@@ -1552,13 +1580,13 @@
      * @throws NamingException
      *             If something went wrong
      */
-    public List<Entry> parseLdif( String ldif ) throws NamingException
+    public List<LdifEntry> parseLdif( String ldif ) throws NamingException
     {
-        log.debug( "Starts parsing ldif buffer" );
+        LOG.debug( "Starts parsing ldif buffer" );
 
         if ( StringTools.isEmpty( ldif ) )
         {
-            return new ArrayList<Entry>();
+            return new ArrayList<LdifEntry>();
         }
 
         StringReader strIn = new StringReader( ldif );
@@ -1566,18 +1594,18 @@
 
         try
         {
-            List<Entry> entries = parseLdif( inf );
+            List<LdifEntry> entries = parseLdif( inf );
 
-            if ( log.isDebugEnabled() )
+            if ( LOG.isDebugEnabled() )
             {
-                log.debug( "Parsed {} entries.", ( entries == null ? Integer.valueOf( 0 ) : Integer.valueOf( entries.size() ) ) );
+                LOG.debug( "Parsed {} entries.", ( entries == null ? Integer.valueOf( 0 ) : Integer.valueOf( entries.size() ) ) );
             }
 
             return entries;
         }
         catch (NamingException ne)
         {
-            log.error( "Cannot parse the ldif buffer : {}", ne.getMessage() );
+            LOG.error( "Cannot parse the ldif buffer : {}", ne.getMessage() );
             throw new NamingException( "Error while parsing the ldif buffer" );
         }
     }
@@ -1590,14 +1618,15 @@
      * Gets the next LDIF on the channel.
      * 
      * @return the next LDIF as a String.
+     * @exception NoSuchElementException If we can't read the next entry
      */
-    public Entry next() throws NoSuchElementException
+    private LdifEntry nextInternal()
     {
         try
         {
-            log.debug( "next(): -- called" );
+            LOG.debug( "next(): -- called" );
 
-            Entry entry = prefetched;
+            LdifEntry entry = prefetched;
             readLines();
 
             try
@@ -1607,20 +1636,45 @@
             catch (NamingException ne)
             {
                 error = ne;
+                throw new NoSuchElementException( ne.getMessage() );
             }
 
-            log.debug( "next(): -- returning ldif {}\n", entry );
+            LOG.debug( "next(): -- returning ldif {}\n", entry );
 
             return entry;
         }
         catch (NamingException ne)
         {
-            log.error( "Premature termination of LDIF iterator" );
+            LOG.error( "Premature termination of LDIF iterator" );
             error = ne;
             return null;
         }
     }
 
+    
+    /**
+     * Gets the next LDIF on the channel.
+     * 
+     * @return the next LDIF as a String.
+     * @exception NoSuchElementException If we can't read the next entry
+     */
+    public LdifEntry next()
+    {
+        return nextInternal();
+    }
+
+
+    /**
+     * Tests to see if another LDIF is on the input channel.
+     * 
+     * @return true if another LDIF is available false otherwise.
+     */
+    private boolean hasNextInternal()
+    {
+        return null != prefetched;
+    }
+
+    
     /**
      * Tests to see if another LDIF is on the input channel.
      * 
@@ -1628,11 +1682,23 @@
      */
     public boolean hasNext()
     {
-        log.debug( "hasNext(): -- returning {}", ( prefetched != null ) ? Boolean.TRUE : Boolean.FALSE );
+        LOG.debug( "hasNext(): -- returning {}", ( prefetched != null ) ? Boolean.TRUE : Boolean.FALSE );
 
-        return null != prefetched;
+        return hasNextInternal();
     }
 
+
+    /**
+     * Always throws UnsupportedOperationException!
+     * 
+     * @see java.util.Iterator#remove()
+     */
+    private void removeInternal()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    
     /**
      * Always throws UnsupportedOperationException!
      * 
@@ -1640,15 +1706,31 @@
      */
     public void remove()
     {
-        throw new UnsupportedOperationException();
+        removeInternal();
     }
 
     /**
      * @return An iterator on the file
      */
-    public Iterator<Entry> iterator()
+    public Iterator<LdifEntry> iterator()
     {
-        return this;
+        return new Iterator<LdifEntry>() 
+        {
+            public boolean hasNext() 
+            {
+                return hasNextInternal();
+            }
+          
+            public LdifEntry next() 
+            {
+                return nextInternal();
+            }
+          
+            public void remove() 
+            {
+                throw new UnsupportedOperationException();
+            }
+        };
     }
 
     /**
@@ -1677,10 +1759,10 @@
      * @throws NamingException
      *             If something went wrong
      */
-    public List<Entry> parseLdif( BufferedReader inf ) throws NamingException
+    public List<LdifEntry> parseLdif( BufferedReader inf ) throws NamingException
     {
         // Create a list that will contain the read entries
-        List<Entry> entries = new ArrayList<Entry>();
+        List<LdifEntry> entries = new ArrayList<LdifEntry>();
 
         this.in = inf;
 
@@ -1689,18 +1771,19 @@
         prefetched = parseEntry();
 
         // When done, get the entries one by one.
-        while ( hasNext() )
+        try
         {
-            Entry entry = next();
-
-            if ( error != null )
+            for ( LdifEntry entry:this )
             {
-                throw new NamingException( "Error while parsing ldif : " + error.getMessage() );
+                if ( entry != null )
+                {
+                    entries.add( entry );
+                }
             }
-            else if ( entry != null )
-            {
-                entries.add( entry );
-            }
+        }
+        catch ( NoSuchElementException nsee )
+        {
+            throw new NamingException( "Error while parsing ldif : " + error.getMessage() );
         }
 
         return entries;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java
index af1d285..171c0e5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java
@@ -21,51 +21,67 @@
 
 import java.io.UnsupportedEncodingException;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
 
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.ModificationItemImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.Rdn;
+import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.apache.directory.shared.ldap.util.Base64;
+import org.apache.directory.shared.ldap.util.StringTools;
+
 
 
 /**
  * Some LDIF useful methods
  *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LdifUtils
 {
-
-	/** The array that will be used to match the first char.*/
+    /** The array that will be used to match the first char.*/
     private static boolean[] LDIF_SAFE_STARTING_CHAR_ALPHABET = new boolean[128];
     
     /** The array that will be used to match the other chars.*/
     private static boolean[] LDIF_SAFE_OTHER_CHARS_ALPHABET = new boolean[128];
     
+    /** The default length for a line in a ldif file */
+    private static final int DEFAULT_LINE_LENGTH = 80;
+    
     static
     {
-    	// Initialization of the array that will be used to match the first char.
-    	for (int i = 0; i < 128; i++) 
+        // Initialization of the array that will be used to match the first char.
+        for (int i = 0; i < 128; i++) 
         {
-    		LDIF_SAFE_STARTING_CHAR_ALPHABET[i] = true;
-		}
-    	
+            LDIF_SAFE_STARTING_CHAR_ALPHABET[i] = true;
+        }
+        
         LDIF_SAFE_STARTING_CHAR_ALPHABET[0] = false; // 0 (NUL)
-    	LDIF_SAFE_STARTING_CHAR_ALPHABET[10] = false; // 10 (LF)
-    	LDIF_SAFE_STARTING_CHAR_ALPHABET[13] = false; // 13 (CR)
-    	LDIF_SAFE_STARTING_CHAR_ALPHABET[32] = false; // 32 (SPACE)
-    	LDIF_SAFE_STARTING_CHAR_ALPHABET[58] = false; // 58 (:)
-    	LDIF_SAFE_STARTING_CHAR_ALPHABET[60] = false; // 60 (>)
-    	
-    	// Initialization of the array that will be used to match the other chars.
-    	for (int i = 0; i < 128; i++) 
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[10] = false; // 10 (LF)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[13] = false; // 13 (CR)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[32] = false; // 32 (SPACE)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[58] = false; // 58 (:)
+        LDIF_SAFE_STARTING_CHAR_ALPHABET[60] = false; // 60 (>)
+        
+        // Initialization of the array that will be used to match the other chars.
+        for (int i = 0; i < 128; i++) 
         {
-    		LDIF_SAFE_OTHER_CHARS_ALPHABET[i] = true;
-		}
-    	
+            LDIF_SAFE_OTHER_CHARS_ALPHABET[i] = true;
+        }
+        
         LDIF_SAFE_OTHER_CHARS_ALPHABET[0] = false; // 0 (NUL)
-    	LDIF_SAFE_OTHER_CHARS_ALPHABET[10] = false; // 10 (LF)
-    	LDIF_SAFE_OTHER_CHARS_ALPHABET[13] = false; // 13 (CR)
+        LDIF_SAFE_OTHER_CHARS_ALPHABET[10] = false; // 10 (LF)
+        LDIF_SAFE_OTHER_CHARS_ALPHABET[13] = false; // 13 (CR)
     }
 
     /**
@@ -75,19 +91,19 @@
      * The data does not need to be encoded if all the following are true:
      * 
      * The data cannot start with the following char values:
-     * 		00 (NUL)
-     * 		10 (LF)
-     * 		13 (CR)
-     * 		32 (SPACE)
-     * 		58 (:)
-     * 		60 (<)
-     * 		Any character with value greater than 127
+     *         00 (NUL)
+     *         10 (LF)
+     *         13 (CR)
+     *         32 (SPACE)
+     *         58 (:)
+     *         60 (<)
+     *         Any character with value greater than 127
      * 
      * The data cannot contain any of the following char values:
-     * 		00 (NUL)
-     * 		10 (LF)
-     * 		13 (CR)
-     * 		Any character with value greater than 127
+     *         00 (NUL)
+     *         10 (LF)
+     *         13 (CR)
+     *         Any character with value greater than 127
      * 
      * The data cannot end with a space.
      * 
@@ -96,77 +112,79 @@
      */
     public static boolean isLDIFSafe( String str )
     {
-    	// Checking the first char
-    	char currentChar = str.charAt(0);
+        // Checking the first char
+        char currentChar = str.charAt(0);
         
-    	if ( ( currentChar > 127 ) || !LDIF_SAFE_STARTING_CHAR_ALPHABET[currentChar] )
-    	{
-    		return false;
-    	}
-    	
-    	// Checking the other chars
-    	for (int i = 1; i < str.length(); i++)
-    	{
-        	currentChar = str.charAt(i);
-        	
-        	if ( ( currentChar > 127 ) || !LDIF_SAFE_OTHER_CHARS_ALPHABET[currentChar] )
-        	{
-        		return false;
-        	}
-		}
-    	
-    	// The String cannot end with a space
-    	return ( currentChar != ' ' );
+        if ( ( currentChar > 127 ) || !LDIF_SAFE_STARTING_CHAR_ALPHABET[currentChar] )
+        {
+            return false;
+        }
+        
+        // Checking the other chars
+        for (int i = 1; i < str.length(); i++)
+        {
+            currentChar = str.charAt(i);
+            
+            if ( ( currentChar > 127 ) || !LDIF_SAFE_OTHER_CHARS_ALPHABET[currentChar] )
+            {
+                return false;
+            }
+        }
+        
+        // The String cannot end with a space
+        return ( currentChar != ' ' );
     }
     
     /**
      * Convert an Attributes as LDIF
      * @param attrs the Attributes to convert
-     * @param length the expectend line length
      * @return the corresponding LDIF code as a String
      * @throws NamingException If a naming exception is encountered.
      */
     public static String convertToLdif( Attributes attrs ) throws NamingException
     {
-        return convertToLdif( attrs, 80 );
+        return convertToLdif( attrs, DEFAULT_LINE_LENGTH );
     }
     
     
     /**
+     * Convert a LDIF String to an attributes.
+     * 
+     * @param ldif The LDIF string containing an attribute value
+     * @return An Attributes instance
+     * @exception NamingException If the LDIF String cannot be converted to an Attributes
+     */
+    public static Attributes convertAttributesFromLdif( String ldif ) throws NamingException
+    {
+        LdifAttributesReader reader = new  LdifAttributesReader();
+        
+        return reader.parseAttributes( ldif );
+    }
+    
+    /**
      * Convert an Attributes as LDIF
      * @param attrs the Attributes to convert
-     * @param length the expectend line length
+     * @param length the expected line length
      * @return the corresponding LDIF code as a String
      * @throws NamingException If a naming exception is encountered.
      */
     public static String convertToLdif( Attributes attrs, int length ) throws NamingException
     {
-		StringBuilder sb = new StringBuilder();
-		
-		NamingEnumeration ne = attrs.getAll();
-		
-		while ( ne.hasMore() )
-		{
-			Object attribute = ne.next();
+        StringBuilder sb = new StringBuilder();
+        
+        NamingEnumeration<? extends Attribute> ne = attrs.getAll();
+        
+        while ( ne.hasMore() )
+        {
+            Object attribute = ne.next();
             
-			if ( attribute instanceof Attribute ) 
+            if ( attribute instanceof Attribute ) 
             {
-				sb.append( convertToLdif( (Attribute) attribute, length ) );
-			}			
-		}
-		
-		return sb.toString();
-	}
-    
-    /**
-     * Convert an Entry to LDIF
-     * @param entry the entry to convert
-     * @return the corresponding LDIF as a String
-     * @throws NamingException If a naming exception is encountered.
-     */
-    public static String convertToLdif( Entry entry ) throws NamingException
-    {
-        return convertToLdif( entry, 80 );
+                sb.append( convertToLdif( (Attribute) attribute, length ) );
+            }            
+        }
+        
+        return sb.toString();
     }
     
     /**
@@ -175,7 +193,19 @@
      * @return the corresponding LDIF as a String
      * @throws NamingException If a naming exception is encountered.
      */
-    public static String convertToLdif( Entry entry, int length ) throws NamingException
+    public static String convertToLdif( LdifEntry entry ) throws NamingException
+    {
+        return convertToLdif( entry, DEFAULT_LINE_LENGTH );
+    }
+    
+    /**
+     * Convert an Entry to LDIF
+     * @param entry the entry to convert
+     * @param length The maximum line's length 
+     * @return the corresponding LDIF as a String
+     * @throws NamingException If a naming exception is encountered.
+     */
+    public static String convertToLdif( LdifEntry entry, int length ) throws NamingException
     {
         StringBuilder sb = new StringBuilder();
         
@@ -196,14 +226,101 @@
         
         sb.append( '\n' );
 
-        // Now, iterate through all the attributes
-        NamingEnumeration ne = entry.getAttributes().getAll();;
-        
-        while ( ne.hasMore() )
+        switch ( entry.getChangeType() )
         {
-            Attribute attribute = (Attribute)ne.next();
-            
-            sb.append( convertToLdif( (Attribute) attribute, length ) );
+            case Delete :
+                if ( entry.getAttributes() != null )
+                {
+                    throw new NamingException( "Invalid Entry : a deleted entry should not contain attributes" );
+                }
+                
+                break;
+                
+            case Add :
+                if ( ( entry.getAttributes() == null ) )
+                {
+                    throw new NamingException( "Invalid Entry : a added or modified entry should contain attributes" );
+                }
+
+                // Now, iterate through all the attributes
+                NamingEnumeration<? extends Attribute> ne = entry.getAttributes().getAll();
+                
+                while ( ne.hasMore() )
+                {
+                    Attribute attribute = ne.next();
+                    
+                    sb.append( convertToLdif( attribute, length ) );
+                }
+                
+                break;
+                
+            case ModDn :
+            case ModRdn :
+                if ( entry.getAttributes() != null )
+                {
+                    throw new NamingException( "Invalid Entry : a modifyDN operation entry should not contain attributes" );
+                }
+                
+                // Stores the deleteoldrdn flag
+                sb.append( "deleteoldrdn: " );
+                
+                if ( entry.isDeleteOldRdn() )
+                {
+                    sb.append( "1" );
+                }
+                else
+                {
+                    sb.append( "0" );
+                }
+                
+                sb.append( '\n' );
+                
+                // Stores the optional newSuperior
+                if ( ! StringTools.isEmpty( entry.getNewSuperior() ) )
+                {
+                    Attribute newSuperior = new AttributeImpl( "newsuperior", entry.getNewSuperior() );
+                    sb.append( convertToLdif( newSuperior, length ) );
+                }
+                
+                // Stores the new RDN
+                Attribute newRdn = new AttributeImpl( "newrdn", entry.getNewRdn() );
+                sb.append( convertToLdif( newRdn, length ) );
+                
+                break;
+                
+            case Modify :
+                for ( ModificationItem modification:entry.getModificationItems() )
+                {
+                    switch ( modification.getModificationOp() )
+                    {
+                        case DirContext.ADD_ATTRIBUTE :
+                            sb.append( "add: " );
+                            break;
+                            
+                        case DirContext.REMOVE_ATTRIBUTE :
+                            sb.append( "delete: " );
+                            break;
+                            
+                        case DirContext.REPLACE_ATTRIBUTE :
+                            sb.append( "replace: " );
+                            break;
+                            
+                        default :
+                            break; // Do nothing
+                            
+                    }
+                    
+                    sb.append( modification.getAttribute().getID() );
+                    sb.append( '\n' );
+                    
+                    sb.append( convertToLdif( modification.getAttribute() ) );
+                    sb.append( "-\n" );
+                }
+                break;
+                
+            default :
+                break; // Do nothing
+                
         }
         
         sb.append( '\n' );
@@ -212,24 +329,27 @@
     }
     
     /**
-     * Base64 encode a String  
+     * Base64 encode a String
+     * @param str The string to encode
+     * @return the base 64 encoded string
      */
     private static String encodeBase64( String str )
     {
-        char[] encoded;
+        char[] encoded =null;
         
         try
         {
             // force encoding using UTF-8 charset, as required in RFC2849 note 7
-            encoded = Base64.encode( ( ( String ) str ).getBytes( "UTF-8" ) );
+            encoded = Base64.encode( str.getBytes( "UTF-8" ) );
         }
         catch ( UnsupportedEncodingException e )
         {
-            encoded = Base64.encode( ( ( String ) str ).getBytes() );
+            encoded = Base64.encode( str.getBytes() );
         }
         
         return new String( encoded );
     }
+    
 
     /**
      * Converts an Attribute as LDIF
@@ -237,18 +357,31 @@
      * @return the corresponding LDIF code as a String
      * @throws NamingException If a naming exception is encountered.
      */
-	private static String convertToLdif( Attribute attr, int length ) throws NamingException
-	{
-		StringBuilder sb = new StringBuilder();
-		
-		// iterating on the attribute's values
-		for ( int i = 0; i < attr.size(); i++ )
+    public static String convertToLdif( Attribute attr ) throws NamingException
+    {
+        return convertToLdif( attr, DEFAULT_LINE_LENGTH );
+    }
+    
+    
+    /**
+     * Converts an Attribute as LDIF
+     * @param attr the Attribute to convert
+     * @param length the expected line length
+     * @return the corresponding LDIF code as a String
+     * @throws NamingException If a naming exception is encountered.
+     */
+    public static String convertToLdif( Attribute attr, int length ) throws NamingException
+    {
+        StringBuilder sb = new StringBuilder();
+        
+        // iterating on the attribute's values
+        for ( int i = 0; i < attr.size(); i++ )
         {
-			StringBuilder lineBuffer = new StringBuilder();
-			
+            StringBuilder lineBuffer = new StringBuilder();
+            
             lineBuffer.append( attr.getID() );
-			
-			Object value = attr.get( i );
+            
+            Object value = attr.get( i );
             
             // First, deal with null value (which is valid)
             if ( value == null )
@@ -257,53 +390,54 @@
             }
             else if ( value instanceof byte[] )
             {
-            	// It is binary, so we have to encode it using Base64 before adding it
-            	char[] encoded = Base64.encode( ( byte[] ) value );
-            	
-            	lineBuffer.append( ":: " + new String( encoded ) );                        	
+                // It is binary, so we have to encode it using Base64 before adding it
+                char[] encoded = Base64.encode( ( byte[] ) value );
+                
+                lineBuffer.append( ":: " + new String( encoded ) );                            
             }
             else if ( value instanceof String )
             {
-            	// It's a String but, we have to check if encoding isn't required
-            	String str = (String) value;
+                // It's a String but, we have to check if encoding isn't required
+                String str = (String) value;
                 
-            	if ( !LdifUtils.isLDIFSafe( str ) )
-            	{
+                if ( !LdifUtils.isLDIFSafe( str ) )
+                {
                     lineBuffer.append( ":: " + encodeBase64( (String)value ) );
-            	}
-            	else
-            	{
-            		lineBuffer.append( ": " + value );
-            	}
+                }
+                else
+                {
+                    lineBuffer.append( ": " + value );
+                }
             }
             
             lineBuffer.append( "\n" );
             sb.append( stripLineToNChars( lineBuffer.toString(), length ) );
         }
-		
-		return sb.toString();
-	}
-	
-	/**
-	 * Strips the String every n specified characters
-	 * @param str the string to strip
-	 * @param nbChars the number of characters
-	 * @return the stripped String
-	 */
-	public static String stripLineToNChars( String str, int nbChars)
-	{
+        
+        return sb.toString();
+    }
+    
+    
+    /**
+     * Strips the String every n specified characters
+     * @param str the string to strip
+     * @param nbChars the number of characters
+     * @return the stripped String
+     */
+    public static String stripLineToNChars( String str, int nbChars)
+    {
         int strLength = str.length();
 
         if ( strLength <= nbChars )
-		{
-			return str;
-		}
+        {
+            return str;
+        }
         
         if ( nbChars < 2 )
         {
             throw new IllegalArgumentException( "The length of each line must be at least 2 chars long" );
         }
-		
+        
         // We will first compute the new size of the LDIF result
         // It's at least nbChars chars plus one for \n
         int charsPerLine = nbChars - 1;
@@ -340,6 +474,368 @@
         System.arraycopy( orig, posSrc, buffer, posDst, remaining == 0 ? charsPerLine : remaining );
         
         return new String( buffer );
-	}
+    }
+    
+    
+    /**
+     * Compute a reverse LDIF of an AddRequest. It's simply a delete request
+     * of the added entry
+     *
+     * @param dn the dn of the added entry
+     * @return a reverse LDIF
+     */
+    public static LdifEntry reverseAdd( LdapDN dn )
+    {
+        LdifEntry entry = new LdifEntry();
+        entry.setChangeType( ChangeType.Delete );
+        entry.setDn( dn.getUpName() );
+        return entry;
+    }
+
+    
+    /**
+     * Compute a reverse LDIF of a DeleteRequest. We have to get the previous
+     * entry in order to restore it.
+     *
+     * @param dn The deleted entry DN
+     * @param deletedEntry The entry which has been deleted
+     * @return A reverse LDIF
+     */
+    public static LdifEntry reverseDel( LdapDN dn, Attributes deletedEntry )
+    {
+        LdifEntry entry = new LdifEntry();
+        
+        entry.setDn( dn.getUpName() );
+        entry.setChangeType( ChangeType.Add );
+        NamingEnumeration<? extends Attribute> attributes = deletedEntry.getAll();
+        
+        while ( attributes.hasMoreElements() )
+        {
+            entry.addAttribute( attributes.nextElement() );
+        }       
+
+        return entry;
+    }
+    
+    
+    /**
+     * Compute a reverse LDIF for a forward change which if in LDIF format
+     * would represent a moddn operation.  Hence there is no newRdn in the
+     * picture here.
+     *
+     * @param newSuperiorDn the new parent dn to be (must not be null)
+     * @param modifiedDn the dn of the entry being moved (must not be null)
+     * @return a reverse LDIF
+     * @throws NamingException if something went wrong
+     */
+    public static LdifEntry reverseModifyDn( LdapDN newSuperiorDn, LdapDN modifiedDn ) throws NamingException
+    {
+        LdifEntry entry = new LdifEntry();
+        LdapDN currentParent = null;
+        LdapDN newDn = null;
+
+        if ( newSuperiorDn == null )
+        {
+            throw new NullPointerException( "newSuperiorDn must not be null" );
+        }
+
+        if ( modifiedDn == null )
+        {
+            throw new NullPointerException( "modifiedDn must not be null" );
+        }
+
+        if ( modifiedDn.size() == 0 )
+        {
+            throw new IllegalArgumentException( "Don't think about moving the rootDSE." );
+        }
+
+        currentParent = ( LdapDN ) modifiedDn.clone();
+        currentParent.remove( currentParent.size() - 1 );
+
+        newDn = ( LdapDN ) newSuperiorDn.clone();
+        newDn.add( modifiedDn.getRdn() );
+
+        entry.setChangeType( ChangeType.ModDn );
+        entry.setDn( newDn.getUpName() );
+        entry.setNewSuperior( currentParent.getUpName() );
+        entry.setDeleteOldRdn( false );
+        return entry;
+    }
+
+
+    /**
+     * Revert a DN to it's previous version by removing the first RDN and adding the given RDN
+     *
+     * @param t0 The initial Attributes
+     * @param t0_dn The initial DN
+     * @param t1_rdn The new RDN
+     * @return A new LDIF entry with a reverted DN
+     * @throws NamingException If the name reverting failed
+     */
+    public static LdifEntry reverseRename( Attributes t0, LdapDN t0_dn, Rdn t1_rdn ) throws NamingException
+    {
+        LdifEntry entry = new LdifEntry();
+        LdapDN parent = null;
+        LdapDN newDn = null;
+
+        if ( t1_rdn == null )
+        {
+            throw new NullPointerException( "newRdn must not be null" );
+        }
+
+        if ( t0_dn == null )
+        {
+            throw new NullPointerException( "modifiedDn must not be null" );
+        }
+
+        if ( t0_dn.size() == 0 )
+        {
+            throw new IllegalArgumentException( "Don't think about renaming the rootDSE." );
+        }
+
+        parent = ( LdapDN ) t0_dn.clone();
+        parent.remove( parent.size() - 1 );
+
+        newDn = ( LdapDN ) parent.clone();
+        newDn.add( t1_rdn );
+
+        entry.setChangeType( ChangeType.ModRdn );
+        entry.setDeleteOldRdn( reverseDoDeleteOldRdn( t0, t1_rdn ) );
+        entry.setDn( newDn.getUpName() );
+        entry.setNewRdn( t0_dn.getRdn().getUpName() );
+        return entry;
+    }
+
+
+
+    /**
+     * Compute a reverse LDIF for a forward change which if in LDIF format
+     * would represent a modrdn operation.
+     *
+     * @param t0 the entry the way it was before changes were made
+     * @param t1_parentDn the new superior dn if this is a move, otherwise null
+     * @param t0_dn the dn of the entry being modified
+     * @param t1_rdn the new rdn to use
+     * @return A reverse LDIF
+     * @throws NamingException If something went wrong
+     */
+    public static LdifEntry reverseModifyRdn( Attributes t0, LdapDN t1_parentDn, LdapDN t0_dn, Rdn t1_rdn )
+            throws NamingException
+    {
+        if ( t0_dn == null )
+        {
+            throw new NullPointerException( "t0_dn must not be null" );
+        }
+
+        if ( t0_dn.size() == 0 )
+        {
+            throw new IllegalArgumentException( "Don't think about a move op on the rootDSE." );
+        }
+
+        // if there is no new superior in the picture then this is a rename
+        // operation where the parent is retained and only the rdn is changed
+        if ( t1_parentDn == null )
+        {
+            return reverseRename( t0, t0_dn, t1_rdn );
+        }
+
+        // if there is no rdn change then this is a raw move operation without
+        // a name change, we can delegate this to a simpler method
+        if ( t1_rdn == null )
+        {
+            return reverseModifyDn( t1_parentDn, t0_dn );
+        }
+
+        // -------------------------------------------------------------------
+        // Below here we do a move and change the name of the rdn all in one
+        // -------------------------------------------------------------------
+
+        // the reverse LDIF we will create
+        LdifEntry reverse = new LdifEntry();
+
+        // take the dn before the forward change was applied, and get it's
+        // parent, this parent will be the newSuperiorDn to be used for the
+        // reverse LDIF.  This is the same as t0_parentDn.
+        LdapDN reverseNewSuperiorDn = ( LdapDN ) t0_dn.clone();
+        reverseNewSuperiorDn.remove( reverseNewSuperiorDn.size() - 1 );
+
+        // take the rdn before the forward change, this will be the newRdn
+        // of the reverse LDIF, this is the same as a t0_rdn.
+        Rdn reverseNewRdn = t0_dn.getRdn();
+
+        // take the newSuperiorDn of the forward operation and append to it
+        // the new rdn of the forward operation to get the new dn after the
+        // change.  This will be the dn of the reverse ldif.  And this is just
+        // the same as t1_dn.
+        LdapDN reverseDn = ( LdapDN ) t1_parentDn.clone();
+        reverseDn.add( t1_rdn );
+
+        reverse.setDn( reverseDn.getUpName() );
+        reverse.setNewSuperior( reverseNewSuperiorDn.getUpName() );
+        reverse.setNewRdn( reverseNewRdn.getUpName() );
+        reverse.setChangeType( ChangeType.ModRdn );
+        reverse.setDeleteOldRdn( reverseDoDeleteOldRdn( t0, t1_rdn ) );
+
+        return reverse;
+    }
+
+
+    private static boolean reverseDoDeleteOldRdn( Attributes t0_entry, Rdn t1_rdn )
+    {
+        // Consider simple example changes (rename or move does not matter)
+        // -------------------------------------------------------------------
+        // Example A:  t0 (ou=foo) => t1 (ou=bar)
+        //
+        // If at t0 ou=foo contained an ou value of 'bar' then the reverse
+        // LDIF must not delete the old rdn which would be bar.  Otherwise
+        // we must delete the old rdn.
+        //
+        // Example B:  t0 (cn=foo) => t1 (ou=bar)
+        //
+        // Here it's similar to example (A) except because the rdn attribute
+        // is different which shifts basically changes how we check for the
+        // presence of the rdn.  If cn=foo at t0 contains the ou attribute
+        // with a 'bar' value then we cannot delete the oldRdn in the reverse
+        // LDAP.  The logic below expresses this.
+        //
+        // @TODO this code stinks because it does not consider whitespace and
+        // case varience which requires schema awareness.  This must change.
+
+        // look up attribute in t0 using t1's rdn attribute type
+        Attribute t0_attr = t0_entry.get( t1_rdn.getUpType() );
+
+        // if we don't have that attribute in t0 then we need to make sure the
+        // reverse LDIF deletes the t1 rdn of 'bar', if we do have that attribute
+        // then we check if the value 'bar' is in it, if not there we delete
+        // if there we do not
+        return t0_attr == null || ! t0_attr.contains( t1_rdn.getUpValue() );
+    }
+
+
+    /**
+     *
+     * Compute the reversed LDIF for a modify request. We will deal with the
+     * three kind of modifications :
+     * - add
+     * - remove
+     * - replace
+     *
+     * As the modifications should be issued in a reversed order ( ie, for
+     * the initials modifications {A, B, C}, the reversed modifications will
+     * be ordered like {C, B, A}), we will change the modifications order.
+     *
+     * @param dn the dn of the modified entry
+     * @param forwardModifications the modification items for the forward change
+     * @param modifiedEntry The modified entry. Necessary for the destructive modifications
+     * @return A reversed LDIF
+     * @throws NamingException If something went wrong
+     */
+    public static LdifEntry reverseModify( LdapDN dn, List<ModificationItemImpl> forwardModifications,
+                                       Attributes modifiedEntry ) throws NamingException
+    {
+        // First, protect the original entry by cloning it : we will modify it
+        Attributes clonedEntry = ( Attributes ) modifiedEntry.clone();
+
+        LdifEntry entry = new LdifEntry();
+        entry.setChangeType( ChangeType.Modify );
+
+        entry.setDn( dn.getUpName() );
+
+        // As the reversed modifications should be pushed in reversed order,
+        // we create a list to temporarily store the modifications.
+        List<ModificationItemImpl> reverseModifications = new ArrayList<ModificationItemImpl>();
+
+        // Loop through all the modifications. For each modification, we will
+        // have to apply it to the modified entry in order to be able to generate
+        // the reversed modification
+        for ( ModificationItem modification : forwardModifications )
+        {
+            switch ( modification.getModificationOp() )
+            {
+                case DirContext.ADD_ATTRIBUTE :
+                    Attribute mod = modification.getAttribute();
+
+                    Attribute previous = modifiedEntry.get( mod.getID() );
+
+                    if ( mod.equals( previous ) )
+                    {
+                        continue;
+                    }
+
+                    ModificationItemImpl reverseModification = new ModificationItemImpl( DirContext.REMOVE_ATTRIBUTE, mod );
+                    reverseModifications.add( 0, reverseModification );
+                    break;
+
+                case DirContext.REMOVE_ATTRIBUTE :
+                    mod = modification.getAttribute();
+
+                    previous = modifiedEntry.get( mod.getID() );
+
+                    if ( previous == null )
+                    {
+                        // Nothing to do if the previous attribute didn't exist
+                        continue;
+                    }
+
+                    if ( mod.get() == null )
+                    {
+                        reverseModification = new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, previous );
+                        reverseModifications.add( 0, reverseModification );
+                        continue;
+                    }
+
+                    reverseModification = new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, mod );
+                    reverseModifications.add( 0, reverseModification );
+                    break;
+
+                case DirContext.REPLACE_ATTRIBUTE :
+                    mod = modification.getAttribute();
+
+                    previous = modifiedEntry.get( mod.getID() );
+
+                    if ( mod.get() == null )
+                    {
+                        reverseModification = new ModificationItemImpl( DirContext.REPLACE_ATTRIBUTE, previous );
+                        reverseModifications.add( 0, reverseModification );
+                        continue;
+                    }
+
+                    if ( previous == null )
+                    {
+                        Attribute emptyAttribute = new AttributeImpl( mod.getID() );
+                        reverseModification = new ModificationItemImpl( DirContext.REPLACE_ATTRIBUTE, emptyAttribute );
+                        reverseModifications.add( 0, reverseModification );
+                        continue;
+                    }
+
+                    reverseModification = new ModificationItemImpl( DirContext.REPLACE_ATTRIBUTE, previous );
+                    reverseModifications.add( 0, reverseModification );
+                    break;
+                    
+                default :
+                    break; // Do nothing
+                    
+            }
+
+            AttributeUtils.applyModification( clonedEntry, modification );
+
+        }
+
+        // Special case if we don't have any reverse modifications
+        if ( reverseModifications.size() == 0 )
+        {
+            throw new IllegalArgumentException( "Could not deduce reverse modifications from provided modifications: "
+                    + forwardModifications );
+        }
+
+        // Now, push the reversed list into the entry
+        for ( ModificationItemImpl modification:reverseModifications )
+        {
+            entry.addModificationItem( modification );
+        }
+
+        // Return the reverted entry
+        return entry;
+    }
 }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbandonRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbandonRequestImpl.java
index a4a2256..cd5409f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbandonRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbandonRequestImpl.java
@@ -107,12 +107,13 @@
 
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + abandonId;
-        hash = hash*31 + super.hashCode();
+        int hash = 37;
+        hash = hash*17 + abandonId;
+        hash = hash*17 + super.hashCode();
         
         return hash;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractMessage.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractMessage.java
index 3e2be84..76d03de 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractMessage.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractMessage.java
@@ -207,13 +207,15 @@
             return false;
         }
 
-        Map controls = msg.getControls();
+        Map<String, Control> controls = msg.getControls();
+        
         if ( controls.size() != this.controls.size() )
         {
             return false;
         }
 
-        Iterator list = this.controls.keySet().iterator();
+        Iterator<String> list = this.controls.keySet().iterator();
+        
         while ( list.hasNext() )
         {
             if ( !controls.containsKey( list.next() ) )
@@ -227,14 +229,15 @@
     
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + id;
-        hash = hash*31 + ( type == null ? 0 : type.hashCode() );
-        hash = hash*31 + ( parameters == null ? 0 : parameters.hashCode() );
-        hash = hash*31 + ( controls == null ? 0 : controls.hashCode() );
+        int hash = 37;
+        hash = hash*17 + id;
+        hash = hash*17 + ( type == null ? 0 : type.hashCode() );
+        hash = hash*17 + ( parameters == null ? 0 : parameters.hashCode() );
+        hash = hash*17 + ( controls == null ? 0 : controls.hashCode() );
         
         return hash;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractRequest.java
index 21b230c..ab3e58c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AbstractRequest.java
@@ -65,12 +65,13 @@
     
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + (hasResponse ? 0 : 1 );
-        hash = hash*31 + super.hashCode();
+        int hash = 37;
+        hash = hash*17 + (hasResponse ? 0 : 1 );
+        hash = hash*17 + super.hashCode();
         
         return hash;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AddRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AddRequestImpl.java
index 22642b4..e2c5743 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AddRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AddRequestImpl.java
@@ -218,14 +218,15 @@
 
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + ( attributes == null ? 0 : attributes.hashCode() );
-        hash = hash*31 + ( entry == null ? 0 : entry.hashCode() );
-        hash = hash*31 + ( response == null ? 0 : response.hashCode() );
-        hash = hash*31 + super.hashCode();
+        int hash = 37;
+        hash = hash*17 + ( attributes == null ? 0 : attributes.hashCode() );
+        hash = hash*17 + ( entry == null ? 0 : entry.hashCode() );
+        hash = hash*17 + ( response == null ? 0 : response.hashCode() );
+        hash = hash*17 + super.hashCode();
         
         return hash;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/DerefAliasesEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AliasDerefMode.java
similarity index 71%
rename from ldap/src/main/java/org/apache/directory/shared/ldap/message/DerefAliasesEnum.java
rename to ldap/src/main/java/org/apache/directory/shared/ldap/message/AliasDerefMode.java
index b80de92..daf06b3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/DerefAliasesEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AliasDerefMode.java
@@ -27,29 +27,34 @@
 
 /**
  * Type-safe derefAliases search parameter enumeration which determines the mode
- * of alias handling. Note that the names of these ValuedEnums correspond to the
- * value for the java.naming.ldap.derefAliases JNDI LDAP specific property.
+ * of alias handling. Note that the jndi values of these ValuedEnums correspond
+ * to the string value for the java.naming.ldap.derefAliases JNDI LDAP specific
+ * property.  The integer value represents the values used in the LDAP ASN.1 for
+ * different settings.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Revision$
  */
-public enum DerefAliasesEnum
+public enum AliasDerefMode
 {
     /** Alias handling mode value that treats aliases like entries */
-    NEVER_DEREF_ALIASES(0),
+    NEVER_DEREF_ALIASES( 0, "never" ),
 
     /** Alias handling mode value that dereferences only when searching */
-    DEREF_IN_SEARCHING(1),
+    DEREF_IN_SEARCHING( 1, "searching" ),
 
     /** Alias handling mode value that dereferences only in finding the base */
-    DEREF_FINDING_BASE_OBJ(2),
+    DEREF_FINDING_BASE_OBJ( 2, "finding" ),
 
     /** Alias handling mode value that dereferences always */
-    DEREF_ALWAYS(3);
+    DEREF_ALWAYS( 3, "always" );
 
 
     /** Stores the integer value of each element of the enumeration */
     private int value;
+    /** Stores the integer value of each element of the enumeration */
+    private String jndiValue;
+
     
     /**
      * Private constructor so no other instances can be created other than the
@@ -57,9 +62,10 @@
      * 
      * @param value the integer value of the enumeration.
      */
-    private DerefAliasesEnum( int value )
+    private AliasDerefMode( int value, String jndiValue )
     {
        this.value = value;
+       this.jndiValue = jndiValue;
     }
 
     
@@ -81,9 +87,9 @@
      *            java.naming.ldap.derefAliases property
      * @return the enumeration for the environment
      */
-    public static DerefAliasesEnum getEnum( Map<String, DerefAliasesEnum> env )
+    public static AliasDerefMode getEnum( Map<String, Object> env )
     {
-        DerefAliasesEnum property = env.get( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES );
+        String property = ( String ) env.get( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES );
         
         if ( null == property )
         {
@@ -91,7 +97,28 @@
         }
         else
         {
-            return property;
+            if ( property.trim().equalsIgnoreCase( "always" ) )
+            {
+                return DEREF_ALWAYS;
+            }
+            else if ( property.trim().equalsIgnoreCase( "never" ) )
+            {
+                return NEVER_DEREF_ALIASES;
+            }
+            else if ( property.trim().equalsIgnoreCase( "finding" ) )
+            {
+                return DEREF_FINDING_BASE_OBJ;
+            }
+            else if ( property.trim().equalsIgnoreCase( "searching" ) )
+            {
+                return DEREF_IN_SEARCHING;
+            }
+            else
+            {
+                throw new IllegalArgumentException( "Unrecogniced value '" + property + "' for "
+                        + JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES + " JNDI property.\n"
+                        + "Expected a value of either always, never, searching, or finding." );
+            }
         }
     }
     
@@ -171,4 +198,10 @@
                 throw new IllegalArgumentException( "Class has bug: check for valid enumeration values" );
         }
     }
+
+
+    public String getJndiValue()
+    {
+        return jndiValue;
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributeImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributeImpl.java
index 0677d79..529a248 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributeImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributeImpl.java
@@ -57,13 +57,14 @@
 
     /** In case we have only one value, just use this container */
     private Object value;
-    
+
     /** the list of attribute values, if unordered */
     private List<Object> list;
-    
+
     /** The number of values stored */
     private int size = 0;
 
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -117,6 +118,7 @@
         size = 1;
     }
 
+
     /**
      * Create a copy of an Attribute, be it an AttributeImpl
      * instance of a BasicAttribute instance
@@ -132,9 +134,9 @@
         }
         else if ( attribute instanceof AttributeImpl )
         {
-            AttributeImpl clone = (AttributeImpl)attribute.clone();
-            
-            upId  = clone.upId;
+            AttributeImpl clone = ( AttributeImpl ) attribute.clone();
+
+            upId = clone.upId;
             list = clone.list;
             size = clone.size;
             value = clone.value;
@@ -142,9 +144,9 @@
         else if ( attribute instanceof BasicAttribute )
         {
             upId = attribute.getID();
-            
-            NamingEnumeration values = attribute.getAll();
-            
+
+            NamingEnumeration<?> values = attribute.getAll();
+
             while ( values.hasMoreElements() )
             {
                 add( values.nextElement() );
@@ -156,6 +158,7 @@
         }
     }
 
+
     // ------------------------------------------------------------------------
     // javax.naming.directory.Attribute Interface Method Implementations
     // ------------------------------------------------------------------------
@@ -171,26 +174,29 @@
         {
             return new IteratorNamingEnumeration<Object>( new Iterator<Object>()
             {
-                private boolean more = (size != 0);
-                    
-                public boolean hasNext() 
+                private boolean more = ( size != 0 );
+
+
+                public boolean hasNext()
                 {
                     return more;
                 }
-                
-                public Object next() 
+
+
+                public Object next()
                 {
                     more = false;
                     return value;
                 }
-                
-                public void remove() 
+
+
+                public void remove()
                 {
                     value = null;
                     more = true;
                     size = 0;
                 }
-            });
+            } );
         }
         else
         {
@@ -248,17 +254,17 @@
      */
     public boolean contains( Object attrVal )
     {
-        switch (size)
+        switch ( size )
         {
-            case 0 :
+            case 0:
                 return false;
-                
-            case 1 :
+
+            case 1:
                 return AttributeUtils.equals( value, attrVal );
-                
-            default :
-                Iterator values = list.iterator();
-            
+
+            default:
+                Iterator<Object> values = list.iterator();
+
                 while ( values.hasNext() )
                 {
                     if ( AttributeUtils.equals( values.next(), attrVal ) )
@@ -266,7 +272,7 @@
                         return true;
                     }
                 }
-                
+
                 return false;
         }
     }
@@ -284,25 +290,25 @@
     public boolean add( Object attrVal )
     {
         boolean exists = false;
-        
+
         if ( contains( attrVal ) )
         {
             // Do not duplicate values
             return true;
         }
-        
+
         // First copy the value
         attrVal = AttributeUtils.cloneValue( attrVal );
-        
+
         switch ( size )
         {
-            case 0 :
+            case 0:
                 value = attrVal;
                 size++;
                 return true;
-                
-            case 1 :
-                exists = value.equals( attrVal );
+
+            case 1:
+                exists = contains( attrVal );
 
                 if ( exists )
                 {
@@ -318,10 +324,10 @@
                     value = null;
                     return true;
                 }
-                
-            default :
-                exists = list.contains( attrVal ); 
-            
+
+            default:
+                exists = contains( attrVal );
+
                 list.add( attrVal );
                 size++;
                 return exists;
@@ -341,25 +347,88 @@
     {
         switch ( size )
         {
-            case 0 :
+            case 0:
                 return false;
-                
-            case 1 :
-                value = null;
-                size--;
-                return true;
-                
-            case 2 : 
-                list.remove( attrVal );
-                value = list.get(0);
-                size = 1;
-                list = null;
-                return true;
-                
-            default :
-                list.remove( attrVal );
-                size--;
-                return true;
+
+            case 1:
+                if ( contains( attrVal ) )
+                {
+                    value = null;
+                    size--;
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+
+            case 2:
+                if ( contains( attrVal ) )
+                {
+                    if ( attrVal instanceof byte[] )
+                    {
+                        for ( Object val : list )
+                        {
+                            if ( val instanceof byte[] )
+                            {
+                                if ( Arrays.equals( ( byte[] )val, ( byte[] ) attrVal ) )
+                                {
+                                    list.remove( val );
+                                    value = list.get( 0 );
+                                    size = 1;
+                                    list = null;
+                                    return true;
+                                }
+                            }
+                        }
+    
+                        return false;
+                    }
+                    else
+                    {
+                        list.remove( attrVal );
+                        value = list.get( 0 );
+                        size = 1;
+                        list = null;
+                        return true;
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+
+            default:
+                if ( contains( attrVal ) )
+                {
+                    if ( attrVal instanceof byte[] )
+                    {
+                        for ( Object val : list )
+                        {
+                            if ( val instanceof byte[] )
+                            {
+                                if ( Arrays.equals( ( byte[] ) val, ( byte[] ) attrVal ) )
+                                {
+                                    list.remove( val );
+                                    size--;
+                                    return true;
+                                }
+                            }
+                        }
+    
+                        return false;
+                    }
+                    else
+                    {
+                        list.remove( attrVal );
+                        size--;
+                        return true;
+                    }
+                }
+                else
+                {
+                    return false;
+                }
         }
     }
 
@@ -371,15 +440,15 @@
     {
         switch ( size )
         {
-            case 0 :
+            case 0:
                 return;
-                
-            case 1 :
+
+            case 1:
                 value = null;
                 size = 0;
                 return;
-                
-            default :
+
+            default:
                 list = null;
                 size = 0;
                 return;
@@ -419,8 +488,8 @@
     {
         try
         {
-            AttributeImpl clone = (AttributeImpl)super.clone();
-            
+            AttributeImpl clone = ( AttributeImpl ) super.clone();
+
             if ( size < 2 )
             {
                 clone.value = AttributeUtils.cloneValue( value );
@@ -428,14 +497,14 @@
             else
             {
                 clone.list = new ArrayList<Object>( size );
-                
+
                 for ( int i = 0; i < size; i++ )
                 {
                     Object newValue = AttributeUtils.cloneValue( list.get( i ) );
                     clone.list.add( newValue );
                 }
             }
-            
+
             return clone;
         }
         catch ( CloneNotSupportedException cnse )
@@ -466,20 +535,20 @@
      */
     public Object get( int index )
     {
-        if ( (index < 0 ) || ( index > size + 1 ) )
+        if ( ( index < 0 ) || ( index > size + 1 ) )
         {
             return null;
         }
-        
+
         switch ( size )
         {
-            case 0 :
+            case 0:
                 return null;
-                
-            case 1 :
+
+            case 1:
                 return value;
-                
-            default :
+
+            default:
                 return list.get( index );
         }
     }
@@ -495,33 +564,32 @@
      */
     public Object remove( int index )
     {
-        if ( (index < 0 ) || ( index > size + 1 ) )
+        if ( ( index < 0 ) || ( index > size + 1 ) )
         {
             return null;
         }
-        
+
         switch ( size )
         {
-            case 0 :
+            case 0:
                 return null;
-                
-            case 1 :
+
+            case 1:
                 Object result = value;
                 value = null;
                 size = 0;
                 return result;
-                
-            case 2 :
+
+            case 2:
                 Object removed = list.remove( index );
-                value = list.get(0);
+                value = list.get( 0 );
                 size = 1;
                 list = null;
                 return removed;
-                
-                
-            default :
+
+            default:
                 size--;
-            
+
                 return list.remove( index );
         }
     }
@@ -540,17 +608,17 @@
     {
         // First copy the value
         attrVal = AttributeUtils.cloneValue( attrVal );
-        
+
         switch ( size )
         {
-            case 0 :
+            case 0:
                 size++;
                 value = attrVal;
                 return;
-                
-            case 1 :
+
+            case 1:
                 list = new ArrayList<Object>();
-                
+
                 if ( index == 0 )
                 {
                     list.add( attrVal );
@@ -565,8 +633,8 @@
                 size++;
                 value = null;
                 return;
-                
-            default :
+
+            default:
                 list.add( index, attrVal );
                 size++;
                 return;
@@ -587,15 +655,15 @@
     {
         // First copy the value
         attrVal = AttributeUtils.cloneValue( attrVal );
-        
+
         switch ( size )
         {
-            case 0 :
+            case 0:
                 size++;
                 value = attrVal;
                 return null;
-                
-            case 1 :
+
+            case 1:
                 if ( index == 0 )
                 {
                     Object result = value;
@@ -611,26 +679,54 @@
                     value = null;
                     return null;
                 }
-                
-            default :
+
+            default:
                 Object oldValue = list.get( index );
                 list.set( index, attrVal );
                 return oldValue;
         }
     }
+    
+    
+    /**
+     * Compute the hash code for this attribute. It's a combinaison
+     * of the ID and all the values' hash codes.
+     * 
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int hash = 37;
+        
+        hash += hash*17 + StringTools.toLowerCase( getID() ).hashCode();
+        
+        if ( ( list != null ) && ( list.size() != 0 ) )
+        {
+            for ( Object value:list )
+            {
+                if ( value instanceof byte[] )
+                {
+                    hash += hash*17 + Arrays.hashCode( (byte[])value );
+                }
+                else 
+                {
+                    hash += hash*17 + value.hashCode();
+                }
+            }
+        }
+        
+        return hash;
+    }
 
 
     /**
-     * Checks for equality between this Attribute instance and another. The
-     * lockable properties are not factored into the equality semantics and
-     * neither is the Attribute implementation. The Attribute ID's are compared
-     * with regard to case and value order is only considered if the Attribute
-     * arguement is ordered itself.
+     * Checks for equality between this Attribute instance and another. The 
+     * Attribute ID's aren't compared with regard to case.
      * 
      * TODO start looking at comparing syntaxes to determine if attributes are
      *       really equal
-     * @param obj
-     *            the Attribute to test for equality
+     * @param obj the Attribute to test for equality
      * @return true if the obj is an Attribute and equals this Attribute false
      *         otherwise
      */
@@ -647,8 +743,8 @@
         }
 
         Attribute attr = ( Attribute ) obj;
-        
-        if ( !upId.equals( attr.getID() ) )
+
+        if ( !StringTools.toLowerCase( upId ).equals( StringTools.toLowerCase( attr.getID() ) ) )
         {
             return false;
         }
@@ -687,57 +783,39 @@
             // We have to do that because attribute's values are
             // not ordered.
             Map<Integer, Object> hash = new HashMap<Integer, Object>();
-            
-            for ( Object v:list )
+
+            for ( Object v : list )
             {
                 int h = 0;
-                
+
                 if ( v instanceof String )
                 {
                     h = v.hashCode();
                 }
                 else if ( v instanceof byte[] )
                 {
-                    byte[] bv = (byte[])v;
+                    byte[] bv = ( byte[] ) v;
                     h = Arrays.hashCode( bv );
                 }
                 else
                 {
                     return false;
                 }
-                
+
                 hash.put( Integer.valueOf( h ), v );
             }
-            
+
             try
             {
-                NamingEnumeration attrValues = attr.getAll();
-                
+                NamingEnumeration<?> attrValues = attr.getAll();
+
                 while ( attrValues.hasMoreElements() )
                 {
                     Object val = attrValues.next();
-                    
+
                     if ( val instanceof String )
                     {
                         Integer h = Integer.valueOf( val.hashCode() );
-                        
-                        if ( !hash.containsKey( h ) )
-                        {
-                            return false;
-                        }
-                        else
-                        {
-                            Object val2 = hash.remove( h );
-                            
-                            if ( !val.equals( val2 ) )
-                            {
-                                return false;
-                            }
-                        }
-                    }
-                    else if ( val instanceof byte[] )
-                    {
-                        Integer h = Integer.valueOf( Arrays.hashCode( (byte[])val ) );
 
                         if ( !hash.containsKey( h ) )
                         {
@@ -746,8 +824,26 @@
                         else
                         {
                             Object val2 = hash.remove( h );
-                            
-                            if ( !Arrays.equals( (byte[])val, (byte[])val2 ) )
+
+                            if ( !val.equals( val2 ) )
+                            {
+                                return false;
+                            }
+                        }
+                    }
+                    else if ( val instanceof byte[] )
+                    {
+                        Integer h = Integer.valueOf( Arrays.hashCode( ( byte[] ) val ) );
+
+                        if ( !hash.containsKey( h ) )
+                        {
+                            return false;
+                        }
+                        else
+                        {
+                            Object val2 = hash.remove( h );
+
+                            if ( !Arrays.equals( ( byte[] ) val, ( byte[] ) val2 ) )
                             {
                                 return false;
                             }
@@ -758,7 +854,7 @@
                         return false;
                     }
                 }
-                
+
                 if ( hash.size() != 0 )
                 {
                     return false;
@@ -775,45 +871,46 @@
             }
         }
     }
-    
+
+
     /**
      * @see Object#toString()
      */
     public String toString()
     {
         StringBuffer sb = new StringBuffer();
-        
+
         sb.append( "Attribute id : '" ).append( upId ).append( "', " );
-        sb.append( " Values : [");
-        
-        switch (size)
+        sb.append( " Values : [" );
+
+        switch ( size )
         {
-            case 0 :
+            case 0:
                 sb.append( "]\n" );
                 break;
-                
-            case 1 :
-                if ( value instanceof String ) 
+
+            case 1:
+                if ( value instanceof String )
                 {
                     sb.append( '\'' ).append( value ).append( '\'' );
                 }
                 else
                 {
-                    sb.append( StringTools.dumpBytes( (byte[])value ) );
+                    sb.append( StringTools.dumpBytes( ( byte[] ) value ) );
                 }
-                
+
                 sb.append( "]\n" );
                 break;
-                
-            default :
+
+            default:
                 boolean isFirst = true;
-            
-                Iterator values = list.iterator();
-                
+
+                Iterator<Object> values = list.iterator();
+
                 while ( values.hasNext() )
                 {
                     Object v = values.next();
-                    
+
                     if ( isFirst == false )
                     {
                         sb.append( ", " );
@@ -822,21 +919,21 @@
                     {
                         isFirst = false;
                     }
-                    
-                    if ( v instanceof String ) 
+
+                    if ( v instanceof String )
                     {
                         sb.append( '\'' ).append( v ).append( '\'' );
                     }
                     else
                     {
-                        sb.append( StringTools.dumpBytes( (byte[])v ) );
+                        sb.append( StringTools.dumpBytes( ( byte[] ) v ) );
                     }
                 }
-                
+
                 sb.append( "]\n" );
                 break;
         }
-        
+
         return sb.toString();
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributesImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributesImpl.java
index e7905f6..431098a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributesImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/AttributesImpl.java
@@ -20,9 +20,9 @@
 package org.apache.directory.shared.ldap.message;
 
 
-import java.util.Map;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
@@ -43,10 +43,11 @@
  */
 public class AttributesImpl implements Attributes
 {
-    static transient final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
     
     /**
      * An iterator which returns Attributes.  
+     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
      */
     public class AttributeIterator<T> implements Iterator<Attribute>
     {
@@ -159,7 +160,7 @@
         }
         else if ( attributes instanceof BasicAttributes )
         {
-            NamingEnumeration attrs = attributes.getAll();
+            NamingEnumeration<? extends Attribute> attrs = attributes.getAll();
             keyMap = new HashMap<String, AttributeImpl>();
 
             while ( attrs.hasMoreElements() )
@@ -175,11 +176,11 @@
             
             keyMap = new HashMap<String, AttributeImpl>( clone.keyMap.size() );
             
-            Iterator keys = clone.keyMap.keySet().iterator();
+            Iterator<String> keys = clone.keyMap.keySet().iterator();
     
             while ( keys.hasNext() )
             {
-                String key = (String)keys.next();
+                String key = keys.next();
                 AttributeImpl attribute = clone.keyMap.get( key );
                 keyMap.put( key, (AttributeImpl)attribute.clone() );
             }
@@ -358,12 +359,12 @@
     {
         String[] ids = new String[keyMap.size()];
         
-        Iterator values = keyMap.values().iterator();
+        Iterator<AttributeImpl> values = keyMap.values().iterator();
         int i = 0;
         
         while ( values.hasNext() )
         {
-            ids[i++] = ((AttributeImpl)values.next()).getID();
+            ids[i++] = values.next().getID();
         }
         
         return new ArrayNamingEnumeration<String>( ids );
@@ -435,7 +436,7 @@
              
             try
             {
-                NamingEnumeration values = attr.getAll();
+                NamingEnumeration<?> values = attr.getAll();
                  
                 while ( values.hasMore() )
                 {
@@ -492,11 +493,11 @@
     
             clone.keyMap = new HashMap<String, AttributeImpl>( keyMap.size() );
             
-            Iterator keys = keyMap.keySet().iterator();
+            Iterator<String> keys = keyMap.keySet().iterator();
     
             while ( keys.hasNext() )
             {
-                String key = (String)keys.next();
+                String key = keys.next();
                 clone.keyMap.put( key, (AttributeImpl)keyMap.get( key ).clone() );
             }
             
@@ -518,11 +519,11 @@
     {
         StringBuffer buf = new StringBuffer();
 
-        Iterator attrs = keyMap.values().iterator();
+        Iterator<AttributeImpl> attrs = keyMap.values().iterator();
         
         while ( attrs.hasNext() )
         {
-            Attribute attr = (AttributeImpl)attrs.next();
+            Attribute attr = attrs.next();
 
             buf.append( attr );
         }
@@ -565,11 +566,11 @@
             return false;
         }
 
-        NamingEnumeration list = attrs.getAll();
+        NamingEnumeration<? extends Attribute> list = attrs.getAll();
 
         while ( list.hasMoreElements() )
         {
-            Attribute attr = ( Attribute )list.nextElement();
+            Attribute attr = list.nextElement();
             Attribute myAttr = get( attr.getID() );
 
             if ( myAttr == null )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindRequestImpl.java
index 96a7d74..485219c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindRequestImpl.java
@@ -140,7 +140,13 @@
      */
     public void setCredentials( byte[] credentials )
     {
-        this.credentials = credentials;
+        if ( credentials != null )
+        {
+            this.credentials = new byte[ credentials.length ];
+            System.arraycopy( credentials, 0, this.credentials, 0, credentials.length );
+        } else {
+            this.credentials = null;
+        }
         
         if ( credentials != null )
         {
@@ -362,17 +368,18 @@
     
     /**
      * @see Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        int hash = 7;
-        hash = hash*31 + ( credentials == null ? 0 : hCredentials );
-        hash = hash*31 + ( isSimple ? 0 : 1 );
-        hash = hash*31 + ( isVersion3 ? 0 : 1 );
-        hash = hash*31 + ( mechanism == null ? 0 : mechanism.hashCode() );
-        hash = hash*31 + ( name == null ? 0 : name.hashCode() );
-        hash = hash*31 + ( response == null ? 0 : response.hashCode() );
-        hash = hash*31 + super.hashCode();
+        int hash = 37;
+        hash = hash*17 + ( credentials == null ? 0 : hCredentials );
+        hash = hash*17 + ( isSimple ? 0 : 1 );
+        hash = hash*17 + ( isVersion3 ? 0 : 1 );
+        hash = hash*17 + ( mechanism == null ? 0 : mechanism.hashCode() );
+        hash = hash*17 + ( name == null ? 0 : name.hashCode() );
+        hash = hash*17 + ( response == null ? 0 : response.hashCode() );
+        hash = hash*17 + super.hashCode();
         
         return hash;
     }
@@ -388,7 +395,7 @@
         sb.append( "    BindRequest\n" );
         sb.append( "        Version : '" ).append( isVersion3 ? "3" : "2" ).append( "'\n" );
 
-        if ( StringTools.isEmpty( name.toString() ) )
+        if ( StringTools.isEmpty( name.toString() ) && isSimple )
         {
             sb.append( "        Name : anonymous\n" );
         }
@@ -405,9 +412,19 @@
             {
                 sb.append( "        Sasl credentials\n" );
                 sb.append( "            Mechanism :'" ).append( mechanism ).append( "'\n" );
-
-                sb.append( "            Credentials : '" ).append( StringTools.utf8ToString( credentials ) ).append(
-                    '/' ).append( StringTools.dumpBytes( credentials ) ).append( "'\n" );
+                
+                if ( credentials == null )
+                {
+                    sb.append( "            Credentials : null" );
+                }
+                else
+                {
+                    sb.append( "            Credentials : '" ).
+                        append( StringTools.utf8ToString( credentials ) ).
+                        append( '/' ).
+                        append( StringTools.dumpBytes( credentials ) ).
+                        append( "'\n" );
+                }
             }
         }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindResponseImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindResponseImpl.java
index b80f8fe..8c8241c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindResponseImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/BindResponseImpl.java
@@ -68,7 +68,14 @@
      */
     public byte[] getServerSaslCreds()
     {
-        return serverSaslCreds;
+        if ( serverSaslCreds == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ serverSaslCreds.length ];
+        System.arraycopy( serverSaslCreds, 0, copy, 0, serverSaslCreds.length );
+        return copy;
     }
 
 
@@ -82,7 +89,13 @@
      */
     public void setServerSaslCreds( byte[] serverSaslCreds )
     {
-        this.serverSaslCreds = serverSaslCreds;
+        if ( serverSaslCreds != null )
+        {
+            this.serverSaslCreds = new byte[ serverSaslCreds.length ];
+            System.arraycopy( serverSaslCreds, 0, this.serverSaslCreds, 0, serverSaslCreds.length );
+        } else {
+            this.serverSaslCreds = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/CompareRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/CompareRequestImpl.java
index b71f6d7..307d828 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/CompareRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/CompareRequestImpl.java
@@ -125,7 +125,13 @@
      */
     public void setAssertionValue( byte[] attrVal )
     {
-        this.attrVal = attrVal;
+        if ( attrVal != null )
+        {
+            this.attrVal = new byte[ attrVal.length ];
+            System.arraycopy( attrVal, 0, this.attrVal, 0, attrVal.length );
+        } else {
+            this.attrVal = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/EntryChangeControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/EntryChangeControl.java
index f97bced..7a37ef6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/EntryChangeControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/EntryChangeControl.java
@@ -82,7 +82,7 @@
 
     public static final String CONTROL_OID = "2.16.840.1.113730.3.4.7";
 
-    public static final int UNDEFINED_CHANGE_NUMBER = org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControl.UNDEFINED_CHANGE_NUMBER;
+    public static final int UNDEFINED_CHANGE_NUMBER = org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlCodec.UNDEFINED_CHANGE_NUMBER;
 
     private ChangeType changeType = ChangeType.ADD;
 
@@ -137,7 +137,7 @@
     public byte[] getEncodedValue() 
     {
         // should call this codec or something
-        org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControl ecc = new org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControl();
+        org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlCodec ecc = new org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlCodec();
         ecc.setChangeNumber( changeNumber );
         ecc.setChangeType( changeType );
         ecc.setPreviousDn( previousDn );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedRequestImpl.java
index bd97c1a..cebcd6b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedRequestImpl.java
@@ -101,7 +101,14 @@
      */
     public byte[] getPayload()
     {
-        return payload;
+        if ( payload == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ payload.length ];
+        System.arraycopy( payload, 0, copy, 0, payload.length );
+        return copy;
     }
 
 
@@ -113,7 +120,13 @@
      */
     public void setPayload( byte[] payload )
     {
-        this.payload = payload;
+        if ( payload != null )
+        {
+            this.payload = new byte[ payload.length ];
+            System.arraycopy( payload, 0, this.payload, 0, payload.length );
+        } else {
+            this.payload = null;
+        }
     }
 
 
@@ -167,6 +180,11 @@
         {
             return false;
         }
+        
+        if ( !( obj instanceof ExtendedRequest ) )
+        {
+            return false;
+        }
 
         ExtendedRequest req = ( ExtendedRequest ) obj;
         if ( oid != null && req.getOid() == null )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedResponseImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedResponseImpl.java
index cbe1875..09a32d6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedResponseImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ExtendedResponseImpl.java
@@ -73,19 +73,32 @@
      */
     public byte[] getResponse()
     {
-        return value;
+        if ( value == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ value.length ];
+        System.arraycopy( value, 0, copy, 0, value.length );
+        return copy;
     }
 
 
     /**
-     * Sets the reponse OID specific encoded response values.
+     * Sets the response OID specific encoded response values.
      * 
      * @param value
      *            the response specific encoded response values.
      */
     public void setResponse( byte[] value )
     {
-        this.value = value;
+        if ( value != null )
+        {
+            this.value = new byte[ value.length ];
+            System.arraycopy( value, 0, this.value, 0, value.length );
+        } else {
+            this.value = null;
+        }
     }
     
     
@@ -138,6 +151,11 @@
         {
             return false;
         }
+        
+        if ( !( obj instanceof ExtendedResponse ) )
+        {
+            return false;
+        }
 
         ExtendedResponse resp = ( ExtendedResponse ) obj;
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageDecoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageDecoder.java
index 520386c..6ea7e63 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageDecoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageDecoder.java
@@ -20,25 +20,19 @@
 package org.apache.directory.shared.ldap.message;
 
 
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Set;
-
 import org.apache.directory.shared.asn1.Asn1Object;
 import org.apache.directory.shared.asn1.codec.DecoderException;
 import org.apache.directory.shared.asn1.codec.stateful.DecoderCallback;
 import org.apache.directory.shared.asn1.codec.stateful.DecoderMonitor;
 import org.apache.directory.shared.asn1.codec.stateful.StatefulDecoder;
 import org.apache.directory.shared.ldap.codec.ResponseCarryingException;
-import org.apache.directory.shared.ldap.constants.JndiPropertyConstants;
+import org.apache.directory.shared.ldap.message.spi.BinaryAttributeDetector;
 import org.apache.directory.shared.ldap.message.spi.Provider;
 import org.apache.directory.shared.ldap.message.spi.ProviderDecoder;
 import org.apache.directory.shared.ldap.message.spi.TransformerSpi;
-import org.apache.directory.shared.ldap.util.StringTools;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.util.Hashtable;
 
 
 /**
@@ -50,15 +44,6 @@
  */
 public final class MessageDecoder implements ProviderDecoder
 {
-    private static final Logger log = LoggerFactory.getLogger( MessageDecoder.class );
-
-    private static final String BINARY_KEY = JndiPropertyConstants.JNDI_LDAP_ATTRIBUTES_BINARY;
-    
-    private final static Set<String> EMPTY_SET_STRING = new HashSet<String>();
-
-    /** Environment parameters stored here */
-    private final Hashtable<String, Object> env;
-
     /** the ASN.1 provider */
     private final Provider provider;
 
@@ -76,92 +61,29 @@
      * Creates a MessageDecoder using default properties for enabling a BER
      * library provider.
      * 
-     * @param env
-     *            The Map of environment parameters.
-     * @throws MessageException
-     *             if there is a problem creating this decoder.
+     * @param binaryAttributeDetector detects whether or not an attribute is binary
+     * @throws MessageException if there is a problem creating this decoder.
      */
-    public MessageDecoder(final Hashtable<String, Object> env) throws MessageException
+    public MessageDecoder( BinaryAttributeDetector binaryAttributeDetector ) throws MessageException
     {
-        this.env = ( Hashtable<String, Object> ) env.clone();
-        
         // We need to get the encoder class name
-        Hashtable providerEnv = Provider.getEnvironment();
+        Hashtable<Object, Object> providerEnv = Provider.getEnvironment();
         
-        this.env.put( Provider.BERLIB_PROVIDER, providerEnv.get( Provider.BERLIB_PROVIDER ) );
         this.provider = Provider.getProvider( providerEnv );
-
-        Set<String> binaries;
-
-        if ( env.containsKey( BINARY_KEY ) )
-        {
-            Object val = env.get( BINARY_KEY );
-
-            if ( val == null )
-            {
-                if ( log.isWarnEnabled() )
-                {
-                    log.warn( "Null value for " + BINARY_KEY + " key in environment.  Using empty set for binaries." );
-                }
-                
-                binaries = EMPTY_SET_STRING;
-            }
-            else if ( val instanceof String )
-            {
-                // parse out all words based on expected JNDI format of this
-                // attribute
-                String binaryIds = ( String ) val;
-                binaries = new HashSet<String>();
-
-                if ( !StringTools.isEmpty( binaryIds ) )
-                {
-                    String[] binaryArray = binaryIds.split( " " );
-
-                    for ( String binary:binaryArray )
-                    {
-                        binaries.add( StringTools.lowerCaseAscii( StringTools.trim( binary ) ) );
-                    }
-                }
-            } // if already parsed and set as a collection use it
-            else if ( val instanceof Collection )
-            {
-                binaries = new HashSet<String>();
-                binaries.addAll( ( Set<String> ) val );
-            } // complain if it's something else
-            else
-            {
-                if ( log.isWarnEnabled() )
-                {
-                    log.warn( "Unrecognized value for " + BINARY_KEY
-                        + " key in environment.  Using empty set for binaries." );
-                }
-                
-                binaries = EMPTY_SET_STRING;
-            }
-        }
-        else
-        {
-            if ( log.isWarnEnabled() )
-            {
-                log.warn( "Could not find " + BINARY_KEY + " key in environment.  Using empty set for binaries." );
-            }
-            binaries = EMPTY_SET_STRING;
-        }
-
-        this.decoder = this.provider.getDecoder( binaries );
+        this.decoder = this.provider.getDecoder( binaryAttributeDetector );
         this.transformer = this.provider.getTransformer();
         this.decoder.setCallback( new DecoderCallback()
         {
             public void decodeOccurred( StatefulDecoder decoder, Object decoded )
             {
-            	if ( decoded instanceof Asn1Object )
-            	{
-            		cb.decodeOccurred( decoder, transformer.transform( decoded ) );
-            	}
-            	else
-            	{
-            		cb.decodeOccurred( decoder, decoded );
-            	}
+                if ( decoded instanceof Asn1Object )
+                {
+                    cb.decodeOccurred( decoder, transformer.transform( decoded ) );
+                }
+                else
+                {
+                    cb.decodeOccurred( decoder, decoded );
+                }
             }
         } );
     }
@@ -202,14 +124,13 @@
                 }
             }
         }
-        catch (Exception e) 
+        catch ( Exception e )
         {
-            throw (MessageException)e;
+            throw ( MessageException ) e;
         }
 
         // Call on transformer to convert stub based PDU into Message based PDU
-        Message message = transformer.transform( providerEnvelope );
-        return message;
+        return transformer.transform( providerEnvelope );
     }
 
 
@@ -240,8 +161,8 @@
             }
             else
             {
-            	// TODO : this is certainly not the way we should handle such an exception !
-            	throw new ResponseCarryingMessageException( e.getMessage() );
+                // TODO : this is certainly not the way we should handle such an exception !
+                throw new ResponseCarryingMessageException( e.getMessage() );
             }
         }
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageEncoder.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageEncoder.java
index 546a9cd..bdc4cfe 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageEncoder.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/MessageEncoder.java
@@ -22,7 +22,6 @@
 
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.util.Hashtable;
 
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.asn1.codec.stateful.EncoderCallback;
@@ -56,12 +55,9 @@
      * Creates a MessageEncoder using default properties for enabling a BER
      * library provider.
      * 
-     * @param env
-     *            The Map of environment parameters.
-     * @throws MessageException
-     *             if the encoder cannot be created.
+     * @throws MessageException if the encoder cannot be created.
      */
-    public MessageEncoder(final Hashtable env) throws MessageException
+    public MessageEncoder() throws MessageException
     {
         this.provider = Provider.getProvider( Provider.getEnvironment() );
         this.encoder = provider.getEncoder();
@@ -117,13 +113,11 @@
     // ------------------------------------------------------------------------
 
     /**
-     * Encodes a Message object peice by peice often emitting chunks of the
+     * Encodes a Message object piece by piece often emitting chunks of the
      * final PDU to the callback if present.
      * 
-     * @param obj
-     *            the message object to encode into a PDU
-     * @throws org.apache.directory.shared.asn1.codec.EncoderException
-     *             if there are problems while encodinggg
+     * @param obj the message object to encode into a PDU
+     * @throws EncoderException if there are problems while encoding
      */
     public void encode( Object obj ) throws EncoderException
     {
@@ -140,9 +134,7 @@
      * any special callbacks because when encoding we do not need to transform
      * before a value return as we did in the decoder.
      * 
-     * @param cb
-     *            the callback to set on the underlying provider specific
-     *            encoder
+     * @param cb the callback to set on the underlying provider specific encoder
      */
     public void setCallback( EncoderCallback cb )
     {
@@ -153,8 +145,7 @@
     /**
      * Sets the monitor of the underlying implementation.
      * 
-     * @param monitor
-     *            the monitor to set on the underlying implementation
+     * @param monitor the monitor to set on the underlying implementation
      */
     public void setEncoderMonitor( EncoderMonitor monitor )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModificationItemImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModificationItemImpl.java
index 776cce4..0176609 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModificationItemImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModificationItemImpl.java
@@ -41,12 +41,8 @@
 {
     private static final long serialVersionUID = 1L;
     
-    /** 
-     * A special flag set to false by default, used to indicate
-     * that some modification has been done by the server. Usefull
-     * for Operationnal Attributes.
-     */
-    private boolean modifiedByServer;
+    /** A flag set when the server has created this item */
+    private boolean serverModified;
 
     /**
      * Create a modificationItemImpl
@@ -59,7 +55,8 @@
     public ModificationItemImpl( int modificationOp, Attribute attribute ) 
     {
         super( modificationOp, AttributeUtils.toAttributeImpl( attribute ) );
-        modifiedByServer = false;
+        
+        serverModified = false;
     }
     
     /**
@@ -74,7 +71,8 @@
     {
         super( modification.getModificationOp(), 
             AttributeUtils.toAttributeImpl( modification.getAttribute() ) );
-        modifiedByServer = false;
+        
+        serverModified = false;
     }
     
     /**
@@ -85,7 +83,8 @@
     {
         super( modification.getModificationOp(), 
             AttributeUtils.toAttributeImpl( modification.getAttribute() ) );
-        modifiedByServer = false;
+        
+        serverModified = false;
     }
     
     /**
@@ -114,31 +113,30 @@
         return new ModificationItemImpl( getModificationOp(), (Attribute)getAttribute().clone() ); 
     }
     
-
+    
+    
     /**
      * 
-     * tells if the modification has been done by the server
+     * Tells if this modification has been created by the server or not
      *
-     * @return <code>true</code> if the server has modified this attribute
+     * @return <code>true</code> if the server has created this modifictionItem
      */
-    public boolean isModifiedByServer()
+    public boolean isServerModified()
     {
-        return modifiedByServer;
+        return serverModified;
     }
 
     
     /**
-     * 
-     * Method called when the server modifies an operationnal
-     * attribute, as we must protect the attribute from being
-     * checked by the SchemaService interceptor
+     * Set the serverModified item
      *
+     * @param serverModified 
      */
-    public void modifiedByServer()
+    public void setServerModified()
     {
-        modifiedByServer = true;
+        serverModified = true;
     }
-
+    
     
     /**
      * @see Object#toString()
@@ -149,9 +147,9 @@
         
         sb.append( "ModificationItem" );
         
-        if ( modifiedByServer )
+        if ( serverModified )
         {
-            sb.append( "[Op]" );
+            sb.append( "[op]" );
         }
         
         sb.append( " : \n" );
@@ -179,4 +177,53 @@
         
         return sb.toString();
     }
+    
+    
+    /**
+     * @see Object#hashCode()
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        int hash = 37;
+        
+        hash += hash*17 + getModificationOp();
+        hash += hash*17 + getAttribute().hashCode();
+        return hash;
+    }
+    
+    
+    /**
+     * @see Object#equals(Object)
+     */
+    public boolean equals( Object o )
+    {
+        // Basic equals checks
+        if ( this == o )
+        {
+            return true;
+        }
+        
+        if ( o == null )
+        {
+            return false;
+        }
+        
+        if ( ! (o instanceof ModificationItemImpl ) )
+        {
+            return false;
+        }
+        
+        ModificationItemImpl mod = (ModificationItemImpl)o;
+        
+        // Now, compares the modification content
+        // First, the modification type
+        if ( this.getModificationOp() != mod.getModificationOp() )
+        {
+            return false;
+        }
+        
+        // then the attribute
+        return this.getAttribute().equals( mod.getAttribute() );
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModifyRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModifyRequestImpl.java
index d582e11..2927e07 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModifyRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ModifyRequestImpl.java
@@ -275,14 +275,14 @@
 
             Set<Object> attrHash0 = new HashSet<Object>();
 
-            NamingEnumeration iter0 = attr0.getAll();
+            NamingEnumeration<?> iter0 = attr0.getAll();
 
             while ( iter0.hasMoreElements() )
             {
                 attrHash0.add( iter0.next() );
             }
 
-            NamingEnumeration iter1 = attr1.getAll();
+            NamingEnumeration<?> iter1 = attr1.getAll();
 
             while ( iter1.hasMoreElements() )
             {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/PersistentSearchControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/PersistentSearchControl.java
index 553ee6e..df76ea9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/PersistentSearchControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/PersistentSearchControl.java
@@ -22,7 +22,7 @@
 
 import org.apache.directory.shared.asn1.codec.EncoderException;
 import org.apache.directory.shared.ldap.codec.search.controls.ChangeType;
-import org.apache.directory.shared.ldap.codec.search.controls.PSearchControl;
+import org.apache.directory.shared.ldap.codec.search.controls.PSearchControlCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -126,7 +126,7 @@
 
     public byte[] getEncodedValue()
     {
-        PSearchControl psearchCtl = new PSearchControl();
+        PSearchControlCodec psearchCtl = new PSearchControlCodec();
         psearchCtl.setChangesOnly( isChangesOnly() );
         psearchCtl.setChangeTypes( getChangeTypes() );
         psearchCtl.setReturnECs( isReturnECs() );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/Referral.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/Referral.java
index 5c2ffd2..e327c93 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/Referral.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/Referral.java
@@ -93,7 +93,7 @@
      * 
      * @return the alternative url objects.
      */
-    Collection getLdapUrls();
+    Collection<String> getLdapUrls();
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ReferralImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ReferralImpl.java
index 92de866..846a720 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ReferralImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ReferralImpl.java
@@ -52,7 +52,7 @@
      * 
      * @return the alternative url objects.
      */
-    public Collection getLdapUrls()
+    public Collection<String> getLdapUrls()
     {
         return Collections.unmodifiableCollection( urls );
     }
@@ -102,7 +102,7 @@
 
         if ( obj instanceof Referral )
         {
-            Collection refs = ( ( Referral ) obj ).getLdapUrls();
+            Collection<String> refs = ( ( Referral ) obj ).getLdapUrls();
 
             // if their sizes do not match they are not equal
             if ( refs.size() != urls.size() )
@@ -110,7 +110,8 @@
                 return false;
             }
 
-            Iterator list = urls.iterator();
+            Iterator<String> list = urls.iterator();
+            
             while ( list.hasNext() )
             {
                 // if one of our urls is not contained in the obj return false
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequest.java
index aa79cc0..6110abb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequest.java
@@ -93,16 +93,16 @@
      * 
      * @return the alias handling parameter enumeration.
      */
-    DerefAliasesEnum getDerefAliases();
+    AliasDerefMode getDerefAliases();
 
 
     /**
      * Sets the alias handling parameter.
      * 
-     * @param derefAliases
+     * @param aliasDerefAliases
      *            the alias handling parameter enumeration.
      */
-    void setDerefAliases( DerefAliasesEnum derefAliases );
+    void setDerefAliases( AliasDerefMode aliasDerefAliases );
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java
index 13df8a8..21eb0ba 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SearchRequestImpl.java
@@ -61,7 +61,7 @@
     private int timeLimit;
 
     /** Alias dereferencing mode enumeration value */
-    private DerefAliasesEnum derefAliases;
+    private AliasDerefMode aliasDerefMode;
 
     /** Attributes to return */
     private List<String> attributes = new ArrayList<String>();
@@ -147,21 +147,21 @@
      * 
      * @return the alias handling parameter enumeration.
      */
-    public DerefAliasesEnum getDerefAliases()
+    public AliasDerefMode getDerefAliases()
     {
-        return derefAliases;
+        return aliasDerefMode;
     }
 
 
     /**
      * Sets the alias handling parameter.
      * 
-     * @param derefAliases
+     * @param aliasDerefAliases
      *            the alias handling parameter enumeration.
      */
-    public void setDerefAliases( DerefAliasesEnum derefAliases )
+    public void setDerefAliases( AliasDerefMode aliasDerefAliases )
     {
-        this.derefAliases = derefAliases;
+        this.aliasDerefMode = aliasDerefAliases;
     }
 
 
@@ -381,7 +381,7 @@
             return false;
         }
 
-        if ( req.getDerefAliases() != derefAliases )
+        if ( req.getDerefAliases() != aliasDerefMode )
         {
             return false;
         }
@@ -429,7 +429,8 @@
                 return false;
             }
 
-            Iterator list = attributes.iterator();
+            Iterator<String> list = attributes.iterator();
+            
             while ( list.hasNext() )
             {
                 if ( !req.getAttributes().contains( list.next() ) )
@@ -487,6 +488,8 @@
         
         sb.append( "        typesOnly : " ).append( typesOnly ).append( '\n' );
 
+        sb.append( "        Size Limit : " );
+
         if ( sizeLimit == 0 )
         {
             sb.append( "no limit" );
@@ -513,7 +516,7 @@
 
         sb.append( "        Deref Aliases : " );
 
-        switch ( derefAliases.getValue() )
+        switch ( aliasDerefMode.getValue() )
         {
             case LdapConstants.NEVER_DEREF_ALIASES:
                 sb.append( "never Deref Aliases" );
@@ -539,7 +542,7 @@
 
         if ( attributes != null )
         {
-            Iterator it = attributes.iterator();
+            Iterator<String> it = attributes.iterator();
             
             while ( it.hasNext() )
             {
@@ -552,7 +555,7 @@
                     sb.append( ", " );
                 }
                 
-                sb.append( '\'' ).append( (String)it.next() ).append( '\'' );
+                sb.append( '\'' ).append( it.next() ).append( '\'' );
             }
             
         }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ServerSearchResult.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/ServerSearchResult.java
deleted file mode 100644
index a589a74..0000000
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/ServerSearchResult.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-package org.apache.directory.shared.ldap.message;
-
-
-import javax.naming.InvalidNameException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.SearchResult;
-
-import org.apache.directory.shared.ldap.name.LdapDN;
-
-/**
- * Creates a wrapper around a SearchResult object so that we can use the LdapDN
- * instead of parser it over and over
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
- */
-public class ServerSearchResult extends SearchResult
-{
-    /** Unique serial UID */
-    public static final long serialVersionUID = 1L;
-
-    /** Distinguished name for this result */
-    private LdapDN dn;
-    
-    /**
-     * @see javax.naming.directory.SearchResult#SearchResult(String, Object, Attributes)
-     */
-    public ServerSearchResult( String name, Object obj, Attributes attrs ) throws InvalidNameException
-    {
-        super( name, obj, attrs );
-        dn = new LdapDN( name );
-    }
-
-
-    /**
-     * @see javax.naming.directory.SearchResult#SearchResult(String, Object, Attributes)
-     */
-    public ServerSearchResult( String name, Object obj, Attributes attrs, boolean isRelative ) throws InvalidNameException
-    {
-        super( name, obj, attrs, isRelative );
-        dn = new LdapDN( name );
-    }
-
-
-    /**
-     * @see javax.naming.directory.SearchResult#SearchResult(String, Object, Attributes)
-     */
-    public ServerSearchResult( String name, String className, Object obj, Attributes attrs ) throws InvalidNameException
-    {
-        super( name, className, obj, attrs );
-        dn = new LdapDN( name );
-    }
-
-
-    /**
-     * @see javax.naming.directory.SearchResult#SearchResult(String, String, Object, Attributes, boolean)
-     */
-    public ServerSearchResult( String name, String className, Object obj, Attributes attrs, boolean isRelative ) throws InvalidNameException
-    {
-        super( name, className, obj, attrs, isRelative );
-        dn = new LdapDN( name );
-    }
-
-
-    /**
-     * @return The result DN
-     */
-    public LdapDN getDn()
-    {
-        return dn;
-    }
-}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SubentriesControl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SubentriesControl.java
index 938d021..0349678 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/SubentriesControl.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/SubentriesControl.java
@@ -21,7 +21,7 @@
 
 
 import org.apache.directory.shared.asn1.codec.EncoderException;
-import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControl;
+import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlCodec;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -100,7 +100,7 @@
 
     public byte[] getEncodedValue()
     {
-        SubEntryControl ctl = new SubEntryControl();
+        SubEntryControlCodec ctl = new SubEntryControlCodec();
         ctl.setVisibility( isVisible() );
 
         try
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulDisconnect.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulDisconnect.java
index 46fdff6..a295454 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulDisconnect.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulDisconnect.java
@@ -71,7 +71,13 @@
     public GracefulDisconnect(byte[] value) throws DecoderException
     {
         super( 0, EXTENSION_OID );
-        this.value = value;
+        if ( value != null )
+        {
+            this.value = new byte[ value.length ];
+            System.arraycopy( value, 0, this.value, 0, value.length );
+        } else {
+            this.value = null;
+        }
         decodeValue();
     }
 
@@ -107,7 +113,8 @@
             this.timeOffline = codec.getTimeOffline();
             this.delay = codec.getDelay();
             super.getLdapResult().setResultCode( ResultCodeEnum.SUCCESS );
-            List contexts = codec.getReplicatedContexts();
+            List<LdapURL> contexts = codec.getReplicatedContexts();
+            
             for ( int ii = 0; ii < contexts.size(); ii++ )
             {
                 replicatedContexts.addLdapUrl( contexts.get( ii ).toString() );
@@ -126,7 +133,8 @@
         org.apache.directory.shared.ldap.codec.extended.operations.GracefulDisconnect codec = new org.apache.directory.shared.ldap.codec.extended.operations.GracefulDisconnect();
         codec.setTimeOffline( this.timeOffline );
         codec.setDelay( this.delay );
-        Iterator contexts = this.replicatedContexts.getLdapUrls().iterator();
+        Iterator<String> contexts = this.replicatedContexts.getLdapUrls().iterator();
+        
         while ( contexts.hasNext() )
         {
             String urlstr = ( String ) contexts.next();
@@ -170,7 +178,10 @@
         {
             encodeResponse();
         }
-        return value;
+
+        final byte[] copy = new byte[ value.length ];
+        System.arraycopy( value, 0, copy, 0, value.length );
+        return copy;
     }
 
 
@@ -198,14 +209,21 @@
             .getGracefulDisconnect();
         this.delay = codec.getDelay();
         this.timeOffline = codec.getTimeOffline();
-        List contexts = codec.getReplicatedContexts();
+        List<LdapURL> contexts = codec.getReplicatedContexts();
+        
         for ( int ii = 0; ii < contexts.size(); ii++ )
         {
-            LdapURL url = ( LdapURL ) contexts.get( ii );
+            LdapURL url = contexts.get( ii );
             replicatedContexts.addLdapUrl( url.toString() );
         }
 
-        this.value = value;
+        if ( value != null )
+        {
+            this.value = new byte[ value.length ];
+            System.arraycopy( value, 0, this.value, 0, value.length );
+        } else {
+            this.value = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulShutdownRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulShutdownRequest.java
index 717059a..9ae2ac4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulShutdownRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/GracefulShutdownRequest.java
@@ -95,7 +95,13 @@
         try
         {
             GracefulShutdown gs = ( GracefulShutdown ) decoder.decode( payload );
-            this.payload = payload;
+            if ( payload != null )
+            {
+                this.payload = new byte[ payload.length ];
+                System.arraycopy( payload, 0, this.payload, 0, payload.length );
+            } else {
+                this.payload = null;
+            }
             this.timeOffline = gs.getTimeOffline();
             this.delay = gs.getDelay();
         }
@@ -135,7 +141,14 @@
             }
         }
 
-        return payload;
+        if ( payload == null )
+        {
+            return null;
+        }
+
+        final byte[] copy = new byte[ payload.length ];
+        System.arraycopy( payload, 0, copy, 0, payload.length );
+        return copy;
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/StoredProcedureRequest.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/StoredProcedureRequest.java
index 581f2be..a5dd6bf 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/StoredProcedureRequest.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/extended/StoredProcedureRequest.java
@@ -98,9 +98,9 @@
     public ExtendedResponse createExtendedResponse( String id, byte[] berValue, int offset, int length )
         throws NamingException
     {
-    	StoredProcedureResponse resp = ( StoredProcedureResponse ) getResultResponse();
-    	resp.setResponse( berValue );
-    	resp.setOid( id );
+        StoredProcedureResponse resp = ( StoredProcedureResponse ) getResultResponse();
+        resp.setResponse( berValue );
+        resp.setOid( id );
         return resp;
     }
 
@@ -189,7 +189,7 @@
     }
     
     
-    public Class getJavaParameterType( int index )
+    public Class<?> getJavaParameterType( int index )
     {
         throw new NotImplementedException( "class loading of procedure type not implemented" );
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/BinaryAttributeDetector.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/BinaryAttributeDetector.java
new file mode 100644
index 0000000..55b3245
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/BinaryAttributeDetector.java
@@ -0,0 +1,37 @@
+/*

+ *  Licensed to the Apache Software Foundation (ASF) under one

+ *  or more contributor license agreements.  See the NOTICE file

+ *  distributed with this work for additional information

+ *  regarding copyright ownership.  The ASF licenses this file

+ *  to you under the Apache License, Version 2.0 (the

+ *  "License"); you may not use this file except in compliance

+ *  with the License.  You may obtain a copy of the License at

+ *

+ *    http://www.apache.org/licenses/LICENSE-2.0

+ *

+ *  Unless required by applicable law or agreed to in writing,

+ *  software distributed under the License is distributed on an

+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ *  KIND, either express or implied.  See the License for the

+ *  specific language governing permissions and limitations

+ *  under the License.

+ *

+ */

+package org.apache.directory.shared.ldap.message.spi;

+

+

+

+/**

+ * An interface used to abstract the means to detect whether or not an attribute

+ * identifier/descriptor represents a binary attributeType.

+ */

+public interface BinaryAttributeDetector

+{

+    /**

+     * Returns true if the attribute specified is not human readible.

+     *

+     * @param attributeId the identifier/descriptor for the attribute to be checked.

+     * @return true if the attribute specified is not human readible, false otherwise

+     */

+    boolean isBinary( String attributeId );

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/Provider.java b/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/Provider.java
index 5a6e9f9..4ec3296 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/Provider.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/message/spi/Provider.java
@@ -25,7 +25,6 @@
 
 import java.util.Properties;
 import java.util.Hashtable;
-import java.util.Set;
 
 
 /**
@@ -55,7 +54,7 @@
         + System.getProperty( "java.home" ) + "\n\tjava.class.path = " + System.getProperty( "java.class.path" );
 
     /** Use the no-op monitor by default unless we find something else */
-    private static ProviderMonitor monitor = null;
+    private static ProviderMonitor monitor;
 
     static
     {
@@ -75,7 +74,7 @@
 
             if ( fqcn != null )
             {
-                Class mc;
+                Class<?> mc;
 
                 try
                 {
@@ -127,7 +126,7 @@
      * @param vendor
      *            the berlib vendor used by the provider
      */
-    protected Provider(String name, String vendor)
+    protected Provider( String name, String vendor )
     {
         this.name = name;
         this.vendor = vendor;
@@ -175,10 +174,11 @@
      * Gets the decoder associated with this provider.
      * 
      * @return the provider's decoder.
-     * @throws ProviderException
-     *             if the provider or its decoder cannot be found
+     * @throws ProviderException if the provider or its decoder cannot be found
+     * @param binaryAttributeDetector detects whether or not attributes are binary
      */
-    public abstract ProviderDecoder getDecoder( Set binaries ) throws ProviderException;
+    public abstract ProviderDecoder getDecoder( BinaryAttributeDetector binaryAttributeDetector )
+            throws ProviderException;
 
 
     /**
@@ -195,6 +195,7 @@
     // Factory/Environment Methods
     // ------------------------------------------------------------------------
 
+    
     /**
      * Gets an instance of the configured Provider. The configured provider is
      * the classname specified by the <code>asn.1.berlib.provider</code>
@@ -219,16 +220,16 @@
      * property value. The property is searched for within properties object
      * passed in as a parameter for this method only.
      * 
-     * @param a_env
+     * @param env
      *            the environment used to locate the provider
      * @return a singleton instance of the ASN.1 BER Library Provider
      * @throws ProviderException
      *             if the provider cannot be found
      */
-    public static Provider getProvider( Hashtable a_env ) throws ProviderException
+    public static Provider getProvider( Hashtable<Object, Object> env ) throws ProviderException
     {
         Provider provider;
-        String className = ( String ) a_env.get( BERLIB_PROVIDER );
+        String className = ( String ) env.get( BERLIB_PROVIDER );
 
         // --------------------------------------------------------------------
         // Check for a valid property value
@@ -241,7 +242,7 @@
 
         try
         {
-            Class clazz = Class.forName( className );
+            Class<?> clazz = Class.forName( className );
             Method method = clazz.getMethod( "getProvider", (Class[])null );
             provider = ( Provider ) method.invoke( null, (Object[])null );
         }
@@ -296,7 +297,6 @@
         Properties env = new Properties();
         env.setProperty( BERLIB_PROVIDER, DEFAULT_PROVIDER );
         monitor.usingDefaults( USING_DEFAULTS_MSG, env );
-
         return env;
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/AtavSerializer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/AtavSerializer.java
new file mode 100644
index 0000000..d026f54
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/AtavSerializer.java
@@ -0,0 +1,186 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.name;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class which serialize and deserialize an AttributeTypeAndValue
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class AtavSerializer
+{
+    /** The LoggerFactory used by this class */
+    protected static final Logger LOG = LoggerFactory.getLogger( AtavSerializer.class );
+
+    /**
+     * Serialize an AttributeTypeAndValue object.
+     * 
+     * An AttributeTypeAndValue is composed of  a type and a value.
+     * The data are stored following the structure :
+     * 
+     * <li>upName</li> The User provided ATAV
+     * <li>start</li> The position of this ATAV in the DN
+     * <li>length</li> The ATAV length
+     * <li>upType</li> The user Provided Type
+     * <li>normType</li> The normalized AttributeType
+     * <li>isHR<li> Tells if the value is a String or not
+     * <p>
+     * if the value is a String :
+     * <li>upValue</li> The User Provided value.
+     * <li>value</li> The normalized value.
+     * <p>
+     * if the value is binary :
+     * <li>upValueLength</li>
+     * <li>upValue</li> The User Provided value.
+     * <li>valueLength</li>
+     * <li>value</li> The normalized value.
+     *
+     * @param atav the AttributeTypeAndValue to serialize
+     * @param out the OutputStream in which the atav will be serialized
+     * @throws IOException If we can't serialize the atav
+     */
+    public static void serialize( AttributeTypeAndValue atav, ObjectOutput out ) throws IOException
+    {
+        if ( StringTools.isEmpty( atav.getUpName() ) || 
+             StringTools.isEmpty( atav.getUpType() ) ||
+             StringTools.isEmpty( atav.getNormType() ) ||
+             ( atav.getStart() < 0 ) ||
+             ( atav.getLength() < 2 ) ||             // At least a type and '='
+             ( atav.getUpValue() == null ) ||
+             ( atav.getNormValue() == null ) )
+        {
+            String message = "Cannot serialize an wrong ATAV, ";
+            
+            if ( StringTools.isEmpty( atav.getUpName() ) )
+            {
+                message += "the upName should not be null or empty";
+            }
+            else if ( StringTools.isEmpty( atav.getUpType() ) )
+            {
+                message += "the upType should not be null or empty";
+            }
+            else if ( StringTools.isEmpty( atav.getNormType() ) )
+            {
+                message += "the normType should not be null or empty";
+            }
+            else if ( atav.getStart() < 0 )
+            {
+                message += "the start should not be < 0";
+            }
+            else if ( atav.getLength() < 2 )
+            {
+                message += "the length should not be < 2";
+            }
+            else if ( atav.getUpValue() == null )
+            {
+                message += "the upValue should not be null";
+            }
+            else if ( atav.getNormValue() == null )
+            {
+                message += "the value should not be null";
+            }
+                
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        out.writeUTF( atav.getUpName() );
+        out.writeInt( atav.getStart() );
+        out.writeInt( atav.getLength() );
+        out.writeUTF( atav.getUpType() );
+        out.writeUTF( atav.getNormType() );
+        
+        boolean isHR = ( atav.getNormValue() instanceof String );
+        
+        out.writeBoolean( isHR );
+        
+        if ( isHR )
+        {
+            out.writeUTF( (String)atav.getUpValue() );
+            out.writeUTF( (String)atav.getNormValue() );
+        }
+        else
+        {
+            out.writeInt( ((byte[])atav.getUpValue()).length );
+            out.write( (byte[])atav.getUpValue() );
+            out.writeInt( ((byte[])atav.getNormValue()).length );
+            out.write( (byte[])atav.getNormValue() );
+        }
+        
+        out.flush();
+    }
+    
+    
+    /**
+     * Deserialize an AttributeTypeAndValue object
+     * 
+     * We read back the data to create a new ATAV. The structure 
+     * read is exposed in the {@link AttributeTypeAndValue#writeExternal(ObjectOutput)} 
+     * method<p>
+     * 
+     * @param in the input stream
+     * @throws IOException If the input stream can't be read
+     * @return The constructed AttributeTypeAndValue
+     */
+    public static AttributeTypeAndValue deserialize( ObjectInput in ) throws IOException
+    {
+        String upName = in.readUTF();
+        int start = in.readInt();
+        int length = in.readInt();
+        String upType = in.readUTF();
+        String normType = in.readUTF();
+        
+        boolean isHR = in.readBoolean();
+        
+        if ( isHR )
+        {
+            String upValue = in.readUTF();
+            String normValue = in.readUTF();
+            AttributeTypeAndValue atav = 
+                new AttributeTypeAndValue( upType, normType, upValue, normValue, start, length, upName );
+            
+            return atav;
+        }
+        else
+        {
+            int upValueLength = in.readInt();
+            byte[] upValue = new byte[upValueLength];
+            in.readFully( upValue );
+
+            int valueLength = in.readInt();
+            byte[] normValue = new byte[valueLength];
+            in.readFully( normValue );
+
+            AttributeTypeAndValue atav = 
+                new AttributeTypeAndValue( upType, normType, upValue, normValue, start, length, upName );
+            
+            return atav;
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValue.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValue.java
index 327ac92..ba3bade 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValue.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValue.java
@@ -20,11 +20,15 @@
 package org.apache.directory.shared.ldap.name;
 
 
-import java.io.Serializable;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Arrays;
 
 import javax.naming.InvalidNameException;
 
+import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,8 +48,9 @@
  * called upName.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
-public class AttributeTypeAndValue implements Cloneable, Comparable, Serializable
+public class AttributeTypeAndValue implements Cloneable, Comparable, Externalizable
 {
     /**
      * Declares the Serial Version Uid.
@@ -57,17 +62,16 @@
     private static final long serialVersionUID = 1L;
 
     /** The LoggerFactory used by this class */
-    private static Logger log = LoggerFactory.getLogger( AttributeTypeAndValue.class );
+    private static Logger LOG = LoggerFactory.getLogger( AttributeTypeAndValue.class );
 
     /** The normalized Name type */
     private String normType;
 
     /** The user provided Name type */
     private String upType;
-    
 
     /** The name value. It can be a String or a byte array */
-    private Object value;
+    private Object normValue;
 
     /** The name user provided value. It can be a String or a byte array */
     private Object upValue;
@@ -95,7 +99,7 @@
     {
         normType = null;
         upType = null;
-        value = null;
+        normValue = null;
         upValue = null;
         upName = "";
         start = -1;
@@ -105,42 +109,128 @@
 
     /**
      * Construct an AttributeTypeAndValue. The type and value are normalized :
-     * - the type is trimmed and lowercased
-     * - the value is trimmed
+     * <li> the type is trimmed and lowercased </li>
+     * <li> the value is trimmed </li>
+     * <p>
+     * Note that the upValue should <b>not</b> be null or empty, or resolved
+     * to an empty string after having trimmed it. 
      *
-     * @param type
-     *            The type
-     * @param value
-     *            the value
+     * @param upType The Usrr Provided type
+     * @param normType The normalized type
+     * @param upValue The User Provided value
+     * @param normValue The normalized value
      */
-    public AttributeTypeAndValue( String upType, String type, Object upValue, Object value ) throws InvalidNameException
+    public AttributeTypeAndValue( String upType, String normType, Object upValue, Object normValue ) throws InvalidNameException
     {
-        if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) )
+        String upTypeTrimmed = StringTools.trim( upType );
+        String normTypeTrimmed = StringTools.trim( normType );
+        
+        if ( StringTools.isEmpty( upTypeTrimmed ) )
         {
-            log.error( "The type cannot be empty or null" );
-            throw new InvalidNameException( "Null or empty type is not allowed" );
+            if ( StringTools.isEmpty( normTypeTrimmed ) )
+            {
+                String message =  "The type cannot be empty or null";
+                LOG.error( message );
+                throw new InvalidNameException( message );
+            }
+            else
+            {
+                // In this case, we will use the normType instead
+                this.normType = StringTools.lowerCaseAscii( normTypeTrimmed );
+                this.upType = normType;
+            }
         }
-
-        normType = StringTools.lowerCaseAscii( type.trim() );
-        this.upType = upType;
-        this.upValue = upValue;
-
-        if ( value instanceof String )
+        else if ( StringTools.isEmpty( normTypeTrimmed ) )
         {
-            this.value = StringTools.isEmpty( ( String ) value ) ? "" : value;
+            // In this case, we will use the upType instead
+            this.normType = StringTools.lowerCaseAscii( upTypeTrimmed );
+            this.upType = upType;
         }
         else
         {
-            this.value = value;
+            this.normType = StringTools.lowerCaseAscii( normTypeTrimmed );
+            this.upType = upType;
+            
+        }
+            
+
+        if ( ( normValue == null ) || ( upValue == null ) )
+        {
+            if ( normValue instanceof String )
+            {
+                this.normValue = StringTools.isEmpty( ( String ) normValue ) ? "" : normValue;
+            }
+            else
+            {
+                this.normValue = normValue;
+            }
+
+            if ( upValue instanceof String )
+            {
+                this.upValue = StringTools.isEmpty( ( String ) upValue ) ? "" : upValue;
+            }
+            else
+            {
+                this.upValue = upValue;
+            }
+        }
+        else
+        {
+    
+            this.upValue = upValue;
+    
+            if ( normValue instanceof String )
+            {
+                this.normValue = StringTools.isEmpty( ( String ) normValue ) ? "" : normValue;
+            }
+            else
+            {
+                this.normValue = normValue;
+            }
         }
 
-        upName = upType + '=' + upValue;
+        upName = this.upType + '=' + ( this.upValue == null ? "" : this.upValue );
         start = 0;
         length = upName.length();
     }
 
 
     /**
+     * Construct an AttributeTypeAndValue. The type and value are normalized :
+     * <li> the type is trimmed and lowercased </li>
+     * <li> the value is trimmed </li>
+     * <p>
+     * Note that the upValue should <b>not</b> be null or empty, or resolved
+     * to an empty string after having trimmed it. 
+     *
+     * @param upType The User Provided type
+     * @param normType The normalized type
+     * @param upValue The User Provided value
+     * @param normValue The normalized value
+     * @param start Start of this ATAV in the RDN
+     * @param length Length of this ATAV
+     * @param upName The user provided name
+     */
+    /**No protection*/ AttributeTypeAndValue( 
+                            String upType, 
+                            String normType, 
+                            Object upValue, 
+                            Object normValue,
+                            int start, 
+                            int length, 
+                            String upName )
+    {
+        this.upType = upType;
+        this.normType = normType;
+        this.upValue = upValue;
+        this.normValue = normValue;
+        this.start = start;
+        this.length = length;
+        this.upName = upName;
+    }
+
+    
+    /**
      * Get the normalized type of a AttributeTypeAndValue
      *
      * @return The normalized type
@@ -162,22 +252,42 @@
 
 
     /**
-     * Store the type
+     * Store a new type
      *
-     * @param type
-     *            The AttributeTypeAndValue type
+     * @param upType The AttributeTypeAndValue User Provided type
+     * @param type The AttributeTypeAndValue type
+     * 
+     * @throws InvalidNameException if the type or upType are empty or null.
+     * If the upName is invalid.
      */
     public void setType( String upType, String type ) throws InvalidNameException
     {
         if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) )
         {
-            log.error( "The type cannot be empty or null" );
-            throw new InvalidNameException( "The AttributeTypeAndValue type cannot be null or empty " );
+            String message = "The type cannot be empty or null";
+            LOG.error( message );
+            throw new InvalidNameException( message );
+        }
+        
+        if ( StringTools.isEmpty( upType ) || StringTools.isEmpty( upType.trim() ) )
+        {
+            String message = "The User Provided type cannot be empty or null";
+            LOG.error( message );
+            throw new InvalidNameException( message );
+        }
+        
+        int equalPosition = upName.indexOf( '=' );
+        
+        if ( equalPosition <= 1 )
+        {
+            String message = "The User provided name does not contains an '='"; 
+            LOG.error( message );
+            throw new InvalidNameException( message );
         }
 
         normType = type.trim().toLowerCase();
         this.upType = upType;
-        upName = upType + upName.substring( upName.indexOf( '=' ) );
+        upName = upType + upName.substring( equalPosition );
         start = -1;
         length = upName.length();
     }
@@ -193,7 +303,7 @@
     {
         if ( StringTools.isEmpty( type ) || StringTools.isEmpty( type.trim() ) )
         {
-            log.error( "The type cannot be empty or null" );
+            LOG.error( "The type cannot be empty or null" );
             throw new InvalidNameException( "The AttributeTypeAndValue type cannot be null or empty " );
         }
 
@@ -210,9 +320,9 @@
      *
      * @return The value
      */
-    public Object getValue()
+    public Object getNormValue()
     {
-        return value;
+        return normValue;
     }
 
     /**
@@ -239,18 +349,18 @@
     /**
      * Store the value of a AttributeTypeAndValue.
      *
-     * @param value
-     *            The value of the AttributeTypeAndValue
+     * @param value The user provided value of the AttributeTypeAndValue
+     * @param normValue The normalized value
      */
-    public void setValue( Object upValue, Object value )
+    public void setValue( Object upValue, Object normValue )
     {
-        if ( value instanceof String )
+        if ( normValue instanceof String )
         {
-            this.value = StringTools.isEmpty( ( String ) value ) ? "" : ( String ) value;
+            this.normValue = StringTools.isEmpty( ( String ) normValue ) ? "" : ( String ) normValue;
         }
         else
         {
-            this.value = value;
+            this.normValue = normValue;
         }
 
         this.upValue = upValue;
@@ -305,11 +415,11 @@
 
         if ( StringTools.isEmpty( newValue ) )
         {
-            this.value = "";
+            this.normValue = "";
         }
         else
         {
-            this.value = newValue;
+            this.normValue = newValue;
         }
 
         upName = upName.substring( 0, upName.indexOf( '=' ) + 1 ) + value;
@@ -337,8 +447,9 @@
 
 
     /**
-     * Compares two NameComponents. They are equals if : - types are equals,
-     * case insensitive, - values are equals, case sensitive
+     * Compares two NameComponents. They are equals if : 
+     * - types are equals, case insensitive, 
+     * - values are equals, case sensitive
      *
      * @param object
      * @return 0 if both NC are equals, otherwise a positive value if the
@@ -359,7 +470,7 @@
             }
             else
             {
-                return compareValue( value, nc.value, CASE_SENSITIVE );
+                return compareValue( normValue, nc.normValue, CASE_SENSITIVE );
             }
         }
         else
@@ -370,8 +481,9 @@
 
 
     /**
-     * Compares two NameComponents. They are equals if : - types are equals,
-     * case insensitive, - values are equals, case insensitive
+     * Compares two NameComponents. They are equals if : 
+     * - types are equals, case insensitive, 
+     * - values are equals, case insensitive
      *
      * @param object
      * @return 0 if both NC are equals, otherwise a positive value if the
@@ -392,7 +504,7 @@
             }
             else
             {
-                return compareValue( value, nc.value, CASE_INSENSITIVE );
+                return compareValue( normValue, nc.normValue, CASE_INSENSITIVE );
             }
         }
         else
@@ -431,11 +543,11 @@
     /**
      * Compare two values
      *
-     * @param val1
-     *            First String
-     * @param val2
-     *            Second String
-     * @return true if both strings are equals or null.
+     * @param val1 First value
+     * @param val2 Second value
+     * @param sensitivity A flag to define the case sensitivity
+     * @return -1 if the first value is inferior to the second one, +1 if
+     * its superior, 0 if both values are equal
      */
     private int compareValue( Object val1, Object val2, boolean sensitivity )
     {
@@ -499,107 +611,107 @@
      */
     public String normalize()
     {
-        if ( value instanceof String )
+        if ( normValue instanceof String )
         {
-        	// The result will be gathered in a stringBuilder
+            // 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;
+            String normalizedValue =  ( String ) normValue;
             int valueLength = normalizedValue.length();
             boolean escaped = false;
             
             if ( normalizedValue.length() > 0 )
             {
-            	char[] chars = normalizedValue.toCharArray();
+                char[] chars = normalizedValue.toCharArray();
 
-            	// Loop first assuming the DN won't contain any
-            	// char needing to be escaped. This is the case
-            	// for 99.99% of all DN (blind bet, of course ...) 
-            	for ( char c:chars )
-            	{
+                // Loop first assuming the DN won't contain any
+                // char needing to be escaped. This is the case
+                // for 99.99% of all DN (blind bet, of course ...) 
+                for ( char c:chars )
+                {
                     if ( ( c < 0) || ( c > 128 ) )
                     {
-                    	escaped = true;
-                    	break;
+                        escaped = true;
+                        break;
                     }
                     else if ( DN_ESCAPED_CHARS[ c ] )
                     {
-                    	escaped = true;
-                    	break;
+                        escaped = true;
+                        break;
                     }
-            	}
+                }
 
-            	// Here, we have a char to escape. Start again the loop...
-            	if ( escaped )
-            	{
-	                for ( int i = 0; i < valueLength; i++ )
-	                {
-	                    char c = chars[i];
-	                    
-	                    if ( ( c < 0) || ( c > 128 ) )
-	                    {
-		                    // For chars which are not ASCII, use their hexa value prefixed by an '\'
-	                        byte[] bb = StringTools.getBytesUtf8( normalizedValue.substring( i, i + 1 ) );
-	                        
-	                        for ( byte b:bb )
-	                        {
-	                            sb.append( '\\' ).
-	                                append( StringTools.dumpHex( (byte)(( b & 0x00F0 ) >> 4) ) ).
-	                                append( StringTools.dumpHex( b ) );
-	                        }
-	                    }
-	                    else if ( DN_ESCAPED_CHARS[ c ] ) 
-	                    {
-	                    	// Some chars need to be escaped even if they are US ASCII
-	                    	// Just prefix them with a '\'
-	                    	// Special cases are ' ' (space), '#') which need a special
-	                    	// treatment.
-	                        if ( c == ' ' )
-	                        {
-	                            if ( ( i == 0 ) || ( i == valueLength - 1 ) )
-	                            {
-	                                sb.append( '\\' ).append(  c  );
-	                            }
-	                            else
-	                            {
-	                                sb.append( ' ' );
-	                            }
-	
-	                            continue;
-	                        }
-	                        else if ( c == '#' )
-	                        {
-	                            if ( i == 0 )
-	                            {
-	                                sb.append( "\\#" );
-	                                continue;
-	                            }
-	                            else
-	                            {
-	                                sb.append( '#' );
-	                            }
-	                            
-	                            continue;
-	                        }
-	
-	                        sb.append( '\\' ).append( c );
-	                    }
-	                    else
-	                    {
-	                    	// Standard ASCII chars are just appended
-	                        sb.append( c );
-	                    }
-	                }
-	            }
-            	else
-            	{
-            		// The String does not contain any escaped char : 
-            		// just append it. 
-            		sb.append( normalizedValue );
-            	}
+                // Here, we have a char to escape. Start again the loop...
+                if ( escaped )
+                {
+                    for ( int i = 0; i < valueLength; i++ )
+                    {
+                        char c = chars[i];
+                        
+                        if ( ( c < 0) || ( c > 128 ) )
+                        {
+                            // For chars which are not ASCII, use their hexa value prefixed by an '\'
+                            byte[] bb = StringTools.getBytesUtf8( normalizedValue.substring( i, i + 1 ) );
+                            
+                            for ( byte b:bb )
+                            {
+                                sb.append( '\\' ).
+                                    append( StringTools.dumpHex( (byte)(( b & 0x00F0 ) >> 4) ) ).
+                                    append( StringTools.dumpHex( b ) );
+                            }
+                        }
+                        else if ( DN_ESCAPED_CHARS[ c ] ) 
+                        {
+                            // Some chars need to be escaped even if they are US ASCII
+                            // Just prefix them with a '\'
+                            // Special cases are ' ' (space), '#') which need a special
+                            // treatment.
+                            if ( c == ' ' )
+                            {
+                                if ( ( i == 0 ) || ( i == valueLength - 1 ) )
+                                {
+                                    sb.append( '\\' ).append(  c  );
+                                }
+                                else
+                                {
+                                    sb.append( ' ' );
+                                }
+    
+                                continue;
+                            }
+                            else if ( c == '#' )
+                            {
+                                if ( i == 0 )
+                                {
+                                    sb.append( "\\#" );
+                                    continue;
+                                }
+                                else
+                                {
+                                    sb.append( '#' );
+                                }
+                                
+                                continue;
+                            }
+    
+                            sb.append( '\\' ).append( c );
+                        }
+                        else
+                        {
+                            // Standard ASCII chars are just appended
+                            sb.append( c );
+                        }
+                    }
+                }
+                else
+                {
+                    // The String does not contain any escaped char : 
+                    // just append it. 
+                    sb.append( normalizedValue );
+                }
             }
             
             return sb.toString();
@@ -607,7 +719,7 @@
         else
         {
             return normType + "=#"
-                + StringTools.dumpHexPairs( ( byte[] ) value );
+                + StringTools.dumpHexPairs( ( byte[] ) normValue );
         }
     }
 
@@ -616,13 +728,14 @@
      * Gets the hashcode of this object.
      *
      * @see java.lang.Object#hashCode()
+     * @return The instance hash code
      */
     public int hashCode()
     {
-        int result = 17;
+        int result = 37;
 
-        result = result * 37 + ( normType != null ? normType.hashCode() : 0 );
-        result = result * 37 + ( value != null ? value.hashCode() : 0 );
+        result = result*17 + ( normType != null ? normType.hashCode() : 0 );
+        result = result*17 + ( normValue != null ? normValue.hashCode() : 0 );
 
         return result;
     }
@@ -637,12 +750,7 @@
             return true;
         }
         
-        if ( obj == null )
-        {
-            return false;
-        }
-        
-        if ( obj.getClass() != this.getClass() )
+        if ( !( obj instanceof AttributeTypeAndValue ) )
         {
             return false;
         }
@@ -665,12 +773,170 @@
             }
         }
             
-        // Compare the value
-        return ( value == null ? 
-            instance.value == null  :
-            value.equals( instance.value ) );
+        // Compare the values
+        if ( normValue == null )
+        {
+            return instance.normValue == null;
+        }
+        else if ( normValue instanceof String )
+        {
+            if ( instance.normValue instanceof String )
+            {
+                return normValue.equals( instance.normValue );
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else if ( normValue instanceof byte[] )
+        {
+            if ( instance.normValue instanceof byte[] )
+            {
+                return Arrays.equals( (byte[])normValue, (byte[])instance.normValue );
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else
+        {
+            return false;
+        }
     }
 
+    
+    /**
+     * @see Externalizable#readExternal(ObjectInput)<p>
+     * 
+     * An AttributeTypeAndValue is composed of  a type and a value.
+     * The data are stored following the structure :
+     * 
+     * <li>upName</li> The User provided ATAV
+     * <li>start</li> The position of this ATAV in the DN
+     * <li>length</li> The ATAV length
+     * <li>upType</li> The user Provided Type
+     * <li>normType</li> The normalized AttributeType
+     * <li>isHR<li> Tells if the value is a String or not
+     * <p>
+     * if the value is a String :
+     * <li>upValue</li> The User Provided value.
+     * <li>value</li> The normalized value.
+     * <p>
+     * if the value is binary :
+     * <li>upValueLength</li>
+     * <li>upValue</li> The User Provided value.
+     * <li>valueLength</li>
+     * <li>value</li> The normalized value.
+     */
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        if ( StringTools.isEmpty( upName ) || 
+             StringTools.isEmpty( upType ) ||
+             StringTools.isEmpty( normType ) ||
+             ( start < 0 ) ||
+             ( length < 2 ) ||             // At least a type and '='
+             ( upValue == null ) ||
+             ( normValue == null ) )
+        {
+            String message = "Cannot serialize an wrong ATAV, ";
+            
+            if ( StringTools.isEmpty( upName ) )
+            {
+                message += "the upName should not be null or empty";
+            }
+            else if ( StringTools.isEmpty( upType ) )
+            {
+                message += "the upType should not be null or empty";
+            }
+            else if ( StringTools.isEmpty( normType ) )
+            {
+                message += "the normType should not be null or empty";
+            }
+            else if ( start < 0 )
+            {
+                message += "the start should not be < 0";
+            }
+            else if ( length < 2 )
+            {
+                message += "the length should not be < 2";
+            }
+            else if ( upValue == null )
+            {
+                message += "the upValue should not be null";
+            }
+            else if ( normValue == null )
+            {
+                message += "the value should not be null";
+            }
+                
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        out.writeUTF( upName );
+        out.writeInt( start );
+        out.writeInt( length );
+        out.writeUTF( upType );
+        out.writeUTF( normType );
+        
+        boolean isHR = ( normValue instanceof String );
+        
+        out.writeBoolean( isHR );
+        
+        if ( isHR )
+        {
+            out.writeUTF( (String)upValue );
+            out.writeUTF( (String)normValue );
+        }
+        else
+        {
+            out.writeInt( ((byte[])upValue).length );
+            out.write( (byte[])upValue );
+            out.writeInt( ((byte[])normValue).length );
+            out.write( (byte[])normValue );
+        }
+        
+        out.flush();
+    }
+    
+    
+    /**
+     * @see Externalizable#readExternal(ObjectInput)
+     * 
+     * We read back the data to create a new ATAV. The structure 
+     * read is exposed in the {@link AttributeTypeAndValue#writeExternal(ObjectOutput)} 
+     * method<p>
+     */
+    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+    {
+        upName = in.readUTF();
+        start = in.readInt();
+        length = in.readInt();
+        upType = in.readUTF();
+        normType = in.readUTF();
+        
+        boolean isHR = in.readBoolean();
+        
+        if ( isHR )
+        {
+            upValue = in.readUTF();
+            normValue = in.readUTF();
+        }
+        else
+        {
+            int upValueLength = in.readInt();
+            upValue = new byte[upValueLength];
+            in.readFully( (byte[])upValue );
+
+            int valueLength = in.readInt();
+            normValue = new byte[valueLength];
+            in.readFully( (byte[])normValue );
+        }
+    }
+    
+    
     /**
      * A String representation of a AttributeTypeAndValue.
      *
@@ -687,9 +953,9 @@
 
         sb.append( normType ).append( "=" );
 
-        if ( value != null )
+        if ( normValue != null )
         {
-            sb.append( value );
+            sb.append( normValue );
         }
 
         return sb.toString();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/DefaultStringNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/DefaultStringNormalizer.java
index d0de3a8..3af71e2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/DefaultStringNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/DefaultStringNormalizer.java
@@ -32,10 +32,11 @@
  * types only.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DefaultStringNormalizer implements Normalizer
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
     
     private static final DefaultStringNormalizer NORMALIZER = new DefaultStringNormalizer();
     
@@ -61,6 +62,14 @@
         return str;
     }
 
+    
+    /**
+     * Normalize the given String
+     *
+     * @param string The string to normalize
+     * @return The normalized object
+     * @throws NamingException If the normalization throws an error
+     */
     public static Object normalizeString( String string ) throws NamingException
     {
         return NORMALIZER.normalize( string );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
index 0979c42..aee0022 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
@@ -21,7 +21,10 @@
 package org.apache.directory.shared.ldap.name;
 
 
-import java.io.UnsupportedEncodingException;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -33,8 +36,6 @@
 import javax.naming.Name;
 import javax.naming.NamingException;
 
-import org.apache.directory.shared.ldap.name.DefaultStringNormalizer;
-import org.apache.directory.shared.ldap.schema.Normalizer;
 import org.apache.directory.shared.ldap.schema.OidNormalizer;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
@@ -58,11 +59,12 @@
  * is the first RDN (RDN[n]).
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
-public class LdapDN implements Name
+public class LdapDN implements Name, Externalizable
 {
     /** The LoggerFactory used by this class */
-    protected static final Logger log = LoggerFactory.getLogger( LdapDN.class );
+    protected static final Logger LOG = LoggerFactory.getLogger( LdapDN.class );
 
     /**
      * Declares the Serial Version Uid.
@@ -74,17 +76,21 @@
     private static final long serialVersionUID = 1L;
 
     /** Value returned by the compareTo method if values are not equals */
-    public final static int NOT_EQUALS = -1;
+    public static final int NOT_EQUAL = -1;
 
     /** Value returned by the compareTo method if values are equals */
-    public final static int EQUALS = 0;
+    public static final int EQUAL = 0;
 
     /** A flag used to tell if the DN has been normalized */
     private boolean normalized;
 
     // ~ Static fields/initializers
     // -----------------------------------------------------------------
-    /** The RDNs that are elements of the DN */
+    /**
+     *  The RDNs that are elements of the DN
+     * NOTE THAT THESE ARE IN THE OPPOSITE ORDER FROM THAT IMPLIED BY THE JAVADOC!
+     * Rdn[0] is rdns.get(n) and Rdn[n] is rdns.get(0)
+     */
     protected List<Rdn> rdns = new ArrayList<Rdn>( 5 );
 
     /** The user provided name */
@@ -108,7 +114,6 @@
      */
     public LdapDN()
     {
-        super();
         upName = "";
         normName = "";
         normalized = true;
@@ -142,6 +147,7 @@
      * is a String
      *
      * @param list of String name components.
+     * @throws InvalidNameException If the nameComponent is incorrect
      */
     LdapDN( List<String> list ) throws InvalidNameException
     {
@@ -161,16 +167,16 @@
     /**
      * Creates an ldap name using a list of name components.
      *
-     * @param nameComponents
-     *            List of String name components.
+     * @param nameComponents List of String name components.
+     * @throws InvalidNameException If the nameComponent is incorrect
      */
-    LdapDN( Iterator nameComponents ) throws InvalidNameException
+    LdapDN( Iterator<String> nameComponents ) throws InvalidNameException
     {
         if ( nameComponents != null )
         {
             while ( nameComponents.hasNext() )
             {
-                String nameComponent = ( String ) nameComponents.next();
+                String nameComponent = nameComponents.next();
                 add( 0, nameComponent );
             }
         }
@@ -208,6 +214,21 @@
 
 
     /**
+     * Create a DN when deserializing it.
+     * @param upName The user provided name
+     * @param normName the normalized name
+     * @param bytes the name as a byte[]
+     */
+    /* No protection */ LdapDN( String upName, String normName, byte[] bytes )
+    {
+        normalized = true;
+        this.upName = upName;
+        this.normName = normName;
+        this.bytes = bytes;
+    }
+
+
+    /**
      * Static factory which creates a normalized DN from a String and a Map of OIDs.
      *
      * @param name The DN as a String
@@ -266,19 +287,10 @@
      */
     public LdapDN( byte[] bytes ) throws InvalidNameException
     {
-        try
-        {
-            upName = new String( bytes, "UTF-8" );
-            LdapDnParser.parseInternal( upName, rdns );
-            this.normName = toNormName();
-            normalized = false;
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            log.error( "The byte array is not an UTF-8 encoded Unicode String : " + uee.getMessage() );
-            throw new InvalidNameException( "The byte array is not an UTF-8 encoded Unicode String : "
-                + uee.getMessage() );
-        }
+        upName = StringTools.utf8ToString( bytes );
+        LdapDnParser.parseInternal( bytes, rdns );
+        this.normName = toNormName();
+        normalized = false;
     }
 
 
@@ -298,7 +310,7 @@
      */
     public String toNormName()
     {
-        if ( ( rdns == null ) || ( rdns.size() == 0 ) )
+        if ( rdns.size() == 0 )
         {
             bytes = null;
             return "";
@@ -354,7 +366,7 @@
      */
     private String toUpName()
     {
-        if ( ( rdns == null ) || ( rdns.size() == 0 ) )
+        if ( rdns.size() == 0 )
         {
             upName = "";
         }
@@ -413,7 +425,7 @@
         if ( posn > rdns.size() )
         {
             String message = "Impossible to get the position " + posn + ", the DN only has " + rdns.size() + " RDNs";
-            log.error( message );
+            LOG.error( message );
             throw new ArrayIndexOutOfBoundsException( message );
         }
 
@@ -486,20 +498,18 @@
 
 
     /**
-     * Gets the hashcode of this name.
+     * Gets the hash code of this name.
      *
      * @see java.lang.Object#hashCode()
+     * @return the instance hash code
      */
     public int hashCode()
     {
-        int result = 17;
+        int result = 37;
 
-        if ( ( rdns != null ) && ( rdns.size() == 0 ) )
+        for ( Rdn rdn : rdns )
         {
-            for ( Rdn rdn : rdns )
-            {
-                result = result * 37 + rdn.hashCode();
-            }
+            result = result * 17 + rdn.hashCode();
         }
 
         return result;
@@ -529,9 +539,9 @@
 
 
     /**
-     * Get the number of NameComponent conatained in this LdapDN
+     * Get the number of NameComponent contained in this LdapDN
      *
-     * @return The number of NameComponent conatained in this LdapDN
+     * @return The number of NameComponent contained in this LdapDN
      */
     public int size()
     {
@@ -642,8 +652,7 @@
                 }
                 catch ( InvalidNameException e )
                 {
-                    e.printStackTrace();
-                    log.error( "Failed to parse RDN for name " + name.toString(), e );
+                    LOG.error( "Failed to parse RDN for name " + name.toString(), e );
                     return false;
                 }
 
@@ -773,7 +782,7 @@
 
 
     /**
-     * Retrieves the last component of this name.
+     * Retrieves the last (leaf) component of this name.
      *
      * @return the last component of this DN
      */
@@ -813,6 +822,7 @@
      * Retrieves the components of this name as an enumeration of strings. The
      * effect on the enumeration of updates to this name is undefined. If the
      * name has zero components, an empty (non-null) enumeration is returned.
+     * This starts at the root (rightmost) rdn.
      *
      * @return an enumeration of the components of this name, each as string
      */
@@ -839,7 +849,7 @@
             {
                 if ( pos >= rdns.size() )
                 {
-                    log.error( "Exceeded number of elements in the current object" );
+                    LOG.error( "Exceeded number of elements in the current object" );
                     throw new NoSuchElementException();
                 }
 
@@ -855,6 +865,7 @@
      * Retrieves the components of this name as an enumeration of strings. The
      * effect on the enumeration of updates to this name is undefined. If the
      * name has zero components, an empty (non-null) enumeration is returned.
+     * This starts at the root (rightmost) rdn.
      *
      * @return an enumeration of the components of this name, as Rdn
      */
@@ -881,7 +892,7 @@
             {
                 if ( pos >= rdns.size() )
                 {
-                    log.error( "Exceeded number of elements in the current object" );
+                    LOG.error( "Exceeded number of elements in the current object" );
                     throw new NoSuchElementException();
                 }
 
@@ -896,7 +907,8 @@
     /**
      * Creates a name whose components consist of a prefix of the components of
      * this name. Subsequent changes to this name will not affect the name that
-     * is returned and vice versa.
+     * is returned and vice versa. Note this includes the original root (rightmost rdn)
+     * and not the original leaf (leftmost rdn).
      *
      * @param posn
      *            the 0-based index of the component at which to stop. Must be
@@ -916,7 +928,7 @@
         if ( ( posn < 0 ) || ( posn > rdns.size() ) )
         {
             String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]";
-            log.error( message );
+            LOG.error( message );
             throw new ArrayIndexOutOfBoundsException( message );
         }
 
@@ -938,7 +950,8 @@
     /**
      * Creates a name whose components consist of a suffix of the components in
      * this name. Subsequent changes to this name do not affect the name that is
-     * returned and vice versa.
+     * returned and vice versa.   This includes the original leaf (leftmost rdn)
+     * and not the orginal root (rightmost rdn)
      *
      * @param posn
      *            the 0-based index of the component at which to start. Must be
@@ -959,7 +972,7 @@
         if ( ( posn < 0 ) || ( posn > rdns.size() ) )
         {
             String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]";
-            log.error( message );
+            LOG.error( message );
             throw new ArrayIndexOutOfBoundsException( message );
         }
 
@@ -985,7 +998,7 @@
      * components. Compoenents are supposed to be normalized.
      *
      * @param posn the index in this name at which to add the new components.
-     *            Must be in the range [0,size()].
+     *            Must be in the range [0,size()]. Note this is from the opposite end as rnds.get(posn)
      * @param name the components to add
      * @return the updated name (not a new one)
      * @throws ArrayIndexOutOfBoundsException
@@ -1042,7 +1055,7 @@
     }
 
     /**
-     * Adds the components of a name -- in order -- to the end of this name.
+     * Adds the components of a name -- in order -- to the (leaf) end of this name.
      *
      * @param suffix
      *            the components to add
@@ -1068,7 +1081,7 @@
      * components.
      *
      * @param posn the index in this name at which to add the new components.
-     *            Must be in the range [0,size()].
+     *            Must be in the range [0,size()].  Note this is the from the opposite end as rdns.get(posn).
      * @param name the components to add
      * @return the updated name (not a new one)
      * @throws ArrayIndexOutOfBoundsException
@@ -1129,7 +1142,7 @@
 
 
     /**
-     * Adds a single component to the end of this name.
+     * Adds a single component to the (leaf) end of this name.
      *
      * @param comp
      *            the component to add
@@ -1157,7 +1170,7 @@
 
 
     /**
-     * Adds a single RDN to the end of this name.
+     * Adds a single RDN to the (leaf) end of this name.
      *
      * @param newRdn the RDN to add
      * @return the updated name (not a new one)
@@ -1172,8 +1185,27 @@
         return this;
     }
 
+
     /**
-     * Adds a single normalized RDN to the end of this name.
+     * Adds a single RDN to a specific position.
+     *
+     * @param newRdn the RDN to add
+     * @param pos The position where we want to add the Rdn
+     * @return the updated name (not a new one)
+     */
+    public Name add( int pos, Rdn newRdn )
+    {
+        rdns.add( newRdn );
+        
+        normalizeInternal();
+        toUpName();
+
+        return this;
+    }
+
+
+    /**
+     * Adds a single normalized RDN to the (leaf) end of this name.
      *
      * @param newRdn the RDN to add
      * @return the updated name (not a new one)
@@ -1188,13 +1220,13 @@
         // RDN normalized name. The very same for upName.
         if (rdns.size() == 1 )
         {
-        	normName = newRdn.toString();
-        	upName = newRdn.getUpName();
+            normName = newRdn.toString();
+            upName = newRdn.getUpName();
         }
         else
         {
-        	normName = newRdn + "," + normName;
-        	upName = newRdn.getUpName() + "," + upName;
+            normName = newRdn + "," + normName;
+            upName = newRdn.getUpName() + "," + upName;
         }
         
         bytes = StringTools.getBytesUtf8( normName );
@@ -1225,7 +1257,7 @@
         if ( ( posn < 0 ) || ( posn > size() ) )
         {
             String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]";
-            log.error( message );
+            LOG.error( message );
             throw new ArrayIndexOutOfBoundsException( message );
         }
 
@@ -1267,7 +1299,7 @@
         if ( ( posn < 0 ) || ( posn >= rdns.size() ) )
         {
             String message = "The posn(" + posn + ") should be in the range [0, " + rdns.size() + "]";
-            log.error( message );
+            LOG.error( message );
             throw new ArrayIndexOutOfBoundsException( message );
         }
 
@@ -1304,7 +1336,7 @@
         }
         catch ( CloneNotSupportedException cnse )
         {
-            log.error( "The clone operation has failed" );
+            LOG.error( "The clone operation has failed" );
             throw new Error( "Assertion failure : cannot clone the object" );
         }
     }
@@ -1312,6 +1344,7 @@
 
     /**
      * @see java.lang.Object#equals(java.lang.Object)
+     * @return <code>true</code> if the two instances are equals
      */
     public boolean equals( Object obj )
     {
@@ -1371,17 +1404,17 @@
     {
         if ( obj instanceof LdapDN )
         {
-            LdapDN ldapDN = ( LdapDN ) obj;
+            LdapDN dn = ( LdapDN ) obj;
 
-            if ( ldapDN.size() != size() )
+            if ( dn.size() != size() )
             {
-                return size() - ldapDN.size();
+                return size() - dn.size();
             }
 
             for ( int i = rdns.size(); i > 0; i-- )
             {
                 Rdn rdn1 = rdns.get( i - 1 );
-                Rdn rdn2 = ldapDN.rdns.get( i - 1 );
+                Rdn rdn2 = dn.rdns.get( i - 1 );
                 int res = rdn1.compareTo( rdn2 );
 
                 if ( res != 0 )
@@ -1390,7 +1423,7 @@
                 }
             }
 
-            return EQUALS;
+            return EQUAL;
         }
         else
         {
@@ -1422,8 +1455,8 @@
                 if ( oidNormalizer != null )
                 {
                     return new AttributeTypeAndValue( atav.getUpType(), oidNormalizer.getAttributeTypeOid(), 
-                    		atav.getUpValue(),
-                    		((Normalizer<Object>)oidNormalizer.getNormalizer()).normalize( atav.getValue() ) );
+                            atav.getUpValue(),
+                            oidNormalizer.getNormalizer().normalize( atav.getNormValue() ) );
 
                 }
                 else
@@ -1436,7 +1469,7 @@
         else
         {
             // The type is empty : this is not possible...
-            log.error( "Empty type not allowed in a DN" );
+            LOG.error( "Empty type not allowed in a DN" );
             throw new InvalidNameException( "Empty type not allowed in a DN" );
         }
 
@@ -1445,21 +1478,19 @@
     /**
      * This private method is used to normalize the value, when we have found a normalizer.
      * 
-     * @param rdn 
-     * @param oidNormalizer 
-     * @param type 
+     * @param rdn the RDN we want to normalize. It will contain the resulting normalized RDN
+     * @param oidNormalizer the normalizer to use for the RDN
      * @throws NamingException If something went wrong.
      */
-    public static void oidNormalize( Rdn rdn, OidNormalizer oidNormalizer, String type ) throws NamingException
+    private static void oidNormalize( Rdn rdn, OidNormalizer oidNormalizer ) throws NamingException
     {
         Object upValue = rdn.getUpValue();
         String upType = rdn.getUpType();
         rdn.clear();
-        Object normValue = DefaultStringNormalizer.normalizeString( ( String ) upValue );
+        Object normStringValue = DefaultStringNormalizer.normalizeString( (String)upValue );
+        Object normValue = oidNormalizer.getNormalizer().normalize( normStringValue );
 
-        rdn.addAttributeTypeAndValue( upType, oidNormalizer.getAttributeTypeOid(), upValue, 
-            ((Normalizer<Object>)oidNormalizer.getNormalizer()).normalize( normValue ) );
-
+        rdn.addAttributeTypeAndValue( upType, oidNormalizer.getAttributeTypeOid(), upValue, normValue );
     }
 
     /**
@@ -1481,13 +1512,10 @@
             Rdn rdnCopy = ( Rdn ) rdn.clone();
             rdn.clear();
 
-            Iterator atavs = rdnCopy.iterator();
-
-            while ( atavs.hasNext() )
+            for ( AttributeTypeAndValue val:rdnCopy )
             {
-            	AttributeTypeAndValue val = (AttributeTypeAndValue)atavs.next();
                 AttributeTypeAndValue newAtav = atavOidToName( val, oidsMap );
-                rdn.addAttributeTypeAndValue( val.getUpType(), newAtav.getNormType(), val.getUpValue(), newAtav.getValue() );
+                rdn.addAttributeTypeAndValue( val.getUpType(), newAtav.getNormType(), val.getUpValue(), newAtav.getNormValue() );
             }
 
         }
@@ -1507,7 +1535,7 @@
 
                     if ( oidNormalizer != null )
                     {
-                        oidNormalize( rdn, oidNormalizer, type );
+                        oidNormalize( rdn, oidNormalizer );
                     }
                     else
                     {
@@ -1520,7 +1548,7 @@
                             if ( oidNormalizer != null )
                             {
                                 // Ok, just normalize after having removed the 4 first chars
-                                oidNormalize( rdn, oidNormalizer, type );
+                                oidNormalize( rdn, oidNormalizer );
                             }
                             else
                             {
@@ -1541,7 +1569,7 @@
             else
             {
                 // The type is empty : this is not possible...
-                log.error( "We should not have an empty DN" );
+                LOG.error( "We should not have an empty DN" );
                 throw new InvalidNameException( "Empty type not allowed in a DN" );
             }
         }
@@ -1563,11 +1591,9 @@
      * @param dn The DN to transform.
      * @param oidsMap The mapping between names and oids.
      * @return A normalized form of the DN.
-     * @throws InvalidNameException If the DN is invalid.
      * @throws NamingException If something went wrong.
      */
-    public static LdapDN normalize( LdapDN dn, Map<String, OidNormalizer> oidsMap ) throws InvalidNameException,
-        NamingException
+    public static LdapDN normalize( LdapDN dn, Map<String, OidNormalizer> oidsMap ) throws NamingException
     {
         if ( ( dn == null ) || ( dn.size() == 0 ) || ( oidsMap == null ) || ( oidsMap.size() == 0 ) )
         {
@@ -1606,19 +1632,19 @@
      * 'commonname' share the same OID.
      *
      * @param oidsMap The mapping between names and oids.
-     * @throws InvalidNameException If the DN is invalid.
      * @throws NamingException If something went wrong.
+     * @return The normalized DN
      */
-    public void normalize( Map<String, OidNormalizer> oidsMap ) throws InvalidNameException, NamingException
+    public LdapDN normalize( Map<String, OidNormalizer> oidsMap ) throws NamingException
     {
         if ( ( oidsMap == null ) || ( oidsMap.size() == 0 ) )
         {
-            return;
+            return this;
         }
 
         if ( size() == 0 )
         {
-            return;
+            return this;
         }
 
         Enumeration<Rdn> localRdns = getAllRdn();
@@ -1635,6 +1661,7 @@
 
         normalizeInternal();
         normalized = true;
+        return this;
     }
 
 
@@ -1659,4 +1686,111 @@
     {
         return normalized;
     }
+
+
+    /**
+     * @see Externalizable#readExternal(ObjectInput)<p>
+     * 
+     * We have to store a DN data efficiently. Here is the structure :
+     * 
+     * <li>upName</li> The User provided DN<p>
+     * <li>normName</li> May be null if the normName is equaivalent to 
+     * the upName<p>
+     * <li>rdns</li> The rdn's List.<p>
+     * 
+     * for each rdn :
+     * <li>call the RDN write method</li>
+     *
+     *@param out The stream in which the DN will be serialized
+     *@throws IOException If the serialization fail
+     */
+    public void writeExternal( ObjectOutput out ) throws IOException
+    {
+        if ( upName == null )
+        {
+            String message = "Cannot serialize a NULL DN";
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        // Write the UPName
+        out.writeUTF( upName );
+        
+        // Write the NormName if different
+        if ( isNormalized() )
+        {
+            if ( upName.equals( normName ) )
+            {
+                out.writeUTF( "" );
+            }
+            else
+            {
+                out.writeUTF( normName );
+            }
+        }
+        else
+        {
+            String message = "The DN should have been normalized before being serialized";
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        // Should we store the byte[] ???
+        
+        // Write the RDNs. Is it's null, the number will be -1. 
+        out.writeInt( rdns.size() );
+
+        // Loop on the RDNs
+        for ( Rdn rdn:rdns )
+        {
+            out.writeObject( rdn );
+        }
+        
+        out.flush();
+    }
+
+
+    /**
+     * @see Externalizable#readExternal(ObjectInput)
+     * 
+     * We read back the data to create a new LdapDN. The structure 
+     * read is exposed in the {@link LdapDN#writeExternal(ObjectOutput)} 
+     * method<p>
+     * 
+     * @param in The stream from which the DN is read
+     * @throws IOException If the stream can't be read
+     * @throws ClassNotFoundException If the RDN can't be created 
+     */
+    public void readExternal( ObjectInput in ) throws IOException , ClassNotFoundException
+    {
+        // 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;
+        }
+        
+        // A serialized DN is always normalized.
+        normalized = true;
+            
+        // Should we read the byte[] ???
+        bytes = StringTools.getBytesUtf8( upName );
+        
+        // Read the RDNs. Is it's null, the number will be -1.
+        int nbRdns = in.readInt();
+        rdns = new ArrayList<Rdn>( nbRdns );
+        
+        for ( int i = 0; i < nbRdns; i++ )
+        {
+            Rdn rdn = (Rdn)in.readObject();
+            rdns.add( rdn );
+        }
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDNSerializer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDNSerializer.java
new file mode 100644
index 0000000..b7474e2
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDNSerializer.java
@@ -0,0 +1,148 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.name;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class which serialize and deserialize a DN
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class LdapDNSerializer
+{
+    /** The LoggerFactory used by this class */
+    protected static final Logger LOG = LoggerFactory.getLogger( LdapDNSerializer.class );
+
+    /**
+     * Serialize a DN
+     * 
+     * We have to store a DN data efficiently. Here is the structure :
+     * 
+     * <li>upName</li> The User provided DN<p>
+     * <li>normName</li> May be null if the normName is equivalent to 
+     * the upName<p>
+     * <li>rdns</li> The rdn's List.<p>
+     * 
+     * for each rdn :
+     * <li>call the RDN write method</li>
+     * 
+     * @param dn The DN to serialize
+     * @param out the stream in which the DN will be serialized
+     * @throws IOException If we can't write in this stream
+     */
+    public static void serialize( LdapDN dn, ObjectOutput out ) throws IOException
+    {
+        if ( dn.getUpName() == null )
+        {
+            String message = "Cannot serialize a NULL DN";
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        // Write the UPName
+        out.writeUTF( dn.getUpName() );
+        
+        // Write the NormName if different
+        if ( dn.isNormalized() )
+        {
+            if ( dn.getUpName().equals( dn.getNormName() ) )
+            {
+                out.writeUTF( "" );
+            }
+            else
+            {
+                out.writeUTF( dn.getNormName() );
+            }
+        }
+        else
+        {
+            String message = "The DN should have been normalized before being serialized " + dn;
+            LOG.error( message );
+            throw new IOException( message );
+        }
+        
+        // Should we store the byte[] ???
+        
+        // Write the RDNs.
+        // First the number of RDNs
+        out.writeInt( dn.size() );
+        
+        // Loop on the RDNs
+        for ( Rdn rdn:dn.getRdns() )
+        {
+            RdnSerializer.serialize( rdn, out );
+        }
+        
+        out.flush();
+    }
+
+
+    /**
+     * Deserialize a DN
+     * 
+     * We read back the data to create a new LdapDN. The structure 
+     * read is exposed in the {@link LdapDNSerializer#serialize(LdapDN, ObjectOutput)} 
+     * method<p>
+     * 
+     * @param in The input stream from which the DN is read
+     * @return a deserialized DN
+     * @throws IOException If the stream can't be read
+     */
+    public static LdapDN deserialize( ObjectInput in ) throws IOException
+    {
+        // Read the UPName
+        String upName = in.readUTF();
+        
+        // Read the NormName
+        String 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;
+        }
+        
+        // Should we read the byte[] ???
+        byte[] bytes = StringTools.getBytesUtf8( upName );
+        
+        // Read the RDNs. Is it's null, the number will be -1.
+        int nbRdns = in.readInt();
+        
+        LdapDN dn = new LdapDN( upName, normName, bytes );
+        
+        for ( int i = 0; i < nbRdns; i++ )
+        {
+            Rdn rdn = RdnSerializer.deserialize( in );
+            dn.add( 0, rdn );
+        }
+    
+        return dn;
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java
index 60ebacb..2e5377e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDnParser.java
@@ -24,13 +24,13 @@
 
 import javax.naming.InvalidNameException;
 import javax.naming.Name;
+import javax.naming.NameParser;
+
 
 import org.apache.directory.shared.ldap.util.DNUtils;
 import org.apache.directory.shared.ldap.util.Position;
 import org.apache.directory.shared.ldap.util.StringTools;
 
-import javax.naming.NameParser;
-
 
 /**
  * This class parses a DN. The DN MUST respect this BNF grammar (as of RFC2253,
@@ -65,6 +65,7 @@
  * </p>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LdapDnParser implements NameParser
 {
@@ -96,12 +97,9 @@
    /**
     * Parse a DN
     *
-    * @param dn
-    *            The DN to be parsed
-    * @param rdns
-    *            The list that will contain the RDNs
-    * @throws InvalidNameException
-    *             If the DN is invalid
+    * @param dn The DN to be parsed
+    * @param rdns The list that will contain the RDNs
+    * @throws InvalidNameException If the DN is invalid
     */
    public static void parseInternal( String dn, List<Rdn> rdns ) throws InvalidNameException
    {
@@ -111,6 +109,27 @@
            return;
        }
 
+       parseInternal( StringTools.getBytesUtf8( dn ), rdns );
+       
+       return;
+   }
+
+
+   /**
+    * Parse a DN
+    *
+    * @param dn The DN to be parsed
+    * @param rdns The list that will contain the RDNs
+    * @throws InvalidNameException If the DN is invalid
+    */
+   public static void parseInternal( byte[] dn, List<Rdn> rdns ) throws InvalidNameException
+   {
+       if ( dn.length == 0 )
+       {
+           // We have an empty DN, just get out of the function.
+           return;
+       }
+
        Position pos = new Position();
        pos.start = 0;
        Rdn rdn = new Rdn();
@@ -126,13 +145,13 @@
                rdns.add( rdn );
                rdn = new Rdn();
 
-               if ( ( StringTools.isCharASCII( dn, pos.start, ',' ) == false )
-                   && ( StringTools.isCharASCII( dn, pos.start, ';' ) == false ) )
+               if ( ( !StringTools.isCharASCII( dn, pos.start, ',' ) )
+                   && ( !StringTools.isCharASCII( dn, pos.start, ';' ) ) )
                {
 
-                   if ( pos.start != dn.length() )
+                   if ( pos.start != dn.length )
                    {
-                       throw new InvalidNameException( "Bad DN : " + dn );
+                       throw new InvalidNameException( "Bad DN : " + StringTools.utf8ToString( dn ) );
                    }
                    else
                    {
@@ -144,11 +163,11 @@
            }
            while ( RdnParser.parse( dn, pos, rdn ) != DNUtils.PARSING_ERROR );
            
-           throw new InvalidNameException( "Bad DN : " + dn );
+           throw new InvalidNameException( "Bad DN : " + StringTools.utf8ToString( dn ) );
        }
        else
        {
-           throw new InvalidNameException( "Bad DN : " + dn );
+           throw new InvalidNameException( "Bad DN : " + StringTools.utf8ToString( dn ) );
        }
    }
 
@@ -156,18 +175,12 @@
    /**
     * Validate a DN
     *
-    * @param dn
-    *            The DN to be parsed
+    * @param dn The DN to be parsed
     *            
     * @return <code>true</code> if the DN is valid
     */
-   public static boolean validateInternal( String dn )
+   private static boolean validateInternal( byte[] dn )
    {
-       if ( dn.length() == 0 )
-       {
-           // We have an empty DN, just get out of the function.
-           return true;
-       }
 
        Position pos = new Position();
        pos.start = 0;
@@ -180,11 +193,11 @@
            // Now, parse the following nameComponents
            do
            {
-               if ( ( StringTools.isCharASCII( dn, pos.start, ',' ) == false )
-                   && ( StringTools.isCharASCII( dn, pos.start, ';' ) == false ) )
+               if ( ( !StringTools.isCharASCII( dn, pos.start, ',' ) )
+                   && ( !StringTools.isCharASCII( dn, pos.start, ';' ) ) )
                {
 
-                   if ( pos.start != dn.length() )
+                   if ( pos.start != dn.length )
                    {
                        return false;
                    }
@@ -203,6 +216,25 @@
        return false;
    }
 
+   
+   /**
+    * Validate a DN
+    *
+    * @param dn The DN to be parsed
+    *            
+    * @return <code>true</code> if the DN is valid
+    */
+   public static boolean validateInternal( String dn )
+   {
+       if ( dn.length() == 0 )
+       {
+           // We have an empty DN, just get out of the function.
+           return true;
+       }
+
+       return validateInternal( StringTools.getBytesUtf8( dn ) );
+   }
+
 
    /**
     * Parse a String and return a LdapDN if the String is a valid DN
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
index e5c29cf..dc2013f 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
@@ -20,6 +20,10 @@
 package org.apache.directory.shared.ldap.name;
 
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.io.Serializable;
 import java.util.Iterator;
 import java.util.List;
@@ -35,6 +39,8 @@
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
 import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -100,10 +106,14 @@
  * are not case sensitive, we can say that a = A
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
-public class Rdn implements Cloneable, Comparable, Serializable
+public class Rdn implements Cloneable, Comparable, Serializable, Iterable<AttributeTypeAndValue>
 {
-   /**
+    /** The LoggerFactory used by this class */
+    protected static final Logger LOG = LoggerFactory.getLogger( Rdn.class );
+
+    /**
     * Declares the Serial Version Uid.
     *
     * @see <a
@@ -163,11 +173,14 @@
    /** CompareTo() results */
    public static final int UNDEFINED = Integer.MAX_VALUE;
 
+   /** Constant used in comparisons */
    public static final int SUPERIOR = 1;
 
+   /** Constant used in comparisons */
    public static final int INFERIOR = -1;
 
-   public static final int EQUALS = 0;
+   /** Constant used in comparisons */
+   public static final int EQUAL = 0;
 
 
    /**
@@ -216,23 +229,20 @@
    /**
     * A constructor that constructs a RDN from a type and a value. Constructs
     * an Rdn from the given attribute type and value. The string attribute
-    * values are not interpretted as RFC 2253 formatted RDN strings. That is,
-    * the values are used literally (not parsed) and assumed to be unescaped.
+    * values are not interpreted as RFC 2253 formatted RDN strings. That is,
+    * the values are used literally (not parsed) and assumed to be un-escaped.
     *
-    * @param type
-    *            The type of the RDN
-    * @param value
-    *            The value of the RDN
-    * @throws InvalidNameException
-    *             If the RDN is invalid
+    * @param upType The user provided type of the RDN
+    * @param upValue The user provided value of the RDN
+    * @param normType The normalized provided type of the RDN
+    * @param normValue The normalized provided value of the RDN
+    * @throws InvalidNameException If the RDN is invalid
     */
-   public Rdn( String upType, String type, String upValue, String value ) throws InvalidNameException
+   public Rdn( String upType, String normType, String upValue, String normValue ) throws InvalidNameException
    {
-       super();
+       addAttributeTypeAndValue( upType, normType, upValue, normValue );
 
-       addAttributeTypeAndValue( upType, type, upValue, value );
-
-       upName = type + '=' + value;
+       upName = upType + '=' + upValue;
        start = 0;
        length = upName.length();
        // create the internal normalized form
@@ -241,6 +251,23 @@
 
 
    /**
+    * A constructor that constructs a RDN from a type, a position and a length.
+    *
+    * @param start The starting point for this RDN in the user provided DN
+    * @param length The RDN's length
+    * @param upName The user provided name
+    * @param normName the normalized name
+    */
+   /* No protection */ Rdn( int start, int length, String upName, String normName )
+   {
+       this.start = 0;
+       this.length = length;
+       this.upName = upName;
+       this.normName = normName;
+   }
+
+   
+   /**
     * Constructs an Rdn from the given rdn. The contents of the rdn are simply
     * copied into the newly created
     *
@@ -250,7 +277,6 @@
    @SuppressWarnings({"unchecked"})
    public Rdn( Rdn rdn )
    {
-       super();
        nbAtavs = rdn.getNbAtavs();
        this.normName = rdn.normName;
        this.upName = rdn.getUpName();
@@ -268,17 +294,16 @@
 
            default:
                // We must duplicate the treeSet and the hashMap
-               Iterator<AttributeTypeAndValue> iter = rdn.atavs.iterator();
-
                atavs = new TreeSet<AttributeTypeAndValue>();
                atavTypes = new MultiHashMap();
 
-               while ( iter.hasNext() )
+               for ( AttributeTypeAndValue currentAtav:rdn.atavs )
                {
-                   AttributeTypeAndValue currentAtav = iter.next();
                    atavs.add( (AttributeTypeAndValue)currentAtav.clone() );
-                   atavTypes.put( currentAtav.getUpType(), currentAtav );
+                   atavTypes.put( currentAtav.getNormType(), currentAtav );
                }
+               
+               return;
        }
    }
 
@@ -303,13 +328,13 @@
            case 1:
                // We have a single AttributeTypeAndValue
                // We will trim and lowercase type and value.
-               if ( atav.getValue() instanceof String )
+               if ( atav.getNormValue() instanceof String )
                {
                    normName = atav.getNormalizedValue();
                }
                else
                {
-                   normName = atav.getNormType() + "=#" + StringTools.dumpHexPairs( (byte[])atav.getValue() );
+                   normName = atav.getNormType() + "=#" + StringTools.dumpHexPairs( (byte[])atav.getNormValue() );
                }
 
                break;
@@ -343,18 +368,19 @@
    /**
     * Add a AttributeTypeAndValue to the current RDN
     *
-    * @param type
-    *            The type of the added RDN.
-    * @param value
-    *            The value of the added RDN
+    * @param upType The user provided type of the added RDN.
+    * @param type The normalized provided type of the added RDN.
+    * @param upValue The user provided value of the added RDN
+    * @param value The normalized provided value of the added RDN
     * @throws InvalidNameException
     *             If the RDN is invalid
     */
-   // WARNING : The protection level is left unspecified intentionnaly.
+   // WARNING : The protection level is left unspecified intentionally.
    // We need this method to be visible from the DnParser class, but not
    // from outside this package.
    @SuppressWarnings({"unchecked"})
-   /* Unspecified protection */void addAttributeTypeAndValue( String upType, String type, Object upValue, Object value ) throws InvalidNameException
+   /* Unspecified protection */void addAttributeTypeAndValue( String upType, String type, Object upValue, Object value ) 
+       throws InvalidNameException
    {
        // First, let's normalize the type
        String normalizedType = StringTools.lowerCaseAscii(type);
@@ -399,6 +425,56 @@
 
 
    /**
+    * Add a AttributeTypeAndValue to the current RDN
+    *
+    * @param value The added AttributeTypeAndValue
+    */
+   // WARNING : The protection level is left unspecified intentionnaly.
+   // We need this method to be visible from the DnParser class, but not
+   // from outside this package.
+   @SuppressWarnings({"unchecked"})
+   /* Unspecified protection */void addAttributeTypeAndValue( AttributeTypeAndValue value )
+   {
+       String normalizedType = value.getNormType();
+
+       switch ( nbAtavs )
+       {
+           case 0:
+               // This is the first AttributeTypeAndValue. Just stores it.
+               this.atav = value;
+               nbAtavs = 1;
+               atavType = normalizedType;
+               return;
+
+           case 1:
+               // We already have an atav. We have to put it in the HashMap
+               // before adding a new one.
+               // First, create the HashMap,
+               atavs = new TreeSet<AttributeTypeAndValue>();
+
+               // and store the existing AttributeTypeAndValue into it.
+               atavs.add( this.atav );
+               atavTypes = new MultiHashMap();
+               atavTypes.put( atavType, this.atav );
+
+               this.atav = null;
+
+           // Now, fall down to the commmon case
+           // NO BREAK !!!
+
+           default:
+               // add a new AttributeTypeAndValue
+               atavs.add( value );
+               atavTypes.put( normalizedType, value );
+
+               nbAtavs++;
+               break;
+
+       }
+   }
+
+   
+   /**
     * Clear the RDN, removing all the AttributeTypeAndValues.
     */
    public void clear()
@@ -422,6 +498,7 @@
     * @param type
     *            The type of the NameArgument
     * @return The Value to be returned, or null if none found.
+    * @throws InvalidNameException 
     */
    public Object getValue( String type ) throws InvalidNameException
    {
@@ -436,12 +513,10 @@
            case 1:
                if ( StringTools.equals( atav.getNormType(), normalizedType ) )
                {
-                   return atav.getValue();
+                   return atav.getNormValue();
                }
-               else
-               {
-                   return "";
-               }
+
+               return "";
 
            default:
                if ( atavTypes.containsKey( normalizedType ) )
@@ -450,17 +525,16 @@
 
                    if ( obj instanceof AttributeTypeAndValue )
                    {
-                       return ( ( AttributeTypeAndValue ) obj ).getValue();
+                       return ( ( AttributeTypeAndValue ) obj ).getNormValue();
                    }
                    else if ( obj instanceof List )
                    {
                        StringBuffer sb = new StringBuffer();
                        boolean isFirst = true;
+                       List<AttributeTypeAndValue> atavList = ( ( List<AttributeTypeAndValue> ) obj );
 
-                       for ( int i = 0; i < ( ( List ) obj ).size(); i++ )
+                       for ( AttributeTypeAndValue elem:atavList )
                        {
-                           AttributeTypeAndValue elem = ( AttributeTypeAndValue ) ( ( List ) obj ).get( i );
-
                            if ( isFirst )
                            {
                                isFirst = false;
@@ -470,7 +544,7 @@
                                sb.append( ',' );
                            }
 
-                           sb.append( elem.getValue() );
+                           sb.append( elem.getNormValue() );
                        }
 
                        return sb.toString();
@@ -480,15 +554,34 @@
                        throw new InvalidNameException( "Bad object stored in the RDN" );
                    }
                }
-               else
-               {
-                   return "";
-               }
+
+               return "";
        }
    }
 
+   
+   /** 
+    * Get the start position
+    *
+    * @return The start position in the DN
+    */
+   public int getStart()
+   {
+       return start;
+   }
+   
 
    /**
+    * Get the Rdn length
+    *
+    * @return The Rdn length
+    */
+   public int getLength()
+   {
+       return length;
+   }
+   
+   /**
     * Get the AttributeTypeAndValue which type is given as an argument. If we
     * have more than one value associated with the type, we will return only
     * the first one.
@@ -512,38 +605,34 @@
                {
                    return atav;
                }
-               else
-               {
-                   return null;
-               }
+
+               return null;
 
            default:
                if ( atavTypes.containsKey( normalizedType ) )
                {
                    return atavTypes.get( normalizedType );
                }
-               else
-               {
-                   return null;
-               }
+
+               return null;
        }
    }
 
 
    /**
-    * Retrieves the components of this name as an enumeration of strings. The
-    * effect on the enumeration of updates to this name is undefined. If the
-    * name has zero components, an empty (non-null) enumeration is returned.
+    * Retrieves the components of this RDN as an iterator of AttributeTypeAndValue. 
+    * The effect on the iterator of updates to this RDN is undefined. If the
+    * RDN has zero components, an empty (non-null) iterator is returned.
     *
-    * @return an enumeration of the components of this name, each a string
+    * @return an iterator of the components of this RDN, each an AttributeTypeAndValue
     */
    public Iterator<AttributeTypeAndValue> iterator()
    {
-       if ( nbAtavs == 1 )
+       if ( nbAtavs == 1 || nbAtavs == 0 )
        {
            return new Iterator<AttributeTypeAndValue>()
            {
-               private boolean hasMoreElement = true;
+               private boolean hasMoreElement = nbAtavs == 1;
 
 
                public boolean hasNext()
@@ -575,8 +664,9 @@
 
    /**
     * Clone the Rdn
+    * 
+    * @return A clone of the current RDN
     */
-   @SuppressWarnings({"unchecked"})
    public Object clone()
    {
        try
@@ -603,7 +693,7 @@
                    for ( AttributeTypeAndValue currentAtav:this.atavs )
                    {
                        rdn.atavs.add( (AttributeTypeAndValue)currentAtav.clone() );
-                       rdn.atavTypes.put( currentAtav.getUpType(), currentAtav );
+                       rdn.atavTypes.put( currentAtav.getNormType(), currentAtav );
                    }
 
                    break;
@@ -620,12 +710,12 @@
 
    /**
     * Compares two RDNs. They are equals if : 
-    * - their have the same number of NC (AttributeTypeAndValue) 
-    * - each ATAVs are equals 
-    * - comparizon of type are done case insensitive 
-    * - each value is equel, case sensitive 
-    * - Order of ATAV is not important If the RDNs are not equals, a positive number is
-    * returned if the first RDN is greated, negative otherwise
+    * <li>their have the same number of NC (AttributeTypeAndValue) 
+    * <li>each ATAVs are equals 
+    * <li>comparison of type are done case insensitive 
+    * <li>each value is equal, case sensitive 
+    * <li>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
@@ -653,7 +743,7 @@
            switch ( nbAtavs )
            {
                case 0:
-                   return EQUALS;
+                   return EQUAL;
 
                case 1:
                    return atav.compareTo( rdn.atav );
@@ -662,68 +752,32 @@
                    // We have more than one value. We will
                    // go through all of them.
 
-                   for ( AttributeTypeAndValue current:atavs )
+                   // 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<AttributeTypeAndValue> localIterator = atavs.iterator();
+                   Iterator<AttributeTypeAndValue> paramIterator = rdn.atavs.iterator();
+                   
+                   while(localIterator.hasNext() || paramIterator.hasNext())
                    {
-                       String type = current.getNormType();
-
-                       if ( rdn.atavTypes.containsKey( type ) )
+                       if(!localIterator.hasNext())
                        {
-                           List atavLocalList = ( List ) atavTypes.get( type );
-                           List atavParamList = ( List ) rdn.atavTypes.get( type );
-
-                           if ( atavLocalList.size() == 1 )
-                           {
-                               // We have only one ATAV
-                               AttributeTypeAndValue atavLocal = ( AttributeTypeAndValue ) atavLocalList.get( 0 );
-                               AttributeTypeAndValue atavParam = ( AttributeTypeAndValue ) atavParamList.get( 0 );
-
-                               return atavLocal.compareTo( atavParam );
-                           }
-                           else
-                           {
-                               // We have to verify that each value of the
-                               // first list are present in
-                               // the second list
-                               Iterator atavLocals = atavLocalList.iterator();
-
-                               while ( atavLocals.hasNext() )
-                               {
-                                   AttributeTypeAndValue atavLocal = ( AttributeTypeAndValue ) atavLocals.next();
-
-                                   Iterator atavParams = atavParamList.iterator();
-                                   boolean found = false;
-
-                                   while ( atavParams.hasNext() )
-                                   {
-                                       AttributeTypeAndValue atavParam = ( AttributeTypeAndValue ) atavParams.next();
-
-                                       if ( atavLocal.compareTo( atavParam ) == EQUALS )
-                                       {
-                                           found = true;
-                                           break;
-                                       }
-                                   }
-
-                                   if ( !found )
-                                   {
-                                       // The ATAV does not exist in the second
-                                       // RDN
-                                       return SUPERIOR;
-                                   }
-                               }
-                           }
-
-                           return EQUALS;
-                       }
-                       else
-                       {
-                           // We can't find an atav in the rdn : the current
-                           // one is superior
                            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 EQUALS;
+                   return EQUAL;
            }
        }
        else
@@ -734,7 +788,7 @@
 
 
    /**
-    * Returns a String representation of the RDN
+    * @return a String representation of the RDN
     */
    public String toString()
    {
@@ -743,7 +797,7 @@
 
 
    /**
-    * Returns a String representation of the RDN
+    * @return the user provided name
     */
    public String getUpName()
    {
@@ -752,7 +806,17 @@
 
 
    /**
+    * @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 )
    {
@@ -786,7 +850,7 @@
                return atav;
 
            default:
-               return (AttributeTypeAndValue)((TreeSet)atavs).first();
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first();
        }
    }
 
@@ -807,10 +871,11 @@
                return atav.getUpType();
 
            default:
-               return ( ( AttributeTypeAndValue )((TreeSet)atavs).first() ).getUpType();
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first().getUpType();
        }
    }
 
+
    /**
     * Return the normalized type, or the first one of we have more than one (the lowest)
     *
@@ -827,10 +892,32 @@
                return atav.getNormType();
 
            default:
-               return ( ( AttributeTypeAndValue )((TreeSet)atavs).first() ).getNormType();
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first().getNormType();
        }
    }
 
+   
+   /**
+    * Return the normalized value, or the first one of we have more than one (the lowest)
+    *
+    * @return The first normalized value of this RDN
+    */
+   public String getNormValue()
+   {
+       switch ( nbAtavs )
+       {
+           case 0:
+               return null;
+
+           case 1:
+               return (String)atav.getNormValue();
+
+           default:
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first().getNormalizedValue();
+       }
+   }
+
+
    /**
     * Return the value, or the first one of we have more than one (the lowest)
     *
@@ -844,10 +931,10 @@
                return null;
 
            case 1:
-               return atav.getValue();
+               return atav.getNormValue();
 
            default:
-               return ( ( AttributeTypeAndValue )((TreeSet)atavs).first() ).getValue();
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first().getNormValue();
        }
    }
 
@@ -868,7 +955,7 @@
                return atav.getUpValue();
 
            default:
-               return ( ( AttributeTypeAndValue )((TreeSet)atavs).first() ).getUpValue();
+               return ((TreeSet<AttributeTypeAndValue>)atavs).first().getUpValue();
        }
    }
    
@@ -894,7 +981,7 @@
            return false;
        }
 
-       return compareTo( rdn ) == EQUALS;
+       return compareTo( rdn ) == EQUAL;
    }
 
 
@@ -926,27 +1013,20 @@
 
            case 1 :
                attribute = new AttributeImpl( atavType, true );
-               attribute.add( atav.getValue() );
+               attribute.add( atav.getNormValue() );
                attributes.put( attribute );
                break;
 
            default :
-               Iterator types = atavTypes.keySet().iterator();
-
-               while ( types.hasNext() )
+               for ( String type:atavTypes.keySet() )
                {
-                   String type = ( String ) types.next();
-                   List values = ( List ) atavTypes.get( type );
+                   List<AttributeTypeAndValue> values = ( List<AttributeTypeAndValue> ) atavTypes.get( type );
 
                    attribute = new AttributeImpl( type );
 
-                   Iterator iterValues = values.iterator();
-
-                   while ( iterValues.hasNext() )
+                   for ( AttributeTypeAndValue value:values )
                    {
-                       AttributeTypeAndValue value = ( AttributeTypeAndValue ) iterValues.next();
-
-                       attribute.add( value.getValue() );
+                       attribute.add( value.getNormValue() );
                    }
 
                    attributes.put( attribute );
@@ -976,7 +1056,7 @@
     * @throws IllegalArgumentException -
     *             When an Illegal value is provided.
     */
-   public static Object unescapeValue( String value ) throws IllegalArgumentException
+   public static Object unescapeValue( String value )
    {
        if ( StringTools.isEmpty( value ) )
        {
@@ -1052,6 +1132,8 @@
                                isHex = true;
                                pair = ( (byte)( StringTools.getHexValue( chars[i] ) << 4 ) );
                            }
+                       
+                           break;
                    }
                }
                else
@@ -1088,11 +1170,10 @@
 
                            default:
                                byte[] result = StringTools.charToBytes( chars[i] );
-
-                               for ( int j = 0; j < result.length; j++ )
-                               {
-                                   bytes[pos++] = result[j];
-                               }
+                               System.arraycopy( result, 0, bytes, pos, result.length );
+                               pos += result.length;
+                               
+                               break;
                        }
                    }
                }
@@ -1125,8 +1206,32 @@
            switch ( chars[i] )
            {
                case ' ':
-               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 ';':
@@ -1188,6 +1293,7 @@
 
                default:
                    newChars[pos++] = chars[i];
+                   break;
 
            }
        }
@@ -1215,13 +1321,14 @@
    }
 
    /**
-    * Gets the hashcode of this rdn.
-    *
-    * @see java.lang.Object#hashCode()
-    */
+     * Gets the hashcode of this rdn.
+     *
+     * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
+     */
    public int hashCode()
    {
-       int result = 17;
+       int result = 37;
 
        switch ( nbAtavs )
        {
@@ -1231,7 +1338,7 @@
 
            case 1:
                // We have a single AttributeTypeAndValue
-               result = result * 37 + atav.hashCode();
+               result = result * 17 + atav.hashCode();
                break;
 
            default:
@@ -1239,10 +1346,134 @@
 
                for ( AttributeTypeAndValue ata:atavs )
                {
-                   result = result * 37 + ata.hashCode();
+                   result = result * 17 + ata.hashCode();
                }
+           
+               break;
        }
 
        return result;
    }
+
+
+   /**
+    * @see Externalizable#readExternal(ObjectInput)<p>
+    * 
+    * A RDN is composed of on to many ATAVs (AttributeType And Value).
+    * We should write all those ATAVs sequencially, following the 
+    * structure :
+    * 
+    * <li>nbAtavs</li> The number of ATAVs to write. Can't be 0.
+    * <li>upName</li> The User provided RDN
+    * <li>normName</li> The normalized RDN. It can be empty if the normalized
+    * name equals the upName.
+    * <li>atavs</li>
+    * <p>
+    * For each ATAV :<p>
+    * <li>start</li> The position of this ATAV in the upName string
+    * <li>length</li> The ATAV user provided length
+    * <li>Call the ATAV write method</li> 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;
+       }
+       
+       out.flush();
+   }
+
+
+   /**
+    * @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<p>
+    * 
+    * @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<AttributeTypeAndValue>();
+
+               atavTypes = new MultiHashMap();
+
+               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;
+       }
+   }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java
index 2d9567a..cc16ec2 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnParser.java
@@ -20,8 +20,6 @@
 package org.apache.directory.shared.ldap.name;
 
 
-import java.io.UnsupportedEncodingException;
-
 import javax.naming.InvalidNameException;
 
 import org.apache.directory.shared.ldap.util.DNUtils;
@@ -86,6 +84,7 @@
  * <br>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class RdnParser
 {
@@ -95,20 +94,18 @@
      * &lt;oidValue&gt; ::= [0-9] &lt;digits&gt; &lt;oids&gt;
      * </p>
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the byte buffer
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
+     * @param bytes The bytes array to parse
+     * @param pos The current position in the byte buffer
+     * @return The new position in the vyte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
      */
-    private static String parseOidValue( String string, Position pos )
+    private static String parseOidValue( byte[] bytes, Position pos )
     {
         pos.start += pos.length;
         pos.end = pos.start;
 
         // <attributType> ::= [0-9] <digits> <oids>
-        if ( StringTools.isDigit( string, pos.start ) == false )
+        if ( !StringTools.isDigit( bytes, pos.start ) )
         {
             // Nope... An error
             return null;
@@ -118,13 +115,13 @@
             // Let's process an oid
             pos.end++;
 
-            while ( StringTools.isDigit( string, pos.end ) )
+            while ( StringTools.isDigit( bytes, pos.end ) )
             {
                 pos.end++;
             }
 
             // <oids> ::= '.' [0-9] <digits> <oids> | e
-            if ( StringTools.isCharASCII( string, pos.end, '.' ) == false )
+            if ( !StringTools.isCharASCII( bytes, pos.end, '.' ) )
             {
                 return null;
             }
@@ -134,7 +131,7 @@
                 {
                     pos.end++;
 
-                    if ( StringTools.isDigit( string, pos.end ) == false )
+                    if ( !StringTools.isDigit( bytes, pos.end ) )
                     {
                         return null;
                     }
@@ -142,39 +139,38 @@
                     {
                         pos.end++;
 
-                        while ( StringTools.isDigit( string, pos.end ) )
+                        while ( StringTools.isDigit( bytes, pos.end ) )
                         {
                             pos.end++;
                         }
                     }
 
                 }
-                while ( StringTools.isCharASCII( string, pos.end, '.' ) );
+                while ( StringTools.isCharASCII( bytes, pos.end, '.' ) );
 
-                return string.substring( pos.start - pos.length, pos.end );
+                return StringTools.utf8ToString( bytes, pos.start - pos.length, pos.end - pos.start + pos.length );
             }
         }
     }
 
+    
     /**
      * Validate this rule : <br>
      * <p>
      * &lt;oidValue&gt; ::= [0-9] &lt;digits&gt; &lt;oids&gt;
      * </p>
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the byte buffer
+     * @param bytes The byte array to parse
+     * @param pos The current position in the byte buffer
      * @return <code>true</code> if this is a valid OID
      */
-    private static boolean isValidOidValue( String string, Position pos )
+    private static boolean isValidOidValue( byte[] bytes, Position pos )
     {
         pos.start += pos.length;
         pos.end = pos.start;
 
         // <attributType> ::= [0-9] <digits> <oids>
-        if ( StringTools.isDigit( string, pos.start ) == false )
+        if ( !StringTools.isDigit( bytes, pos.start ) )
         {
             // Nope... An error
             return false;
@@ -184,13 +180,13 @@
             // Let's process an oid
             pos.end++;
 
-            while ( StringTools.isDigit( string, pos.end ) )
+            while ( StringTools.isDigit( bytes, pos.end ) )
             {
                 pos.end++;
             }
 
             // <oids> ::= '.' [0-9] <digits> <oids> | e
-            if ( StringTools.isCharASCII( string, pos.end, '.' ) == false )
+            if ( !StringTools.isCharASCII( bytes, pos.end, '.' ) )
             {
                 return false;
             }
@@ -200,7 +196,7 @@
                 {
                     pos.end++;
 
-                    if ( StringTools.isDigit( string, pos.end ) == false )
+                    if ( !StringTools.isDigit( bytes, pos.end ) )
                     {
                         return false;
                     }
@@ -208,47 +204,46 @@
                     {
                         pos.end++;
 
-                        while ( StringTools.isDigit( string, pos.end ) )
+                        while ( StringTools.isDigit( bytes, pos.end ) )
                         {
                             pos.end++;
                         }
                     }
 
                 }
-                while ( StringTools.isCharASCII( string, pos.end, '.' ) );
+                while ( StringTools.isCharASCII( bytes, pos.end, '.' ) );
 
                 return true;
             }
         }
     }
 
+
     /**
      * Parse this rule : <br>
      * <p>
      * &lt;oidPrefix&gt; ::= 'OID.' | 'oid.' | e
      * </p>
      *
-     * @param bytes
-     *            The buffer to parse
-     * @param pos
-     *            The current position in the char array
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
+     * @param bytes The buffer to parse
+     * @param pos The current position in the byte array
+     * @return The new position in the byte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
      */
-    private static int parseOidPrefix( String string, Position pos )
+    private static int parseOidPrefix( byte[] bytes, Position pos )
     {
-    	if ( StringTools.isICharASCII( string, pos.start, 'O' ) &&
-    		 StringTools.isICharASCII( string, pos.start + 1, 'I' ) && 
-    		 StringTools.isICharASCII( string, pos.start + 2, 'D' ) &&
-    		 StringTools.isICharASCII( string, pos.start + 3, '.' ) )
-    	{
-    		pos.end += DNUtils.OID_LOWER.length();
-    		return DNUtils.PARSING_OK;
-    	}
-    	else
-    	{
-    		return DNUtils.PARSING_ERROR;
-    	}
+        if ( StringTools.isICharASCII( bytes, pos.start, 'O' ) &&
+             StringTools.isICharASCII( bytes, pos.start + 1, 'I' ) && 
+             StringTools.isICharASCII( bytes, pos.start + 2, 'D' ) &&
+             StringTools.isICharASCII( bytes, pos.start + 3, '.' ) )
+        {
+            pos.end += DNUtils.OID_LOWER.length();
+            return DNUtils.PARSING_OK;
+        }
+        else
+        {
+            return DNUtils.PARSING_ERROR;
+        }
     }
 
 
@@ -260,28 +255,26 @@
      * </p>
      * The string *MUST* be an ASCII string, not an unicode string.
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the char array
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
+     * @param bytes The byte array to parse
+     * @param pos The current position in the byte array
+     * @return The new position in the byte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
      */
-    private static String parseAttributeType( String string, Position pos )
+    private static String parseAttributeType( byte[] bytes, Position pos )
     {
         // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9] <digits>
         // <oids> | [0-9] <digits> <oids>
-        if ( StringTools.isAlphaASCII( string, pos.start ) )
+        if ( StringTools.isAlphaASCII( bytes, pos.start ) )
         {
             // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9]
             // <digits> <oids>
 
             // We have got an Alpha char, it may be the begining of an OID ?
-            if ( parseOidPrefix( string, pos ) != DNUtils.PARSING_ERROR )
+            if ( parseOidPrefix( bytes, pos ) != DNUtils.PARSING_ERROR )
             {
                 pos.length = 4;
 
-                return parseOidValue( string, pos );
+                return parseOidValue( bytes, pos );
             }
             else
             {
@@ -291,22 +284,23 @@
                 // <keychar> | e
                 pos.end++;
 
-                while ( StringTools.isAlphaDigitMinus( string, pos.end ) )
+                while ( StringTools.isAlphaDigitMinus( bytes, pos.end ) )
                 {
                     pos.end++;
                 }
 
-                return string.substring( pos.start, pos.end );
+                return StringTools.utf8ToString( bytes, pos.start, pos.end - pos.start );
             }
         }
         else
         {
             // An oid
             // <attributType> ::= [0-9] <digits> <oids>
-            return parseOidValue( string, pos );
+            return parseOidValue( bytes, pos );
         }
     }
 
+
     /**
      * Parse this rule : <br>
      * <p>
@@ -315,28 +309,26 @@
      * </p>
      * The string *MUST* be an ASCII string, not an unicode string.
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the char array
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
+     * @param bytes The byte array to parse
+     * @param pos The current position in the byte array
+     * @return The new position in the byte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
      */
-    private static boolean isValidAttributeType( String string, Position pos )
+    private static boolean isValidAttributeType( byte[] bytes, Position pos )
     {
         // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9] <digits>
         // <oids> | [0-9] <digits> <oids>
-        if ( StringTools.isAlphaASCII( string, pos.start ) )
+        if ( StringTools.isAlphaASCII( bytes, pos.start ) )
         {
             // <attributType> ::= [a-zA-Z] <keychars> | <oidPrefix> [0-9]
             // <digits> <oids>
 
             // We have got an Alpha char, it may be the begining of an OID ?
-            if ( parseOidPrefix( string, pos ) != DNUtils.PARSING_ERROR )
+            if ( parseOidPrefix( bytes, pos ) != DNUtils.PARSING_ERROR )
             {
                 pos.length = 4;
 
-                return isValidOidValue( string, pos );
+                return isValidOidValue( bytes, pos );
             }
             else
             {
@@ -346,7 +338,7 @@
                 // <keychar> | e
                 pos.end++;
 
-                while ( StringTools.isAlphaDigitMinus( string, pos.end ) )
+                while ( StringTools.isAlphaDigitMinus( bytes, pos.end ) )
                 {
                     pos.end++;
                 }
@@ -358,7 +350,7 @@
         {
             // An oid
             // <attributType> ::= [0-9] <digits> <oids>
-            return isValidOidValue( string, pos );
+            return isValidOidValue( bytes, pos );
         }
     }
 
@@ -376,17 +368,23 @@
      * &lt;quotechar-or-pairs&gt; | e <br>
      * </p>
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the char array
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
+     * @param bytes The byte array to parse
+     * @param pos The current position in the byte array
+     * @return The new position in the byte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
      */
-    private static Object parseAttributeValue( String string, Position pos )
+    private static Object parseAttributeValue( byte[] bytes, Position pos )
     {
-        StringBuffer sb = new StringBuffer();
-        char c = StringTools.charAt( string, pos.start );
+        if ( pos.start == bytes.length )
+        {
+            // This is an empty value
+            return "";
+        }
+        
+        //StringBuffer sb = new StringBuffer();
+        byte c = bytes[pos.start];
+        byte[] buffer = new byte[bytes.length];
+        int currPos = 0;
 
         if ( c == '#' )
         {
@@ -395,7 +393,7 @@
             int currentPos = pos.start;
 
             // First, we will count the number of hexPairs
-            while ( DNUtils.parseHexPair( string, currentPos ) >= 0 )
+            while ( DNUtils.parseHexPair( bytes, currentPos ) >= 0 )
             {
                 nbHex++;
                 currentPos += DNUtils.TWO_CHARS;
@@ -405,13 +403,13 @@
 
             // Now, convert the value
             // <attributeValue> ::= '#' <hexstring>
-            if ( DNUtils.parseHexString( string, hexValue, pos ) == DNUtils.PARSING_ERROR )
+            if ( DNUtils.parseHexString( bytes, hexValue, pos ) == DNUtils.PARSING_ERROR )
             {
                 return null;
             }
 
             pos.start--;
-            StringTools.trimRight( string, pos );
+            StringTools.trimRight( bytes, pos );
             pos.length = pos.end - pos.start;
 
             return hexValue;
@@ -419,44 +417,64 @@
         else if ( c == '"' )
         {
             pos.start++;
-            pos.length = 0;
             pos.end = pos.start;
             int nbBytes = 0;
+            int length = 0;
 
             // <attributeValue> ::= '"' <quotechar-or-pair> '"'
             // <quotechar-or-pairs> ::= <quotechar> <quotechar-or-pairs> | '\'
             //                                                  <pairchar> <quotechar-or-pairs> | e
             while ( true )
             {
-                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                if ( StringTools.isCharASCII( bytes, pos.end, '\\' ) )
                 {
                     pos.end++;
                     int nbChars = 0;
 
-                    if ( ( nbChars = DNUtils.isPairChar( string, pos.start ) ) != DNUtils.PARSING_ERROR )
-                    {
-                        pos.end += nbChars;
-                    }
-                    else
+                    if ( ( nbChars = DNUtils.countPairChar( bytes, pos.end ) ) == DNUtils.PARSING_ERROR )
                     {
                         return null;
                     }
+                    else
+                    {
+                        if ( nbChars == 1 )
+                        {
+                            buffer[currPos++] = bytes[pos.end];
+                        }
+                        else
+                        {
+                            byte b = StringTools.getHexValue( bytes[pos.end], bytes[pos.end + 1] );
+
+                            buffer[currPos++] = b;
+                        }
+                        
+                        pos.end += nbChars;
+                        length += nbChars;
+                    }
                 }
-                else if ( ( nbBytes = DNUtils.isQuoteChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                else if ( ( nbBytes = DNUtils.isQuoteChar( bytes, pos.end ) ) != DNUtils.PARSING_ERROR )
                 {
+                    for ( int i = 0; i < nbBytes; i++ )
+                    {
+                        buffer[currPos++] = bytes[pos.end + i];
+                    }
+                    
                     pos.end += nbBytes;
+                    length += nbBytes;
                 }
                 else
                 {
-                    pos.length = pos.end - pos.start;
+                    //pos.length = pos.end - pos.start;
                     break;
                 }
             }
 
-            if ( StringTools.isCharASCII( string, pos.end, '"' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '"' ) )
             {
                 pos.end++;
-                return string.substring( pos.start, pos.start + pos.length );
+                pos.length = length + 2;
+                return StringTools.utf8ToString( buffer, length );
+                //return StringTools.utf8ToString( bytes, pos.start, pos.length );
             }
             else
             {
@@ -466,17 +484,17 @@
         else
         {
             int escapedSpace = -1;
-            boolean hasPairChar = false;
 
             while ( true )
             {
-                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                if ( StringTools.isCharASCII( bytes, pos.end, '\\' ) )
                 {
                     // '\' <pairchar> <pairs-or-strings>
                     pos.end++;
 
                     int nbChars = 0;
-                    if ( ( nbChars = DNUtils.isPairChar( string, pos.end ) ) == DNUtils.PARSING_ERROR )
+                    
+                    if ( ( nbChars = DNUtils.countPairChar( bytes, pos.end ) ) == DNUtils.PARSING_ERROR )
                     {
                         return null;
                     }
@@ -484,23 +502,22 @@
                     {
                         if ( nbChars == 1 )
                         {
-                            sb.append( string.charAt( pos.end ) );
+                            buffer[currPos++] = bytes[pos.end];
                         }
                         else
                         {
-                            if ( hasPairChar == false )
-                            {
-                                hasPairChar = true;
-                            }
+                            byte b = StringTools.getHexValue( bytes[pos.end], bytes[pos.end + 1] );
 
-                            byte b = StringTools.getHexValue( string.charAt( pos.end ), string.charAt( pos.end + 1 ) );
-
-                            sb.append( (char)(b & 0x00FF) );
+                            buffer[currPos++] = b;
                         }
 
-                        if ( string.charAt( pos.end ) == ' ' )
+                        if ( bytes[pos.end] == ' ' )
                         {
-                            escapedSpace = sb.length();
+                            escapedSpace = currPos;
+                        }
+                        else
+                        {
+                            escapedSpace = -1;
                         }
 
                         pos.end += nbChars;
@@ -511,63 +528,68 @@
                     int nbChars = 0;
 
                     // <stringchar> <pairs-or-strings>
-                    if ( ( nbChars = DNUtils.isStringChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                    if ( ( nbChars = DNUtils.isStringChar( bytes, pos.end ) ) != DNUtils.PARSING_ERROR )
                     {
+                        // If the char is not a space, we have to switch off the escapedSpace flag
+                        if ( ( escapedSpace != -1 ) && ! StringTools.isCharASCII( bytes, pos.end, ' ' ) )
+                        {
+                            escapedSpace = -1;
+                        }
+                        
                         // A special case : if we have some spaces before the
                         // '+' character,
                         // we MUST skip them.
-                        if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+                        if ( StringTools.isCharASCII( bytes, pos.end, '+' ) )
                         {
                             //StringTools.trimLeft( string, pos );
 
-                            if ( ( DNUtils.isStringChar( string, pos.end ) == DNUtils.PARSING_ERROR )
-                                && ( StringTools.isCharASCII( string, pos.end, '\\' ) == false ) )
+                            if ( ( DNUtils.isStringChar( bytes, pos.end ) == DNUtils.PARSING_ERROR )
+                                && ( !StringTools.isCharASCII( bytes, pos.end, '\\' ) ) )
                             {
                                 // Ok, we are done with the stringchar.
-                                String result = string.substring( pos.start, pos.start + pos.length );
+                                String result = StringTools.trimRight( 
+                                    StringTools.utf8ToString( bytes, pos.start, pos.start + pos.length ) );
                                 
-                                if ( hasPairChar )
-                                {
-                                    return unescapeValue( result );
-                                }
-                                else
-                                {
-                                    return result; 
-                                }
+                                return result;
                             }
                             else
                             {
-                                sb.append( string.charAt( pos.end ) );
-                                pos.end++;
+                                for ( int i = 0; i < nbChars; i++ )
+                                {
+                                    buffer[currPos++] = bytes[pos.end];
+                                    pos.end ++;
+                                }
                             }
                         }
                         else
                         {
-                            sb.append( string.charAt( pos.end ) );
-                            pos.end += nbChars;
+                            for ( int i = 0; i < nbChars; i++ )
+                            {
+                                buffer[currPos++] = bytes[pos.end];
+                                pos.end ++;
+                            }
                         }
                     }
                     else
                     {
                         pos.length = pos.end - pos.start;
-                        String value = sb.toString();
-                        String result = StringTools.trimRight( value, escapedSpace );
-
-                        if ( hasPairChar )
+                        
+                        if ( escapedSpace == -1 )
                         {
-                            return unescapeValue( result );
-                        }
-                        else
-                        {
+                            String result = StringTools.trimRight( StringTools.utf8ToString( buffer, currPos ) );
                             return result;
                         }
                         
+                        String result = StringTools.utf8ToString( buffer, escapedSpace );
+
+                        return result;
                     }
                 }
             }
         }
     }
 
+
     /**
      * Validate this rule : <br>
      * <p>
@@ -581,15 +603,19 @@
      * &lt;quotechar-or-pairs&gt; | e <br>
      * </p>
      *
-     * @param chars
-     *            The char array to parse
-     * @param pos
-     *            The current position in the char array
+     * @param bytes The byte array to parse
+     * @param pos The current position in the byte array
      * @return <code>true</code> if the rule is valid
      */
-    private static boolean isValidAttributeValue( String string, Position pos )
+    private static boolean isValidAttributeValue( byte[] bytes, Position pos )
     {
-        char c = StringTools.charAt( string, pos.start );
+        if( bytes.length <= pos.start )
+        {
+            // no attribute value
+            return true;
+        }
+
+        byte c = bytes[pos.start];
 
         if ( c == '#' )
         {
@@ -598,7 +624,7 @@
             int currentPos = pos.start;
 
             // First, we will count the number of hexPairs
-            while ( DNUtils.parseHexPair( string, currentPos ) >= 0 )
+            while ( DNUtils.parseHexPair( bytes, currentPos ) >= 0 )
             {
                 nbHex++;
                 currentPos += DNUtils.TWO_CHARS;
@@ -608,13 +634,13 @@
 
             // Now, convert the value
             // <attributeValue> ::= '#' <hexstring>
-            if ( DNUtils.parseHexString( string, hexValue, pos ) == DNUtils.PARSING_ERROR )
+            if ( DNUtils.parseHexString( bytes, hexValue, pos ) == DNUtils.PARSING_ERROR )
             {
                 return false;
             }
 
             pos.start--;
-            StringTools.trimRight( string, pos );
+            StringTools.trimRight( bytes, pos );
             pos.length = pos.end - pos.start;
 
             return true;
@@ -631,12 +657,12 @@
             //                                                  <pairchar> <quotechar-or-pairs> | e
             while ( true )
             {
-                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                if ( StringTools.isCharASCII( bytes, pos.end, '\\' ) )
                 {
                     pos.end++;
                     int nbChars = 0;
 
-                    if ( ( nbChars = DNUtils.isPairChar( string, pos.start ) ) != DNUtils.PARSING_ERROR )
+                    if ( ( nbChars = DNUtils.countPairChar( bytes, pos.end ) ) != DNUtils.PARSING_ERROR )
                     {
                         pos.end += nbChars;
                     }
@@ -645,7 +671,7 @@
                         return false;
                     }
                 }
-                else if ( ( nbBytes = DNUtils.isQuoteChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                else if ( ( nbBytes = DNUtils.isQuoteChar( bytes, pos.end ) ) != DNUtils.PARSING_ERROR )
                 {
                     pos.end += nbBytes;
                 }
@@ -656,7 +682,7 @@
                 }
             }
 
-            if ( StringTools.isCharASCII( string, pos.end, '"' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '"' ) )
             {
                 pos.end++;
                 return true;
@@ -670,14 +696,14 @@
         {
             while ( true )
             {
-                if ( StringTools.isCharASCII( string, pos.end, '\\' ) )
+                if ( StringTools.isCharASCII( bytes, pos.end, '\\' ) )
                 {
                     // '\' <pairchar> <pairs-or-strings>
                     pos.end++;
 
                     int nbChars = 0;
                     
-                    if ( ( nbChars = DNUtils.isPairChar( string, pos.end ) ) == DNUtils.PARSING_ERROR )
+                    if ( ( nbChars = DNUtils.countPairChar( bytes, pos.end ) ) == DNUtils.PARSING_ERROR )
                     {
                         return false;
                     }
@@ -691,17 +717,17 @@
                     int nbChars = 0;
 
                     // <stringchar> <pairs-or-strings>
-                    if ( ( nbChars = DNUtils.isStringChar( string, pos.end ) ) != DNUtils.PARSING_ERROR )
+                    if ( ( nbChars = DNUtils.isStringChar( bytes, pos.end ) ) != DNUtils.PARSING_ERROR )
                     {
                         // A special case : if we have some spaces before the
                         // '+' character,
                         // we MUST skip them.
-                        if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+                        if ( StringTools.isCharASCII( bytes, pos.end, '+' ) )
                         {
                             //StringTools.trimLeft( string, pos );
 
-                            if ( ( DNUtils.isStringChar( string, pos.end ) == DNUtils.PARSING_ERROR )
-                                && ( StringTools.isCharASCII( string, pos.end, '\\' ) == false ) )
+                            if ( ( DNUtils.isStringChar( bytes, pos.end ) == DNUtils.PARSING_ERROR )
+                                && ( !StringTools.isCharASCII( bytes, pos.end, '\\' ) ) )
                             {
                                 // Ok, we are done with the stringchar.
                                 return true;
@@ -734,24 +760,29 @@
      * &lt;attributeValue&gt; &lt;nameComponents&gt; | e
      * </p>
      *
-     * @param chars
-     *            The char buffer to parse
-     * @param pos
-     *            The current position in the byte buffer
-     * @return The new position in the char buffer, or PARSING_ERROR if the rule
-     *         does not apply to the char buffer
+     * @param bytes The byte buffer to parse
+     * @param pos The current position in the byte buffer
+     * @param rdn The rdn to generate
+     * @return The new position in the byte buffer, or PARSING_ERROR if the rule
+     *         does not apply to the byte buffer
+     * @throws InvalidNameException If the NameComponent is invalid
      */
-    private static int parseNameComponents( String string, Position pos, Rdn rdn ) throws InvalidNameException
+    private static int parseNameComponents( byte[] bytes, Position pos, Rdn rdn ) throws InvalidNameException
     {
+        if ( rdn == null )
+        {
+            throw new InvalidNameException( "The RDN should not be null" );
+        }
+        
         int newStart = 0;
         String type = null;
         Object value = null;
 
         while ( true )
         {
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '+' ) )
             {
                 pos.start++;
             }
@@ -762,18 +793,18 @@
                 return DNUtils.PARSING_OK;
             }
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( ( type = parseAttributeType( string, pos ) ) == null )
+            if ( ( type = parseAttributeType( bytes, pos ) ) == null )
             {
                 return DNUtils.PARSING_ERROR;
             }
 
             pos.start = pos.end;
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( StringTools.isCharASCII( string, pos.end, '=' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '=' ) )
             {
                 pos.start++;
             }
@@ -782,9 +813,9 @@
                 return DNUtils.PARSING_ERROR;
             }
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            value = parseAttributeValue( string, pos );
+            value = parseAttributeValue( bytes, pos );
 
             newStart = pos.end;
 
@@ -810,21 +841,20 @@
      * &lt;attributeValue&gt; &lt;nameComponents&gt; | e
      * </p>
      *
-     * @param chars
-     *            The char buffer to parse
-     * @param pos
-     *            The current position in the byte buffer
+     * @param bytes The byte buffer to parse
+     * @param pos The current position in the byte buffer
+     * @param isFirstRdn A flag set if the RDN is the first one
      * @return <code>true</code> if the rule is valid
      */
-    private static boolean isValidNameComponents( String string, Position pos, boolean isFirstRdn )
+    private static boolean isValidNameComponents( byte[] bytes, Position pos, boolean isFirstRdn )
     {
         int newStart = 0;
 
         while ( true )
         {
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( StringTools.isCharASCII( string, pos.end, '+' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '+' ) )
             {
                 pos.start++;
             }
@@ -834,18 +864,18 @@
                 return true;
             }
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( !isValidAttributeType( string, pos ) )
+            if ( !isValidAttributeType( bytes, pos ) )
             {
                 return false;
             }
 
             pos.start = pos.end;
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( StringTools.isCharASCII( string, pos.end, '=' ) )
+            if ( StringTools.isCharASCII( bytes, pos.end, '=' ) )
             {
                 pos.start++;
             }
@@ -854,9 +884,9 @@
                 return false;
             }
 
-            StringTools.trimLeft( string, pos );
+            StringTools.trimLeft( bytes, pos );
 
-            if ( !isValidAttributeValue( string, pos ) )
+            if ( !isValidAttributeValue( bytes, pos ) )
             {
                 return false;
             }
@@ -867,37 +897,6 @@
         }
     }
 
-    /**
-     * Unescape pairChars.
-     * 
-     * A PairChar can be a char if it's 
-     *
-     * @param value The value to modify
-     * @param pos
-     *            The current position in the char array
-     * @return The new position in the char array, or PARSING_ERROR if the rule
-     *         does not apply to the char array
-     */
-    private static Object unescapeValue( String value ) throws IllegalArgumentException
-    {
-        byte[] bytes = new byte[value.length()];
-        int pos = 0;
-
-        for ( int i = 0; i < value.length(); i++ ) 
-        {
-            bytes[pos++] = (byte)value.charAt( i );
-        }
-        
-        try
-        {
-            return new String( bytes, "UTF-8" );
-        }
-        catch ( UnsupportedEncodingException uee )
-        {
-            return bytes;
-        }
-    }
-
 
     /**
      * Parse a NameComponent : <br>
@@ -911,9 +910,35 @@
      * @param rdn The constructed RDN
      * @return The new position in the char array, or PARSING_ERROR if the rule
      *         does not apply to the char array
+     * @throws InvalidNameException If the NameComponent is invalid
      */
     public static int parse( String dn, Position pos, Rdn rdn ) throws InvalidNameException
     {
+        return parse( StringTools.getBytesUtf8( dn ), pos, rdn );
+    }
+
+
+    /**
+     * Parse a NameComponent : <br>
+     * <p>
+     * &lt;name-component&gt; ::= &lt;attributeType&gt; &lt;spaces&gt; '='
+     * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
+     * </p>
+     *
+     * @param dn The byte array to parse
+     * @param pos The current position in the buffer
+     * @param rdn The constructed RDN
+     * @return The new position in the byte array, or PARSING_ERROR if the rule
+     *         does not apply to the byte array
+     * @throws InvalidNameException If the NameComponent is invalid
+     */
+    public static int parse( byte[] dn, Position pos, Rdn rdn ) throws InvalidNameException
+    {
+        if ( rdn == null )
+        {
+            throw new InvalidNameException( "Cannot feed a null RDN structure" );
+        }
+        
         String type = null;
         Object value = null;
         int start = pos.start;
@@ -928,14 +953,11 @@
             return DNUtils.PARSING_ERROR;
         }
 
-        if ( rdn != null )
-        {
-            pos.start = pos.end;
-        }
+        pos.start = pos.end;
 
         StringTools.trimLeft( dn, pos );
 
-        if ( StringTools.isCharASCII( dn, pos.start, '=' ) == false )
+        if ( !StringTools.isCharASCII( dn, pos.start, '=' ) )
         {
             return DNUtils.PARSING_ERROR;
         }
@@ -947,31 +969,33 @@
         StringTools.trimLeft( dn, pos );
 
         pos.end = pos.start;
+        
+        int start2 = pos.start;
 
         if ( ( value = parseAttributeValue( dn, pos ) ) == null )
         {
             return DNUtils.PARSING_ERROR;
         }
 
-        if ( rdn != null )
-        {
-            rdn.addAttributeTypeAndValue( type, type, value, value );
-            rdn.normalize();
+        String upValue = StringTools.utf8ToString( dn, start2, pos.length );
+        rdn.addAttributeTypeAndValue( type, type, upValue, value );
 
-            pos.start = pos.end;
-            pos.length = 0;
-        }
+        rdn.normalize();
+
+        pos.start = pos.end;
+        pos.length = 0;
 
         if ( parseNameComponents( dn, pos, rdn ) == DNUtils.PARSING_ERROR )
         {
             return DNUtils.PARSING_ERROR;
         }
         
-        rdn.setUpName( dn.substring( start, pos.end ) );
+        rdn.setUpName( StringTools.utf8ToString( dn, start, pos.end - start ) );
         pos.start = pos.end;
         return DNUtils.PARSING_OK;
     }
 
+
     /**
      * Validate a NameComponent : <br>
      * <p>
@@ -979,11 +1003,12 @@
      * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
      * </p>
      *
-     * @param dn The String to parse
+     * @param dn The byte array to parse
      * @param pos The current position in the buffer
+     * @param isFirstRdn a flag set if the RDN is the first for the current DN
      * @return <code>true</code> if the RDN is valid
      */
-    public static boolean isValid( String dn, Position pos, boolean isfirstRdn )
+    public static boolean isValid( byte[] dn, Position pos, boolean isFirstRdn )
     {
         StringTools.trimLeft( dn, pos );
 
@@ -999,7 +1024,7 @@
 
         StringTools.trimLeft( dn, pos );
 
-        if ( StringTools.isCharASCII( dn, pos.start, '=' ) == false )
+        if ( !StringTools.isCharASCII( dn, pos.start, '=' ) )
         {
             return false;
         }
@@ -1020,7 +1045,7 @@
         pos.start = pos.end;
         pos.length = 0;
 
-        if ( !isValidNameComponents( dn, pos, isfirstRdn )  )
+        if ( !isValidNameComponents( dn, pos, isFirstRdn )  )
         {
             return false;
         }
@@ -1029,6 +1054,7 @@
         return true;
     }
 
+
     /**
      * Parse a NameComponent : <br>
      * <p>
@@ -1036,16 +1062,14 @@
      * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
      * </p>
      *
-     * @param string
-     *            The buffer to parse
-     * @param rdn
-     *            The RDN to fill. Beware that if the RDN is not empty, the new
+     * @param dn The String to parse
+     * @param rdn The RDN to fill. Beware that if the RDN is not empty, the new
      *            AttributeTypeAndValue will be added.
+     * @throws InvalidNameException If the NameComponent is invalid
      */
-    public static void parse( String string, Rdn rdn ) throws InvalidNameException
+    public static void parse( String dn, Rdn rdn ) throws InvalidNameException
     {
-        parse( string, new Position(), rdn );
-        rdn.normalize();
+        parse( StringTools.getBytesUtf8( dn ), new Position(), rdn );
     }
 
     /**
@@ -1055,12 +1079,11 @@
      * &lt;spaces&gt; &lt;attributeValue&gt; &lt;nameComponents&gt;
      * </p>
      *
-     * @param string
-     *            The buffer to parse
+     * @param dn The string to parse
      * @return <code>true</code> if the RDN is valid
      */
-    public static boolean isValid( String string )
+    public static boolean isValid( String dn )
     {
-        return isValid( string, new Position(), false );
+        return isValid( StringTools.getBytesUtf8( dn ), new Position(), false );
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnSerializer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnSerializer.java
new file mode 100644
index 0000000..b2fe402
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/name/RdnSerializer.java
@@ -0,0 +1,150 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.name;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper class which serialize and deserialize a RDN
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class RdnSerializer
+{
+    /** The LoggerFactory used by this class */
+    protected static final Logger LOG = LoggerFactory.getLogger( RdnSerializer.class );
+
+    /**
+     * Serialize a RDN instance
+     * 
+     * A RDN is composed of on to many ATAVs (AttributeType And Value).
+     * We should write all those ATAVs sequencially, following the 
+     * structure :
+     * 
+     * <li>nbAtavs</li> The number of ATAVs to write. Can't be 0.
+     * <li>upName</li> The User provided RDN
+     * <li>normName</li> The normalized RDN. It can be empty if the normalized
+     * name equals the upName.
+     * <li>atavs</li>
+     * <p>
+     * For each ATAV :<p>
+     * <li>start</li> The position of this ATAV in the upName string
+     * <li>length</li> The ATAV user provided length
+     * <li>Call the ATAV write method</li> The ATAV itself
+     *  
+     * @param rdn The RDN to serialize
+     * @param out the stream in which the RDN will be serialized
+     * @throws IOException If we can't write in this stream
+     */
+    public static void serialize( Rdn rdn, ObjectOutput out ) throws IOException
+    {
+        out.writeInt( rdn.getNbAtavs() );
+        out.writeUTF( rdn.getUpName() );
+        out.writeUTF( rdn.getNormName() );
+        out.writeInt( rdn.getStart() );
+        out.writeInt( rdn.getLength() );
+        
+        switch ( rdn.getNbAtavs() )
+        {
+            case 0 :
+                break;
+
+            case 1 :
+                AtavSerializer.serialize( rdn.getAtav(), out );
+                break;
+                
+            default :
+                for ( AttributeTypeAndValue atav:rdn )
+                {
+                    AtavSerializer.serialize( atav, out );
+                }
+            
+                break;
+        }
+        
+        out.flush();
+    }
+    
+    
+    /**
+     * Deserialize a RDN instance
+     * 
+     * We read back the data to create a new RDB. The structure 
+     * read is exposed in the {@link Rdn#writeExternal(ObjectOutput)} 
+     * method<p>
+     * 
+     * @param in The input stream from which the RDN is read
+     * @return a deserialized RDN
+     * @throws IOException If the stream can't be read
+     */
+    public static Rdn deserialize( ObjectInput in ) throws IOException
+    {
+        // Read the ATAV number
+        int nbAtavs = in.readInt();
+        
+        // Read the UPName
+        String upName = in.readUTF();
+        
+        // Read the normName
+        String normName = in.readUTF();
+        
+        if ( StringTools.isEmpty( normName ) )
+        {
+            normName = upName;
+        }
+        
+        // Read the RDN's position and length
+        int start = in.readInt();
+        int length = in.readInt();
+        
+        // Now creates the RDN
+        Rdn rdn = new Rdn( length, start, upName, normName );
+
+        // Read through the Atavs
+        switch ( nbAtavs )
+        {
+            case 0 :
+                return rdn;
+                
+            case 1 :
+                AttributeTypeAndValue atav = AtavSerializer.deserialize( in );
+                
+                rdn.addAttributeTypeAndValue( atav );
+
+                return rdn;
+                
+            default :
+                for ( int i = 0; i < nbAtavs; i++  )
+                {
+                    atav = AtavSerializer.deserialize( in );
+                    rdn.addAttributeTypeAndValue( atav );
+                }
+            
+                return rdn;
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractAttributeType.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractAttributeType.java
index e05b1d1..fcfc005 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractAttributeType.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractAttributeType.java
@@ -21,6 +21,7 @@
 
 
 import java.io.Serializable;
+import javax.naming.NamingException;
 
 
 /**
@@ -74,6 +75,8 @@
 
     /**
      * @see AttributeType#isSingleValue()
+     * @return true if only one value can exist for this AttributeType, false
+     *         otherwise
      */
     public boolean isSingleValue()
     {
@@ -83,6 +86,7 @@
 
     /**
      * @see AttributeType#isCollective()
+     * @return true if the attribute is collective, false otherwise
      */
     public boolean isCollective()
     {
@@ -92,6 +96,7 @@
 
     /**
      * @see AttributeType#isCanUserModify()
+     * @return true if users can modify it, false if only the directory can.
      */
     public boolean isCanUserModify()
     {
@@ -101,6 +106,7 @@
 
     /**
      * @see AttributeType#getUsage()
+     * @return a type safe UsageEnum
      */
     public UsageEnum getUsage()
     {
@@ -110,6 +116,7 @@
 
     /**
      * @see AttributeType#getLength()
+     * @return the length of the attribute
      */
     public int getLength()
     {
@@ -121,6 +128,7 @@
     // M U T A T O R S
     // ------------------------------------------------------------------------
 
+
     /**
      * Sets whether or not an attribute of this AttributeType single valued or
      * multi-valued.
@@ -182,4 +190,71 @@
     {
         this.length = length;
     }
+
+
+    // -----------------------------------------------------------------------
+    // Additional Methods
+    // -----------------------------------------------------------------------
+    /**
+     * Checks to see if this AttributeType is the ancestor of another
+     * attributeType.
+     *
+     * @param descendant the perspective descendant to check
+     * @return true if the descendant is truly a derived from this AttributeType
+     * @throws NamingException if there are problems resolving superior types
+     */
+    public boolean isAncestorOf( AttributeType descendant ) throws NamingException
+    {
+        if ( ( descendant == null ) || equals( descendant ) )
+        {
+            return false;
+        }
+
+        return isAncestorOrEqual( this, descendant );
+    }
+
+
+    /**
+     * Checks to see if this AttributeType is the descendant of another
+     * attributeType.
+     *
+     * @param ancestor the perspective ancestor to check
+     * @return true if this AttributeType truly descends from the ancestor
+     * @throws NamingException if there are problems resolving superior types
+     */
+    public boolean isDescentantOf( AttributeType ancestor ) throws NamingException
+    {
+        if ( ( ancestor == null ) || equals( ancestor ) )
+        {
+            return false;
+        }
+
+        return isAncestorOrEqual( ancestor, this );
+    }
+
+
+    /**
+     * Recursive method which checks to see if a descendant is really an ancestor or if the two
+     * are equal.
+     *
+     * @param ancestor the possible ancestor of the descendant
+     * @param descendant the possible descendant of the ancestor
+     * @return true if the ancestor equals the descendant or if the descendant is really
+     * a subtype of the ancestor. otherwise false
+     * @throws NamingException if there are issues with superior attribute resolution
+     */
+    private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant ) throws NamingException
+    {
+        if ( ( ancestor == null ) || ( descendant == null ) )
+        {
+            return false;
+        }
+
+        if ( ancestor.equals( descendant ) )
+        {
+            return true;
+        }
+
+        return isAncestorOrEqual( ancestor, descendant.getSuperior() );
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSchemaObject.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSchemaObject.java
index e909cab..55eb573 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSchemaObject.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSchemaObject.java
@@ -35,7 +35,7 @@
     protected final String oid;
 
     /** whether or not this SchemaObject is active */
-    protected boolean isObsolete = false;
+    protected boolean isObsolete;
 
     /** a human readable identifiers for this SchemaObject */
     protected String[] names = ArrayUtils.EMPTY_STRING_ARRAY;
@@ -156,7 +156,8 @@
 
         if ( names != null )
         {
-            this.names = names;
+            this.names = new String[names.length];
+            System.arraycopy( names, 0, this.names, 0, names.length );
         }
     }
 
@@ -167,6 +168,8 @@
 
     /**
      * @see SchemaObject#getOid()
+     * @return an OID for this SchemaObject or its MatchingRule if this
+     *         SchemaObject is a MatchingRuleUse object
      */
     public String getOid()
     {
@@ -176,6 +179,7 @@
 
     /**
      * @see SchemaObject#isObsolete()
+     * @return true if inactive, false if active
      */
     public boolean isObsolete()
     {
@@ -185,8 +189,9 @@
 
     /**
      * @see SchemaObject#getNames()
+     * @return the names for this SchemaObject
      */
-    public String[] getNames()
+    public String[] getNamesRef()
     {
         return names;
     }
@@ -194,6 +199,7 @@
 
     /**
      * @see SchemaObject#getSchema()
+     * @return the name of the schema associated with this schemaObject
      */
     public String getSchema()
     {
@@ -203,6 +209,8 @@
     
     /**
      * @see SchemaObject#getName()
+     * @return the first of the names for this SchemaObject or null if one does
+     *         not exist
      */
     public String getName()
     {
@@ -212,6 +220,7 @@
 
     /**
      * @see SchemaObject#getDescription()
+     * @return a short description about this SchemaObject
      */
     public String getDescription()
     {
@@ -255,7 +264,8 @@
      */
     protected void setNames( String[] names )
     {
-        this.names = names;
+        this.names = new String[names.length];
+        System.arraycopy( names, 0, this.names, 0, names.length );
     }
 
 
@@ -275,6 +285,7 @@
     // Object overloads
     // ------------------------------------------------------------------------
 
+
     /**
      * Based on the hashCode of the oid property.
      * 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSyntax.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSyntax.java
index df4a0bf..fae23b4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSyntax.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AbstractSyntax.java
@@ -100,6 +100,7 @@
 
     /**
      * @see org.apache.directory.shared.ldap.schema.Syntax#isHumanReadable()
+     * @return true if the syntax can be interpreted by humans, false otherwise
      */
     public final boolean isHumanReadable()
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeType.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeType.java
index 28c67e5..499e716 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeType.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeType.java
@@ -220,4 +220,26 @@
      *             if there is a failure to resolve the matchingRule
      */
     MatchingRule getSubstr() throws NamingException;
+
+
+    /**
+     * Checks to see if this AttributeType is the ancestor of another
+     * attributeType.
+     *
+     * @param descendant the perspective descendant to check
+     * @return true if the descendant is truely a derived from this AttributeType
+     * @throws NamingException if there are problems resolving superior types
+     */
+    boolean isAncestorOf( AttributeType descendant ) throws NamingException;
+
+
+    /**
+     * Checks to see if this AttributeType is the descendant of another
+     * attributeType.
+     *
+     * @param ancestor the perspective ancestor to check
+     * @return true if this AttributeType truely descends from the ancestor
+     * @throws NamingException if there are problems resolving superior types
+     */
+    boolean isDescentantOf( AttributeType ancestor ) throws NamingException;
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ByteArrayComparator.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ByteArrayComparator.java
index 0e830ef..5a83f5a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ByteArrayComparator.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ByteArrayComparator.java
@@ -29,18 +29,16 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class ByteArrayComparator implements Comparator
+public class ByteArrayComparator implements Comparator<byte[]>
 {
-    public static final ByteArrayComparator INSTANCE = new ByteArrayComparator();
+    /** A static instance of this comparator */
+    public static final Comparator<byte[]> INSTANCE = new ByteArrayComparator();
 
-    /* (non-Javadoc)
+    /**
      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
      */
-    public int compare( Object byteArray1, Object byteArray2 )
+    public int compare( byte[] b1, byte[] b2 )
     {
-        byte[] b1 = ( byte[] ) byteArray1;
-        byte[] b2 = ( byte[] ) byteArray2;
-
         // -------------------------------------------------------------------
         // Handle some basis cases
         // -------------------------------------------------------------------
@@ -73,6 +71,7 @@
         }
         
         int minLength = Math.min( b1.length, b2.length );
+        
         for ( int ii = 0; ii < minLength; ii++ )
         {
             if ( b1[ii] > b2[ii] )
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/CachingNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/CachingNormalizer.java
index 1176e60..30f237f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/CachingNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/CachingNormalizer.java
@@ -77,6 +77,10 @@
 
     /**
      * @see org.apache.directory.shared.ldap.schema.Normalizer#normalize(java.lang.Object)
+     * 
+     * @param value the value to normalize. It must *not* be null !
+     * @return the normalized form for a value
+     * @throws NamingException if an error results during normalization
      */
     public Object normalize( Object value ) throws NamingException
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ComparableComparator.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ComparableComparator.java
index e675094..87754e6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ComparableComparator.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ComparableComparator.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.schema;
 
 
-import java.util.Comparator;
 import java.io.Serializable;
+import java.util.Comparator;
 
 
 /**
@@ -30,10 +30,9 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-@SuppressWarnings("unchecked")
 public class ComparableComparator implements Comparator, Serializable
 {
-    static final long serialVersionUID = -5295278271807198471L;
+    private static final long serialVersionUID = -5295278271807198471L;
 
 
     /**
@@ -48,14 +47,37 @@
      */
     public int compare( Object o1, Object o2 )
     {
+        if ( ( o1 == null ) && ( o2 == null ) )
+        {
+            return 0;
+        }
+        
         if ( o1 instanceof Comparable )
         {
-            return ( ( Comparable ) o1 ).compareTo( o2 );
+            if ( o2 == null )
+            {
+                return -1;
+            }
+            else
+            {
+                return ( ( Comparable ) o1 ).compareTo( o2 );
+            }
         }
 
-        if ( o2 instanceof Comparable )
+        if ( o2 == null )
         {
-            return -( ( Comparable ) o2 ).compareTo( o1 );
+            return 1;
+        }
+        else if ( o2 instanceof Comparable )
+        {
+            if ( o1 == null )
+            {
+                return -1;
+            }
+            else
+            {
+                return -( ( Comparable ) o2 ).compareTo( o1 );
+            }
         }
 
         // before https://issues.apache.org/jira/browse/DIRSERVER-928 it was
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimNormalizer.java
index a68e424..c746fff 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimNormalizer.java
@@ -37,7 +37,7 @@
  */
 public class DeepTrimNormalizer implements Normalizer
 {
-   static final long serialVersionUID = 1L;
+   private static final long serialVersionUID = 1L;
 
    public Object normalize( Object value ) throws NamingException
    {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimToLowerNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimToLowerNormalizer.java
index 4d703aa..1909f74 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimToLowerNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DeepTrimToLowerNormalizer.java
@@ -38,7 +38,7 @@
  */
 public class DeepTrimToLowerNormalizer implements Normalizer
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
     public Object normalize( Object value ) throws NamingException
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DefaultObjectClass.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DefaultObjectClass.java
index fde1d3a..0113460 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DefaultObjectClass.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DefaultObjectClass.java
@@ -20,11 +20,11 @@
 package org.apache.directory.shared.ldap.schema;
 
 
-import java.util.List;
-import java.util.ArrayList;
-
 import java.io.Serializable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 
 /**
  * Objectclass specification bean used to store the schema information for an
@@ -35,7 +35,7 @@
  */
 public class DefaultObjectClass extends AbstractSchemaObject implements ObjectClass, Serializable
 {
-    static final long serialVersionUID = -4744807759763092241L;
+    private static final long serialVersionUID = -4744807759763092241L;
 
     /** empty array of ObjectClasses so we do not have to recreate objects */
     private static final ObjectClass[] EMPTY_OCLASS_ARR = new ObjectClass[0];
@@ -109,19 +109,19 @@
 
     public boolean isStructural()
     {
-    	return type == ObjectClassTypeEnum.STRUCTURAL;
+        return type == ObjectClassTypeEnum.STRUCTURAL;
     }
 
 
     public boolean isAbstract()
     {
-    	return type == ObjectClassTypeEnum.ABSTRACT;
+        return type == ObjectClassTypeEnum.ABSTRACT;
     }
 
     
     public boolean isAuxiliary()
     {
-    	return type == ObjectClassTypeEnum.AUXILIARY;
+        return type == ObjectClassTypeEnum.AUXILIARY;
     }
 
     
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DescriptionUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DescriptionUtils.java
index 6d2adbb..843d3da 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DescriptionUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/DescriptionUtils.java
@@ -73,6 +73,8 @@
      *            the attributeType to generate a description for
      * @return the AttributeTypeDescription Syntax for the attributeType in a
      *         pretty formated string
+     * @throws NamingException If an error is raised while accessing some of the attributeType
+     * data 
      */
     public static String getDescription( AttributeType attributeType ) throws NamingException
     {
@@ -173,6 +175,8 @@
      *            the DIT content rule specification
      * @return the specification according to the DITContentRuleDescription
      *         syntax
+     * @throws NamingException If an error is raised while accessing some of the dITConentRule
+     * data 
      */
     public static String getDescription( DITContentRule dITContentRule ) throws NamingException
     {
@@ -197,51 +201,59 @@
             buf.append( '\n' );
         }
 
-        // print out all the auxillary object class oids
+        // print out all the auxiliary object class oids
         ObjectClass[] aux = dITContentRule.getAuxObjectClasses();
+        
         if ( aux != null && aux.length > 0 )
         {
             buf.append( "AUX\n" );
-            for ( int ii = 0; ii < aux.length; ii++ )
+            
+            for ( ObjectClass objectClass: aux )
             {
                 buf.append( '\t' );
-                buf.append( aux[ii].getOid() );
+                buf.append( objectClass.getOid() );
                 buf.append( '\n' );
             }
         }
 
         AttributeType[] must = dITContentRule.getMustNames();
+        
         if ( must != null && must.length > 0 )
         {
             buf.append( "MUST\n" );
-            for ( int ii = 0; ii < must.length; ii++ )
+            
+            for ( AttributeType attributeType:must )
             {
                 buf.append( '\t' );
-                buf.append( must[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
 
         AttributeType[] may = dITContentRule.getMayNames();
+        
         if ( may != null && may.length > 0 )
         {
             buf.append( "MAY\n" );
-            for ( int ii = 0; ii < may.length; ii++ )
+            
+            for ( AttributeType attributeType:may )
             {
                 buf.append( '\t' );
-                buf.append( may[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
 
         AttributeType[] not = dITContentRule.getNotNames();
+        
         if ( not != null && not.length > 0 )
         {
             buf.append( "NOT\n" );
-            for ( int ii = 0; ii < not.length; ii++ )
+            
+            for ( AttributeType attributeType:not )
             {
                 buf.append( '\t' );
-                buf.append( not[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
@@ -270,6 +282,8 @@
      * @param matchingRule
      *            the MatchingRule to generate the description for
      * @return the MatchingRuleDescription string
+     * @throws NamingException If an error is raised while accessing some of the matchingRule
+     * data 
      */
     public static String getDescription( MatchingRule matchingRule ) throws NamingException
     {
@@ -331,6 +345,8 @@
      * @param matchingRuleUse The matching rule from which we want to generate
      *  a MatchingRuleUseDescription.
      * @return The generated MatchingRuleUseDescription
+     * @throws NamingException If an error is raised while accessing some of the matchingRuleUse
+     * data 
      */
     public static String getDescription( MatchingRuleUse matchingRuleUse ) throws NamingException
     {
@@ -400,6 +416,8 @@
      * @param nameForm
      *            the NameForm to generate the description for
      * @return the NameFormDescription string
+     * @throws NamingException If an error is raised while accessing some of the nameForm
+     * data 
      */
     public static String getDescription( NameForm nameForm ) throws NamingException
     {
@@ -430,21 +448,24 @@
 
         buf.append( "MUST\n" );
         AttributeType[] must = nameForm.getMustUse();
-        for ( int ii = 0; ii < must.length; ii++ )
+        
+        for ( AttributeType attributeType:must )
         {
             buf.append( '\t' );
-            buf.append( must[ii].getOid() );
+            buf.append( attributeType.getOid() );
             buf.append( '\n' );
         }
 
         AttributeType[] may = nameForm.getMayUse();
+
         if ( may != null && may.length > 0 )
         {
             buf.append( "MAY\n" );
-            for ( int ii = 0; ii < must.length; ii++ )
+        
+            for ( AttributeType attributeType:may )
             {
                 buf.append( '\t' );
-                buf.append( may[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
@@ -477,6 +498,8 @@
      * @param objectClass
      *            the ObjectClass to generate a description for
      * @return the description in the ObjectClassDescription syntax
+     * @throws NamingException If an error is raised while accessing some of the objectClass
+     * data 
      */
     public static String getDescription( ObjectClass objectClass ) throws NamingException
     {
@@ -502,13 +525,15 @@
         }
 
         ObjectClass[] sups = objectClass.getSuperClasses();
+
         if ( sups != null && sups.length > 0 )
         {
             buf.append( "SUP\n" );
-            for ( int ii = 0; ii < sups.length; ii++ )
+            
+            for ( ObjectClass sup:sups )
             {
                 buf.append( '\t' );
-                buf.append( sups[ii].getOid() );
+                buf.append( sup.getOid() );
                 buf.append( '\n' );
             }
         }
@@ -523,22 +548,25 @@
         if ( must != null && must.length > 0 )
         {
             buf.append( "MUST\n" );
-            for ( int ii = 0; ii < must.length; ii++ )
+            
+            for ( AttributeType attributeType:must )
             {
                 buf.append( '\t' );
-                buf.append( must[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
 
         AttributeType[] may = objectClass.getMayList();
+        
         if ( may != null && may.length > 0 )
         {
             buf.append( "MAY\n" );
-            for ( int ii = 0; ii < may.length; ii++ )
+
+            for ( AttributeType attributeType:may )
             {
                 buf.append( '\t' );
-                buf.append( may[ii].getOid() );
+                buf.append( attributeType.getOid() );
                 buf.append( '\n' );
             }
         }
@@ -568,6 +596,8 @@
      * @param dITStructureRule
      *            the DITStructureRule to generate the description for
      * @return the description in the DITStructureRuleDescription syntax
+     * @throws NamingException If an error is raised while accessing some of the dITStructureRule
+     * data 
      */
     public static String getDescription( DITStructureRule dITStructureRule ) throws NamingException
     {
@@ -600,10 +630,11 @@
         if ( sups != null && sups.length > 0 )
         {
             buf.append( "SUP\n" );
-            for ( int ii = 0; ii < sups.length; ii++ )
+            
+            for ( DITStructureRule sup:sups )
             {
                 buf.append( '\t' );
-                buf.append( sups[ii].getOid() );
+                buf.append( sup.getOid() );
                 buf.append( '\n' );
             }
         }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/MatchingRule.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/MatchingRule.java
index 34820b5..c7ca961 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/MatchingRule.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/MatchingRule.java
@@ -95,7 +95,7 @@
      * @throws NamingException
      *             if there is a failure resolving the object
      */
-    Comparator getComparator() throws NamingException;
+    Comparator<?> getComparator() throws NamingException;
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/Normalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/Normalizer.java
index ed6c51b..0c7e76b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/Normalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/Normalizer.java
@@ -31,15 +31,16 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public interface Normalizer<T> extends Serializable
+public interface Normalizer extends Serializable
 {
     /**
      * Gets the normalized value.
      * 
-     * @param value the value to normalize. It must *not* be null !
+     * @param value
+     *            the value to normalize. It must *not* be null !
      * @return the normalized form for a value
      * @throws NamingException
      *             if an error results during normalization
      */
-    T normalize( T value ) throws NamingException;
+    Object normalize( Object value ) throws NamingException;
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ObjectIdentifierNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ObjectIdentifierNormalizer.java
index 43ba53d..d0bc756 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ObjectIdentifierNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/ObjectIdentifierNormalizer.java
@@ -31,7 +31,7 @@
  */
 public class ObjectIdentifierNormalizer implements Normalizer
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
     public Object normalize( Object value ) throws NamingException
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/OidNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/OidNormalizer.java
index 287139f..41e7e6e 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/OidNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/OidNormalizer.java
@@ -33,7 +33,7 @@
     private String attributeTypeOid;
 
     /** The normalizer to be used with this OID */
-    private Normalizer<?> normalizer;
+    private Normalizer normalizer;
 
 
     /**
@@ -42,7 +42,7 @@
      * @param attributeTypeOid the oid of the attributeType mapped to the normalizer
      * @param normalizer the associated equality match based normalizer
      */
-    public OidNormalizer( String attributeTypeOid, Normalizer<?> normalizer )
+    public OidNormalizer( String attributeTypeOid, Normalizer normalizer )
     {
         this.attributeTypeOid = attributeTypeOid;
         this.normalizer = normalizer;
@@ -66,7 +66,7 @@
      * 
      * @return The normalizer associated to the current OID
      */
-    public Normalizer<?> getNormalizer()
+    public Normalizer getNormalizer()
     {
         return normalizer;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/PrepareString.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/PrepareString.java
index f0fdcaf..58d84ee 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/PrepareString.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/PrepareString.java
@@ -90,6 +90,16 @@
         WORD
     }
     
+    
+    /**
+     * A private constructor, to avoid instance creation of this static class.
+     */
+    private PrepareString()
+    {
+        // Do nothing
+    }
+    
+    
     /**
      * Tells if a char is a combining mark.
      *
@@ -127,8 +137,9 @@
     *
     * The first step is already done, the step (3) is not done.
     *
-    * @param str
-    * @return Normalised string.
+    * @param str The String to normalize
+    * @param type The string type
+    * @return A normalized string.
     * @throws IOException
     */
    public static String normalize( String str, StringType type ) throws IOException
@@ -166,7 +177,10 @@
      * - transform to spaces
      * - lowercase
      * 
-     * @param array The char array to transform
+     * @param c The char to map
+     * @param target The array which will collect the transformed char
+     * @param pos The current position in the target
+     * @param lowerCase A mask to lowercase the char, if necessary
      * @return The transformed StringBuilder
      */
     private static int map( char c, char[] target, int pos, char lowerCase )
@@ -3948,6 +3962,7 @@
                 }
                 
                 target[pos++] = c;
+                break;
         }
 
         return pos - start;
@@ -3963,7 +3978,7 @@
      *  - Table C.8 of RFC 3454
      *  - character U-FFFD
      *
-     * @param str The String to analyze
+     * @param c The char to analyze
      * @throws InvalidCharacterException If any character is prohibited
      */
     private static void checkProhibited( char c ) throws InvalidCharacterException
@@ -4118,6 +4133,8 @@
             case 0xFF00 :
             case 0xFFE7 :
                 throw new InvalidCharacterException( c );
+            default:
+                break;
         }
         
         // RFC 3454, Table A.1, intervals
@@ -4528,6 +4545,8 @@
             case 0x206E : // NATIONAL DIGIT SHAPES
             case 0x206F : // NOMINAL DIGIT SHAPES
                 throw new InvalidCharacterException( c );
+            default :
+                break;
         }
         
         if ( c == 0xFFFD ) 
@@ -4591,7 +4610,7 @@
      * will be trasnformed to :
      * "+(33)1123456789"
      *
-     * @param array The telephone number char array
+     * @param str The telephone number
      * @return The modified telephone number String
      */
     private static String insignifiantCharTelephoneNumber( String str )
@@ -4630,6 +4649,7 @@
                     }
                 
                     array[pos++] = c;
+                    break;
             }
         }
         
@@ -4644,7 +4664,7 @@
      * will be transformed to :
      * "123456789"
      *
-     * @param array The numeric char array
+     * @param str The numeric String
      * @return The modified numeric StringBuilder
      */
     private static String insignifiantCharNumericString( String str )
@@ -4687,8 +4707,10 @@
      * This method use a finite state machine to parse
      * the text.
      * 
-     * @param array The char array  representing the string
+     * @param str The String to modify
+     * @param caseSensitive A flag telling if the chars must be lowercased
      * @return The modified StringBuilder
+     * @throws InvalidCharacterException If an invalid character is found in the String
      */
     private static String insignifiantSpacesString( String str, boolean caseSensitive ) throws InvalidCharacterException
     {
@@ -4723,7 +4745,7 @@
         char c = '\0';
         
         // First remove starting spaces
-        for (; i < limit; i++ )
+        for ( i=0; i < limit; i++ )
         {
             c = target[i];
             
@@ -4778,7 +4800,7 @@
         // a list of chars and spaces. We will consider that
         // we have couples of chars and spaces :
         // (char * space*)*. We have a special case :
-        // a space followed by a comining char.
+        // a space followed by a combining char.
         boolean spaceSeen = false;
         boolean space2Seen = false;
         
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/RegexNormalizer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/RegexNormalizer.java
index 4cf0b17..566b76a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/RegexNormalizer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/RegexNormalizer.java
@@ -32,7 +32,7 @@
  */
 public class RegexNormalizer implements Normalizer
 {
-    public static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
     
     /** the perl 5 regex engine */
     private final Pattern[] regexes;
@@ -47,14 +47,24 @@
      * @param regexes
      *            the set of regular expressions used to transform values
      */
-    public RegexNormalizer(Pattern[] regexes)
+    public RegexNormalizer( Pattern[] regexes )
     {
-        this.regexes = regexes;
-        matchers = new Matcher[regexes.length];
-
-        for ( int i = 0; i < regexes.length; i++ )
+        if ( regexes != null )
         {
-            matchers[i] = regexes[i].matcher( "" );
+            this.regexes = new Pattern[ regexes.length ];
+            System.arraycopy( regexes, 0, this.regexes, 0, regexes.length );
+
+            matchers = new Matcher[regexes.length];
+
+            for ( int i = 0; i < regexes.length; i++ )
+            {
+                matchers[i] = regexes[i].matcher( "" );
+            }
+        } 
+        else 
+        {
+            this.regexes = null;
+            matchers = new Matcher[0];
         }
     }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaObject.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaObject.java
index a0ca4c8..689926c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaObject.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaObject.java
@@ -60,7 +60,7 @@
      * 
      * @return the names for this SchemaObject
      */
-    String[] getNames();
+    String[] getNamesRef();
 
 
     /**
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java
index 1b23ecf..ff9594c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java
@@ -28,9 +28,9 @@
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
 
 import org.apache.directory.shared.ldap.message.AttributeImpl;
-import org.apache.directory.shared.ldap.message.ModificationItemImpl;
 import org.apache.directory.shared.ldap.schema.syntax.AbstractAdsSchemaDescription;
 import org.apache.directory.shared.ldap.schema.syntax.AbstractSchemaDescription;
 import org.apache.directory.shared.ldap.schema.syntax.AttributeTypeDescription;
@@ -53,23 +53,26 @@
      * @return the resultant entry after the modifications have taken place
      * @throws NamingException if there are problems accessing attributes
      */
-    public static Attributes getTargetEntry( ModificationItemImpl[] mods, Attributes entry ) throws NamingException
+    public static Attributes getTargetEntry( List<? extends ModificationItem> mods, Attributes entry )
+        throws NamingException
     {
         Attributes targetEntry = ( Attributes ) entry.clone();
-        for ( int ii = 0; ii < mods.length; ii++ )
-        {
-            String id = mods[ii].getAttribute().getID();
 
-            switch ( mods[ii].getModificationOp() )
+        for ( ModificationItem mod : mods )
+        {
+            String id = mod.getAttribute().getID();
+
+            switch ( mod.getModificationOp() )
             {
-                case( DirContext.REPLACE_ATTRIBUTE ):
-                    targetEntry.put( mods[ii].getAttribute() );
+                case ( DirContext.REPLACE_ATTRIBUTE  ):
+                    targetEntry.put( mod.getAttribute() );
                     break;
-                case( DirContext.ADD_ATTRIBUTE ):
+
+                case ( DirContext.ADD_ATTRIBUTE  ):
                     Attribute combined = new AttributeImpl( id );
-                    Attribute toBeAdded = mods[ii].getAttribute();
+                    Attribute toBeAdded = mod.getAttribute();
                     Attribute existing = entry.get( id );
-                    
+
                     if ( existing != null )
                     {
                         for ( int jj = 0; jj < existing.size(); jj++ )
@@ -77,25 +80,26 @@
                             combined.add( existing.get( jj ) );
                         }
                     }
-                    
+
                     for ( int jj = 0; jj < toBeAdded.size(); jj++ )
                     {
                         combined.add( toBeAdded.get( jj ) );
                     }
-                    
+
                     targetEntry.put( combined );
                     break;
-                case( DirContext.REMOVE_ATTRIBUTE ):
-                    Attribute toBeRemoved = mods[ii].getAttribute();
-                    
+
+                case ( DirContext.REMOVE_ATTRIBUTE  ):
+                    Attribute toBeRemoved = mod.getAttribute();
+
                     if ( toBeRemoved.size() == 0 )
                     {
                         targetEntry.remove( id );
                     }
-                    else 
+                    else
                     {
                         existing = targetEntry.get( id );
-                        
+
                         if ( existing != null )
                         {
                             for ( int jj = 0; jj < toBeRemoved.size(); jj++ )
@@ -104,16 +108,18 @@
                             }
                         }
                     }
+
                     break;
+
                 default:
-                    throw new IllegalStateException( "undefined modification type: " + mods[ii].getModificationOp() );
+                    throw new IllegalStateException( "undefined modification type: " + mod.getModificationOp() );
             }
         }
-        
+
         return targetEntry;
     }
 
-    
+
     /**
      * Gets the target entry as it would look after a modification operation 
      * were performed on it.
@@ -130,26 +136,26 @@
         NamingEnumeration<String> list = mods.getIDs();
         switch ( modOp )
         {
-            case( DirContext.REPLACE_ATTRIBUTE ):
+            case ( DirContext.REPLACE_ATTRIBUTE  ):
                 while ( list.hasMore() )
                 {
                     targetEntry.put( mods.get( list.next() ) );
                 }
                 break;
-            case( DirContext.REMOVE_ATTRIBUTE ):
+            case ( DirContext.REMOVE_ATTRIBUTE  ):
                 while ( list.hasMore() )
                 {
                     String id = list.next();
                     Attribute toBeRemoved = mods.get( id );
-                    
+
                     if ( toBeRemoved.size() == 0 )
                     {
                         targetEntry.remove( id );
                     }
-                    else 
+                    else
                     {
                         Attribute existing = targetEntry.get( id );
-                        
+
                         if ( existing != null )
                         {
                             for ( int ii = 0; ii < toBeRemoved.size(); ii++ )
@@ -160,25 +166,25 @@
                     }
                 }
                 break;
-            case( DirContext.ADD_ATTRIBUTE ):
+            case ( DirContext.ADD_ATTRIBUTE  ):
                 while ( list.hasMore() )
                 {
                     String id = list.next();
                     Attribute combined = new AttributeImpl( id );
                     Attribute toBeAdded = mods.get( id );
                     Attribute existing = entry.get( id );
-                    
+
                     if ( existing != null )
                     {
                         for ( int ii = 0; ii < existing.size(); ii++ )
                         {
-                            combined.add( existing.get(ii) );
+                            combined.add( existing.get( ii ) );
                         }
                     }
-                    
+
                     for ( int ii = 0; ii < toBeAdded.size(); ii++ )
                     {
-                        combined.add( toBeAdded.get(ii) );
+                        combined.add( toBeAdded.get( ii ) );
                     }
                     targetEntry.put( combined );
                 }
@@ -186,11 +192,11 @@
             default:
                 throw new IllegalStateException( "undefined modification type: " + modOp );
         }
-        
+
         return targetEntry;
     }
-    
-    
+
+
     // ------------------------------------------------------------------------
     // qdescrs rendering operations
     // ------------------------------------------------------------------------
@@ -414,16 +420,16 @@
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( oc.getOid() );
 
-        if ( oc.getNames() != null && oc.getNames().length > 0 )
+        if ( oc.getNamesRef() != null && oc.getNamesRef().length > 0 )
         {
             buf.append( " NAME " );
-            render( buf, oc.getNames() ).append( " " );
+            render( buf, oc.getNamesRef() ).append( " " );
         }
         else
         {
             buf.append( " " );
         }
-        
+
         if ( oc.getDescription() != null )
         {
             buf.append( "DESC " ).append( "'" ).append( oc.getDescription() ).append( "' " );
@@ -456,7 +462,7 @@
             buf.append( " MAY " );
             render( buf, oc.getMayList() );
         }
-        
+
         buf.append( " X-SCHEMA '" );
         buf.append( oc.getSchema() );
         buf.append( "'" );
@@ -532,11 +538,11 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( at.getOid() );
-        
-        if ( at.getNames() != null && at.getNames().length > 0 )
+
+        if ( at.getNamesRef() != null && at.getNamesRef().length > 0 )
         {
             buf.append( " NAME " );
-            render( buf, at.getNames() ).append( " " );
+            render( buf, at.getNamesRef() ).append( " " );
         }
         else
         {
@@ -683,7 +689,7 @@
         if ( atd.getNames() != null && atd.getNames().size() > 0 )
         {
             buf.append( " NAME " );
-            render( buf, atd.getNames().toArray( new String[ atd.getNames().size() ]) ).append( " " );
+            render( buf, atd.getNames().toArray( new String[atd.getNames().size()] ) ).append( " " );
         }
         else
         {
@@ -763,7 +769,7 @@
     public static StringBuffer render( Map<String, List<String>> extensions )
     {
         StringBuffer buf = new StringBuffer();
-        
+
         if ( extensions.isEmpty() )
         {
             return buf;
@@ -855,11 +861,11 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( mr.getOid() );
-        
-        if ( mr.getNames() != null && mr.getNames().length > 0 )
+
+        if ( mr.getNamesRef() != null && mr.getNamesRef().length > 0 )
         {
             buf.append( " NAME " );
-            render( buf, mr.getNames() ).append( " " );
+            render( buf, mr.getNamesRef() ).append( " " );
         }
         else
         {
@@ -929,7 +935,7 @@
 
         buf.append( " X-SCHEMA '" );
         buf.append( syntax.getSchema() );
-        
+
         if ( syntax.isHumanReadable() )
         {
             buf.append( "' X-IS-HUMAN-READABLE 'true'" );
@@ -955,7 +961,7 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( mru.getOid() ).append( " NAME " );
-        render( buf, mru.getNames() ).append( " " );
+        render( buf, mru.getNamesRef() ).append( " " );
 
         if ( mru.getDescription() != null )
         {
@@ -982,7 +988,7 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( dcr.getOid() ).append( " NAME " );
-        render( buf, dcr.getNames() ).append( " " );
+        render( buf, dcr.getNamesRef() ).append( " " );
 
         if ( dcr.getDescription() != null )
         {
@@ -1009,7 +1015,7 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( dsr.getOid() ).append( " NAME " );
-        render( buf, dsr.getNames() ).append( " " );
+        render( buf, dsr.getNamesRef() ).append( " " );
 
         if ( dsr.getDescription() != null )
         {
@@ -1031,7 +1037,7 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( nf.getOid() ).append( " NAME " );
-        render( buf, nf.getNames() ).append( " " );
+        render( buf, nf.getNamesRef() ).append( " " );
 
         if ( nf.getDescription() != null )
         {
@@ -1050,36 +1056,36 @@
     {
         StringBuffer buf = new StringBuffer();
         buf.append( "( " ).append( description.getNumericOid() ).append( " " );
-        
+
         if ( description.getDescription() != null )
         {
             buf.append( "DESC " ).append( "'" ).append( description.getDescription() ).append( "' " );
         }
 
         buf.append( "FQCN " ).append( description.getFqcn() ).append( " " );
-        
+
         if ( description.getBytecode() != null )
         {
             buf.append( "BYTECODE " ).append( description.getBytecode() );
         }
-        
+
         buf.append( " X-SCHEMA '" );
         buf.append( getSchema( description ) );
         buf.append( "' )" );
-        
+
         return buf;
     }
-    
-    
+
+
     private static String getSchema( AbstractSchemaDescription desc )
     {
         List<String> values = desc.getExtensions().get( "X-SCHEMA" );
-        
+
         if ( values == null || values.size() == 0 )
         {
             return "other";
         }
-        
+
         return values.get( 0 );
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/UsageEnum.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/UsageEnum.java
index d166572..63f9e66 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/UsageEnum.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/UsageEnum.java
@@ -86,26 +86,26 @@
         }
         catch( IllegalArgumentException iae )
         {
-        	if ( "directoryOperation".equals( usage ) )
-        	{
-        		return DIRECTORY_OPERATION;
-        	}
-        	else if ( "distributedOperation".equals( usage ) )
-        	{
-        		return DISTRIBUTED_OPERATION;
-        	}
-        	else if ( "dSAOperation".equals( usage ) )
-        	{
-        		return DSA_OPERATION;	
-        	}
-        	else if ( "userApplications".equals( usage ) ) 
-        	{
-        		return USER_APPLICATIONS;
-        	}
-        	else 
-        	{
-        		return null;
-        	}
+            if ( "directoryOperation".equals( usage ) )
+            {
+                return DIRECTORY_OPERATION;
+            }
+            else if ( "distributedOperation".equals( usage ) )
+            {
+                return DISTRIBUTED_OPERATION;
+            }
+            else if ( "dSAOperation".equals( usage ) )
+            {
+                return DSA_OPERATION;    
+            }
+            else if ( "userApplications".equals( usage ) ) 
+            {
+                return USER_APPLICATIONS;
+            }
+            else 
+            {
+                return null;
+            }
         }
     }
     
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/overview.html b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/overview.html
index 3463804..fd49d47 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/overview.html
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/overview.html
@@ -1,4 +1,23 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
 <HTML>
 <HEAD>
 	<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/package.html b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/package.html
index 41acabe..15abed8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/package.html
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/package.html
@@ -1,4 +1,23 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
 <HTML>
 <BODY LANG="en-US" DIR="LTR">
 <P>
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/AttributeTypeLiteral.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/AttributeTypeLiteral.java
new file mode 100644
index 0000000..1ee0463
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/AttributeTypeLiteral.java
@@ -0,0 +1,274 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema.parser;
+
+
+import org.apache.directory.shared.ldap.schema.UsageEnum;
+import org.apache.directory.shared.ldap.util.ArrayUtils;
+
+
+/**
+ * A bean used to hold the literal values of an AttributeType parsed out of an
+ * OpenLDAP schema configuration file.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 504954 $
+ */
+public class AttributeTypeLiteral
+{
+    private boolean obsolete = false;
+    private boolean singleValue = false;
+    private boolean collective = false;
+    private boolean noUserModification = false;
+
+    private String oid;
+    private String description;
+    private String superior;
+    private String equality;
+    private String ordering;
+    private String substr;
+    private String syntax;
+
+    private UsageEnum usage = UsageEnum.USER_APPLICATIONS;
+
+    private String[] names = ArrayUtils.EMPTY_STRING_ARRAY;
+
+    private int length = -1;
+
+
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+
+    public AttributeTypeLiteral(String oid)
+    {
+        this.oid = oid;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Accessors and mutators
+    // ------------------------------------------------------------------------
+
+    public boolean isObsolete()
+    {
+        return obsolete;
+    }
+
+
+    public void setObsolete( boolean obsolete )
+    {
+        this.obsolete = obsolete;
+    }
+
+
+    public boolean isSingleValue()
+    {
+        return singleValue;
+    }
+
+
+    public void setSingleValue( boolean singleValue )
+    {
+        this.singleValue = singleValue;
+    }
+
+
+    public boolean isCollective()
+    {
+        return collective;
+    }
+
+
+    public void setCollective( boolean collective )
+    {
+        this.collective = collective;
+    }
+
+
+    public boolean isNoUserModification()
+    {
+        return noUserModification;
+    }
+
+
+    public void setNoUserModification( boolean noUserModification )
+    {
+        this.noUserModification = noUserModification;
+    }
+
+
+    public String getOid()
+    {
+        return oid;
+    }
+
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+
+    public void setDescription( String description )
+    {
+        this.description = description;
+    }
+
+
+    public String getSuperior()
+    {
+        return superior;
+    }
+
+
+    public void setSuperior( String superior )
+    {
+        this.superior = superior;
+    }
+
+
+    public String getEquality()
+    {
+        return equality;
+    }
+
+
+    public void setEquality( String equality )
+    {
+        this.equality = equality;
+    }
+
+
+    public String getOrdering()
+    {
+        return ordering;
+    }
+
+
+    public void setOrdering( String ordering )
+    {
+        this.ordering = ordering;
+    }
+
+
+    public String getSubstr()
+    {
+        return substr;
+    }
+
+
+    public void setSubstr( String substr )
+    {
+        this.substr = substr;
+    }
+
+
+    public String getSyntax()
+    {
+        return syntax;
+    }
+
+
+    public void setSyntax( String syntax )
+    {
+        this.syntax = syntax;
+    }
+
+
+    public UsageEnum getUsage()
+    {
+        return usage;
+    }
+
+
+    public void setUsage( UsageEnum usage )
+    {
+        this.usage = usage;
+    }
+
+
+    public String[] getNames()
+    {
+        return names;
+    }
+
+
+    public void setNames( String[] names )
+    {
+        this.names = names;
+    }
+
+
+    public int getLength()
+    {
+        return length;
+    }
+
+
+    public void setLength( int length )
+    {
+        this.length = length;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Object overrides
+    // ------------------------------------------------------------------------
+
+    /**
+     * Compute the instance's hash code
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        return getOid().hashCode();
+    }
+
+
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( !( obj instanceof AttributeTypeLiteral ) )
+        {
+            return false;
+        }
+
+        return getOid().equals( ( ( AttributeTypeLiteral ) obj ).getOid() );
+    }
+
+
+    public String toString()
+    {
+        return getOid();
+    }
+
+    /**
+     * Method used to modify the AttributeType OID if it is edited.
+     */
+    public void setOid( String oid )
+    {
+        this.oid = oid;
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ObjectClassLiteral.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ObjectClassLiteral.java
new file mode 100644
index 0000000..85e644f
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ObjectClassLiteral.java
@@ -0,0 +1,193 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema.parser;
+
+
+import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
+import org.apache.directory.shared.ldap.util.ArrayUtils;
+
+
+/**
+ * A bean used to encapsulate the literal String values of an ObjectClass
+ * definition found within an OpenLDAP schema configuration file.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437016 $
+ */
+public class ObjectClassLiteral
+{
+    private boolean obsolete = false;
+
+    private String oid;
+    private String description;
+
+    private String[] names = ArrayUtils.EMPTY_STRING_ARRAY;
+    private String[] superiors = ArrayUtils.EMPTY_STRING_ARRAY;
+    private String[] must = ArrayUtils.EMPTY_STRING_ARRAY;
+    private String[] may = ArrayUtils.EMPTY_STRING_ARRAY;
+
+    private ObjectClassTypeEnum classType = ObjectClassTypeEnum.STRUCTURAL;
+
+
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+
+    public ObjectClassLiteral(String oid)
+    {
+        this.oid = oid;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Accessors and mutators
+    // ------------------------------------------------------------------------
+
+    public boolean isObsolete()
+    {
+        return obsolete;
+    }
+
+
+    public void setObsolete( boolean obsolete )
+    {
+        this.obsolete = obsolete;
+    }
+
+
+    public String getOid()
+    {
+        return oid;
+    }
+
+
+    public void setOid( String oid )
+    {
+        this.oid = oid;
+    }
+
+
+    public String getDescription()
+    {
+        return description;
+    }
+
+
+    public void setDescription( String description )
+    {
+        this.description = description;
+    }
+
+
+    public String[] getNames()
+    {
+        return names;
+    }
+
+
+    public void setNames( String[] names )
+    {
+        this.names = names;
+    }
+
+
+    public String[] getSuperiors()
+    {
+        return superiors;
+    }
+
+
+    public void setSuperiors( String[] superiors )
+    {
+        this.superiors = superiors;
+    }
+
+
+    public String[] getMust()
+    {
+        return must;
+    }
+
+
+    public void setMust( String[] must )
+    {
+        this.must = must;
+    }
+
+
+    public String[] getMay()
+    {
+        return may;
+    }
+
+
+    public void setMay( String[] may )
+    {
+        this.may = may;
+    }
+
+
+    public ObjectClassTypeEnum getClassType()
+    {
+        return classType;
+    }
+
+
+    public void setClassType( ObjectClassTypeEnum classType )
+    {
+        this.classType = classType;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Object overrides
+    // ------------------------------------------------------------------------
+
+    /**
+     * Compute the instance's hash code
+     * @return the instance's hash code 
+     */
+    public int hashCode()
+    {
+        return getOid().hashCode();
+    }
+
+
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( !( obj instanceof ObjectClassLiteral ) )
+        {
+            return false;
+        }
+
+        return getOid().equals( ( ( ObjectClassLiteral ) obj ).getOid() );
+    }
+
+
+    public String toString()
+    {
+        return getOid();
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParser.java
new file mode 100644
index 0000000..a4541c2
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParser.java
@@ -0,0 +1,368 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema.parser;
+
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.directory.shared.ldap.schema.syntax.AbstractSchemaDescription;
+import org.apache.directory.shared.ldap.schema.syntax.AttributeTypeDescription;
+import org.apache.directory.shared.ldap.schema.syntax.ObjectClassDescription;
+import org.apache.directory.shared.ldap.schema.syntax.OpenLdapObjectIdentifierMacro;
+import org.apache.directory.shared.ldap.schema.syntax.parser.AbstractSchemaParser;
+import org.apache.directory.shared.ldap.util.ExceptionUtils;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+
+
+/**
+ * A reusable wrapper for antlr generated OpenLDAP schema parsers.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 494164 $
+ */
+public class OpenLdapSchemaParser extends AbstractSchemaParser
+{
+
+    /** The list of parsed schema descriptions */
+    private List<Object> schemaDescriptions;
+
+    /** The list of attribute type literals, initialized by splitParsedSchemaDescriptions() */
+    private List<AttributeTypeLiteral> attributeTypeLiterals;
+
+    /** The list of object class literals, initialized by splitParsedSchemaDescriptions()*/
+    private List<ObjectClassLiteral> objectClassLiterals;
+
+    /** The map of object identifier macros, initialized by splitParsedSchemaDescriptions()*/
+    private Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros;
+
+    /** Flag whether object identifier macros should be resolved. */
+    private boolean isResolveObjectIdentifierMacros;
+
+
+    /**
+     * Creates a reusable instance of an OpenLdapSchemaParser.
+     *
+     * @throws IOException if the pipe cannot be formed
+     */
+    public OpenLdapSchemaParser() throws IOException
+    {
+        isResolveObjectIdentifierMacros = true;
+        super.setQuirksMode( true );
+    }
+
+
+    /**
+     * Reset the parser 
+     */
+    public void clear()
+    {
+    }
+
+
+    /**
+     * Gets the attribute types.
+     * 
+     * @return the attribute types
+     */
+    public List<AttributeTypeLiteral> getAttributeTypes()
+    {
+        return attributeTypeLiterals;
+    }
+
+
+    /**
+     * Gets the object class types.
+     * 
+     * @return the object class types
+     */
+    public List<ObjectClassLiteral> getObjectClassTypes()
+    {
+        return objectClassLiterals;
+    }
+
+
+    /**
+     * Gets the object identifier macros.
+     * 
+     * @return the object identifier macros
+     */
+    public Map<String, OpenLdapObjectIdentifierMacro> getObjectIdentifierMacros()
+    {
+        return objectIdentifierMacros;
+    }
+
+
+    /**
+     * Splits parsed schema descriptions and resolved
+     * object identifier macros.
+     * 
+     * @throws ParseException the parse exception
+     */
+    private void afterParse() throws ParseException
+    {
+        objectClassLiterals = new ArrayList<ObjectClassLiteral>();
+        attributeTypeLiterals = new ArrayList<AttributeTypeLiteral>();
+        objectIdentifierMacros = new HashMap<String, OpenLdapObjectIdentifierMacro>();
+
+        // split parsed schema descriptions
+        for ( Object obj : schemaDescriptions )
+        {
+            if ( obj instanceof OpenLdapObjectIdentifierMacro )
+            {
+                OpenLdapObjectIdentifierMacro oid = ( OpenLdapObjectIdentifierMacro ) obj;
+                objectIdentifierMacros.put( oid.getName(), oid );
+            }
+            else if ( obj instanceof AttributeTypeDescription )
+            {
+                AttributeTypeDescription atd = ( AttributeTypeDescription ) obj;
+                AttributeTypeLiteral literal = new AttributeTypeLiteral( atd.getNumericOid() );
+                literal.setNames( atd.getNames().toArray( new String[atd.getNames().size()] ) );
+                literal.setDescription( atd.getDescription() );
+                literal.setSuperior( atd.getSuperType() );
+                literal.setEquality( atd.getEqualityMatchingRule() );
+                literal.setOrdering( atd.getOrderingMatchingRule() );
+                literal.setSubstr( atd.getSubstringsMatchingRule() );
+                literal.setSyntax( atd.getSyntax() );
+                literal.setLength( atd.getSyntaxLength() );
+                literal.setObsolete( atd.isObsolete() );
+                literal.setCollective( atd.isCollective() );
+                literal.setSingleValue( atd.isSingleValued() );
+                literal.setNoUserModification( !atd.isUserModifiable() );
+                literal.setUsage( atd.getUsage() );
+                attributeTypeLiterals.add( literal );
+            }
+            else if ( obj instanceof ObjectClassDescription )
+            {
+                ObjectClassDescription ocd = ( ObjectClassDescription ) obj;
+                ObjectClassLiteral literal = new ObjectClassLiteral( ocd.getNumericOid() );
+                literal.setNames( ocd.getNames().toArray( new String[ocd.getNames().size()] ) );
+                literal.setDescription( ocd.getDescription() );
+                literal.setSuperiors( ocd.getSuperiorObjectClasses().toArray(
+                    new String[ocd.getSuperiorObjectClasses().size()] ) );
+                literal.setMay( ocd.getMayAttributeTypes().toArray( new String[ocd.getMayAttributeTypes().size()] ) );
+                literal.setMust( ocd.getMustAttributeTypes().toArray( new String[ocd.getMustAttributeTypes().size()] ) );
+                literal.setClassType( ocd.getKind() );
+                literal.setObsolete( ocd.isObsolete() );
+                objectClassLiterals.add( literal );
+            }
+        }
+
+        if ( isResolveObjectIdentifierMacros() )
+        {
+            // resolve object identifier macros
+            for ( OpenLdapObjectIdentifierMacro oid : objectIdentifierMacros.values() )
+            {
+                resolveObjectIdentifierMacro( oid );
+            }
+
+            // apply object identifier macros to object classes and attribute types
+            for ( ObjectClassLiteral ocl : objectClassLiterals )
+            {
+                ocl.setOid( getResolveOid( ocl.getOid() ) );
+            }
+            for ( AttributeTypeLiteral atl : attributeTypeLiterals )
+            {
+                atl.setOid( getResolveOid( atl.getOid() ) );
+                atl.setSyntax( getResolveOid( atl.getSyntax() ) );
+            }
+        }
+
+    }
+
+
+    private String getResolveOid( String oid )
+    {
+        if ( oid != null && oid.indexOf( ':' ) != -1 )
+        {
+            // resolve OID
+            String[] nameAndSuffix = oid.split( ":" );
+            if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
+            {
+                OpenLdapObjectIdentifierMacro macro = objectIdentifierMacros.get( nameAndSuffix[0] );
+                return macro.getResolvedOid() + "." + nameAndSuffix[1];
+            }
+        }
+        return oid;
+    }
+
+
+    private void resolveObjectIdentifierMacro( OpenLdapObjectIdentifierMacro macro ) throws ParseException
+    {
+        String rawOidOrNameSuffix = macro.getRawOidOrNameSuffix();
+
+        if ( macro.isResolved() )
+        {
+            // finished
+        }
+        else if ( rawOidOrNameSuffix.indexOf( ':' ) != -1 )
+        {
+            // resolve OID
+            String[] nameAndSuffix = rawOidOrNameSuffix.split( ":" );
+            if ( objectIdentifierMacros.containsKey( nameAndSuffix[0] ) )
+            {
+                OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( nameAndSuffix[0] );
+                resolveObjectIdentifierMacro( parentMacro );
+                macro.setResolvedOid( parentMacro.getResolvedOid() + "." + nameAndSuffix[1] );
+            }
+            else
+            {
+                throw new ParseException( "No object identifier macro with name " + nameAndSuffix[0], 0 );
+            }
+
+        }
+        else
+        {
+            // no :suffix, 
+            if ( objectIdentifierMacros.containsKey( rawOidOrNameSuffix ) )
+            {
+                OpenLdapObjectIdentifierMacro parentMacro = objectIdentifierMacros.get( rawOidOrNameSuffix );
+                resolveObjectIdentifierMacro( parentMacro );
+                macro.setResolvedOid( parentMacro.getResolvedOid() );
+            }
+            else
+            {
+                macro.setResolvedOid( rawOidOrNameSuffix );
+            }
+        }
+    }
+
+
+    /**
+     * Parses an OpenLDAP schemaObject element/object.
+     *
+     * @param schemaObject the String image of a complete schema object
+     * @throws IOException If the schemaObject can't be transformed to a byteArrayInputStream
+     * @throws ParseException If the schemaObject can't be parsed
+     */
+    public AbstractSchemaDescription parse( String schemaObject ) throws ParseException
+    {
+        if ( schemaObject == null || schemaObject.trim().equals( "" ) )
+        {
+            throw new ParseException( "The schemaObject is either null or is " + "the empty String!", 0 );
+        }
+
+        reset( schemaObject ); // reset and initialize the parser / lexer pair
+        invokeParser( schemaObject );
+
+        if ( !schemaDescriptions.isEmpty() )
+        {
+            for ( Object obj : schemaDescriptions )
+            {
+                if ( obj instanceof AbstractSchemaDescription )
+                {
+                    return ( AbstractSchemaDescription ) obj;
+                }
+            }
+        }
+        return null;
+    }
+
+
+    private void invokeParser( String subject ) throws ParseException
+    {
+        try
+        {
+            monitor.startedParse( "starting parse on:\n" + subject );
+            schemaDescriptions = parser.openLdapSchema();
+            afterParse();
+            monitor.finishedParse( "Done parsing!" );
+        }
+        catch ( RecognitionException e )
+        {
+            String msg = "Parser failure on:\n\t" + subject;
+            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e );
+            throw new ParseException( msg, e.getColumn() );
+        }
+        catch ( TokenStreamException e2 )
+        {
+            String msg = "Parser failure on:\n\t" + subject;
+            msg += "\nAntlr exception trace:\n" + ExceptionUtils.getFullStackTrace( e2 );
+            throw new ParseException( msg, 0 );
+        }
+    }
+
+
+    /**
+     * Parses a stream of OpenLDAP schemaObject elements/objects.
+     *
+     * @param schemaIn a stream of schema objects
+     * @throws IOException If the schemaObject can't be transformed to a byteArrayInputStream
+     * @throws ParseException If the schemaObject can't be parsed
+     */
+    public void parse( InputStream schemaIn ) throws IOException, ParseException
+    {
+        InputStreamReader in = new InputStreamReader( schemaIn );
+        lexer.prepareNextInput( in );
+        parser.resetState();
+
+        invokeParser( "schema input stream ==> " + schemaIn.toString() );
+    }
+
+
+    /**
+     * Parses a file of OpenLDAP schemaObject elements/objects.
+     *
+     * @param schemaFile a file of schema objects
+     * @throws IOException If the schemaObject can't be transformed to a byteArrayInputStream
+     * @throws ParseException If the schemaObject can't be parsed
+     */
+    public void parse( File schemaFile ) throws IOException, ParseException
+    {
+        FileReader in = new FileReader( schemaFile );
+        lexer.prepareNextInput( in );
+        parser.resetState();
+
+        invokeParser( "schema file ==> " + schemaFile.getAbsolutePath() );
+    }
+
+
+    /**
+     * Checks if object identifier macros should be resolved.
+     * 
+     * @return true, object identifier macros should be resolved.
+     */
+    public boolean isResolveObjectIdentifierMacros()
+    {
+        return isResolveObjectIdentifierMacros;
+    }
+
+
+    /**
+     * Sets if object identifier macros should be resolved.
+     * 
+     * @param isResolveObjectIdentifierMacros true if object identifier macros should be resolved
+     */
+    public void setResolveObjectIdentifierMacros( boolean isResolveObjectIdentifierMacros )
+    {
+        this.isResolveObjectIdentifierMacros = isResolveObjectIdentifierMacros;
+    }
+
+}
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitor.java
similarity index 75%
copy from ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
copy to ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitor.java
index ddf0842..5bc7816 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitor.java
@@ -17,16 +17,22 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.shared.ldap.constants;
+package org.apache.directory.shared.ldap.schema.parser;
+
 
 /**
- * A utility class where we declare all the statically defined DN used in the server.
+ * A monitor for the OpenLdap parser.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev:$
+ * @version $Rev: 437016 $
  */
-public class ServerDNConstants 
+public interface ParserMonitor
 {
-	public static final String ADMINISTRATORS_GROUP_DN = "cn=Administrators,ou=groups,ou=system";
+    void matchedProduction( String prod );
 
+
+    void startedParse( String s );
+
+
+    void finishedParse( String s );
 }
diff --git a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitorAdapter.java
similarity index 73%
copy from ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
copy to ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitorAdapter.java
index ddf0842..3a8f54a 100644
--- a/ldap-constants/src/main/java/org/apache/directory/shared/ldap/constants/ServerDNConstants.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/parser/ParserMonitorAdapter.java
@@ -17,16 +17,28 @@
  *  under the License. 
  *  
  */
-package org.apache.directory.shared.ldap.constants;
+package org.apache.directory.shared.ldap.schema.parser;
+
 
 /**
- * A utility class where we declare all the statically defined DN used in the server.
+ * Document me.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev:$
+ * @version $Rev: 437016 $
  */
-public class ServerDNConstants 
+public class ParserMonitorAdapter implements ParserMonitor
 {
-	public static final String ADMINISTRATORS_GROUP_DN = "cn=Administrators,ou=groups,ou=system";
+    public void matchedProduction( String prod )
+    {
+    }
 
+
+    public void startedParse( String s )
+    {
+    }
+
+
+    public void finishedParse( String s )
+    {
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ACIItemSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ACIItemSyntaxChecker.java
index f872dbd..5b69b36 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ACIItemSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ACIItemSyntaxChecker.java
@@ -61,10 +61,13 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractAdsSchemaDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractAdsSchemaDescription.java
index ee08c6b..f67956e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractAdsSchemaDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractAdsSchemaDescription.java
@@ -27,6 +27,7 @@
  * the BASE64 encoded bytecode of the class.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public abstract class AbstractAdsSchemaDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSchemaDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSchemaDescription.java
index 53f3353..80ead64 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSchemaDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSchemaDescription.java
@@ -112,6 +112,10 @@
     }
 
 
+    /**
+     * Compute the instance's hash code
+     * @return the instance's hash code 
+     */
     public int hashCode()
     {
         return numericOid.hashCode();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSyntaxChecker.java
index 0f52d60..ffc32cd 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AbstractSyntaxChecker.java
@@ -24,13 +24,11 @@
 
 import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeValueException;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
-import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
 
 
 /**
- * Document me.
+ * The abstrcat class implementing common operations for the syntax checking.
  *
- * @todo put me into shared-ldap
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 485042 $
  */
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AcceptAllSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AcceptAllSyntaxChecker.java
index c74efcb..29cf1e7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AcceptAllSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AcceptAllSyntaxChecker.java
@@ -59,6 +59,8 @@
     
     /**
      * @see SyntaxChecker#getSyntaxOid()
+     * 
+     * @return the OID syntax
      */
     public String getSyntaxOid()
     {
@@ -70,6 +72,9 @@
      * Returns true every time.
      * 
      * @see SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
@@ -81,6 +86,9 @@
      * Does nothing but return immediately and no exceptions are ever thrown.
      * 
      * @see SyntaxChecker#assertSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @throws NamingException if the value does not conform to the attribute syntax.
      */
     public void assertSyntax( Object value ) throws NamingException
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AccessPointSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AccessPointSyntaxChecker.java
index ccac619..775b851 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AccessPointSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AccessPointSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescription.java
index e267b6d..987adc9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescription.java
@@ -28,6 +28,7 @@
  * RFC 4512 - 4.1.2. Attribute Types
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class AttributeTypeDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java
index 5b7c240..3bb4b9d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxChecker.java
@@ -74,7 +74,7 @@
     /** The Syntax OID, according to RFC 4517, par. 3.3.1 */
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.3";
 
-	/** The schema parser used to parse the AttributeTypeDescription Syntax */
+    /** The schema parser used to parse the AttributeTypeDescription Syntax */
     private AttributeTypeDescriptionSchemaParser schemaParser = new AttributeTypeDescriptionSchemaParser();
 
     /**
@@ -104,7 +104,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeUsageSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeUsageSyntaxChecker.java
index 53e1e7a..8bd7948 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeUsageSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeUsageSyntaxChecker.java
@@ -66,7 +66,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
@@ -103,10 +103,8 @@
                 {
                     return true;
                 }
-                else
-                {
-                    return false;
-                }
+
+                return false;
             
             case( 'u' ):
                 return "userApplications".equals( strValue );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AudioSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AudioSyntaxChecker.java
index 8cf8387..08c4b03 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AudioSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/AudioSyntaxChecker.java
@@ -60,6 +60,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BinarySyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BinarySyntaxChecker.java
index 3f82d97..864fe0e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BinarySyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BinarySyntaxChecker.java
@@ -58,6 +58,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BitStringSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BitStringSyntaxChecker.java
index de1c267..ed5361f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BitStringSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BitStringSyntaxChecker.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.schema.syntax;
 
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -117,7 +117,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BooleanSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BooleanSyntaxChecker.java
index 6ad9ab6..a9b148a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BooleanSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/BooleanSyntaxChecker.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.schema.syntax;
 
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -65,7 +65,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateListSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateListSyntaxChecker.java
index 613dc64..5aa9637 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateListSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateListSyntaxChecker.java
@@ -62,6 +62,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificatePairSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificatePairSyntaxChecker.java
index a20d58d..ef4c753 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificatePairSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificatePairSyntaxChecker.java
@@ -62,6 +62,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateSyntaxChecker.java
index d4ed5c0..05edf59 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CertificateSyntaxChecker.java
@@ -62,6 +62,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ComparatorDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ComparatorDescription.java
index aba3d8a..2f0839c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ComparatorDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ComparatorDescription.java
@@ -25,6 +25,7 @@
  * An ApacheDS specific schema description.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ComparatorDescription extends AbstractAdsSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CountrySyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CountrySyntaxChecker.java
index 067a95d..ecd600f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CountrySyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/CountrySyntaxChecker.java
@@ -58,7 +58,8 @@
         "JE", "JM", "JO", "JP",
         "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ",
         "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY",
-        "MA", "MC", "MD", "ME", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ",
+        "MA", "MC", "MD", "ME", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", 
+        "MY", "MZ",
         "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ",
         "OM",
         "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY",
@@ -74,7 +75,7 @@
         };
     
     /** The Set which contains the countries */
-    private final static Set<String> COUNTRIES = new HashSet<String>();
+    private static final Set<String> COUNTRIES = new HashSet<String>();
     
     /** Initialization of the country set */
     static
@@ -113,7 +114,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescription.java
index 4d6db42..3ced99f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescription.java
@@ -29,6 +29,7 @@
  * RFC 4512 - 4.1.6.  DIT Content Rule Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DITContentRuleDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxChecker.java
index a06e868..722172d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxChecker.java
@@ -84,7 +84,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescription.java
index 0bd9b33..2abc814 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescription.java
@@ -29,6 +29,7 @@
  * RFC 4512 - 4.1.7.  DIT Structure Rule Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DITStructureRuleDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxChecker.java
index fd39828..2899f1b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxChecker.java
@@ -85,7 +85,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DLSubmitPermissionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DLSubmitPermissionSyntaxChecker.java
index 6ee9d9b..09bdf6d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DLSubmitPermissionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DLSubmitPermissionSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DNSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DNSyntaxChecker.java
index 63f789c..754caa4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DNSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DNSyntaxChecker.java
@@ -63,7 +63,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSAQualitySyntaxSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSAQualitySyntaxSyntaxChecker.java
index 7e4dcd6..0ca83e2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSAQualitySyntaxSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSAQualitySyntaxSyntaxChecker.java
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSETypeSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSETypeSyntaxChecker.java
index a4cee82..29e5780 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSETypeSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DSETypeSyntaxChecker.java
@@ -55,7 +55,7 @@
     
     
     /** The Set which contains the DESBits */
-    private final static Set<String> DSE_BITS = new HashSet<String>();
+    private static final Set<String> DSE_BITS = new HashSet<String>();
     
     /** Initialization of the country set */
     static
@@ -95,7 +95,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
@@ -158,7 +158,7 @@
             String keyword = strValue.substring( i, pos );
             i = pos;
             
-            if ( DSE_BITS.contains( keyword ) == false )
+            if ( !DSE_BITS.contains( keyword ) )
             {
                 // Unkown keyword
                 return false;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DataQualitySyntaxSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DataQualitySyntaxSyntaxChecker.java
index 635dc7f..ee60a35 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DataQualitySyntaxSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DataQualitySyntaxSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DeliveryMethodSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DeliveryMethodSyntaxChecker.java
index 8efa411..3e291ac 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DeliveryMethodSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DeliveryMethodSyntaxChecker.java
@@ -57,7 +57,7 @@
         };
 
     /** The Set which contains the delivery methods */
-    private final static Set<String> DELIVERY_METHODS = new HashSet<String>();
+    private static final Set<String> DELIVERY_METHODS = new HashSet<String>();
     
     /** Initialization of the delivery methods set */
     static
@@ -96,8 +96,13 @@
      * Check if the string contains a delivery method which has 
      * not already been found.
      * 
+     * @param strValue The string we want to look into for a PDM 
+     * @param pos The current position in the string
+     * @param pdms The set containing all the PDM
+     * @return if a Prefered Delivery Method is found in the given string, returns 
+     * its position, otherwise, returns -1
      */
-    private int isPdm( String strValue, int pos, Set<String> pmds )
+    private int isPdm( String strValue, int pos, Set<String> pdms )
     {
         int start = pos;
         
@@ -112,23 +117,23 @@
             return -1;
         }
         
-        String pmd = strValue.substring( start, pos );
+        String pdm = strValue.substring( start, pos );
         
-        if ( ! DELIVERY_METHODS.contains( pmd ) )
+        if ( ! DELIVERY_METHODS.contains( pdm ) )
         {
             // The delivery method is unknown
             return -1;
         }
         else
         {
-            if ( pmds.contains( pmd ) )
+            if ( pdms.contains( pdm ) )
             {
                 // The delivery method has already been found
                 return -1;
             }
             else
             {
-                pmds.add( pmd );
+                pdms.add( pdm );
                 return pos;
             }
         }
@@ -139,7 +144,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DirectoryStringSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DirectoryStringSyntaxChecker.java
index 7ca065e..289c166 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DirectoryStringSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/DirectoryStringSyntaxChecker.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.schema.syntax;
 
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -63,7 +63,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/EnhancedGuideSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/EnhancedGuideSyntaxChecker.java
index 440141c..578192a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/EnhancedGuideSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/EnhancedGuideSyntaxChecker.java
@@ -57,6 +57,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FacsimileTelephoneNumberSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FacsimileTelephoneNumberSyntaxChecker.java
index fb36019..26f65d6 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FacsimileTelephoneNumberSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FacsimileTelephoneNumberSyntaxChecker.java
@@ -54,13 +54,13 @@
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.22";
     
     /** Fax parameters possible values */
-    private final static String TWO_DIMENSIONAL  = "twoDimensional";
-    private final static String FINE_RESOLUTION  = "fineResolution";
-    private final static String UNLIMITED_LENGTH = "unlimitedLength";
-    private final static String B4_LENGTH        = "b4Length";
-    private final static String A3_LENGTH        = "a3Width";
-    private final static String B4_WIDTH         = "b4Width";
-    private final static String UNCOMPRESSED     = "uncompressed";
+    private static final String TWO_DIMENSIONAL  = "twoDimensional";
+    private static final String FINE_RESOLUTION  = "fineResolution";
+    private static final String UNLIMITED_LENGTH = "unlimitedLength";
+    private static final String B4_LENGTH        = "b4Length";
+    private static final String A3_LENGTH        = "a3Width";
+    private static final String B4_WIDTH         = "b4Width";
+    private static final String UNCOMPRESSED     = "uncompressed";
     
     /** A set which contaons all the possible fax parameters values */
     private static Set<String> faxParameters = new HashSet<String>();
@@ -103,7 +103,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FaxSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FaxSyntaxChecker.java
index 8358568..7e9c37a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FaxSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/FaxSyntaxChecker.java
@@ -57,6 +57,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GeneralizedTimeSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GeneralizedTimeSyntaxChecker.java
index 54c3b16..0edf2fd 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GeneralizedTimeSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GeneralizedTimeSyntaxChecker.java
@@ -22,8 +22,8 @@
 
 import java.util.regex.Pattern;
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -110,7 +110,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GuideSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GuideSyntaxChecker.java
index 7fbee5b..c941ae4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GuideSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/GuideSyntaxChecker.java
@@ -56,6 +56,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/Ia5StringSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/Ia5StringSyntaxChecker.java
index 49766c0..c8980fb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/Ia5StringSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/Ia5StringSyntaxChecker.java
@@ -65,7 +65,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/IntegerSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/IntegerSyntaxChecker.java
index f123833..78db7fc 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/IntegerSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/IntegerSyntaxChecker.java
@@ -20,8 +20,8 @@
 package org.apache.directory.shared.ldap.schema.syntax;
 
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue =null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaByteSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaByteSyntaxChecker.java
index 03e9a7b..d49334c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaByteSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaByteSyntaxChecker.java
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaIntegerSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaIntegerSyntaxChecker.java
index c63cd6d..cf9b638 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaIntegerSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaIntegerSyntaxChecker.java
@@ -72,7 +72,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue =null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaLongSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaLongSyntaxChecker.java
index 5b49076..3f17fb2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaLongSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaLongSyntaxChecker.java
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaShortSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaShortSyntaxChecker.java
index fa2b156..f552c06 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaShortSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/JavaShortSyntaxChecker.java
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescription.java
index 3b99346..35cd1cb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescription.java
@@ -29,10 +29,16 @@
  * RFC 4512 - 4.1.5. LDAP Syntaxes
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LdapSyntaxDescription extends AbstractSchemaDescription
 {
 
+    /**
+     * 
+     * Creates a new instance of LdapSyntaxDescription.
+     *
+     */
     public LdapSyntaxDescription()
     {
         this.numericOid = "";
@@ -41,18 +47,6 @@
     }
 
 
-    public List<String> getNames()
-    {
-        throw new UnsupportedOperationException( "Not supported by LdapSyntaxDescription" );
-    }
-
-
-    public void setNames( List<String> names )
-    {
-        throw new UnsupportedOperationException( "Not supported by LdapSyntaxDescription" );
-    }
-
-
     public boolean isObsolete()
     {
         throw new UnsupportedOperationException( "Not supported by LdapSyntaxDescription" );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxChecker.java
index 3fe9372..3893332 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxChecker.java
@@ -46,7 +46,7 @@
     /** The Syntax OID, according to RFC 4517, par. 3.3.18 */
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.54";
 
-	/** The schema parser used to parse the LdapSyntaxDescription Syntax */
+    /** The schema parser used to parse the LdapSyntaxDescription Syntax */
     private LdapSyntaxDescriptionSchemaParser schemaParser = new LdapSyntaxDescriptionSchemaParser();
 
 
@@ -77,7 +77,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue =null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MHSORAddressSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MHSORAddressSyntaxChecker.java
index d7d5956..2504135 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MHSORAddressSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MHSORAddressSyntaxChecker.java
@@ -55,6 +55,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MailPreferenceSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MailPreferenceSyntaxChecker.java
index 9515cb9..cf167ea 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MailPreferenceSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MailPreferenceSyntaxChecker.java
@@ -67,7 +67,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue =null;
 
         if ( value == null )
         {
@@ -92,6 +92,7 @@
             return false;
         }
         
-        return ( ( "NO-LISTS".equals( strValue ) ) || ( "ANY-LIST".equals( strValue ) ) || ( "PROFESSIONAL-LISTS".equals( strValue ) ) );
+        return ( ( "NO-LISTS".equals( strValue ) ) || ( "ANY-LIST".equals( strValue ) ) || 
+            ( "PROFESSIONAL-LISTS".equals( strValue ) ) );
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MasterAndShadowAccessPointSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MasterAndShadowAccessPointSyntaxChecker.java
index 06b2d2a..9a99af1 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MasterAndShadowAccessPointSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MasterAndShadowAccessPointSyntaxChecker.java
@@ -55,6 +55,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescription.java
index 6f9545e..6e97d76 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescription.java
@@ -25,25 +25,39 @@
  * RFC 4512 - 4.1.3. Matching Rule Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class MatchingRuleDescription extends AbstractSchemaDescription
 {
-
+    /** The matching rule's description */
     private String syntax;
 
 
+    /**
+     * 
+     * Creates a new instance of MatchingRuleDescription.
+     *
+     */
     public MatchingRuleDescription()
     {
         syntax = null;
     }
 
 
+    /**
+     * @return The matchingRule's syntax description
+     */
     public String getSyntax()
     {
         return syntax;
     }
 
 
+    /**
+     * Set the matchingRule's syntax description
+     *
+     * @param syntax The description
+     */
     public void setSyntax( String syntax )
     {
         this.syntax = syntax;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java
index 97ee33d..d9f5ea0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleDescriptionSyntaxChecker.java
@@ -53,7 +53,7 @@
     /** The Syntax OID, according to RFC 4517, par. 3.3.19 */
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.30";
 
-	/** The schema parser used to parse the MatchingRuleDescription Syntax */
+    /** The schema parser used to parse the MatchingRuleDescription Syntax */
     private MatchingRuleDescriptionSchemaParser schemaParser = new MatchingRuleDescriptionSchemaParser();
 
 
@@ -85,7 +85,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescription.java
index e377be7..48d6727 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescription.java
@@ -30,6 +30,7 @@
  * RFC 4512 - 4.1.4. Matching Rule Use Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class MatchingRuleUseDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java
index aaec9bb..bf81d89 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxChecker.java
@@ -50,7 +50,7 @@
     /** The Syntax OID, according to RFC 4517, par. 3.3.20 */
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.31";
 
-	/** The schema parser used to parse the MatchingRuleUseDescription Syntax */
+    /** The schema parser used to parse the MatchingRuleUseDescription Syntax */
     private MatchingRuleUseDescriptionSchemaParser schemaParser = new MatchingRuleUseDescriptionSchemaParser();
 
 
@@ -82,7 +82,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameAndOptionalUIDSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameAndOptionalUIDSyntaxChecker.java
index aacc177..813d888 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameAndOptionalUIDSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameAndOptionalUIDSyntaxChecker.java
@@ -72,7 +72,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescription.java
index ca60ec9..65001d2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescription.java
@@ -29,6 +29,7 @@
  * RFC 4512 - 4.1.7.2.  Name Form Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class NameFormDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescriptionSyntaxChecker.java
index 8c159a3..1e5a102 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NameFormDescriptionSyntaxChecker.java
@@ -83,7 +83,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NormalizerDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NormalizerDescription.java
index 39aa119..67d992a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NormalizerDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NormalizerDescription.java
@@ -25,6 +25,7 @@
  * An ApacheDS specific schema description.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class NormalizerDescription extends AbstractAdsSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumberSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumberSyntaxChecker.java
index 13da30d..2482021 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumberSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumberSyntaxChecker.java
@@ -68,7 +68,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericOidSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericOidSyntaxChecker.java
index 5c7ec47..e148b41 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericOidSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericOidSyntaxChecker.java
@@ -74,7 +74,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericStringSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericStringSyntaxChecker.java
index 7a32c8e..ba13c3e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericStringSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/NumericStringSyntaxChecker.java
@@ -72,7 +72,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescription.java
index 3da5530..7576263 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescription.java
@@ -31,6 +31,7 @@
  * RFC 4512 - 4.1.1. Object Class Description
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ObjectClassDescription extends AbstractSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java
index 887c392..3497948 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxChecker.java
@@ -57,7 +57,7 @@
     /** The Syntax OID, according to RFC 4517, par. 3.3.24 */
     private static final String SC_OID = "1.3.6.1.4.1.1466.115.121.1.37";
 
-	/** The schema parser used to parse the ObjectClassDescription Syntax */
+    /** The schema parser used to parse the ObjectClassDescription Syntax */
     private ObjectClassDescriptionSchemaParser schemaParser = new ObjectClassDescriptionSchemaParser();
 
 
@@ -89,7 +89,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassTypeSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassTypeSyntaxChecker.java
index c3629ba..b87dfe7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassTypeSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassTypeSyntaxChecker.java
@@ -63,7 +63,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
@@ -97,10 +97,8 @@
                 {
                     return true;
                 }
-                else
-                {
-                    return false;
-                }
+
+                return false;
             
             case( 'S' ):
                 return "STRUCTURAL".equals( strValue );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectNameSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectNameSyntaxChecker.java
index 08c5497..bbc820d 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectNameSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ObjectNameSyntaxChecker.java
@@ -80,7 +80,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidLenSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidLenSyntaxChecker.java
index cf4edc7..db5ca47 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidLenSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidLenSyntaxChecker.java
@@ -76,7 +76,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidSyntaxChecker.java
index 2044e5a..338a6da 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OidSyntaxChecker.java
@@ -79,7 +79,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OpenLdapObjectIdentifierMacro.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OpenLdapObjectIdentifierMacro.java
new file mode 100644
index 0000000..989a4d7
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OpenLdapObjectIdentifierMacro.java
@@ -0,0 +1,142 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+
+package org.apache.directory.shared.ldap.schema.syntax;
+
+
+/**
+ * An OpenLDAP object identifier macro. 
+ * See http://www.openldap.org/doc/admin24/schema.html#OID%20Macros
+ * <br/>
+ * <code>objectIdentifier &lt;name&gt; { &lt;oid&gt; | &lt;name&gt;[:&lt;suffix&gt;] }</code>
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class OpenLdapObjectIdentifierMacro
+{
+    private String name;
+
+    private String rawOidOrNameSuffix;
+
+    private String resolvedOid;
+
+
+    /**
+     * Instantiates a new OpenLDAP object identifier macro.
+     */
+    public OpenLdapObjectIdentifierMacro()
+    {
+        name = null;
+        rawOidOrNameSuffix = null;
+        resolvedOid = null;
+    }
+
+
+    /**
+     * Gets the name.
+     * 
+     * @return the name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+
+    /**
+     * Sets the name.
+     * 
+     * @param name the new name
+     */
+    public void setName( String name )
+    {
+        this.name = name;
+    }
+
+
+    /**
+     * Gets the raw OID or name plus suffix.
+     * 
+     * @return the raw OID or name plus suffix
+     */
+    public String getRawOidOrNameSuffix()
+    {
+        return rawOidOrNameSuffix;
+    }
+
+
+    /**
+     * Sets the raw OID or name plus suffix.
+     * 
+     * @param rawOidOrNameSuffix the new raw OID or name plus suffix
+     */
+    public void setRawOidOrNameSuffix( String rawOidOrNameSuffix )
+    {
+        this.rawOidOrNameSuffix = rawOidOrNameSuffix;
+    }
+
+
+    /**
+     * Gets the resolved OID, null if not yet resolved.
+     * 
+     * @return the resolved OID
+     */
+    public String getResolvedOid()
+    {
+        return resolvedOid;
+    }
+
+
+    /**
+     * Checks if is resolved.
+     * 
+     * @return true, if is resolved
+     */
+    public boolean isResolved()
+    {
+        return getResolvedOid() != null;
+    }
+
+
+    /**
+     * Sets the resolved OID.
+     * 
+     * @param resolvedOid the new resolved OID
+     */
+    public void setResolvedOid( String resolvedOid )
+    {
+        this.resolvedOid = resolvedOid;
+    }
+
+
+    public String toString()
+    {
+        if ( isResolved() )
+        {
+            return "resolved: " + name + " " + resolvedOid;
+        }
+        else
+        {
+            return "unresolved: " + name + " " + rawOidOrNameSuffix;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OtherMailboxSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OtherMailboxSyntaxChecker.java
index 00158e7..8c031c3 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OtherMailboxSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/OtherMailboxSyntaxChecker.java
@@ -67,7 +67,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PostalAddressSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PostalAddressSyntaxChecker.java
index fea2ac9..73056f8 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PostalAddressSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PostalAddressSyntaxChecker.java
@@ -66,7 +66,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PresentationAddressSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PresentationAddressSyntaxChecker.java
index f7d606e..be5969c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PresentationAddressSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PresentationAddressSyntaxChecker.java
@@ -56,6 +56,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PrintableStringSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PrintableStringSyntaxChecker.java
index 49058f8..1948e03 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PrintableStringSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/PrintableStringSyntaxChecker.java
@@ -87,7 +87,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ProtocolInformationSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ProtocolInformationSyntaxChecker.java
index b18ef5f..3e4ac75 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ProtocolInformationSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/ProtocolInformationSyntaxChecker.java
@@ -55,6 +55,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/RegexSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/RegexSyntaxChecker.java
index fb89423..3a941f2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/RegexSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/RegexSyntaxChecker.java
@@ -80,6 +80,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(java.lang.Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubstringAssertionSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubstringAssertionSyntaxChecker.java
index 52d5257..072a0b0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubstringAssertionSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubstringAssertionSyntaxChecker.java
@@ -57,6 +57,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java
index a1dfc2d..8df23b7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SubtreeSpecificationSyntaxChecker.java
@@ -62,10 +62,13 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierAndConsumerSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierAndConsumerSyntaxChecker.java
index 93707bc..ca0ca5e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierAndConsumerSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierAndConsumerSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierInformationSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierInformationSyntaxChecker.java
index a081669..d3c705c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierInformationSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierInformationSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierOrConsumerSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierOrConsumerSyntaxChecker.java
index a256aab..1c527b4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierOrConsumerSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupplierOrConsumerSyntaxChecker.java
@@ -54,6 +54,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupportedAlgorithmSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupportedAlgorithmSyntaxChecker.java
index f09011a..6bb1875 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupportedAlgorithmSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SupportedAlgorithmSyntaxChecker.java
@@ -56,6 +56,9 @@
     
     /**
      * @see org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker#isValidSyntax(Object)
+     * 
+     * @param value the value of some attribute with the syntax
+     * @return true if the value is in the valid syntax, false otherwise
      */
     public boolean isValidSyntax( Object value )
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxChecker.java
index cdac1d3..72b3411 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxChecker.java
@@ -29,6 +29,7 @@
  * enforce a syntax within the Eve server.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public interface SyntaxChecker
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxCheckerDescription.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxCheckerDescription.java
index b0ac2f5..8794d92 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxCheckerDescription.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/SyntaxCheckerDescription.java
@@ -25,6 +25,7 @@
  * An ApacheDS specific schema description.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class SyntaxCheckerDescription extends AbstractAdsSchemaDescription
 {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelephoneNumberSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelephoneNumberSyntaxChecker.java
index 993a9c9..06fabf9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelephoneNumberSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelephoneNumberSyntaxChecker.java
@@ -54,7 +54,7 @@
     private List<Pattern> compiledREs;
     
     /** The default pattern used to check a TelephoneNumber */
-    private final static String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ]+\\))|[0-9- ]+)+$";
+    private static final String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ]+\\))|[0-9- ]+)+$";
     
     /** The compiled default pattern */
     private Pattern defaultPattern =  Pattern.compile( DEFAULT_REGEXP );
@@ -73,7 +73,7 @@
     /**
      * Creates a new instance of TelephoneNumberSyntaxChecker.
      * 
-     * @param The OID to associate with this SyntaxChecker
+     * @param oid The OID to associate with this SyntaxChecker
      */
     protected TelephoneNumberSyntaxChecker( String oid )
     {
@@ -109,9 +109,12 @@
             return;
         }
     }
-    
+
+
     /**
+     * Set the defaut regular expression for the Telephone number
      * 
+     * @param regexp the default regular expression.
      */
     public void setDefaultRegexp( String regexp )
     {
@@ -134,7 +137,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TeletexTerminalIdentifierSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TeletexTerminalIdentifierSyntaxChecker.java
index 67c6e15..08a31b5 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TeletexTerminalIdentifierSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TeletexTerminalIdentifierSyntaxChecker.java
@@ -71,7 +71,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelexNumberSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelexNumberSyntaxChecker.java
index 7355373..938d6b1 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelexNumberSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/TelexNumberSyntaxChecker.java
@@ -68,7 +68,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/UtcTimeSyntaxChecker.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/UtcTimeSyntaxChecker.java
index 440ee7d..c0db86a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/UtcTimeSyntaxChecker.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/UtcTimeSyntaxChecker.java
@@ -22,8 +22,8 @@
 
 import java.util.regex.Pattern;
 
-import org.apache.directory.shared.ldap.util.StringTools;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -104,7 +104,7 @@
      */
     public boolean isValidSyntax( Object value )
     {
-        String strValue;
+        String strValue = null;
 
         if ( value == null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AbstractSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AbstractSchemaParser.java
index c458775..aa1083b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AbstractSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AbstractSchemaParser.java
@@ -19,28 +19,42 @@
  */
 package org.apache.directory.shared.ldap.schema.syntax.parser;
 
+
 import java.io.StringReader;
 import java.text.ParseException;
 
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitor;
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitorAdapter;
 import org.apache.directory.shared.ldap.schema.syntax.AbstractSchemaDescription;
 
+
+/**
+ * 
+ * TODO AbstractSchemaParser.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
 public abstract class AbstractSchemaParser
 {
 
+    /** the monitor to use for this parser */
+    protected ParserMonitor monitor = new ParserMonitorAdapter();
 
     /** the antlr generated parser being wrapped */
     protected ReusableAntlrSchemaParser parser;
 
     /** the antlr generated lexer being wrapped */
     protected ReusableAntlrSchemaLexer lexer;
-    
-    
-    protected AbstractSchemaParser() 
+
+
+    protected AbstractSchemaParser()
     {
         lexer = new ReusableAntlrSchemaLexer( new StringReader( "" ) );
         parser = new ReusableAntlrSchemaParser( lexer );
     }
-    
+
+
     /**
      * Initializes the plumbing by creating a pipe and coupling the parser/lexer
      * pair with it. param spec the specification to be parsed
@@ -51,7 +65,45 @@
         lexer.prepareNextInput( in );
         parser.resetState();
     }
-    
+
+
+    /**
+     * Sets the parser monitor.
+     * 
+     * @param monitor the new parser monitor
+     */
+    public void setParserMonitor( ParserMonitor monitor )
+    {
+        this.monitor = monitor;
+        parser.setParserMonitor( monitor );
+    }
+
+
+    /**
+     * Sets the quirks mode. 
+     * 
+     * If enabled the parser accepts non-numeric OIDs and some 
+     * special characters in descriptions.
+     * 
+     * @param enabled the new quirks mode
+     */
+    public void setQuirksMode( boolean enabled )
+    {
+        parser.setQuirksMode( enabled );
+    }
+
+
+    /**
+     * Checks if quirks mode is enabled.
+     * 
+     * @return true, if is quirks mode is enabled
+     */
+    public boolean isQuirksMode()
+    {
+        return parser.isQuirksMode();
+    }
+
+
     public abstract AbstractSchemaDescription parse( String schemaDescription ) throws ParseException;
-    
+
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParser.java
index a070848..9285de7 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParser.java
@@ -27,12 +27,14 @@
 
 import antlr.RecognitionException;
 import antlr.TokenStreamException;
+import antlr.TokenStreamRecognitionException;
 
 
 /**
  * A parser for RFC 4512 attribute type descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class AttributeTypeDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +44,6 @@
      */
     public AttributeTypeDescriptionSchemaParser()
     {
-        super();
     }
     
 
@@ -102,6 +103,12 @@
             msg += "\nAntlr column: " + re.getColumn();
             throw new ParseException( msg, re.getColumn() );
         }
+        catch ( TokenStreamRecognitionException tsre )
+        {
+            String msg = "Parser failure on attribute type description:\n\t" + attributeTypeDescription;
+            msg += "\nAntlr message: " + tsre.getMessage();
+            throw new ParseException( msg, 0 );
+        }
         catch ( TokenStreamException tse )
         {
             String msg = "Parser failure on attribute type description:\n\t" + attributeTypeDescription;
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParser.java
index a7c1372..13e3a97 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for ApacheDS comparator descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ComparatorDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public ComparatorDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParser.java
index 2949554..ceea018 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 DIT content rule descriptons
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DITContentRuleDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public DITContentRuleDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParser.java
index 07a37d6..92b3e05 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 DIT structure rule descriptons
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DITStructureRuleDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public DITStructureRuleDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParser.java
index 9b02d5c..59ed146 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 LDAP syntx descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class LdapSyntaxDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public LdapSyntaxDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParser.java
index 19cd38a..7f95a6a 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 matching rule descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class MatchingRuleDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public MatchingRuleDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParser.java
index ab49059..9d2c805 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 matching rule use descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class MatchingRuleUseDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public MatchingRuleUseDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParser.java
index a4e5004..4cc6b1c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 name form descriptons
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class NameFormDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public NameFormDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParser.java
index fe88743..bef799e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for ApacheDS normalizer descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class NormalizerDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public NormalizerDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParser.java
index b928a53..4f0d819 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for RFC 4512 object class descriptons
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class ObjectClassDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public ObjectClassDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaLexer.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaLexer.java
index 755f457..0fd8f3f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaLexer.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaLexer.java
@@ -35,8 +35,9 @@
  * a Antlr Interest Group mail</a> .
  * 
  * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @version $Rev$, $Date$
  */
-class ReusableAntlrSchemaLexer extends AntlrSchemaLexer
+public class ReusableAntlrSchemaLexer extends AntlrSchemaLexer
 {
     private boolean savedCaseSensitive;
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaParser.java
index a4775ef..d117850 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/ReusableAntlrSchemaParser.java
@@ -32,8 +32,9 @@
  * a Antlr Interest Group mail</a> .
  * 
  * @see <a href="http://www.faqs.org/rfcs/rfc3672.html">RFC 3672</a>
+ * @version $Rev$, $Date$
  */
-class ReusableAntlrSchemaParser extends AntlrSchemaParser
+public class ReusableAntlrSchemaParser extends AntlrSchemaParser
 {
     /**
      * Creates a ReusableAntlrSchemaParser instance.
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParser.java
index 67e8176..53a06eb 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParser.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParser.java
@@ -33,6 +33,7 @@
  * A parser for ApacheDS syntax checker descriptions.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class SyntaxCheckerDescriptionSchemaParser extends AbstractSchemaParser
 {
@@ -42,7 +43,6 @@
      */
     public SyntaxCheckerDescriptionSchemaParser()
     {
-        super();
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java
index 7856119..f4f6b0c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/sp/JavaStoredProcUtils.java
@@ -57,7 +57,7 @@
      * @throws NamingException
      *           If an IO error occurs during reading the class file.
      */
-    public static byte[] getClassFileAsStream( Class clazz ) throws NamingException
+    public static byte[] getClassFileAsStream( Class<?> clazz ) throws NamingException
     {
         String fullClassName = clazz.getName();
         int lastDot = fullClassName.lastIndexOf( '.' );
@@ -93,7 +93,7 @@
      * @throws NamingException
      *           If an error occurs during creating the subcontext.
      */
-    public static void loadStoredProcedureClass( LdapContext ctx, Class clazz ) throws NamingException
+    public static void loadStoredProcedureClass( LdapContext ctx, Class<?> clazz ) throws NamingException
     {
         byte[] buf = getClassFileAsStream( clazz );
         String fullClassName = clazz.getName();
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/BaseSubtreeSpecification.java b/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/BaseSubtreeSpecification.java
index 476c5f7..5f907fe 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/BaseSubtreeSpecification.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/BaseSubtreeSpecification.java
@@ -333,7 +333,7 @@
                 // Must use a tempBuffer here because the 
                 // exception could occur after some characters
                 // were added to the buffer.
-            	StringBuilder tempBuffer = new StringBuilder();
+                StringBuilder tempBuffer = new StringBuilder();
                 refinement.printRefinementToBuffer( tempBuffer );
                 buffer.append( tempBuffer );
             }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationModifier.java b/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationModifier.java
index f1216c0..67bdc59 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationModifier.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationModifier.java
@@ -41,10 +41,10 @@
     private LdapDN base = new LdapDN();
 
     /** the set of subordinates entries and their subordinates to exclude */
-    private Set chopBefore = Collections.EMPTY_SET;
+    private Set<LdapDN> chopBefore = Collections.EMPTY_SET;
 
     /** the set of subordinates entries whose subordinates are to be excluded */
-    private Set chopAfter = Collections.EMPTY_SET;
+    private Set<LdapDN> chopAfter = Collections.EMPTY_SET;
 
     /** the minimum distance below base to start including entries */
     private int minBaseDistance = 0;
@@ -100,7 +100,7 @@
      *            the set of subordinates entries and their subordinates to
      *            exclude
      */
-    public void setChopBeforeExclusions( Set chopBefore )
+    public void setChopBeforeExclusions( Set<LdapDN> chopBefore )
     {
         this.chopBefore = chopBefore;
     }
@@ -114,7 +114,7 @@
      *            the set of subordinates entries whose subordinates are to be
      *            excluded
      */
-    public void setChopAfterExclusions( Set chopAfter )
+    public void setChopAfterExclusions( Set<LdapDN> chopAfter )
     {
         this.chopAfter = chopAfter;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ActionTime.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ActionTime.java
index 59625ab..ba1a1f0 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ActionTime.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/ActionTime.java
@@ -64,15 +64,16 @@
     }
 
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( name == null ) ? 0 : name.hashCode() );
-        return result;
+        int h = 37;
+        h = h * 17 + ( ( name == null ) ? 0 : name.hashCode() );
+        
+        return h;
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/LdapOperation.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/LdapOperation.java
index ef92d8d..28d895f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/LdapOperation.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/LdapOperation.java
@@ -68,15 +68,17 @@
     }
 
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( name == null ) ? 0 : name.hashCode() );
-        return result;
+        int h = 37;
+
+        h = h*17 + ( ( name == null ) ? 0 : name.hashCode() );
+        
+        return h;
     }
 
 
@@ -86,20 +88,31 @@
     public boolean equals( Object obj )
     {
         if ( this == obj )
+        {
             return true;
-        if ( obj == null )
+        }
+        
+        if ( ! ( obj  instanceof LdapOperation ) )
+        {
             return false;
-        if ( getClass() != obj.getClass() )
-            return false;
+        }
+
         final LdapOperation other = ( LdapOperation ) obj;
+
         if ( name == null )
         {
             if ( other.name != null )
+            {
                 return false;
+            }
+            else
+            { 
+                return true;
+            }
         }
-        else if ( !name.equals( other.name ) )
-            return false;
-        return true;
+        else 
+        {
+            return name.equals( other.name );
+        }
     }
-    
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/SearchScope.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/SearchScope.java
index fc2a35d..2e5bebd 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/SearchScope.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/SearchScope.java
@@ -59,15 +59,17 @@
     }
     
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( name == null ) ? 0 : name.hashCode() );
-        return result;
+        int h = 37;
+        
+        h = h*17 + ( ( name == null ) ? 0 : name.hashCode() );
+        
+        return h;
     }
 
     /* (non-Javadoc)
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureLanguageSchemeOption.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureLanguageSchemeOption.java
index fd7cbb9..253a213 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureLanguageSchemeOption.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureLanguageSchemeOption.java
@@ -50,15 +50,17 @@
         return "language " + "\"" + language + "\"";
     }
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( language == null ) ? 0 : language.hashCode() );
-        return result;
+        int h = 37;
+        
+        h = h*17 + ( ( language == null ) ? 0 : language.hashCode() );
+        
+        return h;
     }
 
     /* (non-Javadoc)
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureParameter.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureParameter.java
index db57686..7b57a7c 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureParameter.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureParameter.java
@@ -97,15 +97,17 @@
     }
     
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( name == null ) ? 0 : name.hashCode() );
-        return result;
+        int h = 37;
+        
+        h = h*17 + ( ( name == null ) ? 0 : name.hashCode() );
+        
+        return h;
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureSearchContextOption.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureSearchContextOption.java
index 98988d4..3021065 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureSearchContextOption.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/StoredProcedureSearchContextOption.java
@@ -62,16 +62,18 @@
         return "searchContext { scope " + searchScope + " } \"" + baseObject + "\""; 
     }
 
-    /* (non-Javadoc)
+    /**
      * @see java.lang.Object#hashCode()
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ( ( baseObject == null ) ? 0 : baseObject.hashCode() );
-        result = PRIME * result + ( ( searchScope == null ) ? 0 : searchScope.hashCode() );
-        return result;
+        int h = 37;
+        
+        h = h*17 + ( ( baseObject == null ) ? 0 : baseObject.hashCode() );
+        h = h*17 + ( ( searchScope == null ) ? 0 : searchScope.hashCode() );
+        
+        return h;
     }
 
     /* (non-Javadoc)
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecification.java b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecification.java
index 61c23da..1429191 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecification.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/trigger/TriggerSpecification.java
@@ -51,7 +51,7 @@
         }
         if ( spSpecs.size() == 0 )
         {
-        	throw new IllegalArgumentException( "TriggerSpecification cannot be initialized with emtpy SPSPec list." );
+            throw new IllegalArgumentException( "TriggerSpecification cannot be initialized with emtpy SPSPec list." );
         }
         this.ldapOperation = ldapOperation;
         this.actionTime = actionTime;
@@ -69,72 +69,76 @@
     }
 
     public List<SPSpec> getSPSpecs() {
-		return spSpecs;
-	}
+        return spSpecs;
+    }
     
     public static class SPSpec
     {
-    	private String name;
+        private String name;
         
         private List<StoredProcedureOption> options;
         
         private List<StoredProcedureParameter> parameters;
 
         public SPSpec(String name, List<StoredProcedureOption> options, List<StoredProcedureParameter> parameters) {
-			super();
-			this.name = name;
-			this.options = options;
-			this.parameters = parameters;
-		}
+            super();
+            this.name = name;
+            this.options = options;
+            this.parameters = parameters;
+        }
         
-		public String getName() {
-			return name;
-		}
+        public String getName() {
+            return name;
+        }
 
-		public List<StoredProcedureOption> getOptions() {
-			return options;
-		}
+        public List<StoredProcedureOption> getOptions() {
+            return options;
+        }
 
-		public List<StoredProcedureParameter> getParameters() {
-			return parameters;
-		}
+        public List<StoredProcedureParameter> getParameters() {
+            return parameters;
+        }
 
-		@Override
-		public int hashCode() {
-			final int PRIME = 31;
-			int result = 1;
-			result = PRIME * result + ((name == null) ? 0 : name.hashCode());
-			result = PRIME * result + ((options == null) ? 0 : options.hashCode());
-			result = PRIME * result + ((parameters == null) ? 0 : parameters.hashCode());
-			return result;
-		}
+        @Override
+        /**
+         * Compute the instance's hash code
+         * @return the instance's hash code 
+         */
+        public int hashCode() {
+            int h = 37;
+            
+            h = h*17 + ((name == null) ? 0 : name.hashCode());
+            h = h*17 + ((options == null) ? 0 : options.hashCode());
+            h = h*17 + ((parameters == null) ? 0 : parameters.hashCode());
+            return h;
+        }
 
-		@Override
-		public boolean equals(Object obj) {
-			if (this == obj)
-				return true;
-			if (obj == null)
-				return false;
-			if (getClass() != obj.getClass())
-				return false;
-			final SPSpec other = (SPSpec) obj;
-			if (name == null) {
-				if (other.name != null)
-					return false;
-			} else if (!name.equals(other.name))
-				return false;
-			if (options == null) {
-				if (other.options != null)
-					return false;
-			} else if (!options.equals(other.options))
-				return false;
-			if (parameters == null) {
-				if (other.parameters != null)
-					return false;
-			} else if (!parameters.equals(other.parameters))
-				return false;
-			return true;
-		}
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            final SPSpec other = (SPSpec) obj;
+            if (name == null) {
+                if (other.name != null)
+                    return false;
+            } else if (!name.equals(other.name))
+                return false;
+            if (options == null) {
+                if (other.options != null)
+                    return false;
+            } else if (!options.equals(other.options))
+                return false;
+            if (parameters == null) {
+                if (other.parameters != null)
+                    return false;
+            } else if (!parameters.equals(other.parameters))
+                return false;
+            return true;
+        }
 
     }
     
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrl.java b/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrl.java
deleted file mode 100644
index e5b68c1..0000000
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrl.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.shared.ldap.url;
-
-
-import java.util.List;
-
-import javax.naming.Name;
-
-import org.apache.directory.shared.ldap.filter.ExprNode;
-
-
-/**
- * A parsed LDAP URL.
- * 
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Revision$
- */
-public interface LdapUrl
-{
-    /**
-     * Gets the distinguished name of this LdapUrl.
-     * 
-     * @return the non-normalized Dn
-     */
-    Name getName();
-
-
-    /**
-     * Gets the hostname component of this LdapUrl.
-     * 
-     * @return the hostname of the server.
-     */
-    String getHostName();
-
-
-    /**
-     * Gets the port component of this LdapUrl.
-     * 
-     * @return the port number component of the LdapUrl.
-     */
-    int getPort();
-
-
-    /**
-     * Gets the filter component of this LdapUrl as a filter expression tree.
-     * 
-     * @return the filter expression tree's root node.
-     */
-    ExprNode getFilter();
-
-
-    /**
-     * Gets the attributes component of this LdapUrl.
-     * 
-     * @return a List containing the attribute names as Strings to return in the
-     *         search results if this LdapUrl represents a search. If attributes
-     *         are not specified the list will be empty.
-     */
-    List getAttributes();
-
-
-    /**
-     * Gets the extensions component of this LdapUrl. TODO can't say I know what
-     * this is at the moment
-     * 
-     * @return a List containing the extensions
-     */
-    List getExtensions();
-
-
-    /**
-     * Gets the scope of the search if this LdapUrl represents a search URL. The
-     * values returned are defined within the JNDI SearchControls class.
-     * 
-     * @see javax.naming.directory.SearchControls#OBJECT_SCOPE
-     * @see javax.naming.directory.SearchControls#ONELEVEL_SCOPE
-     * @see javax.naming.directory.SearchControls#SUBTREE_SCOPE
-     * @return the scope of the search.
-     */
-    int getScope();
-
-
-    /**
-     * Gets whether or not secure ldaps scheme with SSL is used or normal ldap
-     * scheme is used.
-     * 
-     * @return true if ldaps is the scheme, false if it is ldap
-     */
-    boolean isSecure();
-}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrlParser.java b/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrlParser.java
deleted file mode 100644
index 5299e53..0000000
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/url/LdapUrlParser.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *  
- *    http://www.apache.org/licenses/LICENSE-2.0
- *  
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License. 
- *  
- */
-
-package org.apache.directory.shared.ldap.url;
-
-
-import javax.naming.NamingException;
-
-
-/**
- * An LDAP URL parser.
- * 
- * @see <a href="http://www.faqs.org/rfcs/rfc2255.html">RFC 2255</a>
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Revision$
- */
-public interface LdapUrlParser
-{
-    /**
-     * Parses an LDAP URL.
-     * 
-     * @param a_urlString
-     *            the LDAP URL as a String
-     * @return a parsed instance of LdapUrl.
-     * @throws NamingException
-     *             if the URL or any one of its components is malformed.
-     */
-    LdapUrl parse( String a_urlString ) throws NamingException;
-}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AbstractSimpleComponentsMonitor.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AbstractSimpleComponentsMonitor.java
index ab51807..7567f4b 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AbstractSimpleComponentsMonitor.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AbstractSimpleComponentsMonitor.java
@@ -56,7 +56,7 @@
     }
 
 
-    public List getRemainingComponents()
+    public List<String> getRemainingComponents()
     {
         return Collections.unmodifiableList( components );
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayEnumeration.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayEnumeration.java
index 73fcedc..c684b97 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayEnumeration.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayEnumeration.java
@@ -47,7 +47,13 @@
      */
     public ArrayEnumeration(Object[] array)
     {
-        this.array = array;
+        if ( array != null )
+        {
+            this.array = new Object[ array.length ];
+            System.arraycopy( array, 0, this.array, 0, array.length );
+        } else {
+            this.array = null;
+        }
     }
 
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayUtils.java
index 2e3d1ab..a1adf12 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ArrayUtils.java
@@ -21,8 +21,6 @@
 
 
 import java.lang.reflect.Array;
-import java.util.HashMap;
-import java.util.Map;
 
 
 /**
@@ -51,7 +49,7 @@
     /**
      * An empty immutable <code>Class</code> array.
      */
-    public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
 
     /**
      * An empty immutable <code>String</code> array.
@@ -204,6 +202,7 @@
         {
             return stringIfNull;
         }
+        
         return new ToStringBuilder( array, ToStringStyle.SIMPLE_STYLE ).append( array ).toString();
     }
 
@@ -248,80 +247,6 @@
         return new EqualsBuilder().append( array1, array2 ).isEquals();
     }
 
-
-    // To map
-    // -----------------------------------------------------------------------
-    /**
-     * <p>
-     * Converts the given array into a {@link java.util.Map}. Each element of
-     * the array must be either a {@link java.util.Map.Entry} or an Array,
-     * containing at least two elements, where the first element is used as key
-     * and the second as value.
-     * </p>
-     * <p>
-     * This method can be used to initialize:
-     * </p>
-     * 
-     * <pre>
-     *  // Create a Map mapping colors.
-     *  Map colorMap = MapUtils.toMap(new String[][] {{
-     *      {&quot;RED&quot;, &quot;#FF0000&quot;},
-     *      {&quot;GREEN&quot;, &quot;#00FF00&quot;},
-     *      {&quot;BLUE&quot;, &quot;#0000FF&quot;}});
-     * </pre>
-     * 
-     * <p>
-     * This method returns <code>null</code> if <code>null</code> array
-     * input.
-     * </p>
-     * 
-     * @param array
-     *            an array whose elements are either a
-     *            {@link java.util.Map.Entry} or an Array containing at least
-     *            two elements, may be <code>null</code>
-     * @return a <code>Map</code> that was created from the array
-     * @throws IllegalArgumentException
-     *             if one element of this Array is itself an Array containing
-     *             less then two elements
-     * @throws IllegalArgumentException
-     *             if the array contains elements other than
-     *             {@link java.util.Map.Entry} and an Array
-     */
-    public static Map toMap( Object[] array )
-    {
-        if ( array == null )
-        {
-            return null;
-        }
-        final Map map = new HashMap( ( int ) ( array.length * 1.5 ) );
-        for ( int i = 0; i < array.length; i++ )
-        {
-            Object object = array[i];
-            if ( object instanceof Map.Entry )
-            {
-                Map.Entry entry = ( Map.Entry ) object;
-                map.put( entry.getKey(), entry.getValue() );
-            }
-            else if ( object instanceof Object[] )
-            {
-                Object[] entry = ( Object[] ) object;
-                if ( entry.length < 2 )
-                {
-                    throw new IllegalArgumentException( "Array element " + i + ", '" + object
-                        + "', has a length less than 2" );
-                }
-                map.put( entry[0], entry[1] );
-            }
-            else
-            {
-                throw new IllegalArgumentException( "Array element " + i + ", '" + object
-                    + "', is neither of type Map.Entry nor an Array" );
-            }
-        }
-        return map;
-    }
-
-
     // Clone
     // -----------------------------------------------------------------------
     /**
@@ -601,7 +526,7 @@
             endIndexExclusive = array.length;
         }
         int newSize = endIndexExclusive - startIndexInclusive;
-        Class type = array.getClass().getComponentType();
+        Class<?> type = array.getClass().getComponentType();
         if ( newSize <= 0 )
         {
             return ( Object[] ) Array.newInstance( type, 0 );
@@ -4570,7 +4495,7 @@
      *            1 array of this type.
      * @return A new copy of the array of size 1 greater than the input.
      */
-    private static Object copyArrayGrow1( Object array, Class newArrayComponentType )
+    private static Object copyArrayGrow1( Object array, Class<?> newArrayComponentType )
     {
         if ( array != null )
         {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeSerializerUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeSerializerUtils.java
index d8977cd..46aaa1e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeSerializerUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeSerializerUtils.java
@@ -39,8 +39,6 @@
  */
 public class AttributeSerializerUtils
 {
-    private static final long serialVersionUID = -3756830073760754086L;
-  
     static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
     /** value for type parameter for string (non-binary) attributes */
@@ -50,38 +48,6 @@
     static final byte BYTE_ARRAY_TYPE = 0x01;
     
     /*
-    private class ExtensibleByteArray
-    {
-    	private static final int EXTENSION = 2048;
-    	private List<byte[]> array;
-    	private byte[] currentData;
-    	private int pos = 0;
-    	private int limit = EXTENSION;
-    	
-    	private ExtensibleByteArray()
-    	{
-    		array = new ArrayList<byte[]>();
-    		currentData = new byte[EXTENSION];
-    		array.add( currentData );
-    	}
-    	
-    	private void extend()
-    	{
-    		limit += EXTENSION;
-    		array.add( new byte[EXTENSION] );
-    	}
-    	
-    	private void put( byte b )
-    	{
-    		if ( pos == limit )
-    		{
-    			extend();
-    			currentData = 
-    		}
-    		
-    		
-    	}
-    }*/
     
 
     // -----------------------------------------------------------------------
@@ -309,13 +275,14 @@
         {
             // write the type or is-binary field
             Object first = attr.get();
+            
             if ( first instanceof String )
             {
                 buf[pos] = STRING_TYPE;
                 pos++;
 
                 // write out each value to the buffer whatever type it may be
-                for ( NamingEnumeration ii = attr.getAll(); ii.hasMore(); /**/ )
+                for ( NamingEnumeration<?> ii = attr.getAll(); ii.hasMore(); /**/ )
                 {
                     String value = ( String ) ii.next();
                     pos = write( buf, value, pos );
@@ -327,7 +294,7 @@
                 pos++;
 
                 // write out each value to the buffer whatever type it may be
-                for ( NamingEnumeration ii = attr.getAll(); ii.hasMore(); /**/ )
+                for ( NamingEnumeration<?> ii = attr.getAll(); ii.hasMore(); /**/ )
                 {
                     byte[] value = ( byte[] ) ii.next();
                     pos = write( buf, value, pos );
@@ -354,9 +321,10 @@
         
         try
         {
-            for ( NamingEnumeration ii = attr.getAll(); ii.hasMore(); /**/ )
+            for ( NamingEnumeration<?> ii = attr.getAll(); ii.hasMore(); /**/ )
             {
                 Object value = ii.next();
+                
                 if ( value instanceof String )
                 {
                     size += ( ( String ) value ).length() << 1; // length of sting * 2
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java
index 6923299..a5bf524 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java
@@ -21,7 +21,17 @@
 
 
 import java.text.ParseException;
+
 import java.util.Arrays;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
 
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
@@ -31,12 +41,6 @@
 import org.apache.directory.shared.ldap.schema.NoOpNormalizer;
 import org.apache.directory.shared.ldap.schema.Normalizer;
 
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-
 
 /**
  * A set of utility fuctions for working with Attributes.
@@ -52,17 +56,19 @@
      * @param type the attributeType of the attribute to remove
      * @param entry the entry to remove the attribute from 
      * @return the Attribute that is removed
-     * @throws NamingException if there are problems accessing the attribute
      */
     public static Attribute removeAttribute( AttributeType type, Attributes entry )
     {
         Attribute attr = entry.get( type.getOid() );
+        
         if ( attr == null )
         {
-            String[] aliases = type.getNames();
-            for ( int ii = 0; ii < aliases.length; ii++ )
+            String[] aliases = type.getNamesRef();
+            
+            for ( String alias:aliases )
             {
-                attr = entry.get( aliases[ii] );
+                attr = entry.get( alias );
+
                 if ( attr != null )
                 {
                     return entry.remove( attr.getID() );
@@ -86,13 +92,18 @@
      * @param value2 The second value
      * @return true if both value are null or if they are equal.
      */
-    public final static boolean equals( Object value1, Object value2 )
+    public static final boolean equals( Object value1, Object value2 )
     {
         if ( value1 == value2 )
         {
             return true;
         }
         
+        if ( value1 == null )
+        {
+            return ( value2 == null );
+        }
+        
         if ( value1 instanceof byte[] )
         {
             if ( value2 instanceof byte[] )
@@ -109,7 +120,8 @@
             return value1.equals( value2 );
         }
     }
-    
+
+
     /**
      * Clone the value. An attribute value is supposed to be either a String
      * or a byte array. If it's a String, then we just return it ( as String
@@ -119,7 +131,7 @@
      * @param value The value to clone
      * @return The cloned value
      */
-    public final static Object cloneValue( Object value )
+    public static Object cloneValue( Object value )
     {
         // First copy the value
         Object newValue = null;
@@ -136,6 +148,7 @@
         return newValue;
     }
 
+
     /**
      * Switch from a BasicAttribute to a AttributeImpl. This is
      * necessary to allow cloning to be correctly handled.
@@ -143,7 +156,7 @@
      * @param attribute The attribute to transform
      * @return A instance of AttributeImpl
      */
-    public final static Attribute toAttributeImpl( Attribute attribute )
+    public static final Attribute toAttributeImpl( Attribute attribute )
     {
         if ( attribute instanceof AttributeImpl )
         {
@@ -157,7 +170,7 @@
             
             try
             {
-                NamingEnumeration values = attribute.getAll();
+                NamingEnumeration<?> values = attribute.getAll();
                 
                 while ( values.hasMoreElements() )
                 {
@@ -172,7 +185,8 @@
             }
         }
     }
-    
+
+
     /**
      * Switch from a BasicAttributes to a AttributesImpl. This is
      * necessary to allow cloning to be correctly handled.
@@ -180,7 +194,7 @@
      * @param attributes The attributes to transform
      * @return A instance of AttributesImpl
      */
-    public final static Attributes toAttributesImpl( Attributes attributes )
+    public static final Attributes toAttributesImpl( Attributes attributes )
     {
         if ( attributes instanceof AttributesImpl )
         {
@@ -194,7 +208,7 @@
             
             try
             {
-                NamingEnumeration values = attributes.getAll();
+                NamingEnumeration<?> values = attributes.getAll();
                 
                 while ( values.hasMoreElements() )
                 {
@@ -211,7 +225,8 @@
             }
         }
     }
-    
+
+
     /**
      * Utility method to extract an attribute from Attributes object using
      * all combinationos of the name including aliases.
@@ -220,7 +235,7 @@
      * @param type the attribute type specification
      * @return an Attribute with matching the attributeType spec or null
      */
-    public final static Attribute getAttribute( Attributes attrs, AttributeType type )
+    public static final Attribute getAttribute( Attributes attrs, AttributeType type )
     {
         // check if the attribute's OID is used
         Attribute attr = attrs.get( type.getOid() );
@@ -231,9 +246,9 @@
         }
 
         // optimization bypass to avoid cost of the loop below
-        if ( type.getNames().length == 1 )
+        if ( type.getNamesRef().length == 1 )
         {
-            attr = attrs.get( type.getNames()[0] );
+            attr = attrs.get( type.getNamesRef()[0] );
             
             if ( attr != null )
             {
@@ -242,7 +257,7 @@
         }
         
         // iterate through aliases
-        for ( String alias:type.getNames() )
+        for ( String alias:type.getNamesRef() )
         {
             attr = attrs.get( alias );
             
@@ -263,61 +278,44 @@
      * @param type the attributeType spec of the Attribute to extract
      * @return the modification item on the attributeType specified
      */
-    public final static ModificationItemImpl getModificationItem( ModificationItemImpl[] mods, AttributeType type )
+    public static final ModificationItem getModificationItem( List<ModificationItemImpl> mods, AttributeType type )
     {
         // optimization bypass to avoid cost of the loop below
-        if ( type.getNames().length == 1 )
+        if ( type.getNamesRef().length == 1 )
         {
-            for ( int jj = 0; jj < mods.length; jj++ )
+            for ( ModificationItem mod:mods )
             {
-                if ( mods[jj].getAttribute().getID().equalsIgnoreCase( type.getNames()[0] ) )
+                if ( mod.getAttribute().getID().equalsIgnoreCase( type.getNamesRef()[0] ) )
                 {
-                    return mods[jj];
+                    return mod;
                 }
             }
         }
         
         // check if the attribute's OID is used
-        for ( int jj = 0; jj < mods.length; jj++ )
+        for ( ModificationItem mod:mods )
         {
-            if ( mods[jj].getAttribute().getID().equals( type.getOid() ) )
+            if ( mod.getAttribute().getID().equals( type.getOid() ) )
             {
-                return mods[jj];
+                return mod;
             }
         }
         
         // iterate through aliases
-        for ( int ii = 0; ii < type.getNames().length; ii++ )
+        for ( int ii = 0; ii < type.getNamesRef().length; ii++ )
         {
-            for ( int jj = 0; jj < mods.length; jj++ )
+            for ( ModificationItem mod:mods )
             {
-                if ( mods[jj].getAttribute().getID().equalsIgnoreCase( type.getNames()[ii] ) )
+                if ( mod.getAttribute().getID().equalsIgnoreCase( type.getNamesRef()[ii] ) )
                 {
-                    return mods[jj];
+                    return mod;
                 }
             }
         }
         
         return null;
     }
-    
-    
-    /**
-     * Utility method to extract an attribute from an array of modifications.
-     * 
-     * @param mods the array of ModificationItems to extract the Attribute from.
-     * @param type the attributeType spec of the Attribute to extract
-     * @return the extract Attribute or null if no such attribute exists
-     */
-    public final static Attribute getAttribute( ModificationItemImpl[] mods, AttributeType type )
-    {
-        ModificationItemImpl mod = getModificationItem( mods, type );
-        if ( mod != null )
-        {
-            return mod.getAttribute();
-        }
-        return null;
-    }
+
     
     /**
      * Check if an attribute contains a specific value, using the associated matchingRule for that
@@ -328,7 +326,7 @@
      * @return <code>true</code> if the value exists in the attribute</code>
      * @throws NamingException If something went wrong while accessing the data
      */
-    public final static boolean containsValue( Attribute attr, Object compared, AttributeType type ) throws NamingException
+    public static boolean containsValue( Attribute attr, Object compared, AttributeType type ) throws NamingException
     {
         // quick bypass test
         if ( attr.contains( compared ) )
@@ -353,11 +351,9 @@
         {
             String comparedStr = ( String ) normalizer.normalize( compared );
             
-            for ( NamingEnumeration values = attr.getAll(); values.hasMoreElements(); /**/ )
-            //for ( int ii = attr.size() - 1; ii >= 0; ii-- )
+            for ( NamingEnumeration<?> values = attr.getAll(); values.hasMoreElements(); /**/ )
             {
                 String value = (String)values.nextElement();
-                //String value = ( String ) attr.get( ii );
                 if ( comparedStr.equals( normalizer.normalize( value ) ) )
                 {
                     return true;
@@ -418,6 +414,7 @@
                             pos++;
                             
                             state = 1;
+                            break;
                     }
                 }
             }
@@ -426,8 +423,7 @@
                 comparedBytes = ( byte[] ) compared;
             }
             
-            for ( NamingEnumeration values = attr.getAll(); values.hasMoreElements(); /**/ )
-            //for ( int ii = attr.size() - 1; ii >= 0; ii-- )
+            for ( NamingEnumeration<?> values = attr.getAll(); values.hasMoreElements(); /**/ )
             {
                 Object value = values.nextElement();
                 
@@ -444,6 +440,7 @@
         return false;
     }
 
+
     /**
      * Check if an attribute contains a value. The test is case insensitive,
      * and the value is supposed to be a String. If the value is a byte[],
@@ -452,9 +449,8 @@
      * @param attr The attribute to check
      * @param value The value to look for
      * @return true if the value is present in the attribute
-     * @throws NamingException
      */
-    public final static boolean containsValueCaseIgnore( Attribute attr, Object value )
+    public static boolean containsValueCaseIgnore( Attribute attr, Object value )
     {
         // quick bypass test
         if ( attr.contains( value ) )
@@ -468,7 +464,7 @@
             {
                 String strVal = (String)value;
 
-                NamingEnumeration attrVals = attr.getAll();
+                NamingEnumeration<?> attrVals = attr.getAll();
 
                 while ( attrVals.hasMoreElements() )
                 {
@@ -487,7 +483,7 @@
             {
                 byte[] valueBytes = ( byte[] )value;
 
-                NamingEnumeration attrVals = attr.getAll();
+                NamingEnumeration<?> attrVals = attr.getAll();
 
                 while ( attrVals.hasMoreElements() )
                 {
@@ -517,9 +513,9 @@
         throws NamingException
     {
         // quick bypass test
-        for ( int ii = 0; ii < compared.length; ii++ )
+        for ( Object object:compared )
         {
-            if ( attr.contains( compared ) )
+            if ( attr.contains( object ) )
             {
                 return true;
             }
@@ -529,12 +525,14 @@
 
         if ( type.getSyntax().isHumanReadable() )
         {
-            for ( int jj = 0; jj < compared.length; jj++ )
+            for ( Object object:compared )
             {
-                String comparedStr = ( String ) normalizer.normalize( compared[jj] );
+                String comparedStr = ( String ) normalizer.normalize( object );
+                
                 for ( int ii = attr.size(); ii >= 0; ii-- )
                 {
                     String value = ( String ) attr.get( ii );
+                    
                     if ( comparedStr.equals( normalizer.normalize( value ) ) )
                     {
                         return true;
@@ -544,9 +542,10 @@
         }
         else
         {
-            for ( int jj = 0; jj < compared.length; jj++ )
+            for ( Object object:compared )
             {
-                byte[] comparedBytes = ( byte[] ) compared[jj];
+                byte[] comparedBytes = ( byte[] )object;
+                
                 for ( int ii = attr.size(); ii >= 0; ii-- )
                 {
                     if ( ArrayUtils.isEquals( comparedBytes, attr.get( ii ) ) )
@@ -580,7 +579,7 @@
     {
         String id;
 
-        if ( attr0 == null && attr1 == null )
+        if ( ( attr0 == null ) && ( attr1 == null ) )
         {
             throw new IllegalArgumentException( "Cannot figure out attribute ID if both args are null" );
         }
@@ -603,20 +602,14 @@
 
         Attribute attr = new AttributeImpl( id );
 
-        if ( attr0 != null )
+        for ( int ii = 0; ii < attr0.size(); ii++ )
         {
-            for ( int ii = 0; ii < attr0.size(); ii++ )
-            {
-                attr.add( attr0.get( ii ) );
-            }
+            attr.add( attr0.get( ii ) );
         }
 
-        if ( attr1 != null )
+        for ( int ii = 0; ii < attr1.size(); ii++ )
         {
-            for ( int ii = 0; ii < attr1.size(); ii++ )
-            {
-                attr.remove( attr1.get( ii ) );
-            }
+            attr.remove( attr1.get( ii ) );
         }
 
         return attr;
@@ -685,6 +678,7 @@
         return attr;
     }
 
+
     /**
      * Check if the attributes is a BasicAttributes, and if so, switch
      * the case sensitivity to false to avoid tricky problems in the server.
@@ -709,10 +703,10 @@
             else
             {
                 // Ok, bad news : we have to create a new BasicAttributes
-                // whiwh will be case insensitive
+                // which will be case insensitive
                 Attributes newAttrs = new BasicAttributes( true );
                 
-                NamingEnumeration attrs = attributes.getAll();
+                NamingEnumeration<?> attrs = attributes.getAll();
                 
                 if ( attrs != null )
                 {
@@ -794,6 +788,7 @@
         return sb.toString();
     }
 
+
     /**
      * Return a string representing the attribute
      * 
@@ -806,6 +801,7 @@
         return toString( "", attribute );
     }
 
+
     /**
      * Return a string representing the attributes with tabs in front of the
      * string
@@ -819,24 +815,23 @@
     public static String toString( String tabs, Attributes attributes )
     {
         StringBuffer sb = new StringBuffer();
-
         sb.append( tabs ).append( "Attributes\n" );
 
         if ( attributes != null )
         {
-            NamingEnumeration attributesIterator = attributes.getAll();
+            NamingEnumeration<?> attributesIterator = attributes.getAll();
     
             while ( attributesIterator.hasMoreElements() )
             {
                 Attribute attribute = ( Attribute ) attributesIterator.nextElement();
-    
                 sb.append( tabs ).append( attribute.toString() );
             }
         }
         
         return sb.toString();
     }
-    
+
+
     /**
      * Parse attribute's options :
      * 
@@ -865,7 +860,8 @@
             }
         }
     }
-    
+
+
     /**
      * Parse a number :
      * 
@@ -929,14 +925,14 @@
         parseNumber( str, pos );
         
         // We must have at least one '.' number
-        if ( StringTools.isCharASCII( str, pos.start, '.' ) == false )
+        if ( !StringTools.isCharASCII( str, pos.start, '.' ) )
         {
             throw new ParseException( "Invalid OID, missing '.'", pos.start );
         }
         
         pos.start++;
         
-        if ( parseNumber( str, pos ) == false )
+        if ( !parseNumber( str, pos ) )
         {
             throw new ParseException( "Invalid OID, missing a number after a '.'", pos.start );
         }
@@ -944,20 +940,21 @@
         while ( true )
         {
             // Break if we get something which is not a '.'
-            if ( StringTools.isCharASCII( str, pos.start, '.' ) == false )
+            if ( !StringTools.isCharASCII( str, pos.start, '.' ) )
             {
                 break;
             }
             
             pos.start++;
             
-            if ( parseNumber( str, pos ) == false )
+            if ( !parseNumber( str, pos ) )
             {
                 throw new ParseException( "Invalid OID, missing a number after a '.'", pos.start );
             }
         }
     }
-    
+
+
     /**
      * Parse an attribute. The grammar is :
      * attributedescription = attributetype options
@@ -972,7 +969,7 @@
      * keychar = 'a'-z' | 'A'-'Z' / '0'-'9' / '-'
      * number = '0'-'9' / ( '1'-'9' 1*'0'-'9' )
      *
-     * @param attr The parsed attribute,
+     * @param str The parsed attribute,
      * @param pos The position of the attribute in the current string
      * @return The parsed attribute if valid
      */
@@ -1040,4 +1037,223 @@
     {
         return toString( "", attributes );
     }
+
+
+    /**
+     * A method to apply a modification to an existing entry.
+     * 
+     * @param entry The entry on which we want to apply a modification
+     * @param modification the Modification to be applied
+     * @throws NamingException if some operation fails.
+     */
+    public static void applyModification( Attributes entry, ModificationItem modification ) throws NamingException
+    {
+        Attribute modAttr = modification.getAttribute(); 
+        String modificationId = modAttr.getID();
+        
+        switch ( modification.getModificationOp() )
+        {
+            case DirContext.ADD_ATTRIBUTE :
+                Attribute modifiedAttr = entry.get( modificationId ) ;
+                
+                if ( modifiedAttr == null )
+                {
+                    // The attribute should be added.
+                    entry.put( modAttr );
+                }
+                else
+                {
+                    // The attribute exists : the values can be different,
+                    // so we will just add the new values to the existing ones.
+                    NamingEnumeration<?> values = modAttr.getAll();
+                    
+                    while ( values.hasMoreElements() )
+                    {
+                        // If the value already exist, nothing is done.
+                        // Note that the attribute *must* have been
+                        // normalized before.
+                        modifiedAttr.add( values.nextElement() );
+                    }
+                }
+                
+                break;
+                
+            case DirContext.REMOVE_ATTRIBUTE :
+                if ( modAttr.get() == null )
+                {
+                    // We have no value in the ModificationItem attribute :
+                    // we have to remove the whole attribute from the initial
+                    // entry
+                    entry.remove( modificationId );
+                }
+                else
+                {
+                    // We just have to remove the values from the original
+                    // entry, if they exist.
+                    modifiedAttr = entry.get( modificationId ) ;
+                    
+                    if ( modifiedAttr == null )
+                    {
+                        break;
+                    }
+
+                    NamingEnumeration<?> values = modAttr.getAll();
+                    
+                    while ( values.hasMoreElements() )
+                    {
+                        // If the value does not exist, nothing is done.
+                        // Note that the attribute *must* have been
+                        // normalized before.
+                        modifiedAttr.remove( values.nextElement() );
+                    }
+                    
+                    if ( modifiedAttr.size() == 0 )
+                    {
+                        // If this was the last value, remove the attribute
+                        entry.remove( modifiedAttr.getID() );
+                    }
+                }
+
+                break;
+                
+            case DirContext.REPLACE_ATTRIBUTE :
+                if ( modAttr.get() == null )
+                {
+                    // If the modification does not have any value, we have
+                    // to delete the attribute from the entry.
+                    entry.remove( modificationId );
+                }
+                else
+                {
+                    // otherwise, just substitute the existing attribute.
+                    entry.put( modAttr );
+                }
+
+                break;
+        }
+    }
+
+
+    /**
+     * Check if an attribute contains a specific value and remove it using the associated
+     * matchingRule for the attribute type supplied.
+     *
+     * @param attr the attribute we are searching in
+     * @param compared the object we are looking for
+     * @param type the attribute type
+     * @return the value removed from the attribute, otherwise null
+     * @throws NamingException if something went wrong while removing the value
+     */
+    public static Object removeValue( Attribute attr, Object compared, AttributeType type ) throws NamingException
+    {
+        // quick bypass test
+        if ( attr.contains( compared ) )
+        {
+            return attr.remove( compared );
+        }
+
+        MatchingRule matchingRule = type.getEquality();
+        Normalizer normalizer;
+
+        if ( matchingRule != null )
+        {
+            normalizer = type.getEquality().getNormalizer();
+        }
+        else
+        {
+            normalizer = new NoOpNormalizer();
+        }
+
+        if ( type.getSyntax().isHumanReadable() )
+        {
+            String comparedStr = ( String ) normalizer.normalize( compared );
+
+            for ( NamingEnumeration<?> values = attr.getAll(); values.hasMoreElements(); /**/ )
+            {
+                String value = ( String ) values.nextElement();
+                if ( comparedStr.equals( normalizer.normalize( value ) ) )
+                {
+                    return attr.remove( value );
+                }
+            }
+        }
+        else
+        {
+            byte[] comparedBytes = null;
+
+            if ( compared instanceof String )
+            {
+                if ( ( ( String ) compared ).length() < 3 )
+                {
+                    return null;
+                }
+
+                // Tansform the String to a byte array
+                int state = 1;
+                comparedBytes = new byte[( ( String ) compared ).length() / 3];
+                int pos = 0;
+
+                for ( char c:((String)compared).toCharArray() )
+                {
+                    switch ( state )
+                    {
+                        case 1 :
+                            if ( c != '\\' )
+                            {
+                                return null;
+                            }
+
+                            state++;
+                            break;
+
+                        case 2 :
+                            int high = StringTools.getHexValue( c );
+
+                            if ( high == -1 )
+                            {
+                                return null;
+                            }
+
+                            comparedBytes[pos] = (byte)(high << 4);
+
+                            state++;
+                            break;
+
+                        case 3 :
+                            int low = StringTools.getHexValue( c );
+
+                            if ( low == -1 )
+                            {
+                                return null;
+                            }
+
+                            comparedBytes[pos] += (byte)low;
+                            pos++;
+
+                            state = 1;
+                            break;
+                    }
+                }
+            }
+            else
+            {
+                comparedBytes = ( byte[] ) compared;
+            }
+
+            for ( NamingEnumeration<?> values = attr.getAll(); values.hasMoreElements(); /**/ )
+            {
+                Object value = values.nextElement();
+
+                if ( value instanceof byte[] )
+                {
+                    if ( ArrayUtils.isEquals( comparedBytes, value ) )
+                    {
+                        return attr.remove( value );
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributesSerializerUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributesSerializerUtils.java
index e22f6ce..3666066 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributesSerializerUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributesSerializerUtils.java
@@ -103,10 +103,10 @@
         
         try
         {
-            for ( NamingEnumeration ii = attrs.getAll(); ii.hasMore(); /**/)
+            for ( NamingEnumeration<? extends Attribute> ii = attrs.getAll(); ii.hasMore(); /**/)
             {
                 // get an attribute at a time
-                Attribute attr = ( Attribute ) ii.next();
+                Attribute attr = ii.next();
 
                 // write the length of the id and it's value
                 pos = AttributeSerializerUtils.write( buf, attr.getID(), pos );
@@ -119,7 +119,7 @@
                     pos++;
 
                     // write out each value to the buffer whatever type it may be
-                    for ( NamingEnumeration jj = attr.getAll(); jj.hasMore(); /**/)
+                    for ( NamingEnumeration<?> jj = attr.getAll(); jj.hasMore(); /**/)
                     {
                         String value = ( String ) jj.next();
                         pos = AttributeSerializerUtils.write( buf, value, pos );
@@ -131,7 +131,7 @@
                     pos++;
 
                     // write out each value to the buffer whatever type it may be
-                    for ( NamingEnumeration jj = attr.getAll(); jj.hasMore(); /**/)
+                    for ( NamingEnumeration<?> jj = attr.getAll(); jj.hasMore(); /**/)
                     {
                         byte[] value = ( byte[] ) jj.next();
                         pos = AttributeSerializerUtils.write( buf, value, pos );
@@ -162,7 +162,7 @@
 
         try
         {
-            for ( NamingEnumeration ii = attrs.getAll(); ii.hasMore(); /**/)
+            for ( NamingEnumeration<? extends Attribute> ii = attrs.getAll(); ii.hasMore(); /**/)
             {
                 Attribute attr = ( Attribute ) ii.next();
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/Base64.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/Base64.java
index be72c37..f12c78f 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/Base64.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/Base64.java
@@ -89,7 +89,7 @@
      *            data to decode.
      * @return the decoded binary data.
      */
-    public static byte[] decode( char[] a_data )
+    public static byte[] decode( char[] data )
     {
         // as our input could contain non-BASE64 data (newlines,
         // whitespace of any sort, whatever) we must first adjust
@@ -98,12 +98,13 @@
         // (b) think that we miscalculated our data length
         // just because of extraneous throw-away junk
 
-        int l_tempLen = a_data.length;
-        for ( int ii = 0; ii < a_data.length; ii++ )
+        int tempLen = data.length;
+        
+        for ( char c:data)
         {
-            if ( ( a_data[ii] > 255 ) || s_codes[a_data[ii]] < 0 )
+            if ( ( c > 255 ) || s_codes[c] < 0 )
             {
-                --l_tempLen; // ignore non-valid chars and padding
+                --tempLen; // ignore non-valid chars and padding
             }
         }
         // calculate required length:
@@ -111,14 +112,14 @@
         // -- plus 2 bytes if there are 3 extra base64 chars,
         // or plus 1 byte if there are 2 extra.
 
-        int l_len = ( l_tempLen / 4 ) * 3;
+        int l_len = ( tempLen / 4 ) * 3;
 
-        if ( ( l_tempLen % 4 ) == 3 )
+        if ( ( tempLen % 4 ) == 3 )
         {
             l_len += 2;
         }
 
-        if ( ( l_tempLen % 4 ) == 2 )
+        if ( ( tempLen % 4 ) == 2 )
         {
             l_len += 1;
         }
@@ -130,9 +131,9 @@
         int l_index = 0;
 
         // we now go through the entire array (NOT using the 'tempLen' value)
-        for ( int ii = 0; ii < a_data.length; ii++ )
+        for ( char c:data )
         {
-            int l_value = ( a_data[ii] > 255 ) ? -1 : s_codes[a_data[ii]];
+            int l_value = ( c > 255 ) ? -1 : s_codes[c];
 
             if ( l_value >= 0 ) // skip over non-code
             {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ClassUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ClassUtils.java
index 5cd789f..85fc206 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ClassUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ClassUtils.java
@@ -74,7 +74,8 @@
      * Maps primitive <code>Class</code>es to their corresponding wrapper
      * <code>Class</code>.
      */
-    private static Map<Class,Class> primitiveWrapperMap = new HashMap<Class,Class>();
+    private static Map<Class<?>,Class<?>> primitiveWrapperMap = new HashMap<Class<?>,Class<?>>();
+    
     static
     {
         primitiveWrapperMap.put( Boolean.TYPE, Boolean.class );
@@ -137,12 +138,13 @@
      *            the class to get the short name for.
      * @return the class name without the package name or an empty string
      */
-    public static String getShortClassName( Class cls )
+    public static String getShortClassName( Class<?> cls )
     {
         if ( cls == null )
         {
             return EMPTY;
         }
+        
         return getShortClassName( cls.getName() );
     }
 
@@ -166,12 +168,15 @@
         {
             return EMPTY;
         }
+        
         if ( className.length() == 0 )
         {
             return EMPTY;
         }
+        
         char[] chars = className.toCharArray();
         int lastDot = 0;
+        
         for ( int i = 0; i < chars.length; i++ )
         {
             if ( chars[i] == PACKAGE_SEPARATOR_CHAR )
@@ -183,6 +188,7 @@
                 chars[i] = PACKAGE_SEPARATOR_CHAR;
             }
         }
+        
         return new String( chars, lastDot, chars.length - lastDot );
     }
 
@@ -206,6 +212,7 @@
         {
             return valueIfNull;
         }
+        
         return getPackageName( object.getClass().getName() );
     }
 
@@ -220,12 +227,13 @@
      *            <code>null</code>.
      * @return the package name or an empty string
      */
-    public static String getPackageName( Class cls )
+    public static String getPackageName( Class<?> cls )
     {
         if ( cls == null )
         {
             return EMPTY;
         }
+        
         return getPackageName( cls.getName() );
     }
 
@@ -252,11 +260,14 @@
         {
             return EMPTY;
         }
+        
         int i = className.lastIndexOf( PACKAGE_SEPARATOR_CHAR );
+        
         if ( i == -1 )
         {
             return EMPTY;
         }
+        
         return className.substring( 0, i );
     }
 
@@ -273,15 +284,16 @@
      * @return the <code>List</code> of superclasses in order going up from
      *         this one <code>null</code> if null input
      */
-    public static List getAllSuperclasses( Class cls )
+    public static List<Class<?>> getAllSuperclasses( Class<?> cls )
     {
         if ( cls == null )
         {
             return null;
         }
         
-        List<Class> classes = new ArrayList<Class>();
-        Class superclass = cls.getSuperclass();
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+        
+        Class<?> superclass = cls.getSuperclass();
         
         while ( superclass != null )
         {
@@ -310,27 +322,27 @@
      * @return the <code>List</code> of interfaces in order, <code>null</code>
      *         if null input
      */
-    public static List<Class> getAllInterfaces( Class cls )
+    public static List<Class<?>> getAllInterfaces( Class<?> cls )
     {
         if ( cls == null )
         {
             return null;
         }
         
-        List<Class> list = new ArrayList<Class>();
+        List<Class<?>> list = new ArrayList<Class<?>>();
         
         while ( cls != null )
         {
-            Class[] interfaces = cls.getInterfaces();
+            Class<?>[] interfaces = cls.getInterfaces();
             
-            for ( Class interf:interfaces )
+            for ( Class<?> interf:interfaces )
             {
                 if ( list.contains( interf ) == false )
                 {
                     list.add( interf );
                 }
                 
-                for ( Class superIntf:getAllInterfaces( interf ) )
+                for ( Class<?> superIntf:getAllInterfaces( interf ) )
                 {
                     if ( list.contains( superIntf ) == false )
                     {
@@ -341,6 +353,7 @@
             
             cls = cls.getSuperclass();
         }
+        
         return list;
     }
 
@@ -366,14 +379,14 @@
      * @throws ClassCastException
      *             if classNames contains a non String entry
      */
-    public static List convertClassNamesToClasses( List<String> classNames )
+    public static List<Class<?>> convertClassNamesToClasses( List<String> classNames )
     {
         if ( classNames == null )
         {
             return null;
         }
         
-        List<Class> classes = new ArrayList<Class>( classNames.size() );
+        List<Class<?>> classes = new ArrayList<Class<?>>( classNames.size() );
         
         for ( String className:classNames )
         {
@@ -409,7 +422,7 @@
      *             if <code>classes</code> contains a non-<code>Class</code>
      *             entry
      */
-    public static List<String> convertClassesToClassNames( List<Class> classes )
+    public static List<String> convertClassesToClassNames( List<Class<?>> classes )
     {
         if ( classes == null )
         {
@@ -418,7 +431,7 @@
         
         List<String> classNames = new ArrayList<String>( classes.size() );
         
-        for ( Class clazz:classes )
+        for ( Class<?> clazz:classes )
         {
             if ( clazz == null )
             {
@@ -478,20 +491,23 @@
      *            <code>null</code>
      * @return <code>true</code> if assignment possible
      */
-    public static boolean isAssignable( Class[] classArray, Class[] toClassArray )
+    public static boolean isAssignable( Class<?>[] classArray, Class<?>[] toClassArray )
     {
         if ( ArrayUtils.isSameLength( classArray, toClassArray ) == false )
         {
             return false;
         }
+        
         if ( classArray == null )
         {
             classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
+        
         if ( toClassArray == null )
         {
             toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
         }
+        
         for ( int i = 0; i < classArray.length; i++ )
         {
             if ( isAssignable( classArray[i], toClassArray[i] ) == false )
@@ -499,6 +515,7 @@
                 return false;
             }
         }
+        
         return true;
     }
 
@@ -537,65 +554,78 @@
      *            the Class to try to assign into, returns false if null
      * @return <code>true</code> if assignment possible
      */
-    public static boolean isAssignable( Class cls, Class toClass )
+    public static boolean isAssignable( Class<?> cls, Class<?> toClass )
     {
         if ( toClass == null )
         {
             return false;
         }
+        
         // have to check for null, as isAssignableFrom doesn't
         if ( cls == null )
         {
             return !( toClass.isPrimitive() );
         }
+        
         if ( cls.equals( toClass ) )
         {
             return true;
         }
+        
         if ( cls.isPrimitive() )
         {
             if ( toClass.isPrimitive() == false )
             {
                 return false;
             }
+            
             if ( Integer.TYPE.equals( cls ) )
             {
                 return Long.TYPE.equals( toClass ) || Float.TYPE.equals( toClass ) || Double.TYPE.equals( toClass );
             }
+            
             if ( Long.TYPE.equals( cls ) )
             {
                 return Float.TYPE.equals( toClass ) || Double.TYPE.equals( toClass );
             }
+            
             if ( Boolean.TYPE.equals( cls ) )
             {
                 return false;
             }
+            
             if ( Double.TYPE.equals( cls ) )
             {
                 return false;
             }
+            
             if ( Float.TYPE.equals( cls ) )
             {
                 return Double.TYPE.equals( toClass );
             }
+            
             if ( Character.TYPE.equals( cls ) )
             {
                 return Integer.TYPE.equals( toClass ) || Long.TYPE.equals( toClass ) || Float.TYPE.equals( toClass )
                     || Double.TYPE.equals( toClass );
             }
+            
             if ( Short.TYPE.equals( cls ) )
             {
                 return Integer.TYPE.equals( toClass ) || Long.TYPE.equals( toClass ) || Float.TYPE.equals( toClass )
                     || Double.TYPE.equals( toClass );
             }
+            
             if ( Byte.TYPE.equals( cls ) )
             {
                 return Short.TYPE.equals( toClass ) || Integer.TYPE.equals( toClass ) || Long.TYPE.equals( toClass )
                     || Float.TYPE.equals( toClass ) || Double.TYPE.equals( toClass );
             }
+            
             // should never get here
             return false;
         }
+        
         return toClass.isAssignableFrom( cls );
     }
 
@@ -612,13 +642,15 @@
      *         <code>cls</code> is not a primitive. <code>null</code> if
      *         null input.
      */
-    public static Class primitiveToWrapper( Class cls )
+    public static Class<?> primitiveToWrapper( Class<?> cls )
     {
-        Class convertedClass = cls;
+        Class<?> convertedClass = cls;
+        
         if ( cls != null && cls.isPrimitive() )
         {
             convertedClass = primitiveWrapperMap.get( cls );
         }
+        
         return convertedClass;
     }
 
@@ -636,7 +668,7 @@
      *         <code>null</code> if null input. Empty array if an empty array
      *         passed in.
      */
-    public static Class[] primitivesToWrappers( Class[] classes )
+    public static Class<?>[] primitivesToWrappers( Class<?>[] classes )
     {
         if ( classes == null )
         {
@@ -648,11 +680,13 @@
             return ArrayUtils.EMPTY_CLASS_ARRAY;
         }
 
-        Class[] convertedClasses = new Class[classes.length];
+        Class<?>[] convertedClasses = new Class[classes.length];
+        
         for ( int i = 0; i < classes.length; i++ )
         {
             convertedClasses[i] = primitiveToWrapper( classes[i] );
         }
+        
         return convertedClasses;
     }
 
@@ -669,12 +703,13 @@
      * @return <code>true</code> if the class is an inner or static nested
      *         class, false if not or <code>null</code>
      */
-    public static boolean isInnerClass( Class cls )
+    public static boolean isInnerClass( Class<?> cls )
     {
         if ( cls == null )
         {
             return false;
         }
+        
         return ( cls.getName().indexOf( INNER_CLASS_SEPARATOR_CHAR ) >= 0 );
     }
 
@@ -682,7 +717,7 @@
     /**
      * Compares two <code>Class</code>s by name.
      */
-    private static class ClassNameComparator implements Comparator
+    private static class ClassNameComparator implements Comparator<Class<?>>
     {
         /**
          * Compares two <code>Class</code>s by name.
@@ -691,18 +726,18 @@
          *             If <code>o1</code> or <code>o2</code> are not
          *             <code>Class</code> instances.
          */
-        public int compare( Object o1, Object o2 )
+        public int compare( Class<?> class1, Class<?> class2 )
         {
-            Class class1 = ( Class ) o1;
-            Class class2 = ( Class ) o2;
             if ( class1 == null )
             {
                 return class2 == null ? 0 : -1;
             }
+            
             if ( class2 == null )
             {
                 return 1;
             }
+            
             return class1.getName().compareTo( class2.getName() );
         }
     }
@@ -710,12 +745,12 @@
     /**
      * Compares two <code>Class</code>s by name.
      */
-    public static final Comparator CLASS_NAME_COMPARATOR = new ClassNameComparator();
+    public static final Comparator<Class<?>> CLASS_NAME_COMPARATOR = new ClassNameComparator();
 
     /**
      * Compares two <code>Package</code>s by name.
      */
-    private static class PackageNameComparator implements Comparator
+    private static class PackageNameComparator implements Comparator<Package>
     {
 
         /**
@@ -725,18 +760,18 @@
          *             If <code>o1</code> or <code>o2</code> are not
          *             <code>Package</code> instances.
          */
-        public int compare( Object o1, Object o2 )
+        public int compare( Package package1, Package package2 )
         {
-            Package package1 = ( Package ) o1;
-            Package package2 = ( Package ) o2;
             if ( package1 == null )
             {
                 return package2 == null ? 0 : -1;
             }
+
             if ( package2 == null )
             {
                 return 1;
             }
+            
             return package1.getName().compareTo( package2.getName() );
         }
     }
@@ -744,6 +779,6 @@
     /**
      * Compares two <code>Package</code>s by name.
      */
-    public static final Comparator PACKAGE_NAME_COMPARATOR = new PackageNameComparator();
+    public static final Comparator<Package> PACKAGE_NAME_COMPARATOR = new PackageNameComparator();
 
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java
index 98bba58..7539b92 100755
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java
@@ -19,14 +19,12 @@
  */
 package org.apache.directory.shared.ldap.util;
 
-import org.apache.directory.shared.ldap.util.Position;
-import org.apache.directory.shared.ldap.util.StringTools;
-
 
 /**
  * Utility class used by the LdapDN Parser.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
  */
 public class DNUtils
 {
@@ -123,28 +121,52 @@
         };
 
     /**
-     * ' ' | '"' | '#' | '+' | ',' | [0-9] | ';' | '<' | '=' | '>' | [A-F] | '\' |
-     * [a-f] 0x22 | 0x23 | 0x2B | 0x2C | [0x30-0x39] | 0x3B | 0x3C | 0x3D | 0x3E |
+     * ' ' | '"' | '#' | '+' | ',' | [0-9] | ';' | '<' | '=' | '>' | [A-F] | '\' | [a-f]
+     * 0x22 | 0x23 | 0x2B | 0x2C | [0x30-0x39] | 0x3B | 0x3C | 0x3D | 0x3E |
      * [0x41-0x46] | 0x5C | [0x61-0x66]
      */
     private static final boolean[] PAIR_CHAR =
         { 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false, 
-            true,  false, true,  true,  false, false, false, false, 
-            false, false, false, true,  true,  false, false, false, 
-            true,  true,  true,  true,  true,  true,  true,  true, 
-            true,  true,  false, true,  true,  true,  true,  false, 
-            false, true,  true,  true,  true,  true,  true,  false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, true,  false, false, false, 
-            false, true,  true,  true,  true,  true,  true,  false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false, 
-            false, false, false, false, false, false, false, false 
+            false, false, false, false, false, false, false, false, // 00 -> 07
+            false, false, false, false, false, false, false, false, // 08 -> 0F
+            false, false, false, false, false, false, false, false, // 10 -> 17
+            false, false, false, false, false, false, false, false, // 18 -> 1F
+            true,  false, true,  true,  false, false, false, false, // 20 -> 27 ( ' ', '"', '#' )
+            false, false, false, true,  true,  false, false, false, // 28 -> 2F ( '+', ',' )
+            true,  true,  true,  true,  true,  true,  true,  true,  // 30 -> 37 ( '0'..'7' )
+            true,  true,  false, true,  true,  true,  true,  false, // 38 -> 3F ( '8', '9', ';', '<', '=', '>' ) 
+            false, true,  true,  true,  true,  true,  true,  false, // 40 -> 47 ( 'A', 'B', 'C', 'D', 'E', 'F' )
+            false, false, false, false, false, false, false, false, // 48 -> 4F
+            false, false, false, false, false, false, false, false, // 50 -> 57
+            false, false, false, false, true,  false, false, false, // 58 -> 5F ( '\' )
+            false, true,  true,  true,  true,  true,  true,  false, // 60 -> 67 ( 'a', 'b', 'c', 'd', 'e', 'f' )
+            false, false, false, false, false, false, false, false, // 68 -> 6F
+            false, false, false, false, false, false, false, false, // 70 -> 77
+            false, false, false, false, false, false, false, false  // 78 -> 7F
+        };
+
+    /**
+     * ' ' | '"' | '#' | '+' | ',' | ';' | '<' | '=' | '>' | '\' |
+     * 0x22 | 0x23 | 0x2B | 0x2C | 0x3B | 0x3C | 0x3D | 0x3E | 0x5C
+     */
+    private static final boolean[] PAIR_CHAR_ONLY =
+        { 
+            false, false, false, false, false, false, false, false, // 00 -> 07
+            false, false, false, false, false, false, false, false, // 08 -> 0F
+            false, false, false, false, false, false, false, false, // 10 -> 17
+            false, false, false, false, false, false, false, false, // 18 -> 1F
+            true,  false, true,  true,  false, false, false, false, // 20 -> 27 ( ' ', '"', '#' )
+            false, false, false, true,  true,  false, false, false, // 28 -> 2F ( '+', ',' )
+            false, false, false, false, false, false, false, false, // 30 -> 37
+            false, false, false, true,  true,  true,  true,  false, // 38 -> 3F ( ';', '<', '=', '>' ) 
+            false, false, false, false, false, false, false, false, // 40 -> 47
+            false, false, false, false, false, false, false, false, // 48 -> 4F
+            false, false, false, false, false, false, false, false, // 50 -> 57
+            false, false, false, false, true,  false, false, false, // 58 -> 5F ( '\' )
+            false, false, false, false, false, false, false, false, // 60 -> 67
+            false, false, false, false, false, false, false, false, // 68 -> 6F
+            false, false, false, false, false, false, false, false, // 70 -> 77
+            false, false, false, false, false, false, false, false  // 78 -> 7F
         };
 
     /**
@@ -188,34 +210,32 @@
      * [0x3D-0x7F] &lt;safe-chars&gt; ::= &lt;safe-char&gt; &lt;safe-chars&gt; | &lt;safe-char&gt; ::=
      * [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The position of the first character which is not a Safe Char
      */
-    public static int parseSafeString( byte[] byteArray, int index )
+    public static int parseSafeString( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return -1;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
-            if ( ( ( c | 0x7F ) != 0x7F ) || ( SAFE_INIT_CHAR[c] == false ) )
+            if ( ( ( c | 0x7F ) != 0x7F ) || ( !SAFE_INIT_CHAR[c] ) )
             {
                 return -1;
             }
 
             index++;
 
-            while ( index < byteArray.length )
+            while ( index < bytes.length )
             {
-                c = byteArray[index];
+                c = bytes[index];
 
-                if ( ( ( c | 0x7F ) != 0x7F ) || ( SAFE_CHAR[c] == false ) )
+                if ( ( ( c | 0x7F ) != 0x7F ) || ( !SAFE_CHAR[c] ) )
                 {
                     break;
                 }
@@ -232,99 +252,80 @@
      * Walk the buffer while characters are Alpha characters : &lt;alpha&gt; ::=
      * [0x41-0x5A] | [0x61-0x7A]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The position of the first character which is not an Alpha Char
      */
-    public static int parseAlphaASCII( byte[] byteArray, int index )
+    public static int parseAlphaASCII( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return -1;
         }
         else
         {
-            byte b = byteArray[index++];
+            byte b = bytes[index++];
 
-            if ( StringTools.isAlpha( b ) == false )
+            if ( StringTools.isAlpha( b ) )
+            {
+                return index-1;
+            }
+            else
             {
                 return -1;
             }
-            else
-            {
-                return index;
-            }
         }
     }
 
 
     /**
-     * Walk the buffer while characters are Alpha characters : &lt;alpha&gt; ::=
-     * [0x41-0x5A] | [0x61-0x7A]
-     * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @return The position of the first character which is not an Alpha Char
+     * Check if the given char is a pair char only
+     * &lt;pairCharOnly&gt; ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | '\' | '"'
+     *
+     * @param c the char we want to test
+     * @return true if the char is a pair char only
      */
-    public static int parseAlphaASCII( char[] charArray, int index )
+    public static boolean isPairCharOnly( char c )
     {
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( index < 0 ) || ( index >= charArray.length ) )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            char c = charArray[index++];
-
-            if ( StringTools.isAlpha( c ) == false )
-            {
-                return PARSING_ERROR;
-            }
-            else
-            {
-                return index;
-            }
-        }
+        return ( ( ( c | 0x7F ) == 0x7F ) && PAIR_CHAR_ONLY[c & 0x7f] );
     }
 
 
     /**
-     * Check if the current character is a Pair Char &lt;pairchar&gt; ::= ',' | '=' |
-     * '+' | '<' | '>' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F]
+     * Check if the current character is a Pair Char 
+     * &lt;pairchar&gt; ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is a Pair Char
      */
-    public static boolean isPairChar( byte[] byteArray, int index )
+    public static boolean isPairChar( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return false;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
-            if ( ( ( c | 0x7F ) != 0x7F )  || ( PAIR_CHAR[c] == false ) )
+            if ( ( ( c | 0x7F ) != 0x7F )  || ( !PAIR_CHAR[c] ) )
             {
                 return false;
             }
             else
             {
-                if ( StringTools.isHex( byteArray, index++ ) )
+                if ( PAIR_CHAR_ONLY[c] )
                 {
-                    return StringTools.isHex( byteArray, index );
+                    return true;
+                }
+                else if ( StringTools.isHex( bytes, index++ ) )
+                {
+                    return StringTools.isHex( bytes, index );
                 }
                 else
                 {
-                    return true;
+                    return false;
                 }
             }
         }
@@ -332,63 +333,23 @@
 
 
     /**
-     * Check if the current character is a Pair Char &lt;pairchar&gt; ::= ',' | '=' |
-     * '+' | '<' | '>' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F]
-     * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @return <code>true</code> if the current character is a Pair Char
-     */
-    public static boolean isPairChar( char[] charArray, int index )
-    {
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( index < 0 ) || ( index >= charArray.length ) )
-        {
-            return false;
-        }
-        else
-        {
-            char c = charArray[index];
-
-            if ( ( ( c | 0x7F ) != 0x7F )  || ( PAIR_CHAR[c] == false ) )
-            {
-                return false;
-            }
-            else
-            {
-                if ( StringTools.isHex( charArray, index++ ) )
-                {
-                    return StringTools.isHex( charArray, index );
-                }
-                else
-                {
-                    return true;
-                }
-            }
-        }
-    }
-
-    /**
      * Check if the current character is a Pair Char 
      * 
      * &lt;pairchar&gt; ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | 
      *                  '\' | '"' | [0-9a-fA-F] [0-9a-fA-F]
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
-     * @return <code>true</code> if the current character is a Pair Char
+     * @param bytes The byte array which contains the data
+     * @param index Current position in the byte array
+     * @return <code>true</code> if the current byte is a Pair Char
      */
-    public static int isPairChar( String string, int index )
+    public static int countPairChar( byte[] bytes, int index )
     {
-        if ( string == null )
+        if ( bytes == null )
         {
             return PARSING_ERROR;
         }
 
-        int length = string.length();
+        int length = bytes.length;
         
         if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
         {
@@ -396,21 +357,25 @@
         }
         else
         {
-            char c = string.charAt( index );
+            byte c = bytes[index];
 
-            if ( ( ( c | 0x7F ) != 0x7F )  || ( PAIR_CHAR[c] == false ) )
+            if ( ( ( c | 0x7F ) != 0x7F )  || ( !PAIR_CHAR[c] ) )
             {
                 return PARSING_ERROR;
             }
             else
             {
-                if ( StringTools.isHex( string, index++ ) )
+                if ( PAIR_CHAR_ONLY[c] )
                 {
-                    return StringTools.isHex( string, index ) ? 2 : PARSING_ERROR;
+                    return 1;
+                }
+                else if ( StringTools.isHex( bytes, index++ ) )
+                {
+                    return StringTools.isHex( bytes, index ) ? 2 : PARSING_ERROR;
                 }
                 else
                 {
-                    return 1;
+                    return PARSING_ERROR;
                 }
             }
         }
@@ -421,22 +386,20 @@
      * Check if the current character is a String Char. Chars are Unicode, not
      * ASCII. &lt;stringchar&gt; ::= [0x00-0xFFFF] - [,=+<>#;\"\n\r]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The current char if it is a String Char, or '#' (this is simpler
      *         than throwing an exception :)
      */
-    public static int isStringChar( byte[] byteArray, int index )
+    public static int isStringChar( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return -1;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
             if ( ( c | 0x3F ) == 0x3F )
             {
@@ -444,80 +407,7 @@
             }
             else
             {
-                return StringTools.countBytesPerChar( byteArray, index );
-            }
-        }
-    }
-
-
-    /**
-     * Check if the current character is a String Char. Chars are Unicode, not
-     * ASCII. &lt;stringchar&gt; ::= [0x00-0xFFFF] - [,=+<>#;\"\n\r]
-     * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @return The current char if it is a String Char, or '#' (this is simpler
-     *         than throwing an exception :)
-     */
-    public static int isStringChar( char[] charArray, int index )
-    {
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( index < 0 ) || ( index >= charArray.length ) )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            char c = charArray[index];
-
-            if ( ( c == 0x0A ) || ( c == 0x0D ) || ( c == '"' ) || ( c == '#' ) || ( c == '+' ) || ( c == ',' )
-                || ( c == ';' ) || ( c == '<' ) || ( c == '=' ) || ( c == '>' ) )
-            {
-                return PARSING_ERROR;
-            }
-            else
-            {
-                return ONE_CHAR;
-            }
-        }
-    }
-
-    /**
-     * Check if the current character is a String Char. Chars are Unicode, not
-     * ASCII. &lt;stringchar&gt; ::= [0x00-0xFFFF] - [,=+<>#;\"\n\r]
-     * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
-     * @return The current char if it is a String Char, or '#' (this is simpler
-     *         than throwing an exception :)
-     */
-    public static int isStringChar( String string, int index )
-    {
-        if ( string == null )
-        {
-            return PARSING_ERROR;
-        }
-        
-        int length = string.length();
-        
-        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            char c = string.charAt( index );
-
-            if ( ( c | 0x3F) == 0x3F )
-            {
-                return STRING_CHAR[ c ];
-            }
-            else
-            {
-                return ONE_CHAR;
+                return StringTools.countBytesPerChar( bytes, index );
             }
         }
     }
@@ -527,20 +417,20 @@
      * Check if the current character is a Quote Char We are testing Unicode
      * chars &lt;quotechar&gt; ::= [0x00-0xFFFF] - [\"]
      * 
-     * @param byteArray The buffer which contains the data
+     * @param bytes The buffer which contains the data
      * @param index Current position in the buffer
      *
      * @return <code>true</code> if the current character is a Quote Char
      */
-    public static int isQuoteChar( byte[] byteArray, int index )
+    public static int isQuoteChar( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return -1;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
             if ( ( c == '\\' ) || ( c == '"' ) )
             {
@@ -548,75 +438,7 @@
             }
             else
             {
-                return StringTools.countBytesPerChar( byteArray, index );
-            }
-        }
-    }
-
-
-    /**
-     * Check if the current character is a Quote Char We are testing Unicode
-     * chars &lt;quotechar&gt; ::= [0x00-0xFFFF] - [\"]
-     * 
-     * @param charArray The buffer which contains the data
-     * @param index Current position in the buffer
-     *
-     * @return <code>true</code> if the current character is a Quote Char
-     */
-    public static int isQuoteChar( char[] charArray, int index )
-    {
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( index < 0 ) || ( index >= charArray.length ) )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            char c = charArray[index];
-
-            if ( ( c == '\\' ) || ( c == '"' ) )
-            {
-                return PARSING_ERROR;
-            }
-            else
-            {
-                return ONE_CHAR;
-            }
-        }
-    }
-
-    /**
-     * Check if the current character is a Quote Char We are testing Unicode
-     * chars &lt;quotechar&gt; ::= [0x00-0xFFFF] - [\"]
-     * 
-     * @param string The string which contains the data
-     * @param index Current position in the string
-     *
-     * @return <code>true</code> if the current character is a Quote Char
-     */
-    public static int isQuoteChar( String string, int index )
-    {
-        if ( string == null )
-        {
-            return PARSING_ERROR;
-        }
-
-        int length = string.length();
-
-        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            char c = string.charAt( index );
-
-            if ( ( c == '\\' ) || ( c == '"' ) )
-            {
-                return PARSING_ERROR;
-            }
-            else
-            {
-                return ONE_CHAR;
+                return StringTools.countBytesPerChar( bytes, index );
             }
         }
     }
@@ -625,18 +447,16 @@
     /**
      * Parse an hex pair &lt;hexpair&gt; ::= &lt;hex&gt; &lt;hex&gt;
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The new position, -1 if the buffer does not contain an HexPair,
      *         -2 if the buffer contains an hex byte but not two.
      */
-    public static int parseHexPair( byte[] byteArray, int index )
+    public static int parseHexPair( byte[] bytes, int index )
     {
-        if ( StringTools.isHex( byteArray, index ) )
+        if ( StringTools.isHex( bytes, index ) )
         {
-            if ( StringTools.isHex( byteArray, index + 1 ) )
+            if ( StringTools.isHex( bytes, index + 1 ) )
             {
                 return index + 2;
             }
@@ -655,91 +475,30 @@
     /**
      * Parse an hex pair &lt;hexpair&gt; ::= &lt;hex&gt; &lt;hex&gt;
      * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @return The new position, -1 if the buffer does not contain an HexPair,
-     *         -2 if the buffer contains an hex byte but not two.
+     * @param bytes The byte array which contains the data
+     * @param index Current position in the byte array
+     * @return The new position, -1 if the byte array does not contain an HexPair,
+     *         -2 if the byte array contains an hex byte but not two.
      */
-    public static int parseHexPair( char[] charArray, int index )
+    private static byte getHexPair( byte[] bytes, int index )
     {
-        if ( StringTools.isHex( charArray, index ) )
-        {
-            if ( StringTools.isHex( charArray, index + 1 ) )
-            {
-                return index + TWO_CHARS;
-            }
-            else
-            {
-                return BAD_HEX_PAIR;
-            }
-        }
-        else
-        {
-            return PARSING_ERROR;
-        }
+        return StringTools.getHexValue( bytes[index], bytes[index + 1] );
     }
 
-    /**
-     * Parse an hex pair &lt;hexpair&gt; ::= &lt;hex&gt; &lt;hex&gt;
-     * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
-     * @return The new position, -1 if the string does not contain an HexPair,
-     *         -2 if the string contains an hex byte but not two.
-     */
-    public static int parseHexPair( String string, int index )
-    {
-        if ( StringTools.isHex( string, index ) )
-        {
-            if ( StringTools.isHex( string, index + 1 ) )
-            {
-                return index + TWO_CHARS;
-            }
-            else
-            {
-                return BAD_HEX_PAIR;
-            }
-        }
-        else
-        {
-            return PARSING_ERROR;
-        }
-    }
-
-    /**
-     * Parse an hex pair &lt;hexpair&gt; ::= &lt;hex&gt; &lt;hex&gt;
-     * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
-     * @return The new position, -1 if the string does not contain an HexPair,
-     *         -2 if the string contains an hex byte but not two.
-     */
-    private static byte getHexPair( String string, int index )
-    {
-    	return StringTools.getHexValue( string.charAt( index ), string.charAt( index + 1 ) );
-    }
-
+    
     /**
      * Parse an hex string, which is a list of hex pairs &lt;hexstring&gt; ::=
      * &lt;hexpair&gt; &lt;hexpairs&gt; &lt;hexpairs&gt; ::= &lt;hexpair&gt; &lt;hexpairs&gt; | e
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return Return the first position which is not an hex pair, or -1 if
      *         there is no hexpair at the beginning or if an hexpair is invalid
      *         (if we have only one hex instead of 2)
      */
-    public static int parseHexString( byte[] byteArray, int index )
+    public static int parseHexString( byte[] bytes, int index )
     {
-        int result = parseHexPair( byteArray, index );
+        int result = parseHexPair( bytes, index );
 
         if ( result < 0 )
         {
@@ -750,7 +509,7 @@
             index += 2;
         }
 
-        while ( ( result = parseHexPair( byteArray, index ) ) >= 0 )
+        while ( ( result = parseHexPair( bytes, index ) ) >= 0 )
         {
             index += 2;
         }
@@ -763,85 +522,18 @@
      * Parse an hex string, which is a list of hex pairs &lt;hexstring&gt; ::=
      * &lt;hexpair&gt; &lt;hexpairs&gt; &lt;hexpairs&gt; ::= &lt;hexpair&gt; &lt;hexpairs&gt; | e
      * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @return Return the first position which is not an hex pair, or -1 if
-     *         there is no hexpair at the beginning or if an hexpair is invalid
-     *         (if we have only one hex instead of 2)
-     */
-    public static int parseHexString( char[] charArray, int index )
-    {
-        int result = parseHexPair( charArray, index );
-
-        if ( result < 0 )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            index += TWO_CHARS;
-        }
-
-        while ( ( result = parseHexPair( charArray, index ) ) >= 0 )
-        {
-            index += TWO_CHARS;
-        }
-
-        return ( ( result == BAD_HEX_PAIR ) ? PARSING_ERROR : index );
-    }
-
-    /**
-     * Parse an hex string, which is a list of hex pairs &lt;hexstring&gt; ::=
-     * &lt;hexpair&gt; &lt;hexpairs&gt; &lt;hexpairs&gt; ::= &lt;hexpair&gt; &lt;hexpairs&gt; | e
-     * 
-     * @param string
-     *            The string which contains the data
-     * @param pos
-     *            Current position in the string
-     * @return Return the first position which is not an hex pair, or -1 if
-     *         there is no hexpair at the beginning or if an hexpair is invalid
-     *         (if we have only one hex instead of 2)
-     */
-    public static int parseHexString( String string, Position pos )
-    {
-        pos.end = pos.start;
-        int result = parseHexPair( string, pos.start );
-
-        if ( result < 0 )
-        {
-            return PARSING_ERROR;
-        }
-        else
-        {
-            pos.end += TWO_CHARS;
-        }
-
-        while ( ( result = parseHexPair( string, pos.end ) ) >= 0 )
-        {
-            pos.end += TWO_CHARS;
-        }
-
-        return ( ( result == BAD_HEX_PAIR ) ? PARSING_ERROR : PARSING_OK );
-    }
-
-    /**
-     * Parse an hex string, which is a list of hex pairs &lt;hexstring&gt; ::=
-     * &lt;hexpair&gt; &lt;hexpairs&gt; &lt;hexpairs&gt; ::= &lt;hexpair&gt; &lt;hexpairs&gt; | e
-     * 
-     * @param string The string which contains the data
+     * @param bytes The byte array which contains the data
      * @param hex The result as a byte array
      * @param pos Current position in the string
      * @return Return the first position which is not an hex pair, or -1 if
      *         there is no hexpair at the beginning or if an hexpair is invalid
      *         (if we have only one hex instead of 2)
      */
-    public static int parseHexString( String string, byte[] hex, Position pos )
+    public static int parseHexString( byte[] bytes, byte[] hex, Position pos )
     {
-    	int i = 0;
+        int i = 0;
         pos.end = pos.start;
-        int result = parseHexPair( string, pos.start );
+        int result = parseHexPair( bytes, pos.start );
 
         if ( result < 0 )
         {
@@ -849,53 +541,52 @@
         }
         else
         {
-        	hex[i++] = getHexPair( string, pos.end );
+            hex[i++] = getHexPair( bytes, pos.end );
             pos.end += TWO_CHARS;
         }
 
-        while ( ( result = parseHexPair( string, pos.end ) ) >= 0 )
+        while ( ( result = parseHexPair( bytes, pos.end ) ) >= 0 )
         {
-        	hex[i++] = getHexPair( string, pos.end );
+            hex[i++] = getHexPair( bytes, pos.end );
             pos.end += TWO_CHARS;
         }
 
         return ( ( result == BAD_HEX_PAIR ) ? PARSING_ERROR : PARSING_OK );
     }
 
+    
     /**
      * Walk the buffer while characters are Base64 characters : &lt;base64-string&gt;
      * ::= &lt;base64-char&gt; &lt;base64-chars&gt; &lt;base64-chars&gt; ::= &lt;base64-char&gt;
      * &lt;base64-chars&gt; | &lt;base64-char&gt; ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D |
      * [0x41-0x5A] | [0x61-0x7A]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The position of the first character which is not a Base64 Char
      */
-    public static int parseBase64String( byte[] byteArray, int index )
+    public static int parseBase64String( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return -1;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
-            if ( ( ( c | 0x7F ) != 0x7F )  || ( BASE64_CHAR[c] == false ) )
+            if ( ( ( c | 0x7F ) != 0x7F )  || ( !BASE64_CHAR[c] ) )
             {
                 return -1;
             }
 
             index++;
 
-            while ( index < byteArray.length )
+            while ( index < bytes.length )
             {
-                c = byteArray[index];
+                c = bytes[index];
 
-                if ( ( ( c | 0x7F ) != 0x7F )  || ( BASE64_CHAR[c] == false ) )
+                if ( ( ( c | 0x7F ) != 0x7F )  || ( !BASE64_CHAR[c] ) )
                 {
                     break;
                 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/DirectoryClassUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DirectoryClassUtils.java
index f7264cc..231a0e2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/DirectoryClassUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DirectoryClassUtils.java
@@ -20,6 +20,9 @@
 
 package org.apache.directory.shared.ldap.util;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.lang.reflect.Method;
 import java.util.Arrays;
 
@@ -29,9 +32,10 @@
  */
 public class DirectoryClassUtils
 {
+    private static final Logger LOG = LoggerFactory.getLogger( DirectoryClassUtils.class );
     
     /**
-     * A replacement for {@link java.lang.Class.getMethod} with extended capability.
+     * A replacement for {@link java.lang.Class#getMethod} with extended capability.
      * 
      * <p>
      * This method returns parameter-list assignment-compatible method as well as
@@ -41,33 +45,55 @@
      * @param candidateMethodName Name of the method been looked for.
      * @param candidateParameterTypes Types of the parameters in the signature of the method being loooked for.
      * @return The Method found.
-     * @throws NoSuchMethodException
+     * @throws NoSuchMethodException when the method cannot be found
      */
-    public static Method getAssignmentCompatibleMethod( Class clazz,
+    public static Method getAssignmentCompatibleMethod( Class<?> clazz,
                                                         String candidateMethodName,
-                                                        Class[] candidateParameterTypes
+                                                        Class<?>[] candidateParameterTypes
                                                       ) throws NoSuchMethodException
     {
+        if ( LOG.isDebugEnabled() )
+        {
+            StringBuilder buf = new StringBuilder();
+            buf.append( "call to getAssignmentCompatibleMethod(): \n\tclazz = " );
+            buf.append( clazz.getName() );
+            buf.append( "\n\tcandidateMethodName = " );
+            buf.append( candidateMethodName );
+            buf.append( "\n\tcandidateParameterTypes = " );
+
+            for ( Class<?> argClass : candidateParameterTypes )
+            {
+                buf.append( "\n\t\t" );
+                buf.append( argClass.getName() );
+            }
+
+            LOG.debug( buf.toString() );
+        }
+
         try
         {
             // Look for exactly the same signature.
             Method exactMethod = clazz.getMethod( candidateMethodName, candidateParameterTypes );
+            
             if ( exactMethod != null )
             {
                 return exactMethod;
             }
         }
-        catch ( SecurityException e ) { }
-        catch ( NoSuchMethodException e ) { }
-        
+        catch ( Exception e )
+        {
+            LOG.info( "Could not find accessible exact match for candidateMethod {}", candidateMethodName, e );
+        }
+
+
         /**
          * Look for the assignment-compatible signature.
          */
         
-        // Get all methods of the clazz.
+        // Get all methods of the class.
         Method[] methods = clazz.getMethods();
         
-        // For each method of the clazz...
+        // For each method of the class...
         for ( int mx = 0; mx < methods.length; mx++ )
         {
             // If the method name does not match...
@@ -78,7 +104,7 @@
             }
             
             // ... Get parameter types list.
-            Class[] parameterTypes = methods[ mx ].getParameterTypes();
+            Class<?>[] parameterTypes = methods[ mx ].getParameterTypes();
             
             // If parameter types list length mismatch...
             if ( parameterTypes.length != candidateParameterTypes.length )
@@ -102,8 +128,7 @@
             return methods[ mx ];
         }
         
-        throw new NoSuchMethodException( clazz.getName() + "." + candidateMethodName + "(" + Arrays.toString( candidateParameterTypes ) + ")" );
-        
+        throw new NoSuchMethodException( clazz.getName() + "." + candidateMethodName
+            + "(" + Arrays.toString( candidateParameterTypes ) + ")" );
     }
-
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/DummySSLSocketFactory.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DummySSLSocketFactory.java
new file mode 100644
index 0000000..efaba9f
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/DummySSLSocketFactory.java
@@ -0,0 +1,211 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.util;
+
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+
+/**
+ * A SSLSocketFactory that accepts every certificat without validation.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DummySSLSocketFactory extends SSLSocketFactory
+{
+
+    /** The default instance. */
+    private static SocketFactory instance;
+
+
+    /**
+     * Gets the default instance.
+     * 
+     * Note: This method is invoked from the JNDI framework when 
+     * creating a ldaps:// connection.
+     * 
+     * @return the default instance
+     */
+    public static SocketFactory getDefault()
+    {
+        if ( instance == null )
+        {
+            instance = new DummySSLSocketFactory();
+        }
+        return instance;
+    }
+
+    /** The delegate. */
+    private SSLSocketFactory delegate;
+
+
+    /**
+     * Creates a new instance of DummySSLSocketFactory.
+     */
+    public DummySSLSocketFactory()
+    {
+        try
+        {
+            TrustManager tm = new X509TrustManager()
+            {
+                public X509Certificate[] getAcceptedIssuers()
+                {
+                    return new X509Certificate[0];
+                }
+
+
+                public void checkClientTrusted( X509Certificate[] arg0, String arg1 ) throws CertificateException
+                {
+                }
+
+
+                public void checkServerTrusted( X509Certificate[] arg0, String arg1 ) throws CertificateException
+                {
+                }
+            };
+            TrustManager[] tma =
+                { tm };
+            SSLContext sc = SSLContext.getInstance( "TLS" ); //$NON-NLS-1$
+            sc.init( null, tma, new SecureRandom() );
+            delegate = sc.getSocketFactory();
+        }
+        catch ( Exception e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * @see javax.net.ssl.SSLSocketFactory#getDefaultCipherSuites()
+     */
+    public String[] getDefaultCipherSuites()
+    {
+        return delegate.getDefaultCipherSuites();
+    }
+
+
+    /**
+     * @see javax.net.ssl.SSLSocketFactory#getSupportedCipherSuites()
+     */
+    public String[] getSupportedCipherSuites()
+    {
+        return delegate.getSupportedCipherSuites();
+    }
+
+
+    /**
+     * @see javax.net.ssl.SSLSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
+     */
+    public Socket createSocket( Socket arg0, String arg1, int arg2, boolean arg3 ) throws IOException
+    {
+        try
+        {
+            return delegate.createSocket( arg0, arg1, arg2, arg3 );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+
+    /**
+     * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
+     */
+    public Socket createSocket( String arg0, int arg1 ) throws IOException, UnknownHostException
+    {
+        try
+        {
+            return delegate.createSocket( arg0, arg1 );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+
+    /**
+     * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int)
+     */
+    public Socket createSocket( InetAddress arg0, int arg1 ) throws IOException
+    {
+        try
+        {
+            return delegate.createSocket( arg0, arg1 );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+
+    /**
+     * @see javax.net.SocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
+     */
+    public Socket createSocket( String arg0, int arg1, InetAddress arg2, int arg3 ) throws IOException,
+        UnknownHostException
+    {
+        try
+        {
+            return delegate.createSocket( arg0, arg1, arg2, arg3 );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+
+    /**
+     * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int, java.net.InetAddress, int)
+     */
+    public Socket createSocket( InetAddress arg0, int arg1, InetAddress arg2, int arg3 ) throws IOException
+    {
+        try
+        {
+            return delegate.createSocket( arg0, arg1, arg2, arg3 );
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            throw e;
+        }
+    }
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java
new file mode 100644
index 0000000..8479087
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/GeneralizedTime.java
@@ -0,0 +1,749 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.util;
+
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+
+/**
+ * <p>This class represents the generalized time syntax as defined in 
+ * RFC 4517 section 3.3.13.</p>
+ * 
+ * <p>The date, time and time zone information is internally backed
+ * by an {@link java.util.Calendar} object</p>
+ * 
+ * <p>Leap seconds are not supported, as {@link java.util.Calendar}
+ * does not support leap seconds.</p>
+ * 
+ * <pre>
+ * 3.3.13.  Generalized Time
+ *
+ *  A value of the Generalized Time syntax is a character string
+ *  representing a date and time.  The LDAP-specific encoding of a value
+ *  of this syntax is a restriction of the format defined in [ISO8601],
+ *  and is described by the following ABNF:
+ *
+ *     GeneralizedTime = century year month day hour
+ *                          [ minute [ second / leap-second ] ]
+ *                          [ fraction ]
+ *                          g-time-zone
+ *
+ *     century = 2(%x30-39) ; "00" to "99"
+ *     year    = 2(%x30-39) ; "00" to "99"
+ *     month   =   ( %x30 %x31-39 ) ; "01" (January) to "09"
+ *               / ( %x31 %x30-32 ) ; "10" to "12"
+ *     day     =   ( %x30 %x31-39 )    ; "01" to "09"
+ *               / ( %x31-32 %x30-39 ) ; "10" to "29"
+ *               / ( %x33 %x30-31 )    ; "30" to "31"
+ *     hour    = ( %x30-31 %x30-39 ) / ( %x32 %x30-33 ) ; "00" to "23"
+ *     minute  = %x30-35 %x30-39                        ; "00" to "59"
+ *
+ *     second      = ( %x30-35 %x30-39 ) ; "00" to "59"
+ *     leap-second = ( %x36 %x30 )       ; "60"
+ *
+ *     fraction        = ( DOT / COMMA ) 1*(%x30-39)
+ *     g-time-zone     = %x5A  ; "Z"
+ *                       / g-differential
+ *     g-differential  = ( MINUS / PLUS ) hour [ minute ]
+ *     MINUS           = %x2D  ; minus sign ("-")
+ *
+ *  The <DOT>, <COMMA>, and <PLUS> rules are defined in [RFC4512].
+ *
+ *  The above ABNF allows character strings that do not represent valid
+ *  dates (in the Gregorian calendar) and/or valid times (e.g., February
+ *  31, 1994).  Such character strings SHOULD be considered invalid for
+ *  this syntax.
+ *
+ *  The time value represents coordinated universal time (equivalent to
+ *  Greenwich Mean Time) if the "Z" form of <g-time-zone> is used;
+ *  otherwise, the value represents a local time in the time zone
+ *  indicated by <g-differential>.  In the latter case, coordinated
+ *  universal time can be calculated by subtracting the differential from
+ *  the local time.  The "Z" form of <g-time-zone> SHOULD be used in
+ *  preference to <g-differential>.
+ *
+ *  If <minute> is omitted, then <fraction> represents a fraction of an
+ *  hour; otherwise, if <second> and <leap-second> are omitted, then
+ *  <fraction> represents a fraction of a minute; otherwise, <fraction>
+ *  represents a fraction of a second.
+ *
+ *     Examples:
+ *        199412161032Z
+ *        199412160532-0500
+ *
+ *  Both example values represent the same coordinated universal time:
+ *  10:32 AM, December 16, 1994.
+ *
+ *  The LDAP definition for the Generalized Time syntax is:
+ *
+ *     ( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )
+ *
+ *  This syntax corresponds to the GeneralizedTime ASN.1 type from
+ *  [ASN.1], with the constraint that local time without a differential
+ *  SHALL NOT be used.
+ *
+ * </pre>
+ */
+public class GeneralizedTime implements Comparable<GeneralizedTime>
+{
+
+    public enum Format
+    {
+        YEAR_MONTH_DAY_HOUR_MIN_SEC, YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION,
+
+        YEAR_MONTH_DAY_HOUR_MIN, YEAR_MONTH_DAY_HOUR_MIN_FRACTION,
+
+        YEAR_MONTH_DAY_HOUR, YEAR_MONTH_DAY_HOUR_FRACTION, ;
+    }
+
+    public enum FractionDelimiter
+    {
+        DOT, COMMA
+    }
+
+    public enum TimeZoneFormat
+    {
+        Z, DIFF_HOUR, DIFF_HOUR_MINUTE;
+    }
+
+    private static final TimeZone GMT = TimeZone.getTimeZone( "GMT" );
+
+    /** The user provided value */
+    private String upGeneralizedTime;
+
+    /** The user provided format */
+    private Format upFormat;
+
+    /** The user provided time zone format */
+    private TimeZoneFormat upTimeZoneFormat;
+
+    /** The user provided fraction delimiter */
+    private FractionDelimiter upFractionDelimiter;
+
+    /** the user provided fraction length */
+    private int upFractionLength;
+
+    /** The calendar */
+    private Calendar calendar;
+
+
+    /**
+     * Creates a new instance of GeneralizedTime, based on the given Calendar object.
+     * Uses <pre>Format.YEAR_MONTH_DAY_HOUR_MIN_SEC</pre> as default format and
+     * <pre>TimeZoneFormat.Z</pre> as default time zone format. 
+     *
+     * @param calendar the calendar containing the date, time and timezone information
+     */
+    public GeneralizedTime( Calendar calendar )
+    {
+        if ( calendar == null )
+        {
+            throw new IllegalArgumentException( "Calendar must not be null." );
+        }
+
+        this.calendar = calendar;
+        upGeneralizedTime = null;
+        upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC;
+        upTimeZoneFormat = TimeZoneFormat.Z;
+        upFractionDelimiter = FractionDelimiter.DOT;
+        upFractionLength = 3;
+    }
+
+
+    /**
+     * Creates a new instance of GeneralizedTime, based on the
+     * given generalized time string.
+     *
+     * @param generalizedTime the generalized time
+     * 
+     * @throws ParseException if the given generalized time can't be parsed.
+     */
+    public GeneralizedTime( String generalizedTime ) throws ParseException
+    {
+        if ( generalizedTime == null )
+        {
+            throw new ParseException( "generalizedTime is null", 0 );
+        }
+
+        this.upGeneralizedTime = generalizedTime;
+
+        calendar = Calendar.getInstance();
+        calendar.setTimeInMillis( 0 );
+        calendar.setLenient( false );
+
+        parseYear();
+        parseMonth();
+        parseDay();
+        parseHour();
+
+        if ( upGeneralizedTime.length() < 11 )
+        {
+            throw new ParseException(
+                "Generalized Time too short, doesn't contain field 'minute' or 'fraction of hour' or 'timezone'.", 10 );
+        }
+
+        // pos 10: 
+        // if digit => minute field
+        // if . or , => fraction of hour field
+        // if Z or + or - => timezone field
+        // else error
+        int pos = 10;
+        char c = upGeneralizedTime.charAt( pos );
+        if ( '0' <= c && c <= '9' )
+        {
+            parseMinute();
+
+            if ( upGeneralizedTime.length() < 13 )
+            {
+                throw new ParseException(
+                    "Generalized Time too short, doesn't contain field 'second' or 'fraction of minute' or 'timezone'.",
+                    12 );
+            }
+
+            // pos 12: 
+            // if digit => second field
+            // if . or , => fraction of minute field
+            // if Z or + or - => timezone field
+            // else error
+            pos = 12;
+            c = upGeneralizedTime.charAt( pos );
+            if ( '0' <= c && c <= '9' )
+            {
+                parseSecond();
+
+                if ( upGeneralizedTime.length() < 15 )
+                {
+                    throw new ParseException(
+                        "Generalized Time too short, doesn't contain field 'fraction of second' or 'timezone'.", 14 );
+                }
+
+                // pos 14: 
+                // if . or , => fraction of second field
+                // if Z or + or - => timezone field
+                // else error
+                pos = 14;
+                c = upGeneralizedTime.charAt( pos );
+                if ( c == '.' || c == ',' )
+                {
+                    // read fraction of second
+                    parseFractionOfSecond();
+                    pos += 1 + upFractionLength;
+
+                    parseTimezone( pos );
+                    upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION;
+                }
+                else if ( c == 'Z' || c == '+' || c == '-' )
+                {
+                    // read timezone
+                    parseTimezone( pos );
+                    upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_SEC;
+                }
+                else
+                {
+                    throw new ParseException(
+                        "Invalid Time too short, expected field 'fraction of second' or 'timezone'.", 14 );
+                }
+            }
+            else if ( c == '.' || c == ',' )
+            {
+                // read fraction of minute
+                parseFractionOfMinute();
+                pos += 1 + upFractionLength;
+
+                parseTimezone( pos );
+                upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN_FRACTION;
+            }
+            else if ( c == 'Z' || c == '+' || c == '-' )
+            {
+                // read timezone
+                parseTimezone( pos );
+                upFormat = Format.YEAR_MONTH_DAY_HOUR_MIN;
+            }
+            else
+            {
+                throw new ParseException(
+                    "Invalid Time too short, expected field 'second' or 'fraction of minute' or 'timezone'.", 12 );
+            }
+        }
+        else if ( c == '.' || c == ',' )
+        {
+            // read fraction of hour
+            parseFractionOfHour();
+            pos += 1 + upFractionLength;
+
+            parseTimezone( pos );
+            upFormat = Format.YEAR_MONTH_DAY_HOUR_FRACTION;
+        }
+        else if ( c == 'Z' || c == '+' || c == '-' )
+        {
+            // read timezone
+            parseTimezone( pos );
+            upFormat = Format.YEAR_MONTH_DAY_HOUR;
+        }
+        else
+        {
+            throw new ParseException(
+                "Invalid Generalized Time, expected field 'minute' or 'fraction of hour' or 'timezone'.", 10 );
+        }
+
+        // this calculates and verifies the calendar
+        try
+        {
+            calendar.getTimeInMillis();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            throw new ParseException( "Invalid date/time values.", 0 );
+        }
+    }
+
+
+    private void parseTimezone( int pos ) throws ParseException
+    {
+        if ( upGeneralizedTime.length() < pos + 1 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'timezone'.", pos );
+        }
+
+        char c = upGeneralizedTime.charAt( pos );
+        if ( c == 'Z' )
+        {
+            calendar.setTimeZone( GMT );
+            upTimeZoneFormat = TimeZoneFormat.Z;
+
+            if ( upGeneralizedTime.length() > pos + 1 )
+            {
+                throw new ParseException( "Invalid Generalized Time, expected 'timezone' as the last field.", pos + 1 );
+            }
+        }
+        else if ( c == '+' || c == '-' )
+        {
+            StringBuilder sb = new StringBuilder( "GMT" );
+            sb.append( c );
+
+            String digits = getAllDigits( pos + 1 );
+            sb.append( digits );
+
+            if ( digits.length() == 2 && digits.matches( "^([01]\\d|2[0-3])$" ) )
+            {
+                TimeZone timeZone = TimeZone.getTimeZone( sb.toString() );
+                calendar.setTimeZone( timeZone );
+                upTimeZoneFormat = TimeZoneFormat.DIFF_HOUR;
+            }
+            else if ( digits.length() == 4 && digits.matches( "^([01]\\d|2[0-3])([0-5]\\d)$" ) )
+            {
+                TimeZone timeZone = TimeZone.getTimeZone( sb.toString() );
+                calendar.setTimeZone( timeZone );
+                upTimeZoneFormat = TimeZoneFormat.DIFF_HOUR_MINUTE;
+            }
+            else
+            {
+                throw new ParseException(
+                    "Invalid Generalized Time, expected field 'timezone' must contain 2 or 4 digits.", pos );
+            }
+
+            if ( upGeneralizedTime.length() > pos + 1 + digits.length() )
+            {
+                throw new ParseException( "Invalid Generalized Time, expected 'timezone' as the last field.", pos + 1
+                    + digits.length() );
+            }
+        }
+    }
+
+
+    private void parseFractionOfSecond() throws ParseException
+    {
+        parseFractionDelmiter( 14 );
+        String fraction = getFraction( 14 + 1 );
+        upFractionLength = fraction.length();
+
+        double fract = Double.parseDouble( "0." + fraction );
+        int millisecond = ( int ) Math.round( fract * 1000 );
+
+        calendar.set( Calendar.MILLISECOND, millisecond );
+    }
+
+
+    private void parseFractionOfMinute() throws ParseException
+    {
+        parseFractionDelmiter( 12 );
+        String fraction = getFraction( 12 + 1 );
+        upFractionLength = fraction.length();
+
+        double fract = Double.parseDouble( "0." + fraction );
+        int milliseconds = ( int ) Math.round( fract * 1000 * 60 );
+        int second = milliseconds / 1000;
+        int millisecond = milliseconds - ( second * 1000 );
+
+        calendar.set( Calendar.SECOND, second );
+        calendar.set( Calendar.MILLISECOND, millisecond );
+    }
+
+
+    private void parseFractionOfHour() throws ParseException
+    {
+        parseFractionDelmiter( 10 );
+        String fraction = getFraction( 10 + 1 );
+        upFractionLength = fraction.length();
+
+        double fract = Double.parseDouble( "0." + fraction );
+        int milliseconds = ( int ) Math.round( fract * 1000 * 60 * 60 );
+        int minute = milliseconds / ( 1000 * 60 );
+        int second = ( milliseconds - ( minute * 60 * 1000 ) ) / 1000;
+        int millisecond = milliseconds - ( minute * 60 * 1000 ) - ( second * 1000 );
+
+        calendar.set( Calendar.MINUTE, minute );
+        calendar.set( Calendar.SECOND, second );
+        calendar.set( Calendar.MILLISECOND, millisecond );
+    }
+
+
+    private void parseFractionDelmiter( int fractionDelimiterPos )
+    {
+        char c = upGeneralizedTime.charAt( fractionDelimiterPos );
+        upFractionDelimiter = c == '.' ? FractionDelimiter.DOT : FractionDelimiter.COMMA;
+    }
+
+
+    private String getFraction( int startIndex ) throws ParseException
+    {
+        String fraction = getAllDigits( startIndex );
+
+        // minimum one digit
+        if ( fraction.length() == 0 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain number for 'fraction'.", startIndex );
+        }
+
+        return fraction;
+    }
+
+
+    private String getAllDigits( int startIndex )
+    {
+        StringBuilder sb = new StringBuilder();
+        while ( upGeneralizedTime.length() > startIndex )
+        {
+            char c = upGeneralizedTime.charAt( startIndex );
+            if ( '0' <= c && c <= '9' )
+            {
+                sb.append( c );
+                startIndex++;
+            }
+            else
+            {
+                break;
+            }
+        }
+        return sb.toString();
+    }
+
+
+    private void parseSecond() throws ParseException
+    {
+        // read minute
+        if ( upGeneralizedTime.length() < 14 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'second'.", 12 );
+        }
+        try
+        {
+            int second = Integer.parseInt( upGeneralizedTime.substring( 12, 14 ) );
+            calendar.set( Calendar.SECOND, second );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'second' is not numeric.", 12 );
+        }
+    }
+
+
+    private void parseMinute() throws ParseException
+    {
+        // read minute
+        if ( upGeneralizedTime.length() < 12 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'minute'.", 10 );
+        }
+        try
+        {
+            int minute = Integer.parseInt( upGeneralizedTime.substring( 10, 12 ) );
+            calendar.set( Calendar.MINUTE, minute );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'minute' is not numeric.", 10 );
+        }
+    }
+
+
+    private void parseHour() throws ParseException
+    {
+        if ( upGeneralizedTime.length() < 10 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'hour'.", 8 );
+        }
+        try
+        {
+            int hour = Integer.parseInt( upGeneralizedTime.substring( 8, 10 ) );
+            calendar.set( Calendar.HOUR_OF_DAY, hour );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'hour' is not numeric.", 8 );
+        }
+    }
+
+
+    private void parseDay() throws ParseException
+    {
+        if ( upGeneralizedTime.length() < 8 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'day'.", 6 );
+        }
+        try
+        {
+            int day = Integer.parseInt( upGeneralizedTime.substring( 6, 8 ) );
+            calendar.set( Calendar.DAY_OF_MONTH, day );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'day' is not numeric.", 6 );
+        }
+    }
+
+
+    private void parseMonth() throws ParseException
+    {
+        if ( upGeneralizedTime.length() < 6 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'month'.", 4 );
+        }
+        try
+        {
+            int month = Integer.parseInt( upGeneralizedTime.substring( 4, 6 ) );
+            calendar.set( Calendar.MONTH, month - 1 );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'month' is not numeric.", 4 );
+        }
+    }
+
+
+    private void parseYear() throws ParseException
+    {
+        if ( upGeneralizedTime.length() < 4 )
+        {
+            throw new ParseException( "Generalized Time too short, doesn't contain field 'century/year'.", 0 );
+        }
+        try
+        {
+            int year = Integer.parseInt( upGeneralizedTime.substring( 0, 4 ) );
+            calendar.set( Calendar.YEAR, year );
+        }
+        catch ( NumberFormatException e )
+        {
+            throw new ParseException( "Invalid Generalized Time, field 'century/year' is not numeric.", 0 );
+        }
+    }
+
+
+    /**
+     * Returns the string representation of this generalized time. 
+     * This method uses the same format as the user provided format.
+     *
+     * @return the string representation of this generalized time
+     */
+    public String toGeneralizedTime()
+    {
+        return toGeneralizedTime( upFormat, upFractionDelimiter, upFractionLength, upTimeZoneFormat );
+    }
+
+
+    /**
+     * Returns the string representation of this generalized time.
+     * 
+     * @param format the target format
+     * @param fractionDelimiter the target fraction delimiter, may be null
+     * @param fractionLenth the fraction length
+     * @param timeZoneFormat the target time zone format
+     * 
+     * @return the string
+     */
+    public String toGeneralizedTime( Format format, FractionDelimiter fractionDelimiter, int fractionLength,
+        TimeZoneFormat timeZoneFormat )
+    {
+        NumberFormat twoDigits = new DecimalFormat( "00" );
+        NumberFormat fourDigits = new DecimalFormat( "00" );
+        String fractionFormat = "";
+        for ( int i = 0; i < fractionLength && i < 3; i++ )
+        {
+            fractionFormat += "0";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append( fourDigits.format( calendar.get( Calendar.YEAR ) ) );
+        sb.append( twoDigits.format( calendar.get( Calendar.MONTH ) + 1 ) );
+        sb.append( twoDigits.format( calendar.get( Calendar.DAY_OF_MONTH ) ) );
+        sb.append( twoDigits.format( calendar.get( Calendar.HOUR_OF_DAY ) ) );
+
+        switch ( format )
+        {
+            case YEAR_MONTH_DAY_HOUR_MIN_SEC:
+                sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+                sb.append( twoDigits.format( calendar.get( Calendar.SECOND ) ) );
+                break;
+
+            case YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION:
+                sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+                sb.append( twoDigits.format( calendar.get( Calendar.SECOND ) ) );
+
+                NumberFormat fractionDigits = new DecimalFormat( fractionFormat );
+                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+                sb.append( fractionDigits.format( calendar.get( Calendar.MILLISECOND ) ) );
+                break;
+
+            case YEAR_MONTH_DAY_HOUR_MIN:
+                sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+                break;
+
+            case YEAR_MONTH_DAY_HOUR_MIN_FRACTION:
+                sb.append( twoDigits.format( calendar.get( Calendar.MINUTE ) ) );
+
+                // sec + millis => fraction of minute
+                double millisec = 1000 * calendar.get( Calendar.SECOND ) + calendar.get( Calendar.MILLISECOND );
+                double fraction = millisec / ( 1000 * 60 );
+                fractionDigits = new DecimalFormat( "0." + fractionFormat );
+                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+                sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+                break;
+
+            case YEAR_MONTH_DAY_HOUR_FRACTION:
+                // min + sec + millis => fraction of minute
+                millisec = 1000 * 60 * calendar.get( Calendar.MINUTE ) + 1000 * calendar.get( Calendar.SECOND )
+                    + calendar.get( Calendar.MILLISECOND );
+                fraction = millisec / ( 1000 * 60 * 60 );
+                fractionDigits = new DecimalFormat( "0." + fractionFormat );
+                sb.append( fractionDelimiter == FractionDelimiter.COMMA ? ',' : '.' );
+                sb.append( fractionDigits.format( fraction ).substring( 2 ) );
+
+                break;
+        }
+
+        if ( timeZoneFormat == TimeZoneFormat.Z && calendar.getTimeZone().hasSameRules( GMT ) )
+        {
+            sb.append( 'Z' );
+        }
+        else
+        {
+            TimeZone timeZone = calendar.getTimeZone();
+            int rawOffset = timeZone.getRawOffset();
+            sb.append( rawOffset < 0 ? '-' : '+' );
+
+            rawOffset = Math.abs( rawOffset );
+            int hour = rawOffset / ( 60 * 60 * 1000 );
+            int minute = ( rawOffset - ( hour * 60 * 60 * 1000 ) ) / ( 1000 * 60 );
+
+            if ( hour < 10 )
+            {
+                sb.append( '0' );
+            }
+            sb.append( hour );
+
+            if ( timeZoneFormat == TimeZoneFormat.DIFF_HOUR_MINUTE || timeZoneFormat == TimeZoneFormat.Z )
+            {
+                if ( hour < 10 )
+                {
+                    sb.append( '0' );
+                }
+                sb.append( minute );
+            }
+        }
+
+        return sb.toString();
+    }
+
+
+    /**
+     * Gets the calendar. It could be used to manipulate this 
+     * {@link GeneralizedTime} settings.
+     * 
+     * @return the calendar
+     */
+    public Calendar getCalendar()
+    {
+        return calendar;
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return toGeneralizedTime();
+    }
+
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + calendar.hashCode();
+        return result;
+    }
+
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( obj instanceof GeneralizedTime )
+        {
+            GeneralizedTime other = ( GeneralizedTime ) obj;
+            return calendar.equals( other.calendar );
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+    /**
+     * Compares this GeneralizedTime object with the specified GeneralizedTime object.
+     * 
+     * @param other the other GeneralizedTime object
+     * 
+     * @return a negative integer, zero, or a positive integer as this object
+     *      is less than, equal to, or greater than the specified object.
+     * 
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    public int compareTo( GeneralizedTime other )
+    {
+        return calendar.compareTo( other.calendar );
+    }
+
+}
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributeWrapper.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributeWrapper.java
new file mode 100644
index 0000000..a8b82a0
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributeWrapper.java
@@ -0,0 +1,140 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.util;

+

+

+import javax.naming.directory.Attribute;

+import javax.naming.directory.DirContext;

+import javax.naming.NamingEnumeration;

+import javax.naming.NamingException;

+

+

+/**

+ * A read only wrapper around an Attributes object.

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public class ImmutableAttributeWrapper implements Attribute

+{

+    private final Attribute wrapped;

+

+

+    public ImmutableAttributeWrapper( Attribute wrapped )

+    {

+        this.wrapped = wrapped;

+    }

+

+

+    public NamingEnumeration<?> getAll() throws NamingException

+    {

+        return wrapped.getAll();

+    }

+

+

+    public Object get() throws NamingException

+    {

+        return wrapped.get();

+    }

+

+

+    public int size()

+    {

+        return wrapped.size();

+    }

+

+

+    public String getID()

+    {

+        return wrapped.getID();

+    }

+

+

+    public boolean contains( Object attrVal )

+    {

+        return wrapped.contains( attrVal );

+    }

+

+

+    public boolean add( Object attrVal )

+    {

+        throw new UnsupportedOperationException( "Value addition not supported for immutable attribute" );

+    }

+

+

+    public boolean remove( Object attrval )

+    {

+        throw new UnsupportedOperationException( "Value removal not supported for immutable attribute" );

+    }

+

+

+    public void clear()

+    {

+        throw new UnsupportedOperationException( "Clearing all values not supported for immutable attribute" );

+    }

+

+

+    public DirContext getAttributeSyntaxDefinition() throws NamingException

+    {

+        return wrapped.getAttributeSyntaxDefinition();

+    }

+

+

+    public DirContext getAttributeDefinition() throws NamingException

+    {

+        return wrapped.getAttributeDefinition();

+    }

+

+

+    @SuppressWarnings ( { "CloneDoesntCallSuperClone" } )

+    public Object clone()

+    {

+        throw new IllegalStateException( "Now why would you ever want to clone an immutable object?" );

+    }

+

+

+    public boolean isOrdered()

+    {

+        return wrapped.isOrdered();

+    }

+

+

+    public Object get( int ix ) throws NamingException

+    {

+        return wrapped.get( ix );

+    }

+

+

+    public Object remove( int ix )

+    {

+        throw new UnsupportedOperationException( "Value removal not supported for immutable attribute" );

+    }

+

+

+    public void add( int ix, Object attrVal )

+    {

+        throw new UnsupportedOperationException( "Value addition not supported for immutable attribute" );

+    }

+

+

+    public Object set( int ix, Object attrVal )

+    {

+        throw new UnsupportedOperationException( "Value alteration is not supported for immutable attribute" );

+    }

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributesWrapper.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributesWrapper.java
new file mode 100644
index 0000000..a723158
--- /dev/null
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/ImmutableAttributesWrapper.java
@@ -0,0 +1,140 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *  http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.directory.shared.ldap.util;

+

+

+import javax.naming.NamingEnumeration;

+import javax.naming.NamingException;

+import javax.naming.directory.Attribute;

+import javax.naming.directory.Attributes;

+

+

+/**

+ * Document me!

+ *

+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>

+ * @version $Rev$, $Date$

+ */

+public class ImmutableAttributesWrapper implements Attributes

+{

+    private final Attributes wrapped;

+

+

+    public ImmutableAttributesWrapper( Attributes wrapped )

+    {

+        this.wrapped = wrapped;

+    }

+

+

+    public boolean isCaseIgnored()

+    {

+        return wrapped.isCaseIgnored();

+    }

+

+

+    public int size()

+    {

+        return wrapped.size();

+    }

+

+

+    public Attribute get( String attrID )

+    {

+        return new ImmutableAttributeWrapper( wrapped.get( attrID ) );

+    }

+

+

+    public NamingEnumeration<? extends Attribute> getAll()

+    {

+        return new ImmutableEnumeration( wrapped.getAll() );

+    }

+

+

+    public NamingEnumeration<String> getIDs()

+    {

+        return wrapped.getIDs();

+    }

+

+

+    public Attribute put( String attrID, Object val )

+    {

+        throw new UnsupportedOperationException( "Putting attributes not supported by immutable attributes" );

+    }

+

+

+    public Attribute put( Attribute attr )

+    {

+        throw new UnsupportedOperationException( "Putting attributes not supported by immutable attributes" );

+    }

+

+

+    public Attribute remove( String attrID )

+    {

+        throw new UnsupportedOperationException( "Removing attributes not supported by immutable attributes" );

+    }

+

+

+    @SuppressWarnings ( { "CloneDoesntCallSuperClone" } )

+    public Object clone()

+    {

+        throw new IllegalStateException( "Now why would you want to clone() an immutable object in the first place." );

+    }

+

+

+    class ImmutableEnumeration implements NamingEnumeration

+    {

+        private NamingEnumeration wrappedEnum;

+

+

+        public ImmutableEnumeration( NamingEnumeration<? extends Attribute> all )

+        {

+            wrappedEnum = all;

+        }

+

+

+        public Attribute next() throws NamingException

+        {

+            return new ImmutableAttributeWrapper( ( Attribute ) wrappedEnum.next() );

+        }

+

+

+        public boolean hasMore() throws NamingException

+        {

+            return wrappedEnum.hasMore();

+        }

+

+

+        public void close() throws NamingException

+        {

+            wrappedEnum.close();

+        }

+

+

+        public boolean hasMoreElements()

+        {

+            return wrappedEnum.hasMoreElements();

+        }

+

+

+        public Attribute nextElement()

+        {

+            return new ImmutableAttributeWrapper( ( Attribute ) wrappedEnum.nextElement() );

+        }

+    }

+}

diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/JoinIterator.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/JoinIterator.java
index 1e614d0..7e01f53 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/JoinIterator.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/JoinIterator.java
@@ -55,7 +55,13 @@
                 + "null, empty or composed of less than two Iterators" );
         }
 
-        this.iterators = iterators;
+        if ( iterators != null )
+        {
+            this.iterators = new Iterator[ iterators.length ];
+            System.arraycopy( iterators, 0, this.iterators, 0, iterators.length );
+        } else {
+            this.iterators = null;
+        }
         this.index = 0;
     }
 
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/LongComparator.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/LongComparator.java
index 8a7950e..b9138d4 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/LongComparator.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/LongComparator.java
@@ -49,22 +49,22 @@
      */
     public int compare( Object obj1, Object obj2 )
     {
-    	try
-    	{
+        try
+        {
             Long long1 = (Long)obj1;
             Long long2 = (Long)obj2;
             return long1.compareTo( long2 );
-    	}
-    	catch ( NullPointerException npe )
-    	{
-	        if ( obj1 == null )
-	        {
-	            throw new IllegalArgumentException( "Argument 'obj1' is null" );
-	        }
-	        else
-	        {
-	            throw new IllegalArgumentException( "Argument 'obj2' is null" );
-	        }
-    	}
+        }
+        catch ( NullPointerException npe )
+        {
+            if ( obj1 == null )
+            {
+                throw new IllegalArgumentException( "Argument 'obj1' is null" );
+            }
+            else
+            {
+                throw new IllegalArgumentException( "Argument 'obj2' is null" );
+            }
+        }
     }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/MultiMap.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/MultiMap.java
index dbdd7ff..175162e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/MultiMap.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/MultiMap.java
@@ -53,7 +53,7 @@
  * @version $Revision$ $Date$
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public interface MultiMap extends Map
+public interface MultiMap<K,V> extends Map<K,V>
 {
 
     /**
@@ -78,7 +78,7 @@
      * @throws NullPointerException
      *             if the key or value is null and null is invalid
      */
-    public Object remove( Object key, Object item );
+    Object remove( K key, V item );
 
 
     // -----------------------------------------------------------------------
@@ -117,7 +117,7 @@
      * @throws NullPointerException
      *             if the key is null and null keys are invalid
      */
-    Object get( Object key );
+    V get( K key );
 
 
     /**
@@ -135,7 +135,7 @@
      * @throws NullPointerException
      *             if the value is null and null value are invalid
      */
-    boolean containsValue( Object value );
+    boolean containsValue( V value );
 
 
     /**
@@ -161,7 +161,7 @@
      * @throws IllegalArgumentException
      *             if the key or value is invalid
      */
-    Object put( Object key, Object value );
+    V put( K key, V value );
 
 
     /**
@@ -183,7 +183,7 @@
      * @throws NullPointerException
      *             if the key is null and null keys are invalid
      */
-    Object remove( Object key );
+    V remove( K key );
 
 
     /**
@@ -195,6 +195,5 @@
      * 
      * @return a collection view of the values contained in this map
      */
-    Collection values();
-
+    Collection<V> values();
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/NamespaceTools.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/NamespaceTools.java
index 976475b..43787c2 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/NamespaceTools.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/NamespaceTools.java
@@ -25,8 +25,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.naming.CompositeName;
-import javax.naming.InvalidNameException;
 import javax.naming.Name;
 import javax.naming.NamingException;
 
@@ -41,315 +39,47 @@
 {
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
-
-    /**
-     * Checks to see if a distinguished name is a root.
-     * 
-     * @param a_dn
-     *            distinguished name to test.
-     * @return true if it has only one component, false otherwise.
-     * @throws InvalidNameException
-     *             if a_dn is not syntactically correctly
-     */
-    public static boolean isRoot( String a_dn ) throws InvalidNameException
-    {
-        if ( a_dn == null )
-        {
-            throw new InvalidNameException( "A null DN is not a valid name." );
-        }
-        else if ( a_dn.indexOf( '=' ) == -1 )
-        {
-            throw new InvalidNameException( "A DN should have an = sign." );
-        }
-        else if ( a_dn.indexOf( ',' ) == -1 )
-        {
-            return true;
-        }
-
-        return false;
-    }
-
-
-    /**
-     * Given a child distinguished name this method gets the distinguished name
-     * of the parent. If the child is only composed of one component then null
-     * is returned.
-     * 
-     * @param a_childDN
-     *            the distinguished name of the child.
-     * @return the parent's distinguished name, or null if the child is a root.
-     * @throws InvalidNameException
-     *             if dn is not syntactically correctly
-     */
-    public static String getParent( String a_childDN ) throws InvalidNameException
-    {
-        int l_index = -1;
-
-        if ( a_childDN == null )
-        {
-            throw new InvalidNameException( "A null DN is not a valid name." );
-        }
-        else if ( a_childDN.indexOf( '=' ) == -1 )
-        {
-            throw new InvalidNameException( "A DN should have an = sign." );
-        }
-        else if ( ( l_index = a_childDN.indexOf( ',' ) ) == -1 )
-        {
-            return null;
-        }
-
-        return ( a_childDN.substring( l_index + 1 ) );
-    }
-
-
-    /**
-     * Parses an LDAP relative distinguished name to create a Name instance.
-     * 
-     * @param a_rdn
-     *            string representing the LDAP relative distinguished name.
-     * @return the parsed Name of a_rdn.
-     * @throws InvalidNameException
-     *             if <tt>a_dn</tt> is not a valid name, or if the dn violates
-     *             the syntax rules of this name public static Name parse(String
-     *             a_rdn) throws InvalidNameException { ArrayList l_list ; if
-     *             (a_rdn == null || a_rdn.equals("")) { return new LdapName(new
-     *             ArrayList()) ; } else if (a_rdn.indexOf(',') == -1) { if
-     *             (a_rdn.indexOf('=') == -1) { throw new
-     *             InvalidNameException(a_rdn + " is not a valid distinguished
-     *             name component.") ; } l_list = new ArrayList() ;
-     *             l_list.add(a_rdn) ; return new LdapName(l_list) ; } l_list =
-     *             new ArrayList() ; String l_rest = a_rdn ; String l_token =
-     *             null ; int l_index = -1 ; while ((l_index =
-     *             l_rest.indexOf(',')) != -1) { l_token = l_rest.substring(0,
-     *             l_index) ; l_rest = l_rest.substring(l_index + 1) ; if
-     *             (l_token.indexOf('=') == -1) { throw new
-     *             InvalidNameException(a_rdn + " is not a valid relative DN
-     *             component.") ; } l_list.add(l_token) ; } if
-     *             (l_rest.indexOf('=') == -1) { throw new
-     *             InvalidNameException(l_rest + " is not a valid relative DN
-     *             component.") ; } l_list.add(l_rest) ; return new
-     *             LdapName(l_list) ; }
-     */
-
-    /**
-     * Gets a DN parser.
-     * 
-     * @return the distinguished name parser. public static NameParser
-     *         getNameParser() { return new NameParser() { public Name
-     *         parse(String a_rdn) throws InvalidNameException { return
-     *         NamespaceTools.parse(a_rdn) ; } } ; }
-     */
-
-    /**
-     * TODO What is this method for??? It does not make sense out of a Context
-     *       implementation.
-     * @param a_name
-     *            the potentially federated name to get this namespaces
-     *            component from.
-     * @return this namespaces name component.
-     * @throws InvalidNameException
-     *             when a_name is a CompositeName greater than size 1. public
-     *             static Name getNamespaceName(Name a_name) throws
-     *             InvalidNameException { if (a_name instanceof CompositeName) { //
-     *             We do not federate! if (a_name.size() > 1) { throw new
-     *             InvalidNameException(a_name.toString() + " has more
-     *             components than namespace can handle") ; } // Turn component
-     *             that belongs to you into a compound name return
-     *             parse(a_name.get(0)); } else { // Already parsed return
-     *             a_name ; } }
-     */
-
-    /**
-     * Generates the string representation of a name.
-     * 
-     * TODO what the hell are these functions for if toString on a Name returns
-     *       the string representation for me?
-     * @param a_name
-     *            the Name object to convert to a string.
-     * @return the name as a string.
-     * @throws InvalidNameException
-     *             if the name is a federated composite name.
-     */
-    public static String getNamespaceString( Name a_name ) throws InvalidNameException
-    {
-        if ( a_name instanceof CompositeName )
-        {
-            // We do not federate!
-            if ( a_name.size() > 1 )
-            {
-                throw new InvalidNameException( a_name.toString() + " has more components than namespace can handle" );
-            }
-
-            // Turn component that belongs to you into a compound name
-            return a_name.get( 0 );
-        }
-        else
-        {
-            // Already parsed
-            return a_name.toString();
-        }
-    }
-
-
-    /**
-     * Generates the string representation of a name off of a base prefix.
-     * 
-     * @param a_base
-     *            the prefix of the name.
-     * @param a_name
-     *            the name to add to the prefix.
-     * @return the name as a string off of a base.
-     * @throws InvalidNameException
-     *             if the name is a federated composite name or if a_base is an
-     *             invalid DN.
-     */
-    public static String getNamespaceString( String a_base, Name a_name ) throws InvalidNameException
-    {
-        if ( a_name instanceof CompositeName )
-        {
-            // We do not federate!
-            if ( a_name.size() > 1 )
-            {
-                throw new InvalidNameException( a_name.toString() + " has more components than namespace can handle" );
-            }
-
-            StringBuffer l_buf = new StringBuffer( a_base );
-            l_buf.append( ',' );
-            l_buf.append( a_name.get( 0 ) );
-            return l_buf.toString();
-        }
-        else
-        {
-            // Already parsed
-            return a_name.toString();
-        }
-    }
-
-
-    /**
-     * Fast and efficiently get last index of a comma from a_name and return
-     * substring from comma to end of the string.
-     * 
-     * @param a_name
-     *            the name from which the last component is to be extracted.
-     * @return the last component in a_name.
-     */
-    public static String getLastComponent( String a_name )
-    {
-        if ( null == a_name )
-        {
-            return null;
-        }
-
-        int l_commaIndex = -1;
-        if ( ( l_commaIndex = a_name.lastIndexOf( ',' ) ) == -1 )
-        {
-            return a_name;
-        }
-
-        return a_name.substring( l_commaIndex );
-    }
-
-
-    /**
-     * Quickly splits off the relative distinguished name component.
-     * 
-     * @param a_name
-     *            the distinguished name or a name fragment
-     * @return the rdn TODO the name rdn is misused rename refactor this method
-     */
-    public static String getRdn( String a_name )
-    {
-        if ( null == a_name )
-        {
-            return null;
-        }
-
-        int l_commaIndex = -1;
-        if ( ( l_commaIndex = a_name.indexOf( ',' ) ) == -1 )
-        {
-            return a_name;
-        }
-
-        return a_name.substring( 0, l_commaIndex );
-    }
-
-
-    /**
-     * Sets the rdn of a distinguished name string.
-     * 
-     * @param a_name
-     *            the distinguished name to append the rdn to
-     * @param a_rdn
-     *            the relative distinguished name to append
-     * @return the appended dn with the extra rdn added TODO the name rdn is
-     *         misused rename refactor this method
-     */
-    public static String setRdn( String a_name, String a_rdn )
-    {
-        if ( null == a_name )
-        {
-            return null;
-        }
-
-        int l_commaIndex = -1;
-
-        if ( ( l_commaIndex = a_name.indexOf( ',' ) ) == -1 )
-        {
-            return a_name;
-        }
-
-        StringBuffer l_suffix = new StringBuffer();
-        l_suffix.append( a_name.substring( l_commaIndex, a_name.length() ) );
-        l_suffix.insert( 0, a_rdn );
-        return l_suffix.toString();
-    }
-
-
+    
     /**
      * Gets the attribute of a single attribute rdn or name component.
      * 
-     * @param a_rdn
-     *            the name component
+     * @param rdn the name component
      * @return the attribute name TODO the name rdn is misused rename refactor
      *         this method
      */
-    public static String getRdnAttribute( String a_rdn )
+    public static String getRdnAttribute( String rdn )
     {
-        int l_index = a_rdn.indexOf( '=' );
-        return a_rdn.substring( 0, l_index );
+        int index = rdn.indexOf( '=' );
+        return rdn.substring( 0, index );
     }
 
 
     /**
      * Gets the value of a single name component of a distinguished name.
      * 
-     * @param a_rdn
-     *            the name component to get the value from
+     * @param rdn the name component to get the value from
      * @return the value of the single name component TODO the name rdn is
      *         misused rename refactor this method
      */
-    public static String getRdnValue( String a_rdn )
+    public static String getRdnValue( String rdn )
     {
-        int l_index = a_rdn.indexOf( '=' );
-        return a_rdn.substring( l_index + 1, a_rdn.length() );
+        int index = rdn.indexOf( '=' );
+        return rdn.substring( index + 1, rdn.length() );
     }
 
 
     /**
      * Checks to see if two names are siblings.
      * 
-     * @param a_name1
-     *            the first name
-     * @param a_name2
-     *            the second name
+     * @param name1 the first name
+     * @param name2 the second name
      * @return true if the names are siblings, false otherwise.
      */
-    public static boolean isSibling( Name a_name1, Name a_name2 )
+    public static boolean isSibling( Name name1, Name name2 )
     {
-        if ( a_name1.size() == a_name2.size() )
+        if ( name1.size() == name2.size() )
         {
-            return a_name2.startsWith( a_name1.getPrefix( 1 ) );
+            return name2.startsWith( name1.getPrefix( 1 ) );
         }
 
         return false;
@@ -359,15 +89,13 @@
     /**
      * Tests to see if a candidate entry is a descendant of a base.
      * 
-     * @param a_ancestor
-     *            the base ancestor
-     * @param a_descendant
-     *            the candidate to test for descendancy
+     * @param ancestor the base ancestor
+     * @param descendant the candidate to test for descendancy
      * @return true if the candidate is a descendant
      */
-    public static boolean isDescendant( Name a_ancestor, Name a_descendant )
+    public static boolean isDescendant( Name ancestor, Name descendant )
     {
-        return a_descendant.startsWith( a_ancestor );
+        return descendant.startsWith( ancestor );
     }
 
 
@@ -376,18 +104,16 @@
      * Both name arguments must be normalized. The returned name is also
      * normalized.
      * 
-     * @param ancestor
-     *            the normalized distinguished name of the ancestor context
-     * @param descendant
-     *            the normalized distinguished name of the descendant context
+     * @param ancestor the normalized distinguished name of the ancestor context
+     * @param descendant the normalized distinguished name of the descendant context
      * @return the relatve normalized name between the ancestor and the
      *         descendant contexts
-     * @throws javax.naming.NamingException
-     *             if the contexts are not related in the ancestual sense
+     * @throws javax.naming.NamingException if the contexts are not related in the ancestual sense
      */
     public static Name getRelativeName( Name ancestor, Name descendant ) throws NamingException
     {
         LdapDN rdn = null;
+        
         if ( descendant instanceof LdapDN )
         {
             rdn = ( LdapDN ) descendant.clone();
@@ -420,8 +146,7 @@
      * 2247</a> to infer an LDAP name from a Kerberos realm name or a DNS
      * domain name.
      * 
-     * @param realm
-     *            the realm or domain name
+     * @param realm the realm or domain name
      * @return the LDAP name for the realm or domain
      */
     public static String inferLdapName( String realm )
@@ -455,8 +180,7 @@
     /**
      * Gets the '+' appended components of a composite name component.
      * 
-     * @param compositeNameComponent
-     *            a single name component not a whole name
+     * @param compositeNameComponent a single name component not a whole name
      * @return the components of the complex name component in order
      * @throws NamingException
      *             if nameComponent is invalid (starts with a +)
@@ -490,6 +214,7 @@
                     lastIndex = ii;
                 }
             }
+            
             if ( ii == 0 )
             {
                 if ( lastIndex == compositeNameComponent.length() - 1 )
@@ -540,49 +265,4 @@
 
         return false;
     }
-
-
-    /**
-     * Lowercases the attribute of a complex name component or a simple one with
-     * a single attribute value pair.
-     * 
-     * @param nameComponent
-     *            the name component to lower the case of attribute types
-     * @return the name component with all attribute types lowercased
-     * @throws NamingException
-     *             if the component is malformed
-     */
-    public String toLowerAttributeType( String nameComponent ) throws NamingException
-    {
-        String attr = null;
-        String value = null;
-        StringBuffer buf = new StringBuffer();
-
-        if ( hasCompositeComponents( nameComponent ) )
-        {
-            String[] comps = getCompositeComponents( nameComponent );
-            for ( int ii = 0; ii < comps.length; ii++ )
-            {
-                attr = getRdnAttribute( nameComponent );
-                value = getRdnValue( nameComponent );
-                buf.append( attr.toLowerCase() );
-                buf.append( "=" );
-                buf.append( value );
-
-                if ( ii != comps.length - 1 )
-                {
-                    buf.append( "+" );
-                }
-            }
-
-            return buf.toString();
-        }
-
-        attr = getRdnAttribute( nameComponent );
-        value = getRdnValue( nameComponent );
-        buf.append( attr.toLowerCase() );
-        buf.append( "=" );
-        buf.append( value );
-        return buf.toString();
-    }
 }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/NestableDelegate.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/NestableDelegate.java
index f2e97b2..a0cf572 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/NestableDelegate.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/NestableDelegate.java
@@ -27,7 +27,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 
 
@@ -260,18 +259,21 @@
      *             chain
      * @since 2.0
      */
-    public int indexOfThrowable( Class type, int fromIndex )
+    public int indexOfThrowable( Class<?> type, int fromIndex )
     {
         if ( fromIndex < 0 )
         {
             throw new IndexOutOfBoundsException( "The start index was out of bounds: " + fromIndex );
         }
+        
         Throwable[] throwables = ExceptionUtils.getThrowables( this.nestable );
+        
         if ( fromIndex >= throwables.length )
         {
             throw new IndexOutOfBoundsException( "The start index was out of bounds: " + fromIndex + " >= "
                 + throwables.length );
         }
+        
         for ( int i = fromIndex; i < throwables.length; i++ )
         {
             if ( throwables[i].getClass().equals( type ) )
@@ -279,6 +281,7 @@
                 return i;
             }
         }
+        
         return -1;
     }
 
@@ -365,17 +368,23 @@
 
         synchronized ( out )
         {
-            for ( Iterator iter = stacks.iterator(); iter.hasNext(); )
+            boolean isFirst = true;
+            
+            for ( String[] st:stacks )
             {
-                String[] st = ( String[] ) iter.next();
-                for ( int i = 0, len = st.length; i < len; i++ )
+                if ( isFirst )
                 {
-                    out.println( st[i] );
+                    isFirst = false;
                 }
-                if ( iter.hasNext() )
+                else
                 {
                     out.print( separatorLine );
                 }
+
+                for ( String s:st )
+                {
+                    out.println( s );
+                }
             }
         }
     }
@@ -417,18 +426,19 @@
      *            The list containing String[] elements
      * @since 2.0
      */
-    protected void trimStackFrames( List stacks )
+    protected void trimStackFrames( List<String[]> stacks )
     {
         for ( int size = stacks.size(), i = size - 1; i > 0; i-- )
         {
-            String[] curr = ( String[] ) stacks.get( i );
-            String[] next = ( String[] ) stacks.get( i - 1 );
+            String[] curr = stacks.get( i );
+            String[] next = stacks.get( i - 1 );
 
-            List currList = new ArrayList( Arrays.asList( curr ) );
-            List nextList = new ArrayList( Arrays.asList( next ) );
+            List<String> currList = new ArrayList<String>( Arrays.asList( curr ) );
+            List<String> nextList = new ArrayList<String>( Arrays.asList( next ) );
             ExceptionUtils.removeCommonFrames( currList, nextList );
 
             int trimmed = curr.length - currList.size();
+            
             if ( trimmed > 0 )
             {
                 currList.add( "\t... " + trimmed + " more" );
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java
index f2a1dd7..cb2317e 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java
@@ -35,7 +35,7 @@
 import javax.naming.NamingException;
 
 import org.apache.directory.shared.ldap.NotImplementedException;
-import org.apache.directory.shared.ldap.ldif.Entry;
+import org.apache.directory.shared.ldap.ldif.LdifEntry;
 import org.apache.directory.shared.ldap.ldif.LdifReader;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
 
@@ -200,7 +200,15 @@
         {
             try
             {
-                properties.load( new FileInputStream( file ) );
+                final FileInputStream fis = new FileInputStream( file );
+                try
+                {
+                    properties.load( fis );
+                }
+                finally
+                {
+                    fis.close();
+                }
             }
             catch ( IOException e )
             {
@@ -577,11 +585,11 @@
         
         LdifReader ldifReader = new LdifReader( new StringReader( ldif ) );
         
-        Entry entry = ldifReader.next();
+        LdifEntry entry = ldifReader.next();
         
         if ( entry != null )
         {
-        	values = entry.getAttributes();
+            values = entry.getAttributes();
         }
         return values;
     }
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/SequencedHashMap.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/SequencedHashMap.java
index 036e5db..9812570 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/SequencedHashMap.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/SequencedHashMap.java
@@ -119,6 +119,10 @@
         }
 
 
+        /**
+         * Compute the instance's hash code
+         * @return the instance's hash code 
+         */
         public int hashCode()
         {
             // implemented per api docs for Map.Entry.hashCode()
@@ -622,6 +626,7 @@
 
     /**
      * Implements {@link Map#hashCode()}.
+     * @return the instance's hash code 
      */
     public int hashCode()
     {
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java
index cce7ece..d51d711 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java
@@ -48,8 +48,8 @@
 public class StringTools
 {
     /** The default charset, because it's not provided by JDK 1.5 */
-	static String defaultCharset = null;
-	
+    static String defaultCharset = null;
+    
 
     
     // ~ Static fields/initializers
@@ -313,38 +313,38 @@
     
     private static final char[] TO_LOWER_CASE =
     {
-    	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-    	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
-    	' ',  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
-    	'(',  ')',  0x2A, '+',  ',',  '-',  '.',  '/',
-    	'0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  
-    	'8',  '9',  ':',  0x3B, 0x3C, '=',  0x3E, '?',
-    	0x40, 'a',  'b',  'c',  'd',  'e',  'f',  'g', 
-    	'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-    	'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-    	'x',  'y',  'z',  0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
-    	0x60, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
-    	'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-    	'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-    	'x',  'y',  'z',  0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
-    	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    	0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
-    	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    	0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
-    	0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
-    	0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
-    	0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
-    	0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
-    	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-    	0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
-    	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
-    	0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
-    	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-    	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
-    	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-    	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+        0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+        ' ',  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, '\'',
+        '(',  ')',  0x2A, '+',  ',',  '-',  '.',  '/',
+        '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  
+        '8',  '9',  ':',  0x3B, 0x3C, '=',  0x3E, '?',
+        0x40, 'a',  'b',  'c',  'd',  'e',  'f',  'g', 
+        'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+        'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+        'x',  'y',  'z',  0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+        0x60, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
+        'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
+        'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
+        'x',  'y',  'z',  0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+        0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+        0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
+        0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+        0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+        0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+        0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+        0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+        0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+        0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+        0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+        0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+        0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+        0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+        0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
     };
     
 
@@ -461,8 +461,7 @@
      * to a single space to perserve the whitespace separated tokenization order
      * of the String.
      * 
-     * @param string
-     *            the string to deep trim.
+     * @param string the string to deep trim.
      * @return the trimmed string.
      */
     public static final String deepTrim( String string )
@@ -488,10 +487,8 @@
     /**
      * Put common code to deepTrim(String) and deepTrimToLower here.
      * 
-     * @param str
-     *            the string to deep trim
-     * @param toLowerCase
-     *            how to normalize for case: upper or lower
+     * @param str the string to deep trim
+     * @param toLowerCase how to normalize for case: upper or lower
      * @return the deep trimmed string
      * @see StringTools#deepTrim( String )
      * 
@@ -566,12 +563,9 @@
      * length of the truncated string so size of '...' can be interpreted.
      * Useful for large strings in UIs or hex dumps to log files.
      * 
-     * @param str
-     *            the string to truncate
-     * @param head
-     *            the amount of the head to display
-     * @param tail
-     *            the amount of the tail to display
+     * @param str the string to truncate
+     * @param head the amount of the head to display
+     * @param tail the amount of the tail to display
      * @return the center truncated string
      */
     public static final String centerTrunc( String str, int head, int tail )
@@ -630,6 +624,11 @@
      */
     public static final String toLowerCase( String value )
     {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+        
         char[] chars = value.toCharArray();
         
         for ( int i = 0; i < chars.length; i++ )
@@ -650,6 +649,11 @@
      */
     public static final String toUpperCase( String value )
     {
+        if ( ( null == value ) || ( value.length() == 0 ) )
+        {
+            return "";
+        }
+        
         char[] chars = value.toCharArray();
         
         for ( int i = 0; i < chars.length; i++ )
@@ -687,15 +691,11 @@
     /**
      * This method is used to insert HTML block dynamically
      * 
-     * @param source
-     *            the HTML code to be processes
-     * @param replaceNl
-     *            if true '\n' will be replaced by &lt;br>
-     * @param replaceTag
-     *            if true '<' will be replaced by &lt; and '>' will be replaced
+     * @param source the HTML code to be processes
+     * @param replaceNl if true '\n' will be replaced by &lt;br>
+     * @param replaceTag if true '<' will be replaced by &lt; and '>' will be replaced
      *            by &gt;
-     * @param replaceQuote
-     *            if true '\"' will be replaced by &quot;
+     * @param replaceQuote if true '\"' will be replaced by &quot;
      * @return the formated html block
      */
     public static final String formatHtml( String source, boolean replaceNl, boolean replaceTag,
@@ -903,7 +903,7 @@
      * @return the filter accepted path component Strings in the order
      *         encountered
      */
-    public static final List getPaths( String paths, FileFilter filter )
+    public static final List<String> getPaths( String paths, FileFilter filter )
     {
         int start = 0;
         int stop = -1;
@@ -978,8 +978,7 @@
     /**
      * Helper function that dump a byte in hex form
      * 
-     * @param octet
-     *            The byte to dump
+     * @param octet The byte to dump
      * @return A string representation of the byte
      */
     public static final String dumpByte( byte octet )
@@ -1004,8 +1003,7 @@
     /**
      * Helper function that dump an array of bytes in hex form
      * 
-     * @param buffer
-     *            The bytes array to dump
+     * @param buffer The bytes array to dump
      * @return A string representation of the array of bytes
      */
     public static final String dumpBytes( byte[] buffer )
@@ -1083,8 +1081,7 @@
     /**
      * Return the Unicode char which is coded in the bytes at position 0.
      * 
-     * @param bytes
-     *            The byte[] represntation of an Unicode string.
+     * @param bytes The byte[] represntation of an Unicode string.
      * @return The first char found.
      */
     public static final char bytesToChar( byte[] bytes )
@@ -1097,10 +1094,8 @@
      * Count the number of bytes needed to return an Unicode char. This can be
      * from 1 to 6.
      * 
-     * @param bytes
-     *            The bytes to read
-     * @param pos
-     *            Position to start counting. It must be a valid start of a
+     * @param bytes The bytes to read
+     * @param pos Position to start counting. It must be a valid start of a
      *            encoded char !
      * @return The number of bytes to create a char, or -1 if the encoding is
      *         wrong. TODO : Should stop after the third byte, as a char is only
@@ -1147,8 +1142,7 @@
     /**
      * Return the number of bytes that hold an Unicode char.
      * 
-     * @param car
-     *            The character to be decoded
+     * @param car The character to be decoded
      * @return The number of bytes to hold the char. TODO : Should stop after
      *         the third byte, as a char is only 2 bytes long.
      */
@@ -1188,8 +1182,7 @@
     /**
      * Count the number of bytes included in the given char[].
      * 
-     * @param chars
-     *            The char array to decode
+     * @param chars The char array to decode
      * @return The number of bytes in the char array
      */
     public static final int countBytes( char[] chars )
@@ -1220,10 +1213,8 @@
      * Return the Unicode char which is coded in the bytes at the given
      * position.
      * 
-     * @param bytes
-     *            The byte[] represntation of an Unicode string.
-     * @param pos
-     *            The current position to start decoding the char
+     * @param bytes The byte[] represntation of an Unicode string.
+     * @param pos The current position to start decoding the char
      * @return The decoded char, or -1 if no char can be decoded TODO : Should
      *         stop after the third byte, as a char is only 2 bytes long.
      */
@@ -1411,8 +1402,7 @@
     /**
      * Count the number of chars included in the given byte[].
      * 
-     * @param bytes
-     *            The byte array to decode
+     * @param bytes The byte array to decode
      * @return The number of char in the byte array
      */
     public static final int countChars( byte[] bytes )
@@ -1438,17 +1428,14 @@
     /**
      * Check if a text is present at the current position in a buffer.
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @param text
-     *            The text we want to check
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param text The text we want to check
      * @return <code>true</code> if the buffer contains the text.
      */
-    public static final int areEquals( byte[] byteArray, int index, String text )
+    public static final int areEquals( byte[] bytes, int index, String text )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( byteArray.length <= index ) || ( index < 0 )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 )
             || ( text == null ) )
         {
             return NOT_EQUAL;
@@ -1459,7 +1446,7 @@
             {
                 byte[] data = text.getBytes( "UTF-8" );
 
-                return areEquals( byteArray, index, data );
+                return areEquals( bytes, index, data );
             }
             catch ( UnsupportedEncodingException uee )
             {
@@ -1472,17 +1459,14 @@
     /**
      * Check if a text is present at the current position in a buffer.
      * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @param text
-     *            The text we want to check
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param text The text we want to check
      * @return <code>true</code> if the buffer contains the text.
      */
-    public static final int areEquals( char[] charArray, int index, String text )
+    public static final int areEquals( char[] chars, int index, String text )
     {
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( charArray.length <= index ) || ( index < 0 )
+        if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 )
             || ( text == null ) )
         {
             return NOT_EQUAL;
@@ -1491,7 +1475,7 @@
         {
             char[] data = text.toCharArray();
 
-            return areEquals( charArray, index, data );
+            return areEquals( chars, index, data );
         }
     }
 
@@ -1499,28 +1483,24 @@
     /**
      * Check if a text is present at the current position in a buffer.
      * 
-     * @param charArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @param charArray2
-     *            The text we want to check
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param chars2 The text we want to check
      * @return <code>true</code> if the buffer contains the text.
      */
-    public static final int areEquals( char[] charArray, int index, char[] charArray2 )
+    public static final int areEquals( char[] chars, int index, char[] chars2 )
     {
-
-        if ( ( charArray == null ) || ( charArray.length == 0 ) || ( charArray.length <= index ) || ( index < 0 )
-            || ( charArray2 == null ) || ( charArray2.length == 0 )
-            || ( charArray2.length > ( charArray.length + index ) ) )
+        if ( ( chars == null ) || ( chars.length == 0 ) || ( chars.length <= index ) || ( index < 0 )
+            || ( chars2 == null ) || ( chars2.length == 0 )
+            || ( chars2.length > ( chars.length + index ) ) )
         {
             return NOT_EQUAL;
         }
         else
         {
-            for ( int i = 0; i < charArray2.length; i++ )
+            for ( int i = 0; i < chars2.length; i++ )
             {
-                if ( charArray[index++] != charArray2[i] )
+                if ( chars[index++] != chars2[i] )
                 {
                     return NOT_EQUAL;
                 }
@@ -1533,19 +1513,19 @@
     /**
      * Check if a text is present at the current position in another string.
      * 
-     * @param string1 The string which contains the data
+     * @param string The string which contains the data
      * @param index Current position in the string
      * @param text The text we want to check
      * @return <code>true</code> if the string contains the text.
      */
-    public static final boolean areEquals( String string1, int index, String text )
+    public static final boolean areEquals( String string, int index, String text )
     {
-        if ( ( string1 == null ) || ( text == null ) ) 
+        if ( ( string == null ) || ( text == null ) ) 
         {
             return false;
         }
         
-        int length1 = string1.length();
+        int length1 = string.length();
         int length2 = text.length();
 
         if ( ( length1 == 0 ) || ( length1 <= index ) || ( index < 0 )
@@ -1555,7 +1535,7 @@
         }
         else
         {
-        	return string1.substring( index ).startsWith( text );
+            return string.substring( index ).startsWith( text );
         }
     }
     
@@ -1563,28 +1543,25 @@
     /**
      * Check if a text is present at the current position in a buffer.
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
-     * @param byteArray2
-     *            The text we want to check
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
+     * @param bytes2 The text we want to check
      * @return <code>true</code> if the buffer contains the text.
      */
-    public static final int areEquals( byte[] byteArray, int index, byte[] byteArray2 )
+    public static final int areEquals( byte[] bytes, int index, byte[] bytes2 )
     {
 
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( byteArray.length <= index ) || ( index < 0 )
-            || ( byteArray2 == null ) || ( byteArray2.length == 0 )
-            || ( byteArray2.length > ( byteArray.length + index ) ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( bytes.length <= index ) || ( index < 0 )
+            || ( bytes2 == null ) || ( bytes2.length == 0 )
+            || ( bytes2.length > ( bytes.length + index ) ) )
         {
             return NOT_EQUAL;
         }
         else
         {
-            for ( int i = 0; i < byteArray2.length; i++ )
+            for ( int i = 0; i < bytes2.length; i++ )
             {
-                if ( byteArray[index++] != byteArray2[i] )
+                if ( bytes[index++] != bytes2[i] )
                 {
                     return NOT_EQUAL;
                 }
@@ -1677,6 +1654,7 @@
         }
     }
 
+
     /**
      * Test if the current character is equal to a specific character.
      * 
@@ -1706,6 +1684,37 @@
         }
     }
 
+
+    /**
+     * Test if the current character is equal to a specific character.
+     * 
+     * @param string The String which contains the data
+     * @param index Current position in the string
+     * @param car The character we want to compare with the current string
+     *            position
+     * @return <code>true</code> if the current character equals the given
+     *         character.
+     */
+    public static final boolean isICharASCII( byte[] bytes, int index, char car )
+    {
+        if ( bytes == null )
+        {
+            return false;
+        }
+        
+        int length = bytes.length;
+        
+        if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) )
+        {
+            return false;
+        }
+        else
+        {
+            return ( ( bytes[ index ] | 0x20 ) & car ) == car;
+        }
+    }
+
+
     /**
      * Test if the current character is a bit, ie 0 or 1.
      * 
@@ -1739,10 +1748,8 @@
     /**
      * Get the character at a given position in a string, checking fo limits
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return The character ar the given position, or '\0' if something went wrong 
      */
     public static final char charAt( String string, int index )
@@ -1764,16 +1771,52 @@
         }
     }
 
-    public static byte getHexValue( char c1, char c2 )
+    
+    /**
+     * Translate two chars to an hex value. The chars must be 
+     * in [a-fA-F0-9]
+     *
+     * @param high The high value 
+     * @param low The low value
+     * @return A byte representation of the two chars
+     */
+    public static byte getHexValue( char high, char low )
     {
-        if ( ( c1 > 127 ) || (c2 > 127 ) || ( c1 < 0 ) | ( c2 < 0 ) )
+        if ( ( high > 127 ) || ( low > 127 ) || ( high < 0 ) | ( low < 0 ) )
         {
             return -1;
         }
         
-        return (byte)( ( HEX_VALUE[c1] << 4 ) | HEX_VALUE[c2] );
+        return (byte)( ( HEX_VALUE[high] << 4 ) | HEX_VALUE[low] );
     }
 
+
+    /**
+     * Translate two bytes to an hex value. The bytes must be 
+     * in [0-9a-fA-F]
+     *
+     * @param high The high value 
+     * @param low The low value
+     * @return A byte representation of the two bytes
+     */
+    public static byte getHexValue( byte high, byte low )
+    {
+        if ( ( high > 127 ) || ( low > 127 ) || ( high < 0 ) | ( low < 0 ) )
+        {
+            return -1;
+        }
+        
+        return (byte)( ( HEX_VALUE[high] << 4 ) | HEX_VALUE[low] );
+    }
+
+    
+    /**
+     * Return an hex value from a sinle char
+     * The char must be in [0-9a-fA-F]
+     *
+     * @param c The char we want to convert
+     * @return A byte between 0 and 15
+     */
     public static byte getHexValue( char c )
     {
         if ( ( c > 127 ) || ( c < 0 ) )
@@ -1788,21 +1831,19 @@
      * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
      * [0x41-0x46] | [0x61-0x66]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is a Hex Char
      */
-    public static final boolean isHex( byte[] byteArray, int index )
+    public static final boolean isHex( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return false;
         }
         else
         {
-            byte c = byteArray[index];
+            byte c = bytes[index];
 
             if ( ( ( c | 0x7F ) != 0x7F ) || ( HEX[c] == false ) )
             {
@@ -1820,10 +1861,8 @@
      * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
      * [0x41-0x46] | [0x61-0x66]
      * 
-     * @param chars
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is a Hex Char
      */
     public static final boolean isHex( char[] chars, int index )
@@ -1851,10 +1890,8 @@
      * Check if the current character is an Hex Char &lt;hex> ::= [0x30-0x39] |
      * [0x41-0x46] | [0x61-0x66]
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return <code>true</code> if the current character is a Hex Char
      */
     public static final boolean isHex( String string, int index )
@@ -1890,22 +1927,22 @@
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
-     * @param byteArray
-     *            The buffer which contains the data
+     * @param bytes The buffer which contains the data
      * @return <code>true</code> if the current character is a Digit
      */
-    public static final boolean isDigit( byte[] byteArray )
+    public static final boolean isDigit( byte[] bytes )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) )
         {
             return false;
         }
         else
         {
-            return ( ( ( ( byteArray[0] | 0x7F ) != 0x7F ) || !DIGIT[byteArray[0]] ) ? false : true );
+            return ( ( ( ( bytes[0] | 0x7F ) != 0x7F ) || !DIGIT[bytes[0]] ) ? false : true );
         }
     }
 
+    
     /**
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
@@ -1919,6 +1956,7 @@
         return ( car >= '0' ) && ( car <= '9' );
     }
 
+    
     /**
      * Test if the current byte is an Alpha character : 
      * &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A]
@@ -1933,6 +1971,7 @@
         return ( ( c > 0 ) && ( c <= 127 ) && ALPHA[c] );
     }
 
+    
     /**
      * Test if the current character is an Alpha character : 
      * &lt;alpha> ::= [0x41-0x5A] | [0x61-0x7A]
@@ -1952,22 +1991,20 @@
      * Test if the current character is an Alpha character : &lt;alpha> ::=
      * [0x41-0x5A] | [0x61-0x7A]
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is an Alpha
      *         character
      */
-    public static final boolean isAlphaASCII( byte[] byteArray, int index )
+    public static final boolean isAlphaASCII( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return false;
         }
         else
         {
-            byte c = byteArray[index++];
+            byte c = bytes[index];
 
             if ( ( ( c | 0x7F ) != 0x7F ) || ( ALPHA[c] == false ) )
             {
@@ -1985,10 +2022,8 @@
      * Test if the current character is an Alpha character : &lt;alpha> ::=
      * [0x41-0x5A] | [0x61-0x7A]
      * 
-     * @param chars
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is an Alpha
      *         character
      */
@@ -2000,7 +2035,7 @@
         }
         else
         {
-            char c = chars[index++];
+            char c = chars[index];
 
             if ( ( c > 127 ) || ( ALPHA[c] == false ) )
             {
@@ -2013,14 +2048,13 @@
         }
     }
 
+    
     /**
      * Test if the current character is an Alpha character : &lt;alpha> ::=
      * [0x41-0x5A] | [0x61-0x7A]
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return <code>true</code> if the current character is an Alpha
      *         character
      */
@@ -2039,7 +2073,7 @@
         }
         else
         {
-            char c = string.charAt( index++ );
+            char c = string.charAt( index );
 
             if ( ( c > 127 ) || ( ALPHA[c] == false ) )
             {
@@ -2052,14 +2086,13 @@
         }
     }
 
+    
     /**
      * Test if the current character is a lowercased Alpha character : <br/>
      * &lt;alpha> ::= [0x61-0x7A]
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return <code>true</code> if the current character is a lower Alpha
      *         character
      */
@@ -2078,7 +2111,7 @@
         }
         else
         {
-            char c = string.charAt( index++ );
+            char c = string.charAt( index );
 
             if ( ( c > 127 ) || ( ALPHA_LOWER_CASE[c] == false ) )
             {
@@ -2091,14 +2124,13 @@
         }
     }
 
+    
     /**
      * Test if the current character is a uppercased Alpha character : <br/>
      * &lt;alpha> ::= [0x61-0x7A]
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return <code>true</code> if the current character is a lower Alpha
      *         character
      */
@@ -2117,7 +2149,7 @@
         }
         else
         {
-            char c = string.charAt( index++ );
+            char c = string.charAt( index );
 
             if ( ( c > 127 ) || ( ALPHA_UPPER_CASE[c] == false ) )
             {
@@ -2135,21 +2167,19 @@
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is a Digit
      */
-    public static final boolean isDigit( byte[] byteArray, int index )
+    public static final boolean isDigit( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return false;
         }
         else
         {
-            return ( ( ( ( byteArray[index] | 0x7F ) !=  0x7F ) || !DIGIT[byteArray[index]] ) ? false : true );
+            return ( ( ( ( bytes[index] | 0x7F ) !=  0x7F ) || !DIGIT[bytes[index]] ) ? false : true );
         }
     }
 
@@ -2158,10 +2188,8 @@
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
-     * @param chars
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
      * @return <code>true</code> if the current character is a Digit
      */
     public static final boolean isDigit( char[] chars, int index )
@@ -2176,14 +2204,13 @@
         }
     }
 
+    
     /**
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return <code>true</code> if the current character is a Digit
      */
     public static final boolean isDigit( String string, int index )
@@ -2206,12 +2233,12 @@
         }
     }
 
+    
     /**
      * Test if the current character is a digit &lt;digit> ::= '0' | '1' | '2' |
      * '3' | '4' | '5' | '6' | '7' | '8' | '9'
      * 
-     * @param chars
-     *            The buffer which contains the data
+     * @param chars The buffer which contains the data
      * @return <code>true</code> if the current character is a Digit
      */
     public static final boolean isDigit( char[] chars )
@@ -2226,15 +2253,14 @@
         }
     }
 
+    
     /**
      * Check if the current character is an 7 bits ASCII CHAR (between 0 and
      * 127). 
      * &lt;char> ::= &lt;alpha> | &lt;digit>
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return The position of the next character, if the current one is a CHAR.
      */
     public static final boolean isAlphaDigit( String string, int index )
@@ -2252,7 +2278,7 @@
         }
         else
         {
-            char c = string.charAt( index++ );
+            char c = string.charAt( index );
 
             if ( ( c > 127 ) || ( ALPHA_DIGIT[c] == false ) )
             {
@@ -2266,26 +2292,23 @@
     }
 
 
-
     /**
      * Check if the current character is an 7 bits ASCII CHAR (between 0 and
      * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
      * 
-     * @param byteArray
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param bytes The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The position of the next character, if the current one is a CHAR.
      */
-    public static final boolean isAlphaDigitMinus( byte[] byteArray, int index )
+    public static final boolean isAlphaDigitMinus( byte[] bytes, int index )
     {
-        if ( ( byteArray == null ) || ( byteArray.length == 0 ) || ( index < 0 ) || ( index >= byteArray.length ) )
+        if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) )
         {
             return false;
         }
         else
         {
-            byte c = byteArray[index++];
+            byte c = bytes[index];
 
             if ( ( ( c | 0x7F ) != 0x7F ) || ( CHAR[c] == false ) )
             {
@@ -2303,10 +2326,8 @@
      * Check if the current character is an 7 bits ASCII CHAR (between 0 and
      * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
      * 
-     * @param chars
-     *            The buffer which contains the data
-     * @param index
-     *            Current position in the buffer
+     * @param chars The buffer which contains the data
+     * @param index Current position in the buffer
      * @return The position of the next character, if the current one is a CHAR.
      */
     public static final boolean isAlphaDigitMinus( char[] chars, int index )
@@ -2317,7 +2338,7 @@
         }
         else
         {
-            char c = chars[index++];
+            char c = chars[index];
 
             if ( ( c > 127 ) || ( CHAR[c] == false ) )
             {
@@ -2330,14 +2351,13 @@
         }
     }
 
+    
     /**
      * Check if the current character is an 7 bits ASCII CHAR (between 0 and
      * 127). &lt;char> ::= &lt;alpha> | &lt;digit> | '-'
      * 
-     * @param string
-     *            The string which contains the data
-     * @param index
-     *            Current position in the string
+     * @param string The string which contains the data
+     * @param index Current position in the string
      * @return The position of the next character, if the current one is a CHAR.
      */
     public static final boolean isAlphaDigitMinus( String string, int index )
@@ -2355,7 +2375,7 @@
         }
         else
         {
-            char c = string.charAt( index++ );
+            char c = string.charAt( index );
 
             if ( ( c > 127 ) || ( CHAR[c] == false ) )
             {
@@ -2368,6 +2388,7 @@
         }
     }
 
+    
     // Empty checks
     // -----------------------------------------------------------------------
     /**
@@ -2388,8 +2409,7 @@
      * String. That functionality is available in isBlank().
      * </p>
      * 
-     * @param str
-     *            the String to check, may be null
+     * @param str the String to check, may be null
      * @return <code>true</code> if the String is empty or null
      */
     public static final boolean isEmpty( String str )
@@ -2401,8 +2421,7 @@
     /**
      * Checks if a bytes array is empty or null.
      * 
-     * @param bytes
-     *            The bytes array to check, may be null
+     * @param bytes The bytes array to check, may be null
      * @return <code>true</code> if the bytes array is empty or null
      */
     public static final boolean isEmpty( byte[] bytes )
@@ -2424,8 +2443,7 @@
      *  StringUtils.isNotEmpty(&quot;  bob  &quot;) = true
      * </pre>
      * 
-     * @param str
-     *            the String to check, may be null
+     * @param str the String to check, may be null
      * @return <code>true</code> if the String is not empty and not null
      */
     public static final boolean isNotEmpty( String str )
@@ -2449,8 +2467,7 @@
      *  StringUtils.trim(&quot;    abc    &quot;) = &quot;abc&quot;
      * </pre>
      * 
-     * @param str
-     *            the String to be trimmed, may be null
+     * @param str the String to be trimmed, may be null
      * @return the trimmed string, <code>null</code> if null String input
      */
     public static final String trim( String str )
@@ -2520,8 +2537,7 @@
      *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
      * </pre>
      * 
-     * @param str
-     *            the String to be trimmed, may be null
+     * @param str the String to be trimmed, may be null
      * @return the trimmed string, <code>null</code> if null String input
      */
     public static final String trimLeft( String str )
@@ -2558,8 +2574,7 @@
      *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
      * </pre>
      * 
-     * @param chars
-     *            the chars array to be trimmed, may be null
+     * @param chars the chars array to be trimmed, may be null
      * @return the position of the first char which is not a space, or the last
      *         position of the array.
      */
@@ -2578,6 +2593,7 @@
         return pos;
     }
 
+
     /**
      * <p>
      * Removes spaces (char &lt;= 32) from a position in this array, handling
@@ -2618,6 +2634,44 @@
 
     /**
      * <p>
+     * Removes spaces (char &lt;= 32) from a position in this array, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     * 
+     * <pre>
+     *  StringUtils.trimLeft(null)          = null
+     *  StringUtils.trimLeft(&quot;&quot;,...)            = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;     &quot;,...)       = &quot;&quot;
+     *  StringUtils.trimLeft(&quot;abc&quot;,...)         = &quot;abc&quot;
+     *  StringUtils.trimLeft(&quot;    abc    &quot;,...) = &quot;abc    &quot;
+     * </pre>
+     * 
+     * @param bytes the byte array to be trimmed, may be null
+     * @param pos The starting position
+     */
+    public static final void trimLeft( byte[] bytes, Position pos )
+    {
+        if ( bytes == null )
+        {
+            return;
+        }
+
+        int length = bytes.length;
+        
+        while ( ( pos.start < length ) && ( bytes[ pos.start ] == ' ' ) )
+        {
+            pos.start++;
+        }
+        
+        pos.end = pos.start;
+
+        return;
+    }
+
+    
+    /**
+     * <p>
      * Removes spaces (char &lt;= 32) from start of this array, handling
      * <code>null</code> by returning <code>null</code>.
      * </p>
@@ -2631,8 +2685,7 @@
      *  StringUtils.trimLeft(&quot;    abc    &quot;) = &quot;abc    &quot;
      * </pre>
      * 
-     * @param bytes
-     *            the byte array to be trimmed, may be null
+     * @param bytes the byte array to be trimmed, may be null
      * @return the position of the first byte which is not a space, or the last
      *         position of the array.
      */
@@ -2667,8 +2720,7 @@
      *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
      * </pre>
      * 
-     * @param str
-     *            the String to be trimmed, may be null
+     * @param str the String to be trimmed, may be null
      * @return the trimmed string, <code>null</code> if null String input
      */
     public static final String trimRight( String str )
@@ -2752,8 +2804,7 @@
      *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
      * </pre>
      * 
-     * @param chars
-     *            the chars array to be trimmed, may be null
+     * @param chars the chars array to be trimmed, may be null
      * @return the position of the first char which is not a space, or the last
      *         position of the array.
      */
@@ -2772,6 +2823,7 @@
         return pos;
     }
 
+
     /**
      * <p>
      * Removes spaces (char &lt;= 32) from end of this string, handling
@@ -2787,8 +2839,7 @@
      *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
      * </pre>
      * 
-     * @param string
-     *            the string to be trimmed, may be null
+     * @param string the string to be trimmed, may be null
      * @return the position of the first char which is not a space, or the last
      *         position of the string.
      */
@@ -2812,6 +2863,54 @@
         return ( pos.end == string.length() ? string : string.substring( 0, pos.end ) );
     }
 
+
+    /**
+     * <p>
+     * Removes spaces (char &lt;= 32) from end of this string, handling
+     * <code>null</code> by returning <code>null</code>.
+     * </p>
+     * Trim removes start characters &lt;= 32.
+     * 
+     * <pre>
+     *  StringUtils.trimRight(null)          = null
+     *  StringUtils.trimRight(&quot;&quot;)            = &quot;&quot;
+     *  StringUtils.trimRight(&quot;     &quot;)       = &quot;&quot;
+     *  StringUtils.trimRight(&quot;abc&quot;)         = &quot;abc&quot;
+     *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
+     * </pre>
+     * 
+     * @param bytes the byte array to be trimmed, may be null
+     * @return the position of the first char which is not a space, or the last
+     *         position of the byte array.
+     */
+    public static final String trimRight( byte[] bytes, Position pos )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        while ( ( pos.end >= 0 ) && ( bytes[pos.end - 1] == ' ' ) )
+        {
+            if ( ( pos.end > 1 ) && ( bytes[pos.end - 2] == '\\' ) )
+            {
+                break;
+            }
+            
+            pos.end--;
+        }
+
+        if ( pos.end == bytes.length )
+        {
+            return StringTools.utf8ToString( bytes );
+        }
+        else
+        {
+            return StringTools.utf8ToString( bytes, pos.end );
+        }
+    }
+
+
     /**
      * <p>
      * Removes spaces (char &lt;= 32) from end of this array, handling
@@ -2827,8 +2926,7 @@
      *  StringUtils.trimRight(&quot;    abc    &quot;) = &quot;    abc&quot;
      * </pre>
      * 
-     * @param bytes
-     *            the chars array to be trimmed, may be null
+     * @param bytes the byte array to be trimmed, may be null
      * @return the position of the first char which is not a space, or the last
      *         position of the array.
      */
@@ -2864,8 +2962,7 @@
      *  StringUtils.upperCase(&quot;aBc&quot;) = &quot;ABC&quot;
      * </pre>
      * 
-     * @param str
-     *            the String to upper case, may be null
+     * @param str the String to upper case, may be null
      * @return the upper cased String, <code>null</code> if null String input
      */
     public static final String upperCase( String str )
@@ -2893,8 +2990,7 @@
      *  StringUtils.lowerCase(&quot;aBc&quot;) = &quot;abc&quot;
      * </pre>
      * 
-     * @param str
-     *            the String to lower case, may be null
+     * @param str the String to lower case, may be null
      * @return the lower cased String, <code>null</code> if null String input
      */
     public static final String lowerCase( String str )
@@ -2907,6 +3003,7 @@
         return str.toLowerCase();
     }
 
+    
     /**
      * Rewrote the toLowercase method to improve performances.
      * In Ldap, attributesType are supposed to use ASCII chars :
@@ -2928,12 +3025,13 @@
         
         for ( char c:chars )
         {
-        	chars[pos++] = TO_LOWER_CASE[c];
+            chars[pos++] = TO_LOWER_CASE[c];
         }
         
         return new String( chars );
     }
 
+    
     // Equals
     // -----------------------------------------------------------------------
     /**
@@ -2955,10 +3053,8 @@
      * </pre>
      * 
      * @see java.lang.String#equals(Object)
-     * @param str1
-     *            the first String, may be null
-     * @param str2
-     *            the second String, may be null
+     * @param str1 the first String, may be null
+     * @param str2 the second String, may be null
      * @return <code>true</code> if the Strings are equal, case sensitive, or
      *         both <code>null</code>
      */
@@ -2971,8 +3067,7 @@
     /**
      * Return an UTF-8 encoded String
      * 
-     * @param bytes
-     *            The byte array to be transformed to a String
+     * @param bytes The byte array to be transformed to a String
      * @return A String.
      */
     public static final String utf8ToString( byte[] bytes )
@@ -2992,13 +3087,12 @@
         }
     }
 
+
     /**
      * Return an UTF-8 encoded String
      * 
-     * @param bytes
-     *            The byte array to be transformed to a String
-     * @param length
-     *            The length of the byte array to be converted
+     * @param bytes The byte array to be transformed to a String
+     * @param length The length of the byte array to be converted
      * @return A String.
      */
     public static final String utf8ToString( byte[] bytes, int length )
@@ -3020,10 +3114,35 @@
 
 
     /**
+     * Return an UTF-8 encoded String
+     * 
+     * @param bytes  The byte array to be transformed to a String
+     * @param start the starting position in the byte array  
+     * @param length The length of the byte array to be converted
+     * @return A String.
+     */
+    public static final String utf8ToString( byte[] bytes, int start, int length )
+    {
+        if ( bytes == null )
+        {
+            return "";
+        }
+
+        try
+        {
+            return new String( bytes, start, length, "UTF-8" );
+        }
+        catch ( UnsupportedEncodingException uee )
+        {
+            return "";
+        }
+    }
+
+
+    /**
      * Return UTF-8 encoded byte[] representation of a String
      * 
-     * @param string
-     *            The string to be transformed to a byte array
+     * @param string The string to be transformed to a byte array
      * @return The transformed byte array
      */
     public static final byte[] getBytesUtf8( String string )
@@ -3048,21 +3167,20 @@
     /**
      * Utility method that return a String representation of a list
      * 
-     * @param list
-     *            The list to transform to a string
+     * @param list The list to transform to a string
      * @return A csv string
      */
-    public static final String listToString( List list )
+    public static final String listToString( List<?> list )
     {
         if ( ( list == null ) || ( list.size() == 0 ) )
         {
             return "";
         }
 
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         boolean isFirst = true;
 
-        Iterator iter = list.iterator();
+        Iterator<?> iter = list.iterator();
 
         while ( iter.hasNext() )
         {
@@ -3085,11 +3203,11 @@
     /**
      * Utility method that return a String representation of a list
      * 
-     * @param list
-     *            The list to transform to a string
+     * @param list The list to transform to a string
+     * @param tabs The tabs to add in ffront of the elements
      * @return A csv string
      */
-    public static final String listToString( List list, String tabs )
+    public static final String listToString( List<?> list, String tabs )
     {
         if ( ( list == null ) || ( list.size() == 0 ) )
         {
@@ -3098,7 +3216,7 @@
 
         StringBuffer sb = new StringBuffer();
 
-        Iterator iter = list.iterator();
+        Iterator<?> iter = list.iterator();
 
         while ( iter.hasNext() )
         {
@@ -3115,11 +3233,10 @@
      * Utility method that return a String representation of a map. The elements
      * will be represented as "key = value"
      * 
-     * @param map
-     *            The map to transform to a string
+     * @param map The map to transform to a string
      * @return A csv string
      */
-    public static final String mapToString( Map map )
+    public static final String mapToString( Map<?,?> map )
     {
         if ( ( map == null ) || ( map.size() == 0 ) )
         {
@@ -3129,9 +3246,7 @@
         StringBuffer sb = new StringBuffer();
         boolean isFirst = true;
 
-        Iterator iter = map.keySet().iterator();
-
-        while ( iter.hasNext() )
+        for ( Map.Entry<?, ?> entry:map.entrySet() )
         {
             if ( isFirst )
             {
@@ -3142,9 +3257,8 @@
                 sb.append( ", " );
             }
 
-            Object key = iter.next();
-            sb.append( key );
-            sb.append( " = '" ).append( map.get( key ) ).append( "'" );
+            sb.append( entry.getKey() );
+            sb.append( " = '" ).append( entry.getValue() ).append( "'" );
         }
 
         return sb.toString();
@@ -3155,11 +3269,11 @@
      * Utility method that return a String representation of a map. The elements
      * will be represented as "key = value"
      * 
-     * @param map
-     *            The map to transform to a string
+     * @param map The map to transform to a string
+     * @param tabs The tabs to add in ffront of the elements
      * @return A csv string
      */
-    public static final String mapToString( Map map, String tabs )
+    public static final String mapToString( Map<?,?> map, String tabs )
     {
         if ( ( map == null ) || ( map.size() == 0 ) )
         {
@@ -3168,21 +3282,18 @@
 
         StringBuffer sb = new StringBuffer();
 
-        Iterator iter = map.keySet().iterator();
-
-        while ( iter.hasNext() )
+        for ( Map.Entry<?, ?> entry:map.entrySet() )
         {
-            Object key = iter.next();
             sb.append( tabs );
-            sb.append( key );
-            Object value = map.get( key );
+            sb.append( entry.getKey() );
 
-            sb.append( " = '" ).append( value.toString() ).append( "'\n" );
+            sb.append( " = '" ).append( entry.getValue().toString() ).append( "'\n" );
         }
 
         return sb.toString();
     }
 
+    
     /**
      * Get the default charset
      * 
@@ -3190,29 +3301,33 @@
      */
     public static final String getDefaultCharsetName()
     {
-    	if ( null == defaultCharset ) 
-    	{
-    		try 
-    		{
-    			// Try with jdk 1.5 method, if we are using a 1.5 jdk :)
-    			Method method = Charset.class.getMethod( "defaultCharset", new Class[0] );
-    			defaultCharset = ((Charset) method.invoke( null, new Object[0]) ).name();
-    		} 
-    		catch (Exception e) 
-    		{
-    			// fall back to old method
-    			defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
-    		}
-    	}
+        if ( null == defaultCharset ) 
+        {
+            try 
+            {
+                // Try with jdk 1.5 method, if we are using a 1.5 jdk :)
+                Method method = Charset.class.getMethod( "defaultCharset", new Class[0] );
+                defaultCharset = ((Charset) method.invoke( null, new Object[0]) ).name();
+            } 
+            catch (Exception e) 
+            {
+                // fall back to old method
+                defaultCharset = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding();
+            }
+        }
 
-    	return defaultCharset;
+        return defaultCharset;
     }
     
+    
     /**
      * Decodes values of attributes in the DN encoded in hex into a UTF-8 
      * String.  RFC2253 allows a DN's attribute to be encoded in hex.
      * The encoded value starts with a # then is followed by an even 
      * number of hex characters.  
+     * 
+     * @param str the string to decode
+     * @return the decoded string
      */
     public static final String decodeHexString( String str ) throws InvalidNameException
     {
@@ -3251,7 +3366,7 @@
      * String is returned.
      * 
      * @param str the string containing hex escapes
-     * @return decoded string
+     * @return the decoded string
      */
     public static final String decodeEscapedHex( String str ) throws InvalidNameException
     {
@@ -3272,11 +3387,14 @@
         // create buffer and add everything before start of scan
         StringBuffer buf = new StringBuffer();
         ByteBuffer bb = new ByteBuffer();
+        boolean escaped = false;
         
         // start scaning until we find an escaped series of bytes
         for ( int ii = 0; ii < length; ii++ )
         {
-            if ( str.charAt( ii ) == '\\' )
+            char c = str.charAt( ii );
+            
+            if ( c == '\\' )
             {
                 // we have the start of a hex escape sequence
                 if ( isHex( str, ii+1 ) && isHex ( str, ii+2 ) )
@@ -3285,23 +3403,60 @@
                     int advancedBy = collectEscapedHexBytes( bb, str, ii );
                     ii+=advancedBy-1;
                     buf.append( StringTools.utf8ToString( bb.buffer(), bb.position() ) );
+                    escaped = false;
                     continue;
                 }
-                else
+                else if ( !escaped )
                 {
-                    buf.append( str.charAt( ii ) );
+                    // It may be an escaped char ( ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\' )
+                    escaped = true;
                     continue;
                 }
             }
 
-            buf.append( str.charAt( ii ) );
+            
+            if ( escaped )
+            {
+                if ( DNUtils.isPairCharOnly( c ) )
+                {
+                    // It is an escaped char ( ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\' )
+                    // Stores it into the buffer without the '\'
+                    escaped = false;
+                    buf.append( c );
+                    continue;
+                }
+                else
+                {
+                    throw new InvalidNameException( "The DN must contain valid escaped characters." );
+                }
+            }
+            else
+            {
+                buf.append( str.charAt( ii ) );
+            }
         }
-        
+
+        if ( escaped )
+        {
+            // We should not have a '\' at the end of the string
+            throw new InvalidNameException( "The DN must not ends with a '\\'." );
+        }
+
         return buf.toString();
     }
 
 
-    private static int collectEscapedHexBytes( ByteBuffer bb, String str, int index )
+    /**
+     * Collects an hex sequence from a string, and returns the value
+     * as an integer, after having modified the initial value (the escaped
+     * hex value is transsformed to the byte it represents).
+     *
+     * @param bb the buffer which will contain the unescaped byte
+     * @param str the initial string with ecaped chars 
+     * @param index the position in the string of the escaped data
+     * @return the byte as an integer
+     */
+    public static int collectEscapedHexBytes( ByteBuffer bb, String str, int index )
     {
         int advanceBy = 0;
         
@@ -3323,6 +3478,7 @@
         return advanceBy;
     }
     
+    
     /**
      * Thansform an array of ASCII bytes to a string. the byte array should contains
      * only values in [0, 127].
@@ -3347,6 +3503,7 @@
         return new String( result );
     }
     
+    
     /**
      * Build an AttributeType froma byte array. An AttributeType contains
      * only chars within [0-9][a-z][A-Z][-.].
@@ -3356,22 +3513,23 @@
      */
     public static String getType( byte[] bytes)
     {
-    	if ( bytes == null )
-    	{
-    		return null;
-    	}
-    	
-    	char[] chars = new char[bytes.length];
+        if ( bytes == null )
+        {
+            return null;
+        }
+        
+        char[] chars = new char[bytes.length];
         int pos = 0;
         
         for ( byte b:bytes )
         {
-        	chars[pos++] = TO_LOWER_CASE[b];
+            chars[pos++] = TO_LOWER_CASE[b];
         }
         
         return new String( chars );
     }
     
+    
     /**
      * 
      * Check that a String is a valid IA5String. An IA5String contains only
@@ -3429,6 +3587,7 @@
         return true;
     }
 
+    
     /**
      * Check if the current char is in the unicodeSubset : all chars but
      * '\0', '(', ')', '*' and '\'
@@ -3447,9 +3606,9 @@
         char c = str.charAt( pos );
         
         return ( ( c > 127 ) || UNICODE_SUBSET[c] );
-        
     }
 
+    
     /**
      * Check if the current char is in the unicodeSubset : all chars but
      * '\0', '(', ')', '*' and '\'
diff --git a/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java b/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java
index 85f7d78..312c0d9 100644
--- a/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java
+++ b/ldap/src/main/java/org/apache/directory/shared/ldap/util/UnixCrypt.java
@@ -19,7 +19,7 @@
  */
 
 /*
- * @(#)UnixCrypt.java	0.9 96/11/25
+ * @(#)UnixCrypt.java    0.9 96/11/25
  *
  * Copyright (c) 1996 Aki Yoshida. All rights reserved.
  *
@@ -32,8 +32,8 @@
 /**
  * Unix crypt(3C) utility
  *
- * @version 	0.9, 11/25/96
- * @author 	Aki Yoshida
+ * @version     0.9, 11/25/96
+ * @author     Aki Yoshida
  */
 
 /**
diff --git a/ldap/src/site/site.xml b/ldap/src/site/site.xml
new file mode 100644
index 0000000..020b38e
--- /dev/null
+++ b/ldap/src/site/site.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!--
+  @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+-->
+<project name="${project.name}">
+    <bannerLeft>
+        <name>${project.name}</name>
+    </bannerLeft>
+    <publishDate position="navigation-bottom" format="dd-MM-yyyy HH:mm" />
+    <body>
+        <menu name="Parent">
+            <item name="Apache Directory Shared" href="../index.html" />
+        </menu>
+        <menu ref="reports" />
+    </body>
+</project>
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java
index 1cabccd..9442840 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/aci/ACIItemParserTest.java
@@ -23,8 +23,6 @@
 
 import java.text.ParseException;
 
-import org.apache.directory.shared.ldap.aci.ACIItemParser;
-
 import junit.framework.TestCase;
 
 
@@ -64,6 +62,13 @@
     }
 
 
+    private void checkItemToString( String spec, ACIItem item ) throws Exception
+    {
+        // try to parse the result of item.toString() again
+        parser.parse( item.toString() );
+    }
+
+
     /**
      * Tests the parser with a rangeOfValues with a nested filter.
      */
@@ -73,7 +78,8 @@
             + "itemOrUserFirst itemFirst  :{ protectedItems  "
             + "{ rangeOfValues (&(&(|(|(cn=ccc)(!(cn=ddd))(&(cn=aaa)(cn=bbb)))))) " + "}  , itemPermissions {  } } }";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
         
         
         spec = " { identificationTag \"id8\", precedence 0, authenticationLevel simple "
@@ -82,7 +88,8 @@
             + "{ protectedItems { rangeOfValues (|(!(cn=aaa))(sn=bbb)) }, grantsAndDenials { grantAdd } } "
             + " } } }";
         
-        parser.parse( spec );
+        item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -100,7 +107,8 @@
             + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
             + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -116,7 +124,8 @@
             + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
             + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -126,7 +135,8 @@
             + "itemOrUserFirst userFirst: { " + "userClasses { allUsers }, "
             + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -136,7 +146,8 @@
             + "itemOrUserFirst userFirst: { " + "userClasses { allUsers, name { \"ou=blah\" } }, "
             + "userPermissions { { protectedItems {entry}, " + "grantsAndDenials { grantAdd } } } } }";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -151,7 +162,8 @@
             + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
             + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -164,7 +176,8 @@
             + "userPermissions { { protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
             + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -223,7 +236,8 @@
             + "{ precedence 10, userClasses {allUsers  , userGroup { \"1.2=y,z=t\"  , \"a=b,c=d\" } "
             + " , subtree { { base \"ou=people\" } } }   , grantsAndDenials  {  denyCompare  , grantModify } } } }}";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -260,7 +274,8 @@
             + "userPermissions { { grantsAndDenials { grantBrowse }, protectedItems{ entry  , attributeType { cn  , ou }  , attributeValue {x=y,m=n,k=l} , "
             + "rangeOfValues (cn=ErsinEr) }  } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -294,7 +309,8 @@
             + "rangeOfValues (cn=ErsinEr) }  , grantsAndDenials { grantBrowse } } } }, "
             + " identificationTag \"id2\"   , authenticationLevel none, precedence 14 }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -348,7 +364,8 @@
             + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
             + "minimum  1, maximum   2 } } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -362,7 +379,8 @@
             + " attributeValue { ou=people  , cn=Ersin  }  , rangeOfValues (cn=ErsinEr) , "
             + "classes and : { item: xyz , or:{item:X,item:Y}   }}  " + " }}";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
@@ -384,7 +402,7 @@
     }
 
 
-    public void testRestrictedValueComponentsOrderDoesNotMatter() throws Exception
+    public void testMaxValueCountComponentsOrderDoesNotMatter() throws Exception
     {
         String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
             + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
@@ -393,11 +411,12 @@
             + "maxValueCount { { type 10.11.12, maxCount 10 }, { maxCount 20, type 11.12.13  } } "
             + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
-    public void testMaxValueCountComponentsOrderDoesNotMatter() throws Exception
+    public void testRestrictedValueComponentsOrderDoesNotMatter() throws Exception
     {
         String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
             + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
@@ -406,10 +425,24 @@
             + "restrictedBy { { type 10.11.12, valuesIn ou }, { valuesIn cn, type 11.12.13  } } "
             + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
 
 
+    public void testMaxImmSubComponentsOrderDoesNotMatter() throws Exception
+    {
+        String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
+            + "itemOrUserFirst userFirst:  { userClasses {  allUsers  , name { \"ou=people,cn=ersin\" }, "
+            + "subtree {{ base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\"," + "minimum  1, maximum   2 } } }  , "
+            + "userPermissions { { protectedItems{ entry  , maxImmSub 5 "
+            + " }  , grantsAndDenials { grantBrowse } } } }  }   ";
+        
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
+    }
+    
+    
     public void testSubtreeSpecificationComponentsOrderDoesNotMatter() throws Exception
     {
         String spec = "{ identificationTag \"id2\"   , precedence 14, authenticationLevel none  , "
@@ -418,7 +451,8 @@
             + "subtree {{ minimum 7, maximum 9, base \"ou=system\" }, { base \"ou=ORGANIZATIONUNIT\","
             + " maximum   2, minimum  1 } } }  }  }   ";
 
-        parser.parse( spec );
+        ACIItem item = parser.parse( spec );
+        checkItemToString( spec, item );
     }
     
     
@@ -454,7 +488,7 @@
         try
         {
             parser.parse( spec );
-            fail("Expected ParseException, invalid protected item 'attributeValue { must_be_a_name_value_pair }'");
+            fail("Expected ParseException, invalid protected item 'attributeValue { x=y,m=n,k=l,x }'");
         }
         catch ( ParseException e )
         {
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/add/AddRequestTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/add/AddRequestTest.java
index dd092ac..b406eb9 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/add/AddRequestTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/add/AddRequestTest.java
@@ -143,7 +143,7 @@
 
         assertTrue( expectedTypes.contains( attributeValue.getID().toLowerCase() ) );
 
-        NamingEnumeration values = attributeValue.getAll();
+        NamingEnumeration<?> values = attributeValue.getAll();
         HashSet vals = ( HashSet ) typesVals.get( attributeValue.getID().toLowerCase() );
 
         while ( values.hasMore() )
@@ -615,7 +615,7 @@
 
         assertEquals( "l", attributeValue.getID().toLowerCase() );
 
-        NamingEnumeration values = attributeValue.getAll();
+        NamingEnumeration<?> values = attributeValue.getAll();
 
         while ( values.hasMore() )
         {
@@ -707,7 +707,7 @@
 
         assertEquals( "l", attributeValue.getID().toLowerCase() );
 
-        NamingEnumeration values = attributeValue.getAll();
+        NamingEnumeration<?> values = attributeValue.getAll();
 
         while ( values.hasMore() )
         {
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/bind/BindRequestPerfTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/bind/BindRequestPerfTest.java
index 3c0a57e..882cb7d 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/bind/BindRequestPerfTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/bind/BindRequestPerfTest.java
@@ -83,7 +83,7 @@
         // Decode the BindRequest PDU
         try
         {
-            int nbLoops = 10;
+            int nbLoops = 1000;
             long t0 = System.currentTimeMillis();
             
             for ( int i = 0; i < nbLoops; i++ )
@@ -150,7 +150,7 @@
     public void testEncodeBindRequestPerf() throws Exception
     {
         LdapDN name = new LdapDN( "uid=akarasulu,dc=example,dc=com" );
-        int nbLoops = 10;
+        int nbLoops = 10000;
         long t0 = System.currentTimeMillis();
         ByteBuffer bb=null;
         
@@ -187,6 +187,5 @@
 
         long t1 = System.currentTimeMillis();
         System.out.println( "BindRequest testEncodeBindRequestPerf, " + nbLoops + " loops, Delta = " + (t1 - t0));
-        System.out.println( StringTools.dumpBytes( bb.array() ));
     }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestMatchingRuleAssertionTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestMatchingRuleAssertionTest.java
index b11f8dd..7ea27a0 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestMatchingRuleAssertionTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestMatchingRuleAssertionTest.java
@@ -376,7 +376,7 @@
         ExtensibleMatchFilter extensibleMatchFilter = ( ExtensibleMatchFilter ) sr.getFilter();
         assertNotNull( extensibleMatchFilter );
 
-        assertEquals( "test", extensibleMatchFilter.getMatchingRule().toString() );
+        assertEquals( "test", extensibleMatchFilter.getMatchingRule() );
         assertNull( extensibleMatchFilter.getType() );
         assertEquals( "", extensibleMatchFilter.getMatchValue().toString() );
         assertFalse( extensibleMatchFilter.isDnAttributes() );
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestSubstringTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestSubstringTest.java
index c35f9ce..96a5d75 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestSubstringTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestSubstringTest.java
@@ -153,8 +153,8 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
-        assertEquals( "t", substringFilter.getInitialSubstrings().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
+        assertEquals( "t", substringFilter.getInitialSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -269,8 +269,8 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
-        assertEquals( "t", substringFilter.getInitialSubstrings().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
+        assertEquals( "t", substringFilter.getInitialSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -392,7 +392,7 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
         assertEquals( null, substringFilter.getInitialSubstrings() );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 0 ) );
         assertEquals( null, substringFilter.getFinalSubstrings() );
@@ -509,10 +509,10 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
         assertEquals( null, substringFilter.getInitialSubstrings() );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 0 ) );
-        assertEquals( "t", substringFilter.getFinalSubstrings().toString() );
+        assertEquals( "t", substringFilter.getFinalSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -627,10 +627,10 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
-        assertEquals( "t", substringFilter.getInitialSubstrings().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
+        assertEquals( "t", substringFilter.getInitialSubstrings() );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 0 ) );
-        assertEquals( "t", substringFilter.getFinalSubstrings().toString() );
+        assertEquals( "t", substringFilter.getFinalSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -744,8 +744,8 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
-        assertEquals( "t", substringFilter.getInitialSubstrings().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
+        assertEquals( "t", substringFilter.getInitialSubstrings() );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 0 ) );
 
         // The attributes
@@ -855,11 +855,11 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
         assertEquals( null, substringFilter.getInitialSubstrings() );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 0 ) );
         assertEquals( "t", substringFilter.getAnySubstrings().get( 1 ) );
-        assertEquals( "t", substringFilter.getFinalSubstrings().toString() );
+        assertEquals( "t", substringFilter.getFinalSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -973,8 +973,8 @@
         SubstringFilter substringFilter = ( SubstringFilter ) sr.getFilter();
         assertNotNull( substringFilter );
 
-        assertEquals( "objectclass", substringFilter.getType().toString() );
-        assertEquals( "t", substringFilter.getInitialSubstrings().toString() );
+        assertEquals( "objectclass", substringFilter.getType() );
+        assertEquals( "t", substringFilter.getInitialSubstrings() );
         assertEquals( "*", substringFilter.getAnySubstrings().get( 0 ) );
 
         // The attributes
@@ -1212,7 +1212,7 @@
         assertEquals( "objectclass", substringFilter.getType() );
         assertEquals( null, substringFilter.getInitialSubstrings() );
         assertEquals( 0, substringFilter.getAnySubstrings().size() );
-        assertEquals( "Amos", substringFilter.getFinalSubstrings().toString() );
+        assertEquals( "Amos", substringFilter.getFinalSubstrings() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestTest.java
index d1df9e4..9e80bfd 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/SearchRequestTest.java
@@ -45,7 +45,7 @@
 import org.apache.directory.shared.ldap.codec.search.OrFilter;
 import org.apache.directory.shared.ldap.codec.search.PresentFilter;
 import org.apache.directory.shared.ldap.codec.search.SearchRequest;
-import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControl;
+import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlCodec;
 import org.apache.directory.shared.ldap.message.Message;
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
 import org.apache.directory.shared.ldap.message.ScopeEnum;
@@ -193,7 +193,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "top", assertion.getAssertionValue().toString() );
+        assertEquals( "top", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (...
         equalityMatch = ( AttributeValueAssertionFilter ) orFilters.get( 1 );
@@ -203,7 +203,7 @@
         assertNotNull( assertion );
 
         assertEquals( "ou", assertion.getAttributeDesc() );
-        assertEquals( "contacts", assertion.getAssertionValue().toString() );
+        assertEquals( "contacts", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (! ...
         NotFilter notFilter = ( NotFilter ) andFilters.get( 1 );
@@ -217,7 +217,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "ttt", assertion.getAssertionValue().toString() );
+        assertEquals( "ttt", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -357,7 +357,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "top", assertion.getAssertionValue().toString() );
+        assertEquals( "top", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass~=top) (ou<=contacts) ) (...
         AttributeValueAssertionFilter lessOrEqual = ( AttributeValueAssertionFilter ) orFilters.get( 1 );
@@ -367,7 +367,7 @@
         assertNotNull( assertion );
 
         assertEquals( "ou", assertion.getAttributeDesc() );
-        assertEquals( "contacts", assertion.getAssertionValue().toString() );
+        assertEquals( "contacts", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass~=top) (ou<=contacts) ) (! ...
         NotFilter notFilter = ( NotFilter ) andFilters.get( 1 );
@@ -381,7 +381,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "ttt", assertion.getAssertionValue().toString() );
+        assertEquals( "ttt", assertion.getAssertionValue().get() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -548,7 +548,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "ttt", assertion.getAssertionValue().toString() );
+        assertEquals( "ttt", assertion.getAssertionValue().get() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -942,31 +942,31 @@
             .getAssertion();
 
         assertEquals( "uid", assertion.getAttributeDesc() );
-        assertEquals( "akarasulu", assertion.getAssertionValue().toString() );
+        assertEquals( "akarasulu", assertion.getAssertionValue().get() );
 
         // cn=aok
         assertion = ( ( AttributeValueAssertionFilter ) orFilter.getOrFilter().get( 1 ) ).getAssertion();
 
         assertEquals( "cn", assertion.getAttributeDesc() );
-        assertEquals( "aok", assertion.getAssertionValue().toString() );
+        assertEquals( "aok", assertion.getAssertionValue().get() );
 
         // ou = Human Resources
         assertion = ( ( AttributeValueAssertionFilter ) orFilter.getOrFilter().get( 2 ) ).getAssertion();
 
         assertEquals( "ou", assertion.getAttributeDesc() );
-        assertEquals( "Human Resources", assertion.getAssertionValue().toString() );
+        assertEquals( "Human Resources", assertion.getAssertionValue().get() );
 
         // l=Santa Clara
         assertion = ( ( AttributeValueAssertionFilter ) orFilter.getOrFilter().get( 3 ) ).getAssertion();
 
         assertEquals( "l", assertion.getAttributeDesc() );
-        assertEquals( "Santa Clara", assertion.getAssertionValue().toString() );
+        assertEquals( "Santa Clara", assertion.getAssertionValue().get() );
 
         // cn=abok
         assertion = ( ( AttributeValueAssertionFilter ) orFilter.getOrFilter().get( 4 ) ).getAssertion();
 
         assertEquals( "cn", assertion.getAttributeDesc() );
-        assertEquals( "abok", assertion.getAssertionValue().toString() );
+        assertEquals( "abok", assertion.getAssertionValue().get() );
 
         // The attributes
         Attributes attributes = sr.getAttributes();
@@ -1223,7 +1223,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "top", assertion.getAssertionValue().toString() );
+        assertEquals( "top", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (...
         equalityMatch = ( AttributeValueAssertionFilter ) orFilters.get( 1 );
@@ -1233,7 +1233,7 @@
         assertNotNull( assertion );
 
         assertEquals( "2.5.4.11", assertion.getAttributeDesc() );
-        assertEquals( "contacts", assertion.getAssertionValue().toString() );
+        assertEquals( "contacts", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (! ...
         NotFilter notFilter = ( NotFilter ) andFilters.get( 1 );
@@ -1247,7 +1247,7 @@
         assertNotNull( assertion );
 
         assertEquals( "organizationalUnitName", assertion.getAttributeDesc() );
-        assertEquals( "ttt", assertion.getAssertionValue().toString() );
+        assertEquals( "ttt", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -1322,7 +1322,7 @@
         Control subEntryControl = message.getControls( 0 );
         assertEquals( subEntryControlOID, subEntryControl.getControlType() );
         assertTrue( subEntryControl.getCriticality() );
-        assertTrue( ( ( SubEntryControl ) subEntryControl.getControlValue() ).isVisible() );
+        assertTrue( ( ( SubEntryControlCodec ) subEntryControl.getControlValue() ).isVisible() );
 
         SearchRequest sr = message.getSearchRequest();
         assertEquals( "dc=my-domain,dc=com", sr.getBaseObject().toString() );
@@ -1530,7 +1530,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "top", assertion.getAssertionValue().toString() );
+        assertEquals( "top", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (...
         equalityMatch = ( AttributeValueAssertionFilter ) orFilters.get( 1 );
@@ -1540,7 +1540,7 @@
         assertNotNull( assertion );
 
         assertEquals( "ou", assertion.getAttributeDesc() );
-        assertEquals( "contacts", assertion.getAssertionValue().toString() );
+        assertEquals( "contacts", assertion.getAssertionValue().get() );
 
         // (& (| (objectclass=top) (ou=contacts) ) (! ...
         NotFilter notFilter = ( NotFilter ) andFilters.get( 1 );
@@ -1554,7 +1554,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectclass", assertion.getAttributeDesc() );
-        assertEquals( "ttt", assertion.getAssertionValue().toString() );
+        assertEquals( "ttt", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -2506,7 +2506,7 @@
         AttributeValueAssertion assertion = greaterThanFilter.getAssertion();
 
         assertEquals( "test", assertion.getAttributeDesc() );
-        assertEquals( "", assertion.getAssertionValue().toString() );
+        assertEquals( "", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -2588,7 +2588,7 @@
         AttributeValueAssertion assertion = greaterThanFilter.getAssertion();
 
         assertEquals( "test", assertion.getAttributeDesc() );
-        assertEquals( "", assertion.getAssertionValue().toString() );
+        assertEquals( "", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -2686,7 +2686,7 @@
         AttributeValueAssertion assertion = greaterThanFilter.getAssertion();
 
         assertEquals( "test", assertion.getAttributeDesc() );
-        assertEquals( "", assertion.getAssertionValue().toString() );
+        assertEquals( "", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
 
@@ -2946,7 +2946,7 @@
         assertNotNull( assertion );
 
         assertEquals( "pgpdisabled", assertion.getAttributeDesc() );
-        assertEquals( "0", assertion.getAssertionValue().toString() );
+        assertEquals( "0", assertion.getAssertionValue().get() );
 
         // Check the encoding
         // We won't check the whole PDU, as it may differs because
@@ -3043,7 +3043,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3151,7 +3151,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3264,7 +3264,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(a=b)(c=d))
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters.get( 1 );
@@ -3274,7 +3274,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3388,7 +3388,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3508,7 +3508,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(&(a=b)(c=d)
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters2.get( 1 );
@@ -3518,7 +3518,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3637,7 +3637,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(&(a=b))(c=d))
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters.get( 1 );
@@ -3647,7 +3647,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3770,7 +3770,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(&(a=b)(c=d)...
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters2.get( 1 );
@@ -3780,7 +3780,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
         
         // (&(&(a=b)(c=d))(e=f))
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters.get( 1 );
@@ -3790,7 +3790,7 @@
         assertNotNull( assertion );
 
         assertEquals( "e", assertion.getAttributeDesc() );
-        assertEquals( "f", assertion.getAssertionValue().toString() );
+        assertEquals( "f", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -3910,7 +3910,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(&(a=b))(&...
         andFilter2 = ( AndFilter ) andFilters.get( 1 );
@@ -3927,7 +3927,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -4051,7 +4051,7 @@
         assertNotNull( assertion );
 
         assertEquals( "a", assertion.getAttributeDesc() );
-        assertEquals( "b", assertion.getAssertionValue().toString() );
+        assertEquals( "b", assertion.getAssertionValue().get() );
 
         // (&(&(a=b)(c=d))...
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters2.get( 1 );
@@ -4061,7 +4061,7 @@
         assertNotNull( assertion );
 
         assertEquals( "c", assertion.getAttributeDesc() );
-        assertEquals( "d", assertion.getAssertionValue().toString() );
+        assertEquals( "d", assertion.getAssertionValue().get() );
         
         // (&(&(a=b)(c=d))(&...
         andFilter2 = ( AndFilter ) andFilters.get( 1 );
@@ -4078,7 +4078,7 @@
         assertNotNull( assertion );
 
         assertEquals( "e", assertion.getAttributeDesc() );
-        assertEquals( "f", assertion.getAssertionValue().toString() );
+        assertEquals( "f", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -4215,7 +4215,7 @@
         assertNotNull( assertion );
 
         assertEquals( "e", assertion.getAttributeDesc() );
-        assertEquals( "f", assertion.getAssertionValue().toString() );
+        assertEquals( "f", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -4377,7 +4377,7 @@
         assertNotNull( assertion );
 
         assertEquals( "uid", assertion.getAttributeDesc() );
-        assertEquals( "buster ", assertion.getAssertionValue().toString() );
+        assertEquals( "buster ", assertion.getAssertionValue().get() );
 
         // (&(uid=buster)(sbAttribute=Buy))
         equalityMatch = ( AttributeValueAssertionFilter ) andFilters.get( 1 );
@@ -4387,7 +4387,7 @@
         assertNotNull( assertion );
 
         assertEquals( "sbAttribute", assertion.getAttributeDesc() );
-        assertEquals( "Buy ", assertion.getAssertionValue().toString() );
+        assertEquals( "Buy ", assertion.getAssertionValue().get() );
 
         Attributes attributes = sr.getAttributes();
         assertEquals( 0, attributes.size() );
@@ -4486,7 +4486,7 @@
         assertNotNull( assertion );
 
         assertEquals( "objectClass", assertion.getAttributeDesc() );
-        assertEquals( "person", assertion.getAssertionValue().toString() );
+        assertEquals( "person", assertion.getAssertionValue().get() );
 
         // (&(a=b)(|
         OrFilter orFilter = ( OrFilter ) andFilters.get( 1 );
@@ -4512,6 +4512,6 @@
         assertNotNull( assertion );
 
         assertEquals( "sn", assertion.getAttributeDesc() );
-        assertEquals( "Jagger", assertion.getAssertionValue().toString() );
+        assertEquals( "Jagger", assertion.getAssertionValue().get() );
     }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlTest.java
index bdebf40..a516bc8 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/EntryChangeControlTest.java
@@ -25,7 +25,7 @@
 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
 import org.apache.directory.shared.asn1.codec.DecoderException;
 import org.apache.directory.shared.ldap.codec.search.controls.ChangeType;
-import org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControl;
+import org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlCodec;
 import org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlContainer;
 import org.apache.directory.shared.ldap.codec.search.controls.EntryChangeControlDecoder;
 import org.apache.directory.shared.ldap.name.LdapDN;
@@ -71,7 +71,7 @@
             Assert.fail( de.getMessage() );
         }
 
-        EntryChangeControl entryChange = container.getEntryChangeControl();
+        EntryChangeControlCodec entryChange = container.getEntryChangeControl();
         assertEquals( ChangeType.MODDN, entryChange.getChangeType() );
         assertEquals( "a=b", entryChange.getPreviousDn().toString() );
         assertEquals( 16, entryChange.getChangeNumber() );
@@ -107,7 +107,7 @@
             Assert.fail( de.getMessage() );
         }
 
-        EntryChangeControl entryChange = container.getEntryChangeControl();
+        EntryChangeControlCodec entryChange = container.getEntryChangeControl();
         assertEquals( ChangeType.ADD, entryChange.getChangeType() );
         assertNull( entryChange.getPreviousDn() );
         assertEquals( 16, entryChange.getChangeNumber() );
@@ -181,10 +181,10 @@
             Assert.fail( de.getMessage() );
         }
 
-        EntryChangeControl entryChange = container.getEntryChangeControl();
+        EntryChangeControlCodec entryChange = container.getEntryChangeControl();
         assertEquals( ChangeType.ADD, entryChange.getChangeType() );
         assertNull( entryChange.getPreviousDn() );
-        assertEquals( EntryChangeControl.UNDEFINED_CHANGE_NUMBER, entryChange.getChangeNumber() );
+        assertEquals( EntryChangeControlCodec.UNDEFINED_CHANGE_NUMBER, entryChange.getChangeNumber() );
     }
 
 
@@ -242,7 +242,7 @@
         String expected = StringTools.dumpBytes( bb.array() );
         bb.flip();
 
-        EntryChangeControl entry = new EntryChangeControl();
+        EntryChangeControlCodec entry = new EntryChangeControlCodec();
         entry.setChangeType( ChangeType.MODDN );
         entry.setChangeNumber( 16 );
         entry.setPreviousDn( new LdapDN( "a=b" ) );
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlTest.java
index 63146b7..ad2f738 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/PSearchControlTest.java
@@ -24,7 +24,7 @@
 
 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.ldap.codec.search.controls.PSearchControl;
+import org.apache.directory.shared.ldap.codec.search.controls.PSearchControlCodec;
 import org.apache.directory.shared.ldap.codec.search.controls.PSearchControlContainer;
 import org.apache.directory.shared.ldap.codec.search.controls.PSearchControlDecoder;
 import org.apache.directory.shared.ldap.util.StringTools;
@@ -57,7 +57,7 @@
         String expected = StringTools.dumpBytes( bb.array() );
         bb.flip();
 
-        PSearchControl ctrl = new PSearchControl();
+        PSearchControlCodec ctrl = new PSearchControlCodec();
         ctrl.setChangesOnly( false );
         ctrl.setReturnECs( false );
         ctrl.setChangeTypes( 1 );
@@ -92,10 +92,10 @@
             Assert.fail( de.getMessage() );
         }
 
-        PSearchControl control = container.getPSearchControl();
+        PSearchControlCodec control = container.getPSearchControl();
         int changeTypes = control.getChangeTypes();
-        assertEquals( PSearchControl.CHANGE_TYPE_ADD, changeTypes & PSearchControl.CHANGE_TYPE_ADD );
-        assertEquals( PSearchControl.CHANGE_TYPE_MODDN, changeTypes & PSearchControl.CHANGE_TYPE_MODDN );
+        assertEquals( PSearchControlCodec.CHANGE_TYPE_ADD, changeTypes & PSearchControlCodec.CHANGE_TYPE_ADD );
+        assertEquals( PSearchControlCodec.CHANGE_TYPE_MODDN, changeTypes & PSearchControlCodec.CHANGE_TYPE_MODDN );
         assertEquals( false, control.isChangesOnly() );
         assertEquals( false, control.isReturnECs() );
     }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlTest.java
index 982fa7b..99a527f 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/search/controls/SubEntryControlTest.java
@@ -25,7 +25,7 @@
 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
 import org.apache.directory.shared.asn1.ber.IAsn1Container;
 import org.apache.directory.shared.asn1.codec.DecoderException;
-import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControl;
+import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlCodec;
 import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlContainer;
 import org.apache.directory.shared.ldap.codec.search.controls.SubEntryControlDecoder;
 
@@ -63,7 +63,7 @@
             Assert.fail( de.getMessage() );
         }
 
-        SubEntryControl control = container.getSubEntryControl();
+        SubEntryControlCodec control = container.getSubEntryControl();
         assertTrue( control.isVisible() );
     }
 
@@ -91,7 +91,7 @@
             Assert.fail( de.getMessage() );
         }
 
-        SubEntryControl control = container.getSubEntryControl();
+        SubEntryControlCodec control = container.getSubEntryControl();
         assertFalse( control.isVisible() );
     }
 
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/util/LdapUrlTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/util/LdapUrlTest.java
index c2e4f47..571414d 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/codec/util/LdapUrlTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/codec/util/LdapUrlTest.java
@@ -20,11 +20,18 @@
 package org.apache.directory.shared.ldap.codec.util;
 
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.InvalidNameException;
+import javax.naming.directory.SearchControls;
+
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.ldap.codec.util.LdapURL;
 import org.apache.directory.shared.ldap.codec.util.LdapURLEncodingException;
+import org.apache.directory.shared.ldap.name.LdapDN;
 
 
 /**
@@ -600,4 +607,184 @@
         Assert.assertEquals( "ldap:///??sub??!bindname=cn=Manager%2co=Foo", new LdapURL(
             "ldap:///??sub??!bindname=cn=Manager%2co=Foo" ).toString() );
     }
+
+
+    /**
+     * test an empty ldaps:// LdapURL
+     */
+    public void testLdapDNEmptyLdaps() throws LdapURLEncodingException
+    {
+        Assert.assertEquals( "ldaps:///", new LdapURL( "ldaps:///" ).toString() );
+    }
+
+
+    /**
+     * test an simple ldaps:// LdapURL
+     */
+    public void testLdapDNSimpleLdaps() throws LdapURLEncodingException
+    {
+        Assert.assertEquals( "ldaps://directory.apache.org:80/", new LdapURL( "ldaps://directory.apache.org:80/" )
+            .toString() );
+    }
+
+
+    /**
+     * test the setScheme() method
+     */
+    public void testLdapDNSetScheme() throws LdapURLEncodingException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertEquals( "ldap://", url.getScheme() );
+
+        url.setScheme( "invalid" );
+        Assert.assertEquals( "ldap://", url.getScheme() );
+
+        url.setScheme( "ldap://" );
+        Assert.assertEquals( "ldap://", url.getScheme() );
+
+        url.setScheme( "ldaps://" );
+        Assert.assertEquals( "ldaps://", url.getScheme() );
+
+        url.setScheme( null );
+        Assert.assertEquals( "ldap://", url.getScheme() );
+    }
+
+
+    /**
+     * test the setHost() method
+     */
+    public void testLdapDNSetHost() throws LdapURLEncodingException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertNull( url.getHost() );
+
+        url.setHost( "ldap.apache.org" );
+        Assert.assertEquals( "ldap.apache.org", url.getHost() );
+        Assert.assertEquals( "ldap://ldap.apache.org/", url.toString() );
+
+        url.setHost( null );
+        Assert.assertNull( url.getHost() );
+        Assert.assertEquals( "ldap:///", url.toString() );
+    }
+
+
+    /**
+     * test the setPort() method
+     */
+    public void testLdapDNSetPort() throws LdapURLEncodingException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertEquals( -1, url.getPort() );
+
+        url.setPort( 389 );
+        Assert.assertEquals( 389, url.getPort() );
+        Assert.assertEquals( "ldap://:389/", url.toString() );
+
+        url.setPort( 0 );
+        Assert.assertEquals( -1, url.getPort() );
+        Assert.assertEquals( "ldap:///", url.toString() );
+
+        url.setPort( 65536 );
+        Assert.assertEquals( -1, url.getPort() );
+        Assert.assertEquals( "ldap:///", url.toString() );
+    }
+
+
+    /**
+     * test the setDn() method
+     */
+    public void testLdapDNSetDn() throws LdapURLEncodingException, InvalidNameException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertNull( url.getDn() );
+
+        LdapDN dn = new LdapDN( "dc=example,dc=com" );
+        url.setDn( dn );
+        Assert.assertEquals( dn, url.getDn() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com", url.toString() );
+
+        url.setDn( null );
+        Assert.assertNull( url.getDn() );
+        Assert.assertEquals( "ldap:///", url.toString() );
+    }
+
+
+    /**
+     * test the setAttributes() method
+     */
+    public void testLdapDNSetAttributes() throws LdapURLEncodingException, InvalidNameException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertNotNull( url.getAttributes() );
+        Assert.assertTrue( url.getAttributes().isEmpty() );
+
+        List<String> attributes = new ArrayList<String>();
+        url.setDn( new LdapDN( "dc=example,dc=com" ) );
+
+        url.setAttributes( null );
+        Assert.assertNotNull( url.getAttributes() );
+        Assert.assertTrue( url.getAttributes().isEmpty() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com", url.toString() );
+
+        attributes.add( "cn" );
+        url.setAttributes( attributes );
+        Assert.assertNotNull( url.getAttributes() );
+        Assert.assertEquals( 1, url.getAttributes().size() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com?cn", url.toString() );
+
+        attributes.add( "userPassword;binary" );
+        url.setAttributes( attributes );
+        Assert.assertNotNull( url.getAttributes() );
+        Assert.assertEquals( 2, url.getAttributes().size() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com?cn,userPassword;binary", url.toString() );
+    }
+
+
+    /**
+     * test the setScope() method
+     */
+    public void testLdapDNSetScope() throws LdapURLEncodingException, InvalidNameException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertEquals( SearchControls.OBJECT_SCOPE, url.getScope() );
+
+        url.setDn( new LdapDN( "dc=example,dc=com" ) );
+
+        url.setScope( SearchControls.ONELEVEL_SCOPE );
+        Assert.assertEquals( SearchControls.ONELEVEL_SCOPE, url.getScope() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com??one", url.toString() );
+
+        url.setScope( SearchControls.SUBTREE_SCOPE );
+        Assert.assertEquals( SearchControls.SUBTREE_SCOPE, url.getScope() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com??sub", url.toString() );
+
+        url.setScope( -1 );
+        Assert.assertEquals( SearchControls.OBJECT_SCOPE, url.getScope() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com", url.toString() );
+    }
+
+
+    /**
+     * test the setFilter() method
+     */
+    public void testLdapDNSetFilter() throws LdapURLEncodingException, InvalidNameException
+    {
+        LdapURL url = new LdapURL();
+        Assert.assertNull( url.getFilter() );
+
+        url.setDn( new LdapDN( "dc=example,dc=com" ) );
+
+        url.setFilter( "(objectClass=person)" );
+        Assert.assertEquals( "(objectClass=person)", url.getFilter() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com???(objectClass=person)", url.toString() );
+
+        url.setFilter( "(cn=Babs Jensen)" );
+        Assert.assertEquals( "(cn=Babs Jensen)", url.getFilter() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com???(cn=Babs%20Jensen)", url.toString() );
+
+        url.setFilter( null );
+        Assert.assertNull( url.getFilter() );
+        Assert.assertEquals( "ldap:///dc=example,dc=com", url.toString() );
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValueTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValueTest.java
new file mode 100644
index 0000000..c7878b3
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValueTest.java
@@ -0,0 +1,634 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Arrays;
+
+import javax.naming.NamingException;
+import javax.naming.directory.InvalidAttributeValueException;
+
+import org.apache.directory.shared.ldap.schema.Normalizer;
+import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.Test;
+
+/**
+ * 
+ * Test the ClientBinaryValue class
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ClientBinaryValueTest
+{
+    private static final byte[] BYTES1 = new byte[]{0x01, 0x02, 0x03, 0x04};
+    private static final byte[] BYTES2 = new byte[]{(byte)0x81, (byte)0x82, (byte)0x83, (byte)0x84};
+    private static final byte[] INVALID_BYTES = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05};
+    private static final byte[] BYTES_MOD = new byte[]{0x11, 0x02, 0x03, 0x04};
+    
+    private static final Normalizer BINARY_NORMALIZER = new Normalizer()
+    {
+        private static final long serialVersionUID = 1L;
+        
+        public Object normalize( Object value ) throws NamingException
+        {
+            if ( value instanceof byte[] )
+            {
+                byte[] val = (byte[])value;
+                // each byte will be changed to be > 0, and spaces will be trimmed
+                byte[] newVal = new byte[ val.length ];
+                int i = 0;
+                
+                for ( byte b:val )
+                {
+                    newVal[i++] = (byte)(b & 0x007F); 
+                }
+                
+                return StringTools.trim( newVal );
+            }
+
+            throw new IllegalStateException( "expected byte[] to normalize" );
+        }
+    };
+    
+    private static final SyntaxChecker BINARY_CHECKER = new SyntaxChecker()
+    {
+        public String getSyntaxOid()
+        {
+            return "1.1.1";
+        }
+        public boolean isValidSyntax( Object value )
+        {
+            if ( value == null )
+            {
+                return true;
+            }
+            
+            return ((byte[])value).length < 5 ;
+        }
+
+        public void assertSyntax( Object value ) throws NamingException
+        {
+            if ( ! isValidSyntax( value ) )
+            {
+                throw new InvalidAttributeValueException();
+            }
+        }
+    };
+
+    @Test
+    public void testHashCode()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        assertEquals( 0, cbv.hashCode() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        int h = Arrays.hashCode( StringTools.EMPTY_BYTES );
+        assertEquals( h, cbv.hashCode() );
+        
+        h = Arrays.hashCode( BYTES1 );
+        cbv.set( BYTES1 );
+        assertEquals( h, cbv.hashCode() );
+    }
+
+
+    @Test
+    public void testClear() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue( BYTES2 );
+        cbv.normalize( BINARY_NORMALIZER );
+        cbv.isValid( BINARY_CHECKER );
+        
+        cbv.clear();
+        assertTrue( cbv.isNull() );
+        assertFalse( cbv.isNormalized() );
+        assertFalse( cbv.isValid() );
+        assertNull( cbv.get() );
+        assertNull( cbv.getCopy() );
+        assertNull( cbv.getReference() );
+        assertNull( cbv.getNormalizedValue() );
+        assertNull( cbv.getNormalizedValueCopy() );
+        assertNull( cbv.getNormalizedValueReference() );
+    }
+
+
+    @Test
+    public void testClientBinaryValueNull() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue( null );
+        
+        assertEquals( null, cbv.get() );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertTrue( cbv.isNull() );
+        assertNull( cbv.getNormalizedValue() );
+    }
+
+
+    @Test
+    public void testClientBinaryValueEmpty() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue( StringTools.EMPTY_BYTES );
+        
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.get() ) );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getCopy() ) );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getReference() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+        assertNotNull( cbv.getNormalizedValue() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getNormalizedValue() ) );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getNormalizedValueReference() ) );
+    }
+
+
+    @Test
+    public void testClientBinaryValue() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue( BYTES1 );
+        
+        assertTrue( Arrays.equals( BYTES1, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getCopy() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getReference() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+        assertNotNull( cbv.getNormalizedValue() );
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+    }
+
+
+    @Test
+    public void testSetByteArray() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        cbv.set( BYTES1 );
+        
+        assertTrue( Arrays.equals( BYTES1, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getCopy() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getReference() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+        assertNotNull( cbv.getNormalizedValue() );
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+    }
+
+
+    @Test
+    public void testGetNormalizedValueCopy()  throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue( BYTES2 );
+        
+        assertTrue( Arrays.equals( BYTES2, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES2, cbv.getCopy() ) );
+        assertTrue( Arrays.equals( BYTES2, cbv.getReference() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+        assertNotNull( cbv.getNormalizedValue() );
+        assertTrue( Arrays.equals( BYTES2, cbv.getNormalizedValue() ) );
+        
+        cbv.normalize( BINARY_NORMALIZER );
+        byte[] copy = cbv.getNormalizedValueCopy();
+        assertTrue( Arrays.equals( BYTES1, copy ) );
+        cbv.getNormalizedValueReference()[0]=0x11;
+        assertTrue( Arrays.equals( BYTES1, copy ) );
+    }
+
+
+    @Test
+    public void testNormalizeNormalizer() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        cbv.normalize( BINARY_NORMALIZER );
+        assertTrue( cbv.isNormalized() );
+        assertEquals( null, cbv.getNormalizedValue() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        cbv.normalize( BINARY_NORMALIZER );
+        assertTrue( cbv.isNormalized() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.get() ) );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getNormalizedValue() ) );
+        
+        cbv.set( BYTES1 );
+        cbv.normalize( BINARY_NORMALIZER );
+        assertTrue( cbv.isNormalized() );
+        assertTrue( Arrays.equals( BYTES1, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+
+        cbv.set( BYTES2 );
+        cbv.normalize( BINARY_NORMALIZER );
+        assertTrue( cbv.isNormalized() );
+        assertTrue( Arrays.equals( BYTES2, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+    }
+
+
+    @Test
+    public void testCompareToValueOfbyte() throws NamingException
+    {
+        ClientBinaryValue cbv1 = new ClientBinaryValue();
+        ClientBinaryValue cbv2 = new ClientBinaryValue();
+        
+        assertEquals( 0, cbv1.compareTo( cbv2 ) );
+        
+        cbv1.set(  BYTES1 );
+        assertEquals( 1, cbv1.compareTo( cbv2 ) );
+
+        cbv2.set(  BYTES2 );
+        assertEquals( 1, cbv1.compareTo( cbv2 ) );
+        
+        cbv2.normalize( BINARY_NORMALIZER );
+        assertEquals( 0, cbv1.compareTo( cbv2 ) );
+        
+        cbv1.set( BYTES2 );
+        assertEquals( -1, cbv1.compareTo( cbv2 ) );
+    }
+
+
+    @Test
+    public void testEquals() throws NamingException
+    {
+        ClientBinaryValue cbv1 = new ClientBinaryValue();
+        ClientBinaryValue cbv2 = new ClientBinaryValue();
+        
+        assertEquals( cbv1, cbv2 );
+        
+        cbv1.set(  BYTES1 );
+        assertNotSame( cbv1, cbv2 );
+
+        cbv2.set(  BYTES2 );
+        assertNotSame( cbv1, cbv2 );
+        
+        cbv2.normalize( BINARY_NORMALIZER );
+        assertEquals( cbv1, cbv2 );
+        
+        cbv1.set( BYTES2 );
+        assertNotSame( cbv1, cbv2 );
+    }
+
+
+    @Test
+    public void testClone()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        ClientBinaryValue copy = cbv.clone();
+        
+        assertEquals( cbv, copy );
+        
+        cbv.set( BYTES1 );
+        assertNotSame( cbv, copy );
+        
+        copy = cbv.clone();
+        assertEquals( cbv, copy );
+
+        cbv.getReference()[0] = 0x11;
+        
+        assertTrue( Arrays.equals( BYTES_MOD, cbv.get() ) );
+        assertTrue( Arrays.equals( BYTES1, copy.get() ) );
+    }
+
+
+    @Test
+    public void testGetCopy()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertNull( cbv.getCopy() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertNotNull( cbv.getCopy() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getCopy() ) );
+        
+        cbv.set( BYTES1 );
+        byte[] copy = cbv.getCopy();
+        
+        assertTrue( Arrays.equals( BYTES1, copy ) );
+
+        cbv.getReference()[0] = 0x11;
+        assertTrue( Arrays.equals( BYTES1, copy ) );
+        assertTrue( Arrays.equals( BYTES_MOD, cbv.get() ) );
+    }
+
+
+    @Test
+    public void testCompareTo() throws NamingException
+    {
+        ClientBinaryValue cbv1 = new ClientBinaryValue();
+        ClientBinaryValue cbv2 = new ClientBinaryValue();
+        
+        assertEquals( 0, cbv1.compareTo( cbv2 ) );
+        
+        cbv1.set( BYTES1 );
+        assertEquals( 1, cbv1.compareTo( cbv2 ) );
+        assertEquals( -1, cbv2.compareTo( cbv1 ) );
+        
+        cbv2.set( BYTES1 );
+        assertEquals( 0, cbv1.compareTo( cbv2 ) );
+
+        // Now check that the equals method works on normalized values.
+        cbv1.set( BYTES2 );
+        cbv2.set( BYTES1 );
+        cbv1.normalize( BINARY_NORMALIZER );
+        assertEquals( 0, cbv1.compareTo( cbv2 ) );
+        
+        cbv1.set( BYTES1 );
+        cbv2.set( BYTES2 );
+        assertEquals( 1, cbv1.compareTo( cbv2 ) );
+
+        cbv1.set( BYTES2 );
+        cbv2.set( BYTES1 );
+        assertEquals( -1, cbv1.compareTo( cbv2 ) );
+    }
+
+
+    @Test
+    public void testToString()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertEquals( "null", cbv.toString() );
+
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertEquals( "''", cbv.toString() );
+
+        cbv.set( BYTES1 );
+        assertEquals( "'0x01 0x02 0x03 0x04 '", cbv.toString() );
+        
+        cbv.clear();
+        assertEquals( "null", cbv.toString() );
+    }
+
+
+    @Test
+    public void testGetReference()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertNull( cbv.getReference() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertNotNull( cbv.getReference() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getReference() ) );
+        
+        cbv.set( BYTES1 );
+        byte[] reference = cbv.getReference();
+        
+        assertTrue( Arrays.equals( BYTES1, reference ) );
+
+        cbv.getReference()[0] = 0x11;
+        assertTrue( Arrays.equals( BYTES_MOD, reference ) );
+        assertTrue( Arrays.equals( BYTES_MOD, cbv.get() ) );
+    }
+
+
+    @Test
+    public void testGet()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertNull( cbv.get() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertNotNull( cbv.get() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.get() ) );
+        
+        cbv.set( BYTES1 );
+        byte[] get = cbv.get();
+        
+        assertTrue( Arrays.equals( BYTES1, get ) );
+
+        cbv.getReference()[0] = 0x11;
+        assertTrue( Arrays.equals( BYTES1, get ) );
+        assertTrue( Arrays.equals( BYTES_MOD, cbv.get() ) );
+    }
+
+
+    @Test
+    public void testGetNormalizedValue() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertFalse( cbv.isNormalized() );
+
+        cbv.normalize( BINARY_NORMALIZER );
+        byte[] value = cbv.getNormalizedValue();
+        assertNull( value );
+        assertTrue( cbv.isNormalized() );
+        
+        cbv.set( BYTES2 );
+        cbv.normalize( BINARY_NORMALIZER );
+        value = cbv.getNormalizedValue();
+        assertTrue( Arrays.equals( BYTES1, value ) );
+        cbv.getNormalizedValueReference()[0]=0x11;
+        assertFalse( Arrays.equals( BYTES_MOD, value ) );
+    }
+
+
+    @Test
+    public void testGetNormalizedValueReference() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertFalse( cbv.isNormalized() );
+
+        cbv.normalize( BINARY_NORMALIZER );
+        byte[] value = cbv.getNormalizedValueReference();
+        assertNull( value );
+        assertTrue( cbv.isNormalized() );
+        
+        cbv.set( BYTES2 );
+        cbv.normalize( BINARY_NORMALIZER );
+        value = cbv.getNormalizedValueReference();
+        assertTrue( Arrays.equals( BYTES1, value ) );
+        cbv.getNormalizedValueReference()[0]=0x11;
+        assertTrue( Arrays.equals( BYTES_MOD, value ) );
+    }
+
+
+    @Test
+    public void testIsNull()
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertTrue( cbv.isNull() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertFalse( cbv.isNull() );
+        
+        cbv.set( BYTES1 );
+        assertFalse( cbv.isNull() );
+        
+        cbv.clear();
+        assertTrue( cbv.isNull() );
+    }
+
+
+    @Test
+    public void testIsValid() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertFalse( cbv.isValid() );
+        cbv.isValid( BINARY_CHECKER );
+        assertTrue( cbv.isValid() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertFalse( cbv.isValid() );
+        cbv.isValid( BINARY_CHECKER );
+        assertTrue( cbv.isValid() );
+        
+        cbv.set( BYTES1 );
+        assertFalse( cbv.isNull() );
+        cbv.isValid( BINARY_CHECKER );
+        assertTrue( cbv.isValid() );
+
+        cbv.set( INVALID_BYTES );
+        assertFalse( cbv.isNull() );
+        cbv.isValid( BINARY_CHECKER );
+        assertFalse( cbv.isValid() );
+    }
+
+
+    @Test
+    public void testIsValidSyntaxChecker() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertTrue( cbv.isValid( BINARY_CHECKER ) ) ;
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        
+        cbv.set( BYTES1 );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+
+        cbv.set( INVALID_BYTES );
+        assertFalse( cbv.isValid( BINARY_CHECKER ) );
+    }
+
+
+    @Test
+    public void testNormalize() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        cbv.normalize();
+        assertTrue( cbv.isNormalized() );
+        assertEquals( null, cbv.getNormalizedValue() );
+        
+        cbv.set( StringTools.EMPTY_BYTES );
+        cbv.normalize();
+        assertTrue( cbv.isNormalized() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.getNormalizedValue() ) );
+        
+        cbv.set( BYTES2 );
+        cbv.normalize();
+        assertTrue( cbv.isNormalized() );
+        assertTrue( Arrays.equals( BYTES2, cbv.getNormalizedValue() ) );
+    }
+
+
+    @Test
+    public void testSet() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        cbv.set( null );
+        assertNull( cbv.get() );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertTrue( cbv.isNull() );
+
+        cbv.set( StringTools.EMPTY_BYTES );
+        assertNotNull( cbv.get() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, cbv.get() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+
+        cbv.set( BYTES1 );
+        assertNotNull( cbv.get() );
+        assertTrue( Arrays.equals( BYTES1, cbv.get() ) );
+        assertFalse( cbv.isNormalized() );
+        assertTrue( cbv.isValid( BINARY_CHECKER ) );
+        assertFalse( cbv.isNull() );
+    }
+
+
+    @Test
+    public void testIsNormalized() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertFalse( cbv.isNormalized() );
+        
+        cbv.set( BYTES2 );
+        assertFalse( cbv.isNormalized() );
+        
+        cbv.normalize( BINARY_NORMALIZER );
+        
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+        assertTrue( cbv.isNormalized() );
+        
+        cbv.set( BYTES2 );
+        assertTrue( cbv.isNormalized() );
+
+        cbv.set( BYTES_MOD );
+        assertFalse( cbv.isNormalized() );
+    }
+
+
+    @Test
+    public void testSetNormalized() throws NamingException
+    {
+        ClientBinaryValue cbv = new ClientBinaryValue();
+        
+        assertFalse( cbv.isNormalized() );
+        
+        cbv.setNormalized( true );
+        assertTrue( cbv.isNormalized() );
+        
+        cbv.set(  BYTES2 );
+        assertFalse( cbv.isNormalized() );
+        
+        cbv.normalize( BINARY_NORMALIZER );
+        
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+        assertTrue( cbv.isNormalized() );
+        
+        cbv.setNormalized( false );
+        assertTrue( Arrays.equals( BYTES1, cbv.getNormalizedValue() ) );
+        assertFalse( cbv.isNormalized() );
+
+        cbv.normalize( BINARY_NORMALIZER );
+        cbv.clear();
+        assertFalse( cbv.isNormalized() );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientStringValueTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientStringValueTest.java
new file mode 100644
index 0000000..45c197c
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientStringValueTest.java
@@ -0,0 +1,463 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.schema.DeepTrimToLowerNormalizer;
+import org.apache.directory.shared.ldap.schema.syntax.Ia5StringSyntaxChecker;
+import org.apache.directory.shared.ldap.schema.syntax.OctetStringSyntaxChecker;
+import org.junit.Test;
+
+/**
+ * 
+ * Test the ClientStringValue class
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ClientStringValueTest
+{
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#hashCode()}.
+     */
+    @Test
+    public void testHashCode()
+    {
+        ClientStringValue csv = new ClientStringValue( "test" );
+        
+        int hash = "test".hashCode();
+        assertEquals( hash, csv.hashCode() );
+        
+        csv = new ClientStringValue();
+        hash = "".hashCode();
+        assertEquals( hash, csv.hashCode() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#ClientStringValue()}.
+     */
+    @Test
+    public void testClientStringValueNull() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertNull( csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertFalse( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        assertTrue( csv.isNull() );
+        assertNull( csv.getNormalizedValue() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#ClientStringValue(java.lang.String)}.
+     */
+    @Test
+    public void testClientStringValueEmpty() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue( "" );
+        
+        assertNotNull( csv.get() );
+        assertEquals( "", csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertTrue( csv.isValid( new OctetStringSyntaxChecker() ) );
+        assertFalse( csv.isNull() );
+        assertNotNull( csv.getNormalizedValue() );
+        assertEquals( "", csv.getNormalizedValue() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#ClientStringValue(java.lang.String)}.
+     */
+    @Test
+    public void testClientStringValueString() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue( "test" );
+        
+        assertEquals( "test", csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertTrue( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        assertFalse( csv.isNull() );
+        assertNotNull( csv.getNormalizedValue() );
+        assertEquals( "test", csv.getNormalizedValue() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#get()}.
+     */
+    @Test
+    public void testGet()
+    {
+        ClientStringValue csv = new ClientStringValue( "test" );
+        
+        assertEquals( "test", csv.get() );
+        
+        csv.set( "" );
+        assertEquals( "", csv.get() );
+        
+        csv.clear();
+        assertNull( csv.get() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#getCopy()}.
+     */
+    @Test
+    public void testGetCopy()
+    {
+        ClientStringValue csv = new ClientStringValue( "test" );
+        
+        assertEquals( "test", csv.getCopy() );
+        
+        csv.set( "" );
+        assertEquals( "", csv.getCopy() );
+        
+        csv.clear();
+        assertNull( csv.getCopy() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#set(java.lang.String)}.
+     */
+    @Test
+    public void testSet() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        csv.set( null );
+        assertNull( csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertFalse( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        assertTrue( csv.isNull() );
+
+        csv.set( "" );
+        assertNotNull( csv.get() );
+        assertEquals( "", csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertTrue( csv.isValid( new OctetStringSyntaxChecker() ) );
+        assertFalse( csv.isNull() );
+
+        csv.set( "Test" );
+        assertNotNull( csv.get() );
+        assertEquals( "Test", csv.get() );
+        assertFalse( csv.isNormalized() );
+        assertTrue( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        assertFalse( csv.isNull() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#isNull()}.
+     */
+    @Test
+    public void testIsNull()
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        csv.set( null );
+        assertTrue( csv.isNull() );
+        
+        csv.set( "test" );
+        assertFalse( csv.isNull() );
+        
+        csv.clear();
+        assertTrue( csv.isNull() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#clear()}.
+     */
+    @Test
+    public void testClear() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        csv.clear();
+        assertTrue( csv.isNull() );
+        
+        csv.set( "test" );
+        assertTrue( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        csv.clear();
+        assertTrue( csv.isNull() );
+        assertFalse( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        assertFalse( csv.isNormalized() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#isNormalized()}.
+     */
+    @Test
+    public void testIsNormalized() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertFalse( csv.isNormalized() );
+        
+        csv.set(  "  This is    a   TEST  " );
+        assertFalse( csv.isNormalized() );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertEquals( "this is a test", csv.getNormalizedValue() );
+        assertTrue( csv.isNormalized() );
+        
+        csv.set( "test" );
+        assertFalse( csv.isNormalized() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#setNormalized(boolean)}.
+     */
+    @Test
+    public void testSetNormalized() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertFalse( csv.isNormalized() );
+        
+        csv.setNormalized( true );
+        assertTrue( csv.isNormalized() );
+        
+        csv.set(  "  This is    a   TEST  " );
+        assertFalse( csv.isNormalized() );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertEquals( "this is a test", csv.getNormalizedValue() );
+        assertTrue( csv.isNormalized() );
+        
+        csv.setNormalized( false );
+        assertEquals( "this is a test", csv.getNormalizedValue() );
+        assertFalse( csv.isNormalized() );
+
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        csv.clear();
+        assertFalse( csv.isNormalized() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#getNormalizedValue()}.
+     */
+    @Test
+    public void testGetNormalizedValue() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertEquals( null, csv.getNormalizedValue() );
+        
+        csv.set(  "  This is    a   TEST  " );
+        assertEquals( "  This is    a   TEST  ", csv.getNormalizedValue() );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertEquals( "this is a test", csv.getNormalizedValue() );
+
+        csv.clear();
+        assertFalse( csv.isNormalized() );
+        assertEquals( null, csv.getNormalizedValue() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#getNormalizedValueCopy()}.
+     */
+    @Test
+    public void getNormalizedValueCopy() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertEquals( null, csv.getNormalizedValueCopy() );
+        
+        csv.set(  "  This is    a   TEST  " );
+        assertEquals( "  This is    a   TEST  ", csv.getNormalizedValueCopy() );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertEquals( "this is a test", csv.getNormalizedValueCopy() );
+
+        csv.clear();
+        assertFalse( csv.isNormalized() );
+        assertEquals( null, csv.getNormalizedValueCopy() );
+    }
+
+    
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#normalize(org.apache.directory.shared.ldap.schema.Normalizer)}.
+     */
+    @Test
+    public void testNormalize() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        assertEquals( null, csv.getNormalizedValue() );
+        
+        csv.set( "" );
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        assertEquals( "", csv.getNormalizedValue() );
+
+        csv.set(  "  This is    a   TEST  " );
+        assertEquals( "  This is    a   TEST  ", csv.getNormalizedValue() );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertEquals( "this is a test", csv.getNormalizedValue() );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#isValid(org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker)}.
+     */
+    @Test
+    public void testIsValid() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue( "Test" );
+        
+        assertTrue( csv.isValid( new Ia5StringSyntaxChecker() ) );
+        
+        csv.set(  "é" );
+        assertFalse( csv.isValid( new Ia5StringSyntaxChecker() ) );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#compareTo(org.apache.directory.shared.ldap.entry.Value)}.
+     */
+    @Test
+    public void testCompareTo() throws NamingException
+    {
+        ClientStringValue csv1 = new ClientStringValue();
+        ClientStringValue csv2 = new ClientStringValue();
+        
+        assertEquals( 0, csv1.compareTo( csv2 ) );
+        
+        csv1.set( "Test" );
+        assertEquals( 1, csv1.compareTo( csv2 ) );
+        assertEquals( -1, csv2.compareTo( csv1 ) );
+        
+        csv2.set( "Test" );
+        assertEquals( 0, csv1.compareTo( csv2 ) );
+
+        // Now check that the equals method works on normalized values.
+        csv1.set(  "  This is    a TEST   " );
+        csv2.set( "this is a test" );
+        csv1.normalize( new DeepTrimToLowerNormalizer() );
+        assertEquals( 0, csv1.compareTo( csv2 ) );
+        
+        csv1.set( "a" );
+        csv2.set( "b" );
+        assertEquals( -1, csv1.compareTo( csv2 ) );
+
+        csv1.set( "b" );
+        csv2.set( "a" );
+        assertEquals( 1, csv1.compareTo( csv2 ) );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#clone()}.
+     */
+    @Test
+    public void testClone() throws NamingException
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        ClientStringValue csv1 = (ClientStringValue)csv.clone();
+        
+        assertEquals( csv, csv1 );
+        
+        csv.set( "" );
+        
+        assertNotSame( csv, csv1 );
+        assertNull( csv1.get() );
+        assertEquals( "", csv.get() );
+        
+        csv.set(  "  This is    a   TEST  " );
+        csv1 = (ClientStringValue)csv.clone();
+        
+        assertEquals( csv, csv1 );
+        
+        csv.normalize( new DeepTrimToLowerNormalizer() );
+        
+        assertNotSame( csv, csv1 );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#equals(java.lang.Object)}.
+     */
+    @Test
+    public void testEquals() throws NamingException
+    {
+        ClientStringValue csv1 = new ClientStringValue();
+        ClientStringValue csv2 = new ClientStringValue();
+        
+        assertEquals( csv1, csv2 );
+        
+        csv1.set( "Test" );
+        assertNotSame( csv1, csv2 );
+        
+        csv2.set( "Test" );
+        assertEquals( csv1, csv2 );
+
+        // Now check that the equals method works on normalized values.
+        csv1.set(  "  This is    a TEST   " );
+        csv2.set( "this is a test" );
+        csv1.normalize( new DeepTrimToLowerNormalizer() );
+        assertEquals( csv1, csv2 );
+    }
+
+
+    /**
+     * Test method for {@link org.apache.directory.shared.ldap.entry.client.ClientStringValue#toString()}.
+     */
+    @Test
+    public void testToString()
+    {
+        ClientStringValue csv = new ClientStringValue();
+        
+        assertEquals( "null", csv.toString() );
+
+        csv.set( "" );
+        assertEquals( "", csv.toString() );
+
+        csv.set( "Test" );
+        assertEquals( "Test", csv.toString() );
+        
+        csv.clear();
+        assertEquals( "null", csv.toString() );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttributeTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttributeTest.java
new file mode 100644
index 0000000..abe03dc
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttributeTest.java
@@ -0,0 +1,1465 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry.client;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.naming.NamingException;
+import javax.naming.directory.InvalidAttributeValueException;
+
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.schema.syntax.Ia5StringSyntaxChecker;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test the DefaultClientAttribute class
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DefaultClientAttributeTest
+{
+    private static final Value<String> NULL_STRING_VALUE = new ClientStringValue( null );
+    private static final Value<byte[]> NULL_BINARY_VALUE = new ClientBinaryValue( null );
+    private static final byte[] BYTES1 = new byte[]{ 'a', 'b' };
+    private static final byte[] BYTES2 = new byte[]{ 'b' };
+    private static final byte[] BYTES3 = new byte[]{ 'c' };
+    private static final byte[] BYTES4 = new byte[]{ 'd' };
+    
+    private static final ClientStringValue STR_VALUE1 = new ClientStringValue( "a" );
+    private static final ClientStringValue STR_VALUE2 = new ClientStringValue( "b" );
+    private static final ClientStringValue STR_VALUE3 = new ClientStringValue( "c" );
+    private static final ClientStringValue STR_VALUE4 = new ClientStringValue( "d" );
+
+    private static final ClientBinaryValue BIN_VALUE1 = new ClientBinaryValue( BYTES1 );
+    private static final ClientBinaryValue BIN_VALUE2 = new ClientBinaryValue( BYTES2 );
+    private static final ClientBinaryValue BIN_VALUE3 = new ClientBinaryValue( BYTES3 );
+    private static final ClientBinaryValue BIN_VALUE4 = new ClientBinaryValue( BYTES4 );
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception
+    {
+    }
+
+
+    /**
+     * Test method new DefaultClientAttribute()
+     */
+    @Test
+    public void testDefaultClientAttribute()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+        
+        assertFalse( attr.isHR() );
+        assertEquals( 0, attr.size() );
+        assertNull( attr.getId() );
+        assertNull( attr.getUpId() );
+    }
+
+
+    /**
+     * Test method new DefaultClientAttribute( String )
+     */
+    @Test
+    public void testDefaultClientAttributeString()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "TEST" );
+        
+        assertFalse( attr.isHR() );
+        assertEquals( 0, attr.size() );
+        assertEquals( "test", attr.getId() );
+        assertEquals( "TEST", attr.getUpId() );
+    }
+
+
+    /**
+     * Test method new DefaultClientAttribute( String, Value... )
+     */
+    @Test
+    public void testDefaultClientAttributeStringValueArray()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "Test", STR_VALUE1, STR_VALUE2 );
+        
+        assertTrue( attr.isHR() );
+        assertEquals( 2, attr.size() );
+        assertTrue( attr.contains( "a" ) );
+        assertTrue( attr.contains( "b" ) );
+        assertEquals( "test", attr.getId() );
+        assertEquals( "Test", attr.getUpId() );
+    }
+
+
+    /**
+     * Test method 
+     */
+    @Test
+    public void testDefaultClientAttributeStringStringArray()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "Test", "a", "b" );
+        
+        assertTrue( attr.isHR() );
+        assertEquals( 2, attr.size() );
+        assertTrue( attr.contains( "a" ) );
+        assertTrue( attr.contains( "b" ) );
+        assertEquals( "test", attr.getId() );
+        assertEquals( "Test", attr.getUpId() );
+    }
+
+
+    /**
+     * Test method 
+     */
+    @Test
+    public void testDefaultClientAttributeStringBytesArray()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "Test", BYTES1, BYTES2 );
+        
+        assertFalse( attr.isHR() );
+        assertEquals( 2, attr.size() );
+        assertTrue( attr.contains( BYTES1 ) );
+        assertTrue( attr.contains( BYTES2 ) );
+        assertEquals( "test", attr.getId() );
+        assertEquals( "Test", attr.getUpId() );
+    }
+
+
+    /**
+     * Test method getBytes()
+     */
+    @Test
+    public void testGetBytes() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        attr1.add( (byte[])null );
+        assertNull( attr1.getBytes() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.add( BYTES1, BYTES2 );
+        assertTrue( Arrays.equals( BYTES1, attr2.getBytes() ) );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        attr3.add( "a", "b" );
+        
+        try
+        {
+            attr3.getBytes();
+            fail();
+        }
+        catch ( InvalidAttributeValueException ivae )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    /**
+     * Test method getString()
+     */
+    @Test
+    public void testGetString() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        attr1.add( (String)null );
+        assertNull( attr1.getString() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.add( "a", "b" );
+        assertEquals( "a", attr2.getString() );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        attr3.add( BYTES1, BYTES2 );
+        
+        try
+        {
+            attr3.getString();
+            fail();
+        }
+        catch ( InvalidAttributeValueException ivae )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    /**
+     * Test method getId()
+     */
+    @Test
+    public void testGetId()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+
+        assertNull( attr.getId() );
+        
+        attr.setId( "test" );
+        assertEquals( "test", attr.getId() );
+        
+        attr.setId(  "  TEST  " );
+        assertEquals( "test", attr.getId() );
+    }
+
+
+    /**
+     * Test method SetId(String)
+     */
+    @Test
+    public void testSetId()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+
+        try
+        {
+            attr.setId( null );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            attr.setId( "" );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            attr.setId( "  " );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        attr.setId( "Test" );
+        assertEquals( "test", attr.getId() );
+        
+        attr.setId( " Test " );
+        assertEquals( "test", attr.getId() );
+    }
+
+
+    /**
+     * Test method getUpId()
+     */
+    @Test
+    public void testGetUpId()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+
+        assertNull( attr.getUpId() );
+        
+        attr.setUpId( "test" );
+        assertEquals( "test", attr.getUpId() );
+        
+        attr.setUpId(  "  TEST  " );
+        assertEquals( "TEST", attr.getUpId() );
+    }
+
+
+    /**
+     * Test method setUpId(String)
+     */
+    @Test
+    public void testSetUpId()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+
+        try
+        {
+            attr.setUpId( null );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            attr.setUpId( "" );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            attr.setUpId( "  " );
+            fail();
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+        
+        attr.setUpId( "Test" );
+        assertEquals( "Test", attr.getUpId() );
+        assertEquals( "test", attr.getId() );
+        
+        attr.setUpId( " Test " );
+        assertEquals( "Test", attr.getUpId() );
+        assertEquals( "test", attr.getId() );
+    }
+
+
+    /**
+     * Test method isValid( SyntaxChecker ) 
+     */
+    @Test
+    public void testIsValidSyntaxChecker() throws NamingException
+    {
+        ClientAttribute attr = new DefaultClientAttribute( "test" );
+        
+        attr.add( "test", "another test" );
+        
+        assertTrue( attr.isValid( new Ia5StringSyntaxChecker() ) );
+        
+        attr.add( "é" );
+        assertFalse( attr.isValid( new Ia5StringSyntaxChecker() ) );
+    }
+
+
+    /**
+     * Test method iterator()
+     */
+    @Test
+    public void testIterator()
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+        attr.add(  "a", "b", "c" );
+        
+        Iterator<Value<?>> iter = attr.iterator();
+        
+        assertTrue( iter.hasNext() );
+        
+        String[] values = new String[]{ "a", "b", "c" };
+        int pos = 0;
+        
+        for ( Value<?> val:attr )
+        {
+            assertTrue( val instanceof ClientStringValue );
+            assertEquals( values[pos++], val.get() );
+        }
+    }
+
+
+    /**
+     * Test method add(Value...)
+     */
+    @Test
+    public void testAddValueArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        int nbAdded = attr1.add( new ClientStringValue( null ) );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr1.isHR() );
+        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr2.add( new ClientBinaryValue( null ) );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr2.isHR() );
+        assertEquals( NULL_BINARY_VALUE, attr2.get() );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr3.add( new ClientStringValue( "a" ), new ClientStringValue( "b" ) );
+        assertEquals( 2, nbAdded );
+        assertTrue( attr3.isHR() );
+        assertTrue( attr3.contains( "a" ) );
+        assertTrue( attr3.contains( "b" ) );
+        
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr4.add( new ClientBinaryValue( BYTES1 ), new ClientBinaryValue( BYTES2 ) );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr4.isHR() );
+        assertTrue( attr4.contains( BYTES1 ) );
+        assertTrue( attr4.contains( BYTES2 ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr5.add( new ClientStringValue( "c" ), new ClientBinaryValue( BYTES1 ) );
+        assertEquals( 2, nbAdded );
+        assertTrue( attr5.isHR() );
+        assertTrue( attr5.contains( "ab" ) );
+        assertTrue( attr5.contains( "c" ) );
+
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr6.add( new ClientBinaryValue( BYTES1 ), new ClientStringValue( "c" ) );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr6.isHR() );
+        assertTrue( attr6.contains( BYTES1 ) );
+        assertTrue( attr6.contains( BYTES3 ) );
+
+        EntryAttribute attr7 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr7.add( new ClientBinaryValue( null ), new ClientStringValue( "c" ) );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr7.isHR() );
+        assertTrue( attr7.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr7.contains( BYTES3 ) );
+
+        EntryAttribute attr8 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr8.add( new ClientStringValue( null ), new ClientBinaryValue( BYTES1 ) );
+        assertEquals( 2, nbAdded );
+        assertTrue( attr8.isHR() );
+        assertTrue( attr8.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr8.contains( "ab" ) );
+    }
+
+
+    /**
+     * Test method add( String... )
+     */
+    @Test
+    public void testAddStringArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        int nbAdded = attr1.add( (String)null );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr1.isHR() );
+        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr2.add( "" );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr2.isHR() );
+        assertEquals( "", attr2.getString() );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr3.add( "t" );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr3.isHR() );
+        assertEquals( "t", attr3.getString() );
+        
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr4.add( "a", "b", "c", "d" );
+        assertEquals( 4, nbAdded );
+        assertTrue( attr4.isHR() );
+        assertEquals( "a", attr4.getString() );
+        assertTrue( attr4.contains( "a" ) );
+        assertTrue( attr4.contains( "b" ) );
+        assertTrue( attr4.contains( "c" ) );
+        assertTrue( attr4.contains( "d" ) );
+        
+        nbAdded = attr4.add( "e" );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr4.isHR() );
+        assertEquals( "a", attr4.getString() );
+        assertTrue( attr4.contains( "a" ) );
+        assertTrue( attr4.contains( "b" ) );
+        assertTrue( attr4.contains( "c" ) );
+        assertTrue( attr4.contains( "d" ) );
+        assertTrue( attr4.contains( "e" ) );
+        
+        nbAdded = attr4.add( BYTES1 );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr4.isHR() );
+        assertEquals( "a", attr4.getString() );
+        assertTrue( attr4.contains( "a" ) );
+        assertTrue( attr4.contains( "b" ) );
+        assertTrue( attr4.contains( "c" ) );
+        assertTrue( attr4.contains( "d" ) );
+        assertTrue( attr4.contains( "e" ) );
+        assertTrue( attr4.contains( "ab" ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr5.add( "a", "b", (String)null, "d" );
+        assertEquals( 4, nbAdded );
+        assertTrue( attr5.isHR() );
+        assertTrue( attr5.contains( "a" ) );
+        assertTrue( attr5.contains( "b" ) );
+        assertTrue( attr5.contains( (String)null ) );
+        assertTrue( attr5.contains( "d" ) );
+
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        attr6.setHR( false );
+        nbAdded = attr6.add( "a", (String)null );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr6.isHR() );
+        assertTrue( attr6.contains( new byte[]{'a'} ) );
+        assertTrue( attr6.contains( (byte[])null ) );
+        
+        EntryAttribute attr7 = new DefaultClientAttribute( "test" );
+        
+        attr7.add( "a", "b" );
+        assertEquals( 2, attr7.size() );
+        
+        assertEquals( 1, attr7.add( "b", "c" ) );
+        assertEquals( 3, attr7.size() );
+        assertTrue( attr7.contains( "a", "b", "c" ) );
+    }
+
+
+    /**
+     * Test method add( byte[]... )
+     */
+    @Test
+    public void testAddByteArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        int nbAdded = attr1.add( (byte[])null );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr1.isHR() );
+        assertTrue( Arrays.equals( NULL_BINARY_VALUE.get(), attr1.getBytes() ) );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr2.add( StringTools.EMPTY_BYTES );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr2.isHR() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, attr2.getBytes() ) );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr3.add( BYTES1 );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr3.isHR() );
+        assertTrue( Arrays.equals( BYTES1, attr3.getBytes() ) );
+        
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr4.add( BYTES1, BYTES2, BYTES3, BYTES4 );
+        assertEquals( 4, nbAdded );
+        assertFalse( attr4.isHR() );
+        assertTrue( attr4.contains( BYTES1 ) );
+        assertTrue( attr4.contains( BYTES2 ) );
+        assertTrue( attr4.contains( BYTES3 ) );
+        assertTrue( attr4.contains( BYTES4 ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr5.add( BYTES1, BYTES2, (byte[])null, BYTES3 );
+        assertEquals( 4, nbAdded );
+        assertFalse( attr5.isHR() );
+        assertTrue( attr5.contains( BYTES1 ) );
+        assertTrue( attr5.contains( BYTES2 ) );
+        assertTrue( attr5.contains( (byte[])null ) );
+        assertTrue( attr5.contains( BYTES3 ) );
+
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        attr6.setHR( true );
+        nbAdded = attr6.add( BYTES1, (byte[])null );
+        assertEquals( 2, nbAdded );
+        assertTrue( attr6.isHR() );
+        assertTrue( attr6.contains( "ab" ) );
+        assertTrue( attr6.contains( (String)null ) );
+    }
+
+
+    /**
+     * Test method clear()
+     */
+    @Test
+    public void testClear() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        
+        attr1.add( (String)null );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.isHR() );
+        attr1.clear();
+        assertTrue( attr1.isHR() );
+        assertEquals( 0, attr1.size() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        attr2.add( BYTES1, BYTES2 );
+        assertEquals( 2, attr2.size() );
+        assertFalse( attr2.isHR() );
+        attr2.clear();
+        assertFalse( attr2.isHR() );
+        assertEquals( 0, attr2.size() );
+    }
+
+
+    /**
+     * Test method contains( Value... )
+     */
+    @Test
+    public void testContainsValueArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        assertFalse( attr1.contains( STR_VALUE1 ) );
+        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        
+        attr1.add( (String)null );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        
+        attr1.remove( (String)null );
+        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        assertEquals( 0, attr1.size() );
+        
+        attr1.add(  "a", "b", "c" );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( STR_VALUE2 ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+        assertTrue( attr1.contains( STR_VALUE1, STR_VALUE3 ) );
+        assertFalse( attr1.contains( STR_VALUE4 ) );
+        assertFalse( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( STR_VALUE1, BIN_VALUE2 ) );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        assertEquals( 0, attr2.size() );
+        assertFalse( attr2.contains( BYTES1 ) );
+        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        
+        attr2.add( (byte[])null );
+        assertEquals( 1, attr2.size() );
+        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        
+        attr2.remove( (byte[])null );
+        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        assertEquals( 0, attr2.size() );
+        
+        attr2.add( BYTES1, BYTES2, BYTES3 );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BIN_VALUE1 ) );
+        assertTrue( attr2.contains( BIN_VALUE2 ) );
+        assertTrue( attr2.contains( BIN_VALUE3 ) );
+        assertFalse( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( STR_VALUE2, BIN_VALUE1 ) );
+    }
+
+
+    /**
+     * Test method contains( String... )
+     */
+    @Test
+    public void testContainsStringArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        assertFalse( attr1.contains( "a" ) );
+        assertFalse( attr1.contains( (String)null ) );
+        
+        attr1.add( (String)null );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.contains( (String)null ) );
+        
+        attr1.remove( (String)null );
+        assertFalse( attr1.contains( (String)null ) );
+        assertEquals( 0, attr1.size() );
+        
+        attr1.add(  "a", "b", "c" );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( "a" ) );
+        assertTrue( attr1.contains( "b" ) );
+        assertTrue( attr1.contains( "c" ) );
+        assertFalse( attr1.contains( "e" ) );
+        assertFalse( attr1.contains( (String)null ) );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        assertEquals( 0, attr2.size() );
+        assertFalse( attr2.contains( BYTES1 ) );
+        assertFalse( attr2.contains( (byte[])null ) );
+        
+        attr2.add( (byte[])null );
+        assertEquals( 1, attr2.size() );
+        assertTrue( attr2.contains( (byte[])null ) );
+        
+        attr2.remove( (byte[])null );
+        assertFalse( attr2.contains( (byte[])null ) );
+        assertEquals( 0, attr2.size() );
+        
+        attr2.add( BYTES1, BYTES2, BYTES3 );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( "ab" ) );
+        assertTrue( attr2.contains( "b" ) );
+        assertTrue( attr2.contains( "c" ) );
+        assertFalse( attr2.contains( (String)null ) );
+    }
+
+
+    /**
+     * Test method contains( byte... )
+     */
+    @Test
+    public void testContainsByteArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        assertFalse( attr1.contains( BYTES1 ) );
+        assertFalse( attr1.contains( (byte[])null ) );
+        
+        attr1.add( (byte[])null );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.contains( (byte[])null ) );
+        
+        attr1.remove( (byte[])null );
+        assertFalse( attr1.contains( (byte[])null ) );
+        assertEquals( 0, attr1.size() );
+        
+        attr1.add(  BYTES1, BYTES2, BYTES3 );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( BYTES1 ) );
+        assertTrue( attr1.contains( BYTES2 ) );
+        assertTrue( attr1.contains( BYTES3 ) );
+        assertFalse( attr1.contains( BYTES4 ) );
+        assertFalse( attr1.contains( (byte[])null ) );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        assertEquals( 0, attr2.size() );
+        assertFalse( attr2.contains( "a" ) );
+        assertFalse( attr2.contains( (String)null ) );
+        
+        attr2.add( (String)null );
+        assertEquals( 1, attr2.size() );
+        assertTrue( attr2.contains( (String)null ) );
+        
+        attr2.remove( (String)null );
+        assertFalse( attr2.contains( (String)null ) );
+        assertEquals( 0, attr2.size() );
+        
+        attr2.add( "ab", "b", "c" );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BYTES1 ) );
+        assertTrue( attr2.contains( BYTES2 ) );
+        assertTrue( attr2.contains( BYTES3 ) );
+        assertFalse( attr2.contains( (byte[])null ) );
+    }
+
+
+    /**
+     * Test method get()
+     */
+    @Test
+    public void testGet() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        attr1.add( (String)null );
+        assertEquals( NULL_STRING_VALUE,attr1.get() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.add( "a", "b", "c" );
+        assertEquals( "a", attr2.get().get() );
+        
+        attr2.remove( "a" );
+        assertEquals( "b", attr2.get().get() );
+
+        attr2.remove( "b" );
+        assertEquals( "c", attr2.get().get() );
+
+        attr2.remove( "c" );
+        assertNull( attr2.get() );
+
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        attr3.add( BYTES1, BYTES2, BYTES3 );
+        assertTrue( Arrays.equals( BYTES1, (byte[])attr3.get().get() ) );
+        
+        attr3.remove( BYTES1 );
+        assertTrue( Arrays.equals( BYTES2, (byte[])attr3.get().get() ) );
+
+        attr3.remove( BYTES2 );
+        assertTrue( Arrays.equals( BYTES3, (byte[])attr3.get().get() ) );
+
+        attr3.remove( BYTES3 );
+        assertNull( attr2.get() );
+    }
+
+
+    /**
+     * Test method getAll()
+     */
+    @Test
+    public void testGetAll()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "test" );
+        
+        Iterator<Value<?>> iterator = attr.getAll(); 
+        assertFalse( iterator.hasNext() );
+        
+        attr.add( NULL_STRING_VALUE );
+        iterator = attr.getAll(); 
+        assertTrue( iterator.hasNext() );
+        
+        Value<?> value = iterator.next();
+        assertEquals( NULL_STRING_VALUE, value );
+        
+        attr.clear();
+        iterator = attr.getAll(); 
+        assertFalse( iterator.hasNext() );
+        
+        attr.add(  "a", "b", "c" );
+        iterator = attr.getAll(); 
+        assertTrue( iterator.hasNext() );
+        assertEquals( "a", iterator.next().get() );
+        assertEquals( "b", iterator.next().get() );
+        assertEquals( "c", iterator.next().get() );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    /**
+     * Test method size()
+     */
+    @Test
+    public void testSize() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+
+        assertEquals( 0, attr1.size() );
+        
+        attr1.add( (String)null );
+        assertEquals( 1, attr1.size() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.add( "a", "b" );
+        assertEquals( 2, attr2.size() );
+        
+        attr2.clear();
+        assertEquals( 0, attr2.size() );
+    }
+
+
+    /**
+     * Test method remove( Value... )
+     */
+    @Test
+    public void testRemoveValueArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+
+        assertFalse( attr1.remove( STR_VALUE1 ) );
+
+        attr1.setHR( true );
+        assertFalse( attr1.remove( STR_VALUE1 ) );
+        
+        attr1.put( "a", "b", "c" );
+        assertTrue( attr1.remove( STR_VALUE1 ) );
+        assertEquals( 2, attr1.size() );
+        
+        assertTrue( attr1.remove( STR_VALUE2, STR_VALUE3 ) );
+        assertEquals( 0, attr1.size() );
+        
+        assertFalse( attr1.remove( STR_VALUE4 ) );
+        
+        attr1.put( "a", "b", "c" );
+        assertFalse( attr1.remove( STR_VALUE2, STR_VALUE4 ) );
+        assertEquals( 2, attr1.size() );
+        
+        attr1.clear();
+        attr1.put( "a", (String)null, "b" );
+        assertTrue( attr1.remove( NULL_STRING_VALUE, STR_VALUE1 ) );
+        assertEquals( 1, attr1.size() );
+        
+        attr1.clear();
+        attr1.put( "a", (String)null, "b" );
+        attr1.add( BYTES3 );
+        assertTrue( attr1.remove( NULL_STRING_VALUE, STR_VALUE1, BIN_VALUE3 ) );
+        assertEquals( 1, attr1.size() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+
+        assertFalse( attr2.remove( BIN_VALUE1 ) );
+
+        attr2.setHR( true );
+        assertFalse( attr2.remove( BIN_VALUE1 ) );
+        
+        attr2.put( BYTES1, BYTES2, BYTES3 );
+        assertTrue( attr2.remove( BIN_VALUE1 ) );
+        assertEquals( 2, attr2.size() );
+        
+        assertTrue( attr2.remove( BIN_VALUE2, BIN_VALUE3 ) );
+        assertEquals( 0, attr2.size() );
+        
+        assertFalse( attr2.remove( BIN_VALUE4 ) );
+        
+        attr2.put( BYTES1, BYTES2, BYTES3 );
+        assertFalse( attr2.remove( BIN_VALUE2, STR_VALUE4 ) );
+        assertEquals( 2, attr2.size() );
+        
+        attr2.clear();
+        attr2.put( BYTES1, (byte[])null, BYTES3 );
+        assertTrue( attr2.remove( NULL_STRING_VALUE, BIN_VALUE1 ) );
+        assertEquals( 1, attr2.size() );
+        
+        attr2.clear();
+        attr2.put( BYTES1, (byte[])null, BYTES2 );
+        attr2.add( "c" );
+        assertTrue( attr2.remove( NULL_STRING_VALUE, BIN_VALUE1, STR_VALUE3 ) );
+        assertEquals( 1, attr2.size() );
+    }
+
+
+    /**
+     * Test method remove( byte... )
+     */
+    @Test
+    public void testRemoveByteArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+
+        assertFalse( attr1.remove( BYTES1 ) );
+
+        attr1.setHR( false );
+        assertFalse( attr1.remove( BYTES1 ) );
+        
+        attr1.put( BYTES1, BYTES2, BYTES3 );
+        assertTrue( attr1.remove( BYTES1 ) );
+        assertEquals( 2, attr1.size() );
+        
+        assertTrue( attr1.remove( BYTES2, BYTES3 ) );
+        assertEquals( 0, attr1.size() );
+        
+        assertFalse( attr1.remove( BYTES4 ) );
+        
+        attr1.put( BYTES1, BYTES2, BYTES3 );
+        assertFalse( attr1.remove( BYTES3, BYTES4 ) );
+        assertEquals( 2, attr1.size() );
+        
+        attr1.clear();
+        attr1.put( BYTES1, (byte[])null, BYTES2 ) ;
+        assertTrue( attr1.remove( (byte[])null, BYTES1 ) );
+        assertEquals( 1, attr1.size() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.put( "ab", "b", "c" );
+        
+        assertFalse( attr2.remove( (byte[])null ) );
+        assertTrue( attr2.remove( BYTES1, BYTES2 ) );
+        assertFalse( attr2.remove( BYTES4 ) );
+    }
+
+
+    /**
+     * Test method remove( String... )
+     */
+    @Test
+    public void testRemoveStringArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+
+        assertFalse( attr1.remove( "a" ) );
+
+        attr1.setHR( true );
+        assertFalse( attr1.remove( "a" ) );
+        
+        attr1.put( "a", "b", "c" );
+        assertTrue( attr1.remove( "a" ) );
+        assertEquals( 2, attr1.size() );
+        
+        assertTrue( attr1.remove( "b", "c" ) );
+        assertEquals( 0, attr1.size() );
+        
+        assertFalse( attr1.remove( "d" ) );
+        
+        attr1.put( "a", "b", "c" );
+        assertFalse( attr1.remove( "b", "e" ) );
+        assertEquals( 2, attr1.size() );
+        
+        attr1.clear();
+        attr1.put( "a", (String)null, "b" );
+        assertTrue( attr1.remove( (String )null, "a" ) );
+        assertEquals( 1, attr1.size() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        attr2.put( BYTES1, BYTES2, BYTES3 );
+        
+        assertFalse( attr2.remove( (String)null ) );
+        assertTrue( attr2.remove( "ab", "c" ) );
+        assertFalse( attr2.remove( "d" ) );
+    }
+
+
+    /**
+     * Test method put( String... )
+     */
+    @Test
+    public void testPutStringArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        int nbAdded = attr1.put( (String)null );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr1.isHR() );
+        assertEquals( NULL_STRING_VALUE, attr1.get() );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr2.put( "" );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr2.isHR() );
+        assertEquals( "", attr2.getString() );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr3.put( "t" );
+        assertEquals( 1, nbAdded );
+        assertTrue( attr3.isHR() );
+        assertEquals( "t", attr3.getString() );
+        
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr4.put( "a", "b", "c", "d" );
+        assertEquals( 4, nbAdded );
+        assertTrue( attr4.isHR() );
+        assertTrue( attr4.contains( "a" ) );
+        assertTrue( attr4.contains( "b" ) );
+        assertTrue( attr4.contains( "c" ) );
+        assertTrue( attr4.contains( "d" ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr5.put( "a", "b", (String)null, "d" );
+        assertEquals( 4, nbAdded );
+        assertTrue( attr5.isHR() );
+        assertTrue( attr5.contains( "a" ) );
+        assertTrue( attr5.contains( "b" ) );
+        assertTrue( attr5.contains( (String)null ) );
+        assertTrue( attr5.contains( "d" ) );
+
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        attr6.setHR( false );
+        nbAdded = attr6.put( "a", (String)null );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr6.isHR() );
+        assertTrue( attr6.contains( new byte[]{'a'} ) );
+        assertTrue( attr6.contains( (byte[])null ) );
+    }
+
+
+    /**
+     * Test method put( byte[]... )
+     */
+    @Test
+    public void testPutByteArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        int nbAdded = attr1.put( (byte[])null );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr1.isHR() );
+        assertTrue( Arrays.equals( NULL_BINARY_VALUE.get(), attr1.getBytes() ) );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr2.put( StringTools.EMPTY_BYTES );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr2.isHR() );
+        assertTrue( Arrays.equals( StringTools.EMPTY_BYTES, attr2.getBytes() ) );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr3.put( BYTES1 );
+        assertEquals( 1, nbAdded );
+        assertFalse( attr3.isHR() );
+        assertTrue( Arrays.equals( BYTES1, attr3.getBytes() ) );
+        
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr4.put( BYTES1, BYTES2 );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr4.isHR() );
+        assertTrue( attr4.contains( BYTES1 ) );
+        assertTrue( attr4.contains( BYTES2 ) );
+        
+        nbAdded = attr4.put( BYTES3, BYTES4 );
+        assertEquals( 2, nbAdded );
+        assertFalse( attr4.isHR() );
+        assertTrue( attr4.contains( BYTES3 ) );
+        assertTrue( attr4.contains( BYTES4 ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        
+        nbAdded = attr5.put( BYTES1, BYTES2, (byte[])null, BYTES3 );
+        assertEquals( 4, nbAdded );
+        assertFalse( attr5.isHR() );
+        assertTrue( attr5.contains( BYTES1 ) );
+        assertTrue( attr5.contains( BYTES2 ) );
+        assertTrue( attr5.contains( (byte[])null ) );
+        assertTrue( attr5.contains( BYTES3 ) );
+
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        attr6.setHR( true );
+        nbAdded = attr6.put( BYTES1, (byte[])null );
+        assertEquals( 2, nbAdded );
+        assertTrue( attr6.isHR() );
+        assertTrue( attr6.contains( "ab" ) );
+        assertTrue( attr6.contains( (String)null ) );
+    }
+
+
+    /**
+     * Test method put( Value... )
+     */
+    @Test
+    public void testPutValueArray() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        
+        attr1.put( NULL_STRING_VALUE );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        
+        attr1.put( STR_VALUE1, STR_VALUE2, STR_VALUE3 );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( STR_VALUE2 ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+
+        attr1.put( STR_VALUE1, NULL_STRING_VALUE, STR_VALUE3 );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+        
+        attr1.put( STR_VALUE1, NULL_STRING_VALUE, BIN_VALUE3 );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+        
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        assertEquals( 0, attr2.size() );
+        
+        attr2.put( NULL_BINARY_VALUE );
+        assertEquals( 1, attr2.size() );
+        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        
+        attr2.put( BIN_VALUE1, BIN_VALUE2, BIN_VALUE3 );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BIN_VALUE1 ) );
+        assertTrue( attr2.contains( BIN_VALUE2 ) );
+        assertTrue( attr2.contains( BIN_VALUE3 ) );
+        
+        attr2.put( BIN_VALUE1, NULL_BINARY_VALUE, STR_VALUE3 );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BIN_VALUE1 ) );
+        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( BIN_VALUE3 ) );
+    }
+
+
+    /**
+     * Test method put( List&lt;Value&gt; )
+     */
+    @Test
+    public void testPutListOfValues()
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( 0, attr1.size() );
+        
+        List<Value<?>> list = new ArrayList<Value<?>>();
+        list.add( NULL_STRING_VALUE );
+        
+        attr1.put( list );
+        assertEquals( 1, attr1.size() );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        
+        list.clear();
+        list.add( STR_VALUE1 );
+        list.add( STR_VALUE2 );
+        list.add( STR_VALUE3 );
+        attr1.put( list );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( STR_VALUE2 ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+
+        list.clear();
+        list.add( STR_VALUE1 );
+        list.add( NULL_STRING_VALUE );
+        list.add( STR_VALUE3 );
+        attr1.put( list );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+        
+        list.clear();
+        list.add( STR_VALUE1 );
+        list.add( NULL_STRING_VALUE );
+        list.add( BIN_VALUE3 );
+        attr1.put( list );
+        assertEquals( 3, attr1.size() );
+        assertTrue( attr1.contains( STR_VALUE1 ) );
+        assertTrue( attr1.contains( NULL_STRING_VALUE ) );
+        assertTrue( attr1.contains( STR_VALUE3 ) );
+        
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        assertEquals( 0, attr2.size() );
+        
+        list.clear();
+        list.add( NULL_BINARY_VALUE );
+        attr2.put( list );
+        assertEquals( 1, attr2.size() );
+        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        
+        list.clear();
+        list.add( BIN_VALUE1 );
+        list.add( BIN_VALUE2 );
+        list.add( BIN_VALUE3 );
+        attr2.put( list );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BIN_VALUE1 ) );
+        assertTrue( attr2.contains( BIN_VALUE2 ) );
+        assertTrue( attr2.contains( BIN_VALUE3 ) );
+        
+        list.clear();
+        list.add( BIN_VALUE1 );
+        list.add( NULL_BINARY_VALUE );
+        list.add( STR_VALUE3 );
+        attr2.put( list );
+        assertEquals( 3, attr2.size() );
+        assertTrue( attr2.contains( BIN_VALUE1 ) );
+        assertTrue( attr2.contains( NULL_BINARY_VALUE ) );
+        assertTrue( attr2.contains( BIN_VALUE3 ) );
+    }
+
+
+    /**
+     * Test method toString()
+     */
+    @Test
+    public void testToString() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( "    test: (null)\n", attr1.toString() );
+        
+        attr1.add( "a" );
+        assertEquals( "    test: a\n", attr1.toString() );
+        
+        attr1.add( "b" );
+        assertEquals( "    test: a\n    test: b\n", attr1.toString() );
+
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+
+        attr2.add( BYTES1 );
+        assertEquals( "    test: '0x61 0x62 '\n", attr2.toString() );
+
+        attr2.add( BYTES3 );
+        assertEquals( "    test: '0x61 0x62 '\n    test: '0x63 '\n", attr2.toString() );
+    }
+
+
+    /**
+     * Test method hashCode()
+     */
+    @Test
+    public void testHashCode() throws InvalidAttributeValueException, NamingException
+    {
+        EntryAttribute attr = new DefaultClientAttribute();
+        assertEquals( 37, attr.hashCode() );
+        
+        attr.setHR( true );
+        assertEquals( 37*17 + 1231, attr.hashCode() );
+        
+        attr.setHR(  false );
+        assertEquals( 37*17 + 1237, attr.hashCode() );
+
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        assertEquals( attr1.hashCode(), attr2.hashCode() );
+        
+        attr1.put( "a", "b", "c" );
+        attr2.put( "a", "b", "c" );
+        assertEquals( attr1.hashCode(), attr2.hashCode() );
+        
+        attr1.add( "d" );
+        attr2.add( "d" );
+        assertEquals( attr1.hashCode(), attr2.hashCode() );
+
+        attr1.add( NULL_STRING_VALUE );
+        attr2.add(  NULL_STRING_VALUE );
+        assertEquals( attr1.hashCode(), attr2.hashCode() );
+
+        // Order mess up the hashCode
+        attr1.put( "a", "b", "c" );
+        attr2.put( "c", "b", "a" );
+        assertNotSame( attr1.hashCode(), attr2.hashCode() );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        attr3.put( BYTES1, BYTES2 );
+        attr4.put( BYTES1, BYTES2 );
+        assertEquals( attr3.hashCode(), attr4.hashCode() );
+        
+        attr3.add( BYTES3 );
+        attr4.add( BYTES3 );
+        assertEquals( attr3.hashCode(), attr4.hashCode() );
+        
+        attr3.add( NULL_BINARY_VALUE );
+        attr4.add(  NULL_BINARY_VALUE );
+        assertEquals( attr3.hashCode(), attr4.hashCode() );
+
+        // Order mess up the hashCode
+        attr3.put( BYTES1, BYTES2 );
+        attr4.put( BYTES2, BYTES1 );
+        assertNotSame( attr3.hashCode(), attr4.hashCode() );
+    }
+
+
+    /**
+     * Test method testEquals()
+     */
+    @Test
+    public void testEquals()
+    {
+        EntryAttribute attr1 = new DefaultClientAttribute( "test" );
+        
+        assertFalse( attr1.equals( null ) );
+        
+        EntryAttribute attr2 = new DefaultClientAttribute( "test" );
+        
+        assertTrue( attr1.equals( attr2 ) );
+        
+        attr2.setId( "TEST" );
+        assertTrue( attr1.equals( attr2 ) );
+
+        attr1.setId( "tset" );
+        assertFalse( attr1.equals( attr2 ) );
+        
+        attr1.setUpId( "TEST" );
+        assertTrue( attr1.equals( attr2 ) );
+        
+        attr1.add( "a", "b", "c" );
+        attr2.add( "c", "b", "a" );
+        assertTrue( attr1.equals( attr2 ) );
+        
+        attr1.setHR( true );
+        attr2.setHR( false );
+        assertFalse( attr1.equals( attr2 ) );
+        
+        EntryAttribute attr3 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr4 = new DefaultClientAttribute( "test" );
+        
+        attr3.put( NULL_BINARY_VALUE );
+        attr4.put( NULL_BINARY_VALUE );
+        assertTrue( attr3.equals( attr4 ) );
+        
+        EntryAttribute attr5 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr6 = new DefaultClientAttribute( "test" );
+        
+        attr5.put( NULL_BINARY_VALUE );
+        attr6.put( NULL_STRING_VALUE );
+        assertFalse( attr5.equals( attr6 ) );
+
+        EntryAttribute attr7 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr8 = new DefaultClientAttribute( "test" );
+        
+        attr7.put( "a" );
+        attr8.put( BYTES2 );
+        assertFalse( attr7.equals( attr8 ) );
+
+        EntryAttribute attr9 = new DefaultClientAttribute( "test" );
+        EntryAttribute attr10 = new DefaultClientAttribute( "test" );
+        
+        attr7.put( "a" );
+        attr7.add( BYTES2 );
+        attr8.put( "a", "b" );
+        assertTrue( attr9.equals( attr10 ) );
+    }
+
+
+    /**
+     * Test method testClone()
+     */
+    @Test
+    public void testClone()
+    {
+        EntryAttribute attr = new DefaultClientAttribute( "test" );
+        
+        EntryAttribute clone = attr.clone();
+        
+        assertEquals( attr, clone );
+        attr.setId( "new" );
+        assertEquals( "test", clone.getId() );
+        
+        attr.add( "a", (String)null, "b" );
+        clone = attr.clone();
+        assertEquals( attr, clone );
+        
+        attr.remove( "a" );
+        assertNotSame( attr, clone );
+        
+        clone = attr.clone();
+        assertEquals( attr, clone );
+
+        attr.setHR( false );
+        assertNotSame( attr, clone );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntryTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntryTest.java
new file mode 100644
index 0000000..4835b28
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntryTest.java
@@ -0,0 +1,1158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.shared.ldap.entry.client;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * A test class for the DefaultClientEntry class
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DefaultClientEntryTest
+{
+    private static LdapDN EXAMPLE_DN;
+    private static final byte[] BYTES1 = new byte[]{ 'a', 'b' };
+    private static final byte[] BYTES2 = new byte[]{ 'b' };
+    private static final byte[] BYTES3 = new byte[]{ 'c' };
+    
+    
+    /**
+     * Helper method which creates an entry with 4 attributes.
+     */
+    private Entry createEntry()
+    {
+        try
+        {
+            Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+            
+            EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+            EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+            EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+            EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+            
+            entry.put( attrOC, attrCN, attrSN, attrPWD );
+            
+            return entry;
+        }
+        catch ( NamingException ne )
+        {
+            // Do nothing
+            return null;
+        }
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception
+    {
+        EXAMPLE_DN = new LdapDN( "dc=example,dc=com" );
+    }
+
+
+    /**
+     * Test method for DefaultClientEntry()
+     */
+    @Test
+    public void testDefaultClientEntry()
+    {
+        Entry entry = new DefaultClientEntry();
+        
+        assertNotNull( entry );
+        assertNull( entry.getDn() );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    /**
+     * Test method for DefaultClientEntry( LdapDN )
+     */
+    @Test
+    public void testDefaultClientEntryLdapDN()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertNotNull( entry );
+        assertNotNull( entry.getDn() );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    /**
+     * Test method for DefaultClientEntry( LdapDN, String... )
+     */
+    @Test
+    public void testDefaultClientEntryLdapDNStringArray()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN, "ObjectClass", "cn", "sn" );
+        
+        assertNotNull( entry );
+        assertNotNull( entry.getDn() );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( 3, entry.size() );
+        assertTrue( entry.containsAttribute( "OBJECTCLASS" ) );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        assertTrue( entry.containsAttribute( "SN" ) );
+
+        try
+        {
+            new DefaultClientEntry( EXAMPLE_DN, "ObjectClass", (String)null, "sn" );
+            fail();
+        }
+        catch( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+
+        try
+        {
+            new DefaultClientEntry( EXAMPLE_DN, "ObjectClass", " ", "sn" );
+            fail();
+        }
+        catch( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    /**
+     * Test method for DefaultClientEntry( LdapDN, EntryAttribute... )
+     */
+    @Test
+    public void testDefaultClientEntryLdapDNEntryAttributeArray()
+    {
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+        
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN, attrOC, attrCN, attrPWD );
+        
+        assertNotNull( entry );
+        assertNotNull( entry.getDn() );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( 3, entry.size() );
+        assertTrue( entry.containsAttribute( "OBJECTCLASS" ) );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        assertTrue( entry.containsAttribute( "userPassword" ) );
+        
+        entry = new DefaultClientEntry( EXAMPLE_DN, attrOC, attrCN, attrOC );
+        assertNotNull( entry );
+        assertNotNull( entry.getDn() );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( 2, entry.size() );
+        assertTrue( entry.containsAttribute( "OBJECTCLASS" ) );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        
+        entry = new DefaultClientEntry( EXAMPLE_DN, attrOC, (EntryAttribute)null );
+        assertNotNull( entry );
+        assertNotNull( entry.getDn() );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        assertEquals( 1, entry.size() );
+        assertTrue( entry.containsAttribute( "OBJECTCLASS" ) );
+    }
+
+
+    /**
+     * Test method for add( EntryAttribute... )
+     */
+    @Test
+    public void testAddEntryAttributeArray() throws NamingException
+    {
+        Entry entry = createEntry();
+        
+        assertEquals( 4, entry.size() );
+        assertTrue( entry.containsAttribute( "ObjectClass" ) );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        assertTrue( entry.containsAttribute( "  sn  " ) );
+        assertTrue( entry.containsAttribute( "userPassword" ) );
+    
+        EntryAttribute attr = entry.get( "objectclass" );
+        assertEquals( 2, attr.size() );
+        
+        EntryAttribute attrCN2 = new DefaultClientAttribute( "cn", "test1", "test3" );
+        entry.add( attrCN2 );
+        assertEquals( 4, entry.size() );
+        attr = entry.get( "cn" );
+        assertEquals( 3, attr.size() );
+        assertTrue( attr.contains( "test1", "test2", "test3" ) );
+        
+        // Check adding some byte[] values (they will be transformed to Strings)
+        attrCN2.put( BYTES1, BYTES2 );
+        entry.add( attrCN2 );
+        assertEquals( 4, entry.size() );
+        attr = entry.get( "cn" );
+        assertEquals( 5, attr.size() );
+        assertTrue( attr.contains( "test1", "test2", "test3", "ab", "b" ) );
+    }
+
+
+    /**
+     * Test method for add( String, byte[]... )
+     */
+    @Test
+    public void testAddStringByteArrayArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry();
+        
+        entry.add( "userPassword", (byte[])null );
+        assertEquals( 1, entry.size() );
+        EntryAttribute attributePWD = entry.get( "userPassword" );
+        assertEquals( 1, attributePWD.size() );
+        assertNotNull( attributePWD.get() );
+        assertNull( attributePWD.get().get() );
+        
+        entry.add( "jpegPhoto", BYTES1, BYTES1, BYTES2 );
+        assertEquals( 2, entry.size() );
+        EntryAttribute attributeJPG = entry.get( "jpegPhoto" );
+        assertEquals( 2, attributeJPG.size() );
+        assertNotNull( attributeJPG.get() );
+        assertTrue( attributeJPG.contains( BYTES1 ) );
+        assertTrue( attributeJPG.contains( BYTES2 ) );
+    }
+
+
+    /**
+     * Test method for add( String, String... )
+     */
+    @Test
+    public void testAddStringStringArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry();
+        
+        entry.add( "cn", (String)null );
+        assertEquals( 1, entry.size() );
+        EntryAttribute attributeCN = entry.get( "cn" );
+        assertEquals( 1, attributeCN.size() );
+        assertNotNull( attributeCN.get() );
+        assertNull( attributeCN.get().get() );
+        
+        entry.add( "sn", "test", "test", "TEST" );
+        assertEquals( 2, entry.size() );
+        EntryAttribute attributeSN = entry.get( "sn" );
+        assertEquals( 2, attributeSN.size() );
+        assertNotNull( attributeSN.get() );
+        assertTrue( attributeSN.contains( "test" ) );
+        assertTrue( attributeSN.contains( "TEST" ) );
+    }
+
+
+    /**
+     * Test method for add( String, Value<?>... )
+     */
+    @Test
+    public void testAddStringValueArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry();
+        
+        Value<String> value = new ClientStringValue( (String)null );
+        
+        entry.add( "cn", value );
+        assertEquals( 1, entry.size() );
+        EntryAttribute attributeCN = entry.get( "cn" );
+        assertEquals( 1, attributeCN.size() );
+        assertNotNull( attributeCN.get() );
+        assertNull( attributeCN.get().get() );
+        
+        Value<String> value1 = new ClientStringValue( "test1" );
+        Value<String> value2 = new ClientStringValue( "test2" );
+        Value<String> value3 = new ClientStringValue( "test1" );
+
+        entry.add( "sn", value1, value2, value3 );
+        assertEquals( 2, entry.size() );
+        EntryAttribute attributeSN = entry.get( "sn" );
+        assertEquals( 2, attributeSN.size() );
+        assertNotNull( attributeSN.get() );
+        assertTrue( attributeSN.contains( value1 ) );
+        assertTrue( attributeSN.contains( value2 ) );
+        
+        Value<byte[]> value4 = new ClientBinaryValue( BYTES1 );
+        entry.add( "l", value1, value4 );
+        assertEquals( 3, entry.size() );
+        EntryAttribute attributeL = entry.get( "l" );
+        assertEquals( 2, attributeL.size() );
+        assertNotNull( attributeL.get() );
+        assertTrue( attributeL.contains( value1 ) );
+        
+        // The byte[] value must have been transformed to a String
+        assertTrue( attributeL.contains( "ab" ) );
+    }
+
+
+
+
+    /**
+     * Test method for clear()
+     */
+    @Test
+    public void testClear() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertEquals( 0, entry.size() );
+        assertNull( entry.get( "ObjectClass" ) );
+        entry.clear();
+        assertEquals( 0, entry.size() );
+        assertNull( entry.get( "ObjectClass" ) );
+        
+        entry.add( "ObjectClass", "top", "person" );
+        assertEquals( 1, entry.size() );
+        assertNotNull( entry.get( "ObjectClass" ) );
+        
+        entry.clear();
+        assertEquals( 0, entry.size() );
+        assertNull( entry.get( "ObjectClass" ) );
+    }
+
+
+    /**
+     * Test method for clone()
+     */
+    @Test
+    public void testClone() throws NamingException
+    {
+        Entry entry1 = new DefaultClientEntry();
+        
+        Entry entry2 = entry1.clone();
+        
+        assertEquals( entry1, entry2 );
+        entry2.setDn( EXAMPLE_DN );
+        
+        assertNull( entry1.getDn() );
+        
+        entry1.setDn( EXAMPLE_DN );
+        entry2 = entry1.clone();
+        assertEquals( entry1, entry2 );
+        
+        entry1.add( "objectClass", "top", "person" );
+        entry1.add( "cn", "test1", "test2" );
+        
+        entry2 = entry1.clone();
+        assertEquals( entry1, entry2 );
+        
+        entry1.add( "cn", "test3" );
+        assertEquals( 2, entry2.get( "cn" ).size() );
+        assertFalse( entry2.contains( "cn", "test3" ) );
+        
+        entry1.add( "sn", (String)null );
+        assertFalse( entry2.containsAttribute( "sn" ) );
+    }
+
+    
+    /**
+     * Test method for contains( EntryAttribute... )
+     */
+    @Test
+    public void testContainsEntryAttributeArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+
+        assertFalse( entry.contains( attrOC, attrCN ) );
+        
+        entry.add( attrOC, attrCN );
+
+        assertTrue( entry.contains( attrOC, attrCN ) );
+        assertFalse( entry.contains( attrOC, attrCN, attrSN ) );
+        
+        entry.add( attrSN, attrPWD );
+
+        assertTrue( entry.contains( attrSN, attrPWD ) );
+    }
+
+
+    /**
+     * Test method for contains( String, byte[]... )
+     */
+    @Test
+    public void testContainsStringByteArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertFalse( entry.containsAttribute( "objectClass" ) );
+        
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, (byte[])null, BYTES2 );
+
+        entry.add( attrPWD );
+        
+        assertTrue( entry.contains( "  userPASSWORD  ", BYTES1, BYTES2 ) );
+        assertTrue( entry.contains( "  userPASSWORD  ", (byte[])null ) );
+        
+        // We can search for byte[] using Strings. the strings will be converted to byte[]
+        assertTrue( entry.contains( "  userPASSWORD  ", "ab", "b" ) );
+
+        assertFalse( entry.contains( "  userPASSWORD  ", "ab", "b", "d" ) );
+    }
+
+
+    /**
+     * Test method for contains( String, String... )
+     */
+    @Test
+    public void testContainsStringStringArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertFalse( entry.containsAttribute( "objectClass" ) );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2", (String)null );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+
+        entry.add( attrOC, attrCN, attrSN, attrPWD );
+        
+        assertTrue( entry.contains( "OBJECTCLASS", "top", "person" ) );
+        assertTrue( entry.contains( " cn ", "test1", "test2" ) );
+        assertTrue( entry.contains( "Sn", "Test1", "Test2", (String)null ) );
+        assertTrue( entry.contains( "  userPASSWORD  ", "ab", "b" ) );
+        
+        assertFalse( entry.contains( "OBJECTCLASS", "PERSON" ) );
+        assertFalse( entry.contains( " cn ", "test1", "test3" ) );
+        assertFalse( entry.contains( "Sn", "Test" ) );
+        assertFalse( entry.contains( "  userPASSWORD  ", (String)null ) );
+    }
+
+
+    /**
+     * Test method for contains( Sring, Value<?>... )
+     */
+    @Test
+    public void testContainsStringValueArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertFalse( entry.containsAttribute( "objectClass" ) );
+        
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2", (String)null );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2, (byte[])null );
+
+        entry.add( attrCN, attrPWD );
+        
+        Value<String> strValue1 = new ClientStringValue( "test1" );
+        Value<String> strValue2 = new ClientStringValue( "test2" );
+        Value<String> strValue3 = new ClientStringValue( "test3" );
+        Value<String> strNullValue = new ClientStringValue( null);
+
+        Value<byte[]> binValue1 = new ClientBinaryValue( BYTES1 );
+        Value<byte[]> binValue2 = new ClientBinaryValue( BYTES2 );
+        Value<byte[]> binValue3 = new ClientBinaryValue( BYTES3 );
+        Value<byte[]> binNullValue = new ClientBinaryValue( null );
+
+        assertTrue( entry.contains( "CN", strValue1, strValue2, strNullValue ) );
+        assertTrue( entry.contains( "userpassword", binValue1, binValue2, binNullValue ) );
+        
+        assertFalse( entry.contains( "cn", strValue3 ) );
+        assertFalse( entry.contains( "UserPassword", binValue3 ) );
+    }
+
+
+    /**
+     * Test method for containsAttribute( String )
+     */
+    @Test
+    public void testContainsAttribute() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertFalse( entry.containsAttribute( "objectClass" ) );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+
+        entry.add( attrOC, attrCN, attrSN, attrPWD );
+        
+        assertTrue( entry.containsAttribute( "OBJECTCLASS" ) );
+        assertTrue( entry.containsAttribute( " cn " ) );
+        assertTrue( entry.containsAttribute( "Sn" ) );
+        assertTrue( entry.containsAttribute( "  userPASSWORD  " ) );
+        
+        entry.clear();
+
+        assertFalse( entry.containsAttribute( "OBJECTCLASS" ) );
+        assertFalse( entry.containsAttribute( " cn " ) );
+        assertFalse( entry.containsAttribute( "Sn" ) );
+        assertFalse( entry.containsAttribute( "  userPASSWORD  " ) );
+    }
+
+
+    /**
+     * Test method for equals()
+     */
+    @Test
+    public void testEqualsObject() throws NamingException
+    {
+        Entry entry1 = new DefaultClientEntry();
+        Entry entry2 = new DefaultClientEntry();
+        
+        assertEquals( entry1, entry2 );
+        
+        entry1.setDn( EXAMPLE_DN );
+        assertNotSame( entry1, entry2 );
+        
+        entry2.setDn( EXAMPLE_DN );
+        assertEquals( entry1, entry2 );
+
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+        
+        entry1.put( attrOC, attrCN, attrSN, attrPWD );
+        entry2.put( attrOC, attrCN, attrSN );
+        assertNotSame( entry1, entry2 );
+        
+        entry2.put( attrPWD );
+        assertEquals( entry1, entry2 );
+        
+        EntryAttribute attrL1 = new DefaultClientAttribute( "l", "Paris", "New-York" );
+        EntryAttribute attrL2 = new DefaultClientAttribute( "l", "Paris", "Tokyo" );
+        
+        entry1.put( attrL1 );
+        entry2.put( attrL1 );
+        assertEquals( entry1, entry2 );
+        
+        entry1.add( "l", "London" );
+        assertNotSame( entry1, entry2 );
+
+        entry2.add( attrL2 );
+        assertNotSame( entry1, entry2 );
+
+        entry1.clear();
+        entry2.clear();
+        assertEquals( entry1, entry2 );
+    }
+
+
+    /**
+     * Test method for get( String )
+     */
+    @Test
+    public void testGet() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertNull( entry.get( "objectClass" ) );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+
+        entry.add( attrOC, attrCN, attrSN, attrPWD );
+        
+        assertNotNull( entry.get( "  CN  " ) );
+        EntryAttribute attribute = entry.get( "cN" );
+        
+        assertEquals( attribute, attrCN );
+        
+        assertNull( entry.get( null ) );
+        assertNull( entry.get( "  " ) );
+        assertNull( entry.get( "l" ) );
+    }
+
+
+    /**
+     * Test method for getDN()
+     */
+    @Test
+    public void testGetDn() throws InvalidNameException 
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+        
+        LdapDN testDn = new LdapDN( "cn=test" );
+        entry.setDn( testDn );
+        
+        assertEquals( testDn, entry.getDn() );
+    }
+
+
+    /**
+     * Test method for hashcode()
+     */
+    @Test
+    public void testHashCode() throws InvalidNameException, NamingException
+    {
+        Entry entry1 = new DefaultClientEntry( EXAMPLE_DN );
+        Entry entry2 = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertEquals( entry1.hashCode(), entry2.hashCode() );
+        
+        entry2.setDn( new LdapDN( "ou=system,dc=com" ) );
+        assertNotSame( entry1.hashCode(), entry2.hashCode() );
+        
+        entry2.setDn( EXAMPLE_DN );
+        assertEquals( entry1.hashCode(), entry2.hashCode() );
+        
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+
+        entry1.add( attrOC, attrCN, attrSN, attrPWD );
+        entry2.add( attrOC, attrCN, attrSN, attrPWD );
+
+        assertEquals( entry1.hashCode(), entry2.hashCode() );
+        
+        Entry entry3 = new DefaultClientEntry( EXAMPLE_DN );
+        entry3.add( attrOC, attrSN, attrCN, attrPWD );
+
+        assertEquals( entry1.hashCode(), entry3.hashCode() );
+    }
+
+    
+    /**
+     * Test method for hasObjectClass( String )
+     */
+    @Test
+    public void testHasObjectClass() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertFalse( entry.containsAttribute( "objectClass" ) );
+        assertFalse( entry.hasObjectClass( "top" ) );
+        
+        entry.add( new DefaultClientAttribute( "objectClass", "top", "person" ) );
+        
+        assertTrue( entry.hasObjectClass( "top" ) );
+        assertTrue( entry.hasObjectClass( "person" ) );
+        assertFalse( entry.hasObjectClass( "inetorgperson" ) );
+        assertFalse( entry.hasObjectClass( null ) );
+        assertFalse( entry.hasObjectClass( "" ) );
+    }
+
+    
+    /**
+     * Test method for Iterator()
+     */
+    @Test
+    public void testIterator() throws NamingException
+    {
+        Entry entry = createEntry();
+        
+        Iterator<EntryAttribute> iterator = entry.iterator();
+        
+        assertTrue( iterator.hasNext() );
+        
+        Set<String> expectedIds = new HashSet<String>();
+        expectedIds.add( "objectclass" );
+        expectedIds.add( "cn" );
+        expectedIds.add( "sn" );
+        expectedIds.add( "userpassword" );
+        
+        while ( iterator.hasNext() )
+        {
+            EntryAttribute attribute = iterator.next();
+            
+            String id = attribute.getId();
+            assertTrue( expectedIds.contains( id ) );
+            expectedIds.remove( id );
+        }
+        
+        assertEquals( 0, expectedIds.size() );
+    }
+
+    
+    /**
+     * Test method for put( EntryAttribute... )
+     */
+    @Test
+    public void testPutEntryAttributeArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+        
+        List<EntryAttribute> removed = entry.put( attrOC, attrCN, attrSN, attrPWD );
+        
+        assertEquals( 4, entry.size() );
+        assertEquals( 0, removed.size() );
+        assertTrue( entry.containsAttribute( "ObjectClass" ) );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        assertTrue( entry.containsAttribute( "  sn  " ) );
+        assertTrue( entry.containsAttribute( "userPassword" ) );
+        
+        EntryAttribute attrCN2 = new DefaultClientAttribute( "cn", "test3", "test4" );
+        removed = entry.put( attrCN2 );
+        assertEquals( 4, entry.size() );
+        assertEquals( 1, removed.size() );
+        assertTrue( entry.containsAttribute( "CN" ) );
+        assertTrue( entry.contains( "cn", "test3", "test4" ) );
+    }
+
+
+    /**
+     * Test method for put( String, byte[]... )
+     */
+    @Test
+    public void testPutStringByteArrayArray()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        try
+        {
+            entry.put( (String)null, BYTES1 );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            entry.put( "   ", BYTES1 );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        entry.put( "userPassword", (byte[])null );
+        assertEquals( 1, entry.size() );
+        assertNotNull( entry.get( "userPassword" ) );
+        assertEquals( 1, entry.get( "userPassword" ).size() );
+        assertNull( entry.get( "userPassword" ).get().get() );
+        
+        entry.put(  "jpegPhoto", BYTES1, BYTES2, BYTES1 );
+        assertEquals( 2, entry.size() );
+        assertNotNull( entry.get( "jpegPhoto" ) );
+        assertEquals( 2, entry.get( "JPEGPhoto" ).size() );
+        EntryAttribute attribute = entry.get( "jpegPhoto" );
+        assertTrue( attribute.contains( BYTES1 ) );
+        assertTrue( attribute.contains( BYTES2 ) );
+        assertEquals( "jpegphoto", attribute.getId() );
+        assertEquals( "jpegPhoto", attribute.getUpId() );
+    }
+
+
+    /**
+     * Test method for put( String, String... )
+     */
+    @Test
+    public void testPutStringStringArray()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        try
+        {
+            entry.put( (String)null, "a" );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            entry.put( "   ", "a" );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        entry.put( "sn", (String)null );
+        assertEquals( 1, entry.size() );
+        assertNotNull( "sn", entry.get( "sn" ) );
+        assertEquals( 1, entry.get( "sn" ).size() );
+        assertNull( entry.get( "sn" ).get().get() );
+        
+        entry.put(  "ObjectClass", "top", "person", "top" );
+        assertEquals( 2, entry.size() );
+        assertNotNull( "objectclass", entry.get( "sn" ) );
+        assertEquals( 2, entry.get( "OBJECTCLASS" ).size() );
+        EntryAttribute attribute = entry.get( "objectClass" );
+        assertTrue( attribute.contains( "top" ) );
+        assertTrue( attribute.contains( "person" ) );
+        assertEquals( "objectclass", attribute.getId() );
+        assertEquals( "ObjectClass", attribute.getUpId() );
+    }
+
+
+    /**
+     * Test method for pu( String, Value<?>... )
+     */
+    @Test
+    public void testPutStringValueArray()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        Value<String> strValueTop = new ClientStringValue( "top" );
+        Value<String> strValuePerson = new ClientStringValue( "person" );
+        Value<String> strValueTop2 = new ClientStringValue( "top" );
+        Value<String> strNullValue = new ClientStringValue( null);
+
+        Value<byte[]> binValue1 = new ClientBinaryValue( BYTES1 );
+        Value<byte[]> binValue2 = new ClientBinaryValue( BYTES2 );
+        Value<byte[]> binValue3 = new ClientBinaryValue( BYTES1 );
+        Value<byte[]> binNullValue = new ClientBinaryValue( null );
+
+        try
+        {
+            entry.put( (String)null, strValueTop );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        try
+        {
+            entry.put( "   ", strValueTop );
+            fail();
+        }
+        catch ( IllegalArgumentException iae)
+        {
+            assertTrue( true );
+        }
+        
+        entry.put( "sn", strNullValue );
+        assertEquals( 1, entry.size() );
+        assertNotNull( "sn", entry.get( "sn" ) );
+        assertEquals( 1, entry.get( "sn" ).size() );
+        assertNull( entry.get( "sn" ).get().get() );
+        
+        entry.clear();
+        
+        entry.put(  "ObjectClass", strValueTop, strValuePerson, strValueTop2, strNullValue );
+        assertEquals( 1, entry.size() );
+        assertNotNull( "objectclass", entry.get( "objectclass" ) );
+        assertEquals( 3, entry.get( "OBJECTCLASS" ).size() );
+        EntryAttribute attribute = entry.get( "objectClass" );
+        assertTrue( attribute.contains( "top" ) );
+        assertTrue( attribute.contains( "person" ) );
+        assertTrue( attribute.contains( (String)null ) );
+        assertEquals( "objectclass", attribute.getId() );
+        assertEquals( "ObjectClass", attribute.getUpId() );
+
+        entry.clear();
+        
+        entry.put( "userpassword", strNullValue );
+        assertEquals( 1, entry.size() );
+        assertNotNull( "userpassword", entry.get( "userpassword" ) );
+        assertEquals( 1, entry.get( "userpassword" ).size() );
+        assertNull( entry.get( "userpassword" ).get().get() );
+        
+        entry.clear();
+        
+        entry.put(  "userPassword", binValue1, binValue2, binValue3, binNullValue );
+        assertEquals( 1, entry.size() );
+        assertNotNull( "userpassword", entry.get( "userpassword" ) );
+        assertEquals( 3, entry.get( "userpassword" ).size() );
+        attribute = entry.get( "userpassword" );
+        assertTrue( attribute.contains( BYTES1 ) );
+        assertTrue( attribute.contains( BYTES2 ) );
+        assertTrue( attribute.contains( (byte[])null ) );
+        assertEquals( "userpassword", attribute.getId() );
+        assertEquals( "userPassword", attribute.getUpId() );
+    }
+
+
+    /**
+     * Test method for removeAttributes( String... )
+     */
+    @Test
+    public void testRemoveAttributesStringArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+        
+        entry.put( attrOC, attrCN, attrSN, attrPWD );
+        
+        entry.removeAttributes( "CN", "SN" );
+        
+        assertFalse( entry.containsAttribute( "cn", "sn" ) );
+        assertTrue( entry.containsAttribute( "objectclass", "userpassword" ) );
+        
+        List<EntryAttribute> removed = entry.removeAttributes( "badId" );
+        assertNull( removed );
+        
+        removed = entry.removeAttributes( (String )null );
+        assertNull( removed );
+    }
+    
+    
+    /**
+     * Test method for remove( EntryAttribute... )
+     */
+    @Test
+    public void testRemoveEntryAttributeArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        EntryAttribute attrOC = new DefaultClientAttribute( "objectClass", "top", "person" );
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2" );
+        EntryAttribute attrSN = new DefaultClientAttribute( "sn", "Test1", "Test2" );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2 );
+        
+        entry.put( attrOC, attrCN, attrSN, attrPWD );
+        
+        List<EntryAttribute> removed = entry.remove( attrSN, attrPWD );
+        
+        assertEquals( 2, removed.size() ); 
+        assertEquals( 2, entry.size() );
+        assertTrue( removed.contains( attrSN ) );
+        assertTrue( removed.contains( attrPWD ) );
+        assertTrue( entry.contains( "objectClass", "top", "person" ) );
+        assertTrue( entry.contains( "cn", "test1", "test2" ) );
+        assertFalse( entry.containsAttribute( "sn" ) );
+        assertFalse( entry.containsAttribute( "userPassword" ) );
+
+        removed = entry.remove( attrSN, attrPWD );
+        
+        assertEquals( 0, removed.size() );
+    }
+
+
+    /**
+     * Test method for remove(String, byte[]... )
+     */
+    @Test
+    public void testRemoveStringByteArrayArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, (byte[])null, BYTES2 );
+
+        entry.put( attrPWD );
+        assertTrue( entry.remove( "userPassword", (byte[])null ) );
+        assertTrue( entry.remove( "userPassword", BYTES1, BYTES2 ) );
+        assertFalse( entry.containsAttribute( "userPassword" ) );
+        
+        entry.add( "userPassword", BYTES1, (byte[])null, BYTES2 );
+        assertTrue( entry.remove( "userPassword", (byte[])null ) );
+        assertEquals( 2, entry.get( "userPassword" ).size() );
+        assertTrue( entry.remove( "userPassword", BYTES1, BYTES3 ) );
+        assertEquals( 1, entry.get( "userPassword" ).size() );
+        assertTrue( Arrays.equals( BYTES2, entry.get( "userPassword" ).getBytes() ) );
+        
+        assertFalse( entry.remove( "userPassword", BYTES3 ) );
+        assertFalse( entry.remove( "void", "whatever" ) );
+    }
+
+
+    /**
+     * Test method for remove( String, String... )
+     */
+    @Test
+    public void testRemoveStringStringArray() throws NamingException
+    {
+        Entry entry = createEntry();
+        
+        assertTrue( entry.remove( "cn", "test1" ) );
+        assertTrue( entry.remove( "cn", "test2" ) );
+        assertFalse( entry.containsAttribute( "cn" ) );
+        
+        entry.add( "cn", "test1", (String)null, "test2" );
+        assertTrue( entry.remove( "cn", (String)null ) );
+        assertEquals( 2, entry.get( "cn" ).size() );
+        assertTrue( entry.remove( "cn", "test1", "test3" ) );
+        assertEquals( 1, entry.get( "cn" ).size() );
+        assertEquals( "test2", entry.get( "cn" ).get().get() );
+        
+        assertFalse( entry.remove( "cn", "test3" ) );
+        assertFalse( entry.remove( "void", "whatever" ) );
+    }
+
+
+    /**
+     * Test method for remove(String, Value<?>... )
+     */
+    @Test
+    public void testRemoveStringValueArray() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+
+        EntryAttribute attrCN = new DefaultClientAttribute( "cn", "test1", "test2", (String)null );
+        EntryAttribute attrPWD = new DefaultClientAttribute( "userPassword", BYTES1, BYTES2, (byte[])null );
+
+        entry.add( attrCN, attrPWD );
+        
+        Value<String> strValue1 = new ClientStringValue( "test1" );
+        Value<String> strValue2 = new ClientStringValue( "test2" );
+        Value<String> strValue3 = new ClientStringValue( "test3" );
+        Value<String> strNullValue = new ClientStringValue( null);
+
+        Value<byte[]> binValue1 = new ClientBinaryValue( BYTES1 );
+        Value<byte[]> binValue2 = new ClientBinaryValue( BYTES2 );
+        Value<byte[]> binValue3 = new ClientBinaryValue( BYTES3 );
+        Value<byte[]> binNullValue = new ClientBinaryValue( null );
+        
+        assertTrue( entry.remove( "cn", strValue1, strNullValue ) );
+        assertTrue( entry.contains( "cn", strValue2 ) );
+        assertFalse( entry.remove( "cn", strValue3 ) );
+        assertTrue( entry.remove( "cn", strValue2 ) );
+        assertFalse( entry.containsAttribute( "cn" ) );
+
+        entry.add( attrCN, attrPWD );
+
+        assertTrue( entry.remove( "userpassword", binValue1, binNullValue ) );
+        assertTrue( entry.contains( "userpassword", binValue2 ) );
+        assertFalse( entry.remove( "userpassword", binValue3 ) );
+        assertTrue( entry.remove( "userpassword", binValue2 ) );
+        assertFalse( entry.containsAttribute( "userpassword" ) );
+    }
+    
+    
+    /**
+     * Test method for set( String... )
+     */
+    @Test
+    public void testSet() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+
+        entry.add( "ObjectClass", "top", "person" );
+        entry.add( "cn", "test1", "test2" );
+        entry.add( "sn", "Test" );
+        
+        List<EntryAttribute> removed = entry.set( "objectClass", "CN", "givenName" );
+        
+        assertEquals( 4, entry.size() );
+        assertNotNull( entry.get( "objectclass" ) );
+        assertNotNull( entry.get( "cn" ) );
+        assertNotNull( entry.get( "givenname" ) );
+        assertNotNull( entry.get( "sn" ) );
+        
+        assertNull( entry.get( "objectclass" ).get() );
+        assertNull( entry.get( "cn" ).get() );
+        assertNull( entry.get( "givenname" ).get() );
+        assertNotNull( entry.get( "sn" ).get() );
+        
+        assertNotNull( removed );
+        assertEquals( 2, removed.size() );
+    }
+
+
+    /**
+     * Test method for setDN( LdapDN )
+     */
+    @Test
+    public void testSetDn()
+    {
+        Entry entry = new DefaultClientEntry();
+        
+        assertNull( entry.getDn() );
+        
+        entry.setDn( EXAMPLE_DN );
+        assertEquals( EXAMPLE_DN, entry.getDn() );
+    }
+    
+    
+    /**
+     * Test method for size()
+     */
+    @Test
+    public void testSize() throws NamingException
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertEquals( 0, entry.size() );
+        entry.add( "ObjectClass", "top", "person" );
+        entry.add( "cn", "test" );
+        entry.add( "sn", "Test" );
+        
+        assertEquals( 3, entry.size() );
+       
+        entry.clear();
+        assertEquals( 0, entry.size() );
+    }
+
+    
+    /**
+     * Test method for for {@link org.apache.directory.shared.ldap.entry.client.DefaultClientEntry#toString()}.
+     */
+    @Test
+    public void testToString()
+    {
+        Entry entry = new DefaultClientEntry( EXAMPLE_DN );
+        
+        assertEquals( "ClientEntry\n    dn: dc=example,dc=com\n", entry.toString() );
+        
+        Value<String> strValueTop = new ClientStringValue( "top" );
+        Value<String> strValuePerson = new ClientStringValue( "person" );
+        Value<String> strNullValue = new ClientStringValue( null);
+
+        Value<byte[]> binValue1 = new ClientBinaryValue( BYTES1 );
+        Value<byte[]> binValue2 = new ClientBinaryValue( BYTES2 );
+        Value<byte[]> binNullValue = new ClientBinaryValue( null );
+        
+        entry.put( "ObjectClass", strValueTop, strValuePerson, strNullValue );
+        entry.put( "UserPassword", binValue1, binValue2, binNullValue );
+
+        String expected = 
+            "ClientEntry\n" +
+            "    dn: dc=example,dc=com\n" +
+            "    ObjectClass: top\n" +
+            "    ObjectClass: person\n" +
+            "    ObjectClass: ''\n" +
+            "    UserPassword: '0x61 0x62 '\n" +
+            "    UserPassword: '0x62 '\n" +
+            "    UserPassword: ''\n";
+
+        assertEquals( expected, entry.toString() );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterNodeEqualityTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterNodeEqualityTest.java
index eca151a..05292bd 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterNodeEqualityTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterNodeEqualityTest.java
@@ -20,6 +20,8 @@
 package org.apache.directory.shared.ldap.filter;
 
 
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
+
 import junit.framework.TestCase;
 
 
@@ -29,99 +31,92 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev: 575783 $
  */
-public class FilterNodeEqualityTest extends TestCase 
+public class FilterNodeEqualityTest extends TestCase
 {
-	public void testEqualityEquals()
-	{
-		EqualityNode eqNode1 = new EqualityNode( "attr1", "test" ); 
-		EqualityNode eqNode2 = new EqualityNode( "attr1", "test" );
-		
-		assertEquals( "two exact nodes should be equal", eqNode1, eqNode2 );
-		
-		eqNode2 = new EqualityNode( "attr2", "test" );
-		assertFalse( "different attribute in node should return false on equals()", 
-				eqNode1.equals( eqNode2 ) );
-		
-		eqNode2 = new EqualityNode( "attr2", "foobar" );
-		assertFalse( "different value in node should return false on equals()", 
-				eqNode1.equals( eqNode2 ) );
-		
-		PresenceNode presenceNode = new PresenceNode( "attr1" );
-		assertFalse( "two different leaf nodes should not be equal", eqNode1.equals( presenceNode ) );
-		assertFalse( "two different leaf nodes should not be equal", presenceNode.equals( eqNode1 ) );
-		
-		GreaterEqNode greaterEqNode = new GreaterEqNode ( "attr1", "test" );
-		assertFalse( "two different simple nodes should not be equal", eqNode1.equals( greaterEqNode ) );
-		assertFalse( "two different simple nodes should not be equal", greaterEqNode.equals( eqNode1 ) );
-	}
+    public void testEqualityEquals()
+    {
+        EqualityNode eqNode1 = new EqualityNode( "attr1", new ClientStringValue( "test" ) );
+        EqualityNode eqNode2 = new EqualityNode( "attr1", new ClientStringValue( "test" ) );
+
+        assertEquals( "two exact nodes should be equal", eqNode1, eqNode2 );
+
+        eqNode2 = new EqualityNode( "attr2", new ClientStringValue( "test" ) );
+        assertFalse( "different attribute in node should return false on equals()", eqNode1.equals( eqNode2 ) );
+
+        eqNode2 = new EqualityNode( "attr2", new ClientStringValue( "foobar" ) );
+        assertFalse( "different value in node should return false on equals()", eqNode1.equals( eqNode2 ) );
+
+        PresenceNode presenceNode = new PresenceNode( "attr1" );
+        assertFalse( "two different leaf nodes should not be equal", eqNode1.equals( presenceNode ) );
+        assertFalse( "two different leaf nodes should not be equal", presenceNode.equals( eqNode1 ) );
+
+        GreaterEqNode greaterEqNode = new GreaterEqNode( "attr1", new ClientStringValue( "test" ) );
+        assertFalse( "two different simple nodes should not be equal", eqNode1.equals( greaterEqNode ) );
+        assertFalse( "two different simple nodes should not be equal", greaterEqNode.equals( eqNode1 ) );
+    }
 
 
-	public void testGreaterEqEquals()
-	{
-		GreaterEqNode greaterEqNode1 = new GreaterEqNode( "attr1", "test" ); 
-		GreaterEqNode greaterEqNode2 = new GreaterEqNode( "attr1", "test" );
-		
-		assertEquals( "two exact nodes should be equal", greaterEqNode1, greaterEqNode2 );
-		
-		greaterEqNode2 = new GreaterEqNode( "attr2", "test" );
-		assertFalse( "different attribute in node should return false on equals()", 
-				greaterEqNode1.equals( greaterEqNode2 ) );
-		
-		greaterEqNode2 = new GreaterEqNode( "attr2", "foobar" );
-		assertFalse( "different value in node should return false on equals()", 
-				greaterEqNode1.equals( greaterEqNode2 ) );
-	}
+    public void testGreaterEqEquals()
+    {
+        GreaterEqNode greaterEqNode1 = new GreaterEqNode( "attr1", new ClientStringValue( "test" ) );
+        GreaterEqNode greaterEqNode2 = new GreaterEqNode( "attr1", new ClientStringValue( "test" ) );
+
+        assertEquals( "two exact nodes should be equal", greaterEqNode1, greaterEqNode2 );
+
+        greaterEqNode2 = new GreaterEqNode( "attr2", new ClientStringValue( "test" ) );
+        assertFalse( "different attribute in node should return false on equals()", greaterEqNode1
+            .equals( greaterEqNode2 ) );
+
+        greaterEqNode2 = new GreaterEqNode( "attr2", new ClientStringValue( "foobar" ) );
+        assertFalse( "different value in node should return false on equals()", greaterEqNode1.equals( greaterEqNode2 ) );
+    }
 
 
-	public void testLessEqEquals()
-	{
-		LessEqNode lessEqNode1 = new LessEqNode( "attr1", "test" ); 
-		LessEqNode lessEqNode2 = new LessEqNode( "attr1", "test" );
-		
-		assertEquals( "two exact nodes should be equal", lessEqNode1, lessEqNode2 );
-		
-		lessEqNode2 = new LessEqNode( "attr2", "test" );
-		assertFalse( "different attribute in node should return false on equals()", 
-				lessEqNode1.equals( lessEqNode2 ) );
-		
-		lessEqNode2 = new LessEqNode( "attr2", "foobar" );
-		assertFalse( "different value in node should return false on equals()", 
-				lessEqNode1.equals( lessEqNode2 ) );
-	}
+    public void testLessEqEquals()
+    {
+        LessEqNode lessEqNode1 = new LessEqNode( "attr1", new ClientStringValue( "test" ) );
+        LessEqNode lessEqNode2 = new LessEqNode( "attr1", new ClientStringValue( "test" ) );
+
+        assertEquals( "two exact nodes should be equal", lessEqNode1, lessEqNode2 );
+
+        lessEqNode2 = new LessEqNode( "attr2", new ClientStringValue( "test" ) );
+        assertFalse( "different attribute in node should return false on equals()", lessEqNode1.equals( lessEqNode2 ) );
+
+        lessEqNode2 = new LessEqNode( "attr2", new ClientStringValue( "foobar" ) );
+        assertFalse( "different value in node should return false on equals()", lessEqNode1.equals( lessEqNode2 ) );
+    }
 
 
-	public void testApproximateEqEquals()
-	{
-		ApproximateNode approximateNode1 = new ApproximateNode( "attr1", "test" ); 
-		ApproximateNode approximateNode2 = new ApproximateNode( "attr1", "test" );
-		
-		assertEquals( "two exact nodes should be equal", approximateNode1, approximateNode2 );
-		
-		approximateNode2 = new ApproximateNode( "attr2", "test" );
-		assertFalse( "different attribute in node should return false on equals()", 
-				approximateNode1.equals( approximateNode2 ) );
-		
-		approximateNode2 = new ApproximateNode( "attr2", "foobar" );
-		assertFalse( "different value in node should return false on equals()", 
-				approximateNode1.equals( approximateNode2 ) );
-	}
-	
-	
-	public void testPresenceEquals()
-	{
-		PresenceNode presenceNode1 = new PresenceNode( "attr1" );
-		PresenceNode presenceNode2 = new PresenceNode( "attr1" );
-		
-		assertEquals( "two exact presence nodes on same attribute should be equal", 
-				presenceNode1, presenceNode2 );
-		
-		presenceNode2 = new PresenceNode( "attr2" );
-		assertFalse( "presence nodes on different attributes should not be equal", 
-				presenceNode1.equals( presenceNode2 ) );
-	}
-	
-	
-	public void testSubstringEquals()
-	{
-	}
+    public void testApproximateEqEquals()
+    {
+        ApproximateNode approximateNode1 = new ApproximateNode( "attr1", new ClientStringValue( "test" ) );
+        ApproximateNode approximateNode2 = new ApproximateNode( "attr1", new ClientStringValue( "test" ) );
+
+        assertEquals( "two exact nodes should be equal", approximateNode1, approximateNode2 );
+
+        approximateNode2 = new ApproximateNode( "attr2", new ClientStringValue( "test" ) );
+        assertFalse( "different attribute in node should return false on equals()", approximateNode1
+            .equals( approximateNode2 ) );
+
+        approximateNode2 = new ApproximateNode( "attr2", new ClientStringValue( "foobar" ) );
+        assertFalse( "different value in node should return false on equals()", approximateNode1
+            .equals( approximateNode2 ) );
+    }
+
+
+    public void testPresenceEquals()
+    {
+        PresenceNode presenceNode1 = new PresenceNode( "attr1" );
+        PresenceNode presenceNode2 = new PresenceNode( "attr1" );
+
+        assertEquals( "two exact presence nodes on same attribute should be equal", presenceNode1, presenceNode2 );
+
+        presenceNode2 = new PresenceNode( "attr2" );
+        assertFalse( "presence nodes on different attributes should not be equal", presenceNode1.equals( presenceNode2 ) );
+    }
+
+
+    public void testSubstringEquals()
+    {
+    }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterParserTest.java
index bd40208..ee46777 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/filter/FilterParserTest.java
@@ -83,7 +83,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou~=people)" );
         assertEquals( "ou", node.getAttribute() );
-        assertEquals( "people", node.getValue() );
+        assertEquals( "people", node.getValue().get() );
         assertTrue( node instanceof ApproximateNode );
     }
 
@@ -138,7 +138,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou;lang-de>=\\23\\42asdl fkajsd)" );
         assertEquals( "ou;lang-de", node.getAttribute() );
-        assertEquals( "\\23\\42asdl fkajsd", node.getValue() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
     }
 
 
@@ -147,7 +147,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou;lang-de;version-124>=\\23\\42asdl fkajsd)" );
         assertEquals( "ou;lang-de;version-124", node.getAttribute() );
-        assertEquals( "\\23\\42asdl fkajsd", node.getValue() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
     }
 
 
@@ -156,7 +156,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(1.3.4.2;lang-de;version-124>=\\23\\42asdl fkajsd)" );
         assertEquals( "1.3.4.2;lang-de;version-124", node.getAttribute() );
-        assertEquals( "\\23\\42asdl fkajsd", node.getValue() );
+        assertEquals( "\\23\\42asdl fkajsd", node.getValue().get() );
     }
 
 
@@ -183,7 +183,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=people)" );
         assertEquals( "ou", node.getAttribute() );
-        assertEquals( "people", node.getValue() );
+        assertEquals( "people", node.getValue().get() );
         assertTrue( node instanceof EqualityNode );
     }
 
@@ -210,7 +210,7 @@
     {
         SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=people/in/my/company)" );
         assertEquals( "ou", node.getAttribute() );
-        assertEquals( "people/in/my/company", node.getValue() );
+        assertEquals( "people/in/my/company", node.getValue().get() );
         assertTrue( node instanceof EqualityNode );
     }
 
@@ -632,6 +632,51 @@
         assertNull( node.getFinal() );
     }
     
+    
+    @Test
+    public void testEqualsFilterNullValue() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(ou=)" );
+        assertEquals( "ou", node.getAttribute() );
+        assertEquals( "", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+
+    /**
+     * test a filter with a # in value
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testEqualsFilterWithPoundInValue() throws ParseException
+    {
+        SimpleNode node = ( SimpleNode ) FilterParser.parse( "(uid=#f1)" );
+        assertEquals( "uid", node.getAttribute() );
+        assertEquals( "#f1", node.getValue().get() );
+        assertTrue( node instanceof EqualityNode );
+    }
+
+
+    /**
+     * Test that special and non allowed chars into an assertionValue are not
+     * accepted. ((cf DIRSERVER-1196)
+     *
+     */
+    @Test
+    public void testSpecialCharsInMemberOf()
+    {
+        try
+        {
+            FilterParser.parse("(memberOf=1.2.840.113556.1.4.1301=$#@&*()==,2.5.4.11=local,2.5.4.11=users,2.5.4.11=readimanager)");
+            fail();
+        }
+        catch ( ParseException pe )
+        {
+            assertTrue( true );
+        }
+    }
+
+
     /*
     @Test
     public void testPerf() throws ParseException
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReaderTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReaderTest.java
new file mode 100644
index 0000000..4a487b1
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReaderTest.java
@@ -0,0 +1,774 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.ldif;
+
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.NamingException;
+
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+
+
+/**
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 379008 $
+ */
+public class LdifAttributesReaderTest
+{
+    private byte[] data;
+    
+    private File HJENSEN_JPEG_FILE = null;
+    
+    private File createFile( String name, byte[] data ) throws IOException
+    {
+        File jpeg = File.createTempFile( name, "jpg" );
+        
+        jpeg.createNewFile();
+
+        DataOutputStream os = new DataOutputStream( new FileOutputStream( jpeg ) );
+
+        os.write( data );
+        os.close();
+
+        // This file will be deleted when the JVM
+        // will exit.
+        jpeg.deleteOnExit();
+
+        return jpeg;
+    }
+
+    /**
+     * Create a file to be used by ":<" values
+     */
+    @Before public void setUp() throws Exception
+    {
+        data = new byte[256];
+
+        for ( int i = 0; i < 256; i++ )
+        {
+            data[i] = (byte) i;
+        }
+
+        HJENSEN_JPEG_FILE = createFile( "hjensen", data );
+    }
+
+    @Test public void testLdifNull() throws NamingException
+    {
+        String ldif = null;
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertEquals( 0, attributes.size() );
+    }
+    
+
+    @Test public void testLdifEmpty() throws NamingException
+    {
+        String ldif = "";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertEquals( 0, attributes.size() );
+    }
+
+    
+    @Test public void testLdifEmptyLines() throws NamingException
+    {
+        String ldif = "\n\n\r\r\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+        assertNull( attributes );
+    }
+
+    
+    @Test public void testLdifComments() throws NamingException
+    {
+        String ldif = 
+            "#Comment 1\r" + 
+            "#\r" + 
+            " th\n" + 
+            " is is still a comment\n" + 
+            "\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNull( attributes );
+    }
+
+    
+    @Test public void testLdifVersionStart() throws NamingException
+    {
+        String ldif = 
+            "cn: app1\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName:   app1   \n" + 
+            "dependencies:\n" + 
+            "envVars:";
+
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertEquals( 1, reader.getVersion() );
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+    }
+
+
+    /**
+     * Spaces at the end of values should not be included into values.
+     * 
+     * @throws NamingException
+     */
+    @Test public void testLdifParserEndSpaces() throws NamingException
+    {
+        String ldif = 
+            "cn: app1\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName:   app1   \n" + 
+            "dependencies:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+
+        Attributes attributes = reader.parseAttributes( ldif );
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+    }
+
+
+    @Test public void testLdifParser() throws NamingException
+    {
+        String ldif = 
+            "cn: app1\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName: app1   \n" + 
+            "dependencies:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "dependencies" );
+        assertNull( attr.get() );
+
+        attr = attributes.get( "envvars" );
+        assertNull( attr.get() );
+    }
+
+    
+    @Test public void testLdifParserMuiltiLineComments() throws NamingException
+    {
+        String ldif = 
+            "#comment\n" + 
+            " still a comment\n" + 
+            "cn: app1#another comment\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName: app1\n" + 
+            "serviceType: http\n" + 
+            "dependencies:\n" + 
+            "httpHeaders:\n" + 
+            "startupOptions:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "app1#another comment" ) );
+
+        attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "dependencies" );
+        assertNull( attr.get() );
+
+        attr = attributes.get( "envvars" );
+        assertNull( attr.get() );
+    }
+
+    
+    @Test public void testLdifParserMultiLineEntries() throws NamingException
+    {
+        String ldif = 
+            "#comment\n" + 
+            "cn: app1#another comment\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apAppli\n" +
+            " cation\n" + 
+            "displayName: app1\n" + 
+            "serviceType: http\n" + 
+            "dependencies:\n" + 
+            "httpHeaders:\n" + 
+            "startupOptions:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "app1#another comment" ) );
+
+        attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "dependencies" );
+        assertNull( attr.get() );
+
+        attr = attributes.get( "envvars" );
+        assertNull( attr.get() );
+    }
+
+    
+    @Test public void testLdifParserBase64() throws NamingException, UnsupportedEncodingException
+    {
+        String ldif = 
+            "#comment\n" + 
+            "cn:: RW1tYW51ZWwgTMOpY2hhcm55\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName: app1\n" + 
+            "serviceType: http\n" + 
+            "dependencies:\n" + 
+            "httpHeaders:\n" + 
+            "startupOptions:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny".getBytes( "UTF-8" ) ) );
+
+        attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "dependencies" );
+        assertNull( attr.get() );
+
+        attr = attributes.get( "envvars" );
+        assertNull( attr.get() );
+    }
+
+    
+    @Test public void testLdifParserBase64MultiLine() throws NamingException, UnsupportedEncodingException
+    {
+        String ldif = 
+            "#comment\n" + 
+            "cn:: RW1tYW51ZWwg\n" + 
+            " TMOpY2hhcm55ICA=\n" + 
+            "objectClass: top\n" + 
+            "objectClass: apApplication\n" + 
+            "displayName: app1\n" + 
+            "serviceType: http\n" + 
+            "dependencies:\n" + 
+            "httpHeaders:\n" + 
+            "startupOptions:\n" + 
+            "envVars:";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        assertNotNull( attributes );
+
+        Attribute attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Emmanuel L\u00e9charny  ".getBytes( "UTF-8" ) ) );
+
+        attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "apApplication" ) );
+
+        attr = attributes.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+
+        attr = attributes.get( "dependencies" );
+        assertNull( attr.get() );
+
+        attr = attributes.get( "envvars" );
+        assertNull( attr.get() );
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample1() throws NamingException
+    {
+        String ldif = 
+            "objectclass: top\n" + 
+            "objectclass: person\n" + 
+            "objectclass: organizationalPerson\n" + 
+            "cn: Barbara Jensen\n" + 
+            "cn: Barbara J Jensen\n" + 
+            "cn: Babs Jensen\n" + 
+            "sn: Jensen\n" + 
+            "uid: bjensen\n" + 
+            "telephonenumber: +1 408 555 1212\n" + 
+            "description: A big sailing fan.\n"; 
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "person" ) );
+        assertTrue( attr.contains( "organizationalPerson" ) );
+
+        attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Barbara Jensen" ) );
+        assertTrue( attr.contains( "Barbara J Jensen" ) );
+        assertTrue( attr.contains( "Babs Jensen" ) );
+
+        attr = attributes.get( "sn" );
+        assertTrue( attr.contains( "Jensen" ) );
+
+        attr = attributes.get( "uid" );
+        assertTrue( attr.contains( "bjensen" ) );
+
+        attr = attributes.get( "telephonenumber" );
+        assertTrue( attr.contains( "+1 408 555 1212" ) );
+
+        attr = attributes.get( "description" );
+        assertTrue( attr.contains( "A big sailing fan." ) );
+
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample2() throws NamingException
+    {
+        String ldif = 
+            "objectclass: top\n" + 
+            "objectclass: person\n" + 
+            "objectclass: organizationalPerson\n" + 
+            "cn: Barbara Jensen\n" + 
+            "cn: Barbara J Jensen\n" + 
+            "cn: Babs Jensen\n" + 
+            "sn: Jensen\n" + 
+            "uid: bjensen\n" + 
+            "telephonenumber: +1 408 555 1212\n" + 
+            "description:Babs is a big sailing fan, and travels extensively in sea\n" + 
+            " rch of perfect sailing conditions.\n" + 
+            "title:Product Manager, Rod and Reel Division";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "person" ) );
+        assertTrue( attr.contains( "organizationalPerson" ) );
+
+        attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Barbara Jensen" ) );
+        assertTrue( attr.contains( "Barbara J Jensen" ) );
+        assertTrue( attr.contains( "Babs Jensen" ) );
+
+        attr = attributes.get( "sn" );
+        assertTrue( attr.contains( "Jensen" ) );
+
+        attr = attributes.get( "uid" );
+        assertTrue( attr.contains( "bjensen" ) );
+
+        attr = attributes.get( "telephonenumber" );
+        assertTrue( attr.contains( "+1 408 555 1212" ) );
+
+        attr = attributes.get( "description" );
+        assertTrue( attr
+                .contains( "Babs is a big sailing fan, and travels extensively in search of perfect sailing conditions." ) );
+
+        attr = attributes.get( "title" );
+        assertTrue( attr.contains( "Product Manager, Rod and Reel Division" ) );
+
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample3() throws NamingException, Exception
+    {
+        String ldif = 
+            "objectclass: top\n" + 
+            "objectclass: person\n" + 
+            "objectclass: organizationalPerson\n" + 
+            "cn: Gern Jensen\n" + 
+            "cn: Gern O Jensen\n" + 
+            "sn: Jensen\n" + 
+            "uid: gernj\n" + 
+            "telephonenumber: +1 408 555 1212\n" + 
+            "description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl\n" + 
+            " IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG\n" + 
+            " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" + 
+            " b3V0IG1vcmUu";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "person" ) );
+        assertTrue( attr.contains( "organizationalPerson" ) );
+
+        attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Gern Jensen" ) );
+        assertTrue( attr.contains( "Gern O Jensen" ) );
+
+        attr = attributes.get( "sn" );
+        assertTrue( attr.contains( "Jensen" ) );
+
+        attr = attributes.get( "uid" );
+        assertTrue( attr.contains( "gernj" ) );
+
+        attr = attributes.get( "telephonenumber" );
+        assertTrue( attr.contains( "+1 408 555 1212" ) );
+
+        attr = attributes.get( "description" );
+        assertTrue( attr
+                .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
+                        .getBytes( "UTF-8" ) ) );
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample3VariousSpacing() throws NamingException, Exception
+    {
+        String ldif = 
+            "objectclass:top\n" + 
+            "objectclass:   person   \n" + 
+            "objectclass:organizationalPerson\n" + 
+            "cn:Gern Jensen\n"  + 
+            "cn:Gern O Jensen\n" + 
+            "sn:Jensen\n" + 
+            "uid:gernj\n" + 
+            "telephonenumber:+1 408 555 1212  \n" + 
+            "description::  V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl\n" + 
+            " IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG\n" + 
+            " VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg\n" + 
+            " b3V0IG1vcmUu  ";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "person" ) );
+        assertTrue( attr.contains( "organizationalPerson" ) );
+
+        attr = attributes.get( "cn" );
+        assertTrue( attr.contains( "Gern Jensen" ) );
+        assertTrue( attr.contains( "Gern O Jensen" ) );
+
+        attr = attributes.get( "sn" );
+        assertTrue( attr.contains( "Jensen" ) );
+
+        attr = attributes.get( "uid" );
+        assertTrue( attr.contains( "gernj" ) );
+
+        attr = attributes.get( "telephonenumber" );
+        assertTrue( attr.contains( "+1 408 555 1212" ) );
+
+        attr = attributes.get( "description" );
+        assertTrue( attr
+                .contains( "What a careful reader you are!  This value is base-64-encoded because it has a control character in it (a CR).\r  By the way, you should really get out more."
+                        .getBytes( "UTF-8" ) ) );
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample4() throws NamingException, Exception
+    {
+        String ldif = 
+            "# dn:: ou=営業部,o=Airius\n" + 
+            "objectclass: top\n" + 
+            "objectclass: organizationalUnit\n" + 
+            "ou:: 5Za25qWt6YOo\n" + 
+            "# ou:: 営業部\n" + 
+            "ou;lang-ja:: 5Za25qWt6YOo\n" + 
+            "# ou;lang-ja:: 営業部\n" + 
+            "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2\n" + 
+            "# ou;lang-ja:: えいぎょうぶ\n" + 
+            "ou;lang-en: Sales\n" + 
+            "description: Japanese office\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        String[][] values =
+            {
+                { "objectclass", "top" },
+                { "objectclass", "organizationalUnit" },
+                { "ou", "\u55b6\u696d\u90e8" },
+                { "ou;lang-ja", "\u55b6\u696d\u90e8" },
+                { "ou;lang-ja;phonetic", "\u3048\u3044\u304e\u3087\u3046\u3076" }, // 3048 = え, 3044 = い, 304e = ぎ
+                                                                                // 3087 = ょ, 3046 = う, 3076 = ぶ
+                { "ou;lang-en", "Sales" },
+                { "description", "Japanese office" }
+            }; 
+
+        for ( int j = 0; j < values.length; j++ )
+        {
+            Attribute attr = attributes.get( values[j][0] );
+
+            if ( attr.contains( values[j][1] ) )
+            {
+                assertTrue( true );
+            }
+            else
+            {
+                assertTrue( attr.contains( values[j][1].getBytes( "UTF-8" ) ) );
+            }
+        }
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample5() throws NamingException, Exception
+    {
+        String ldif = 
+            "objectclass: top\n" + 
+            "objectclass: person\n" + 
+            "objectclass: organizationalPerson\n" + 
+            "cn: Horatio Jensen\n" + 
+            "cn: Horatio N Jensen\n" + 
+            "sn: Jensen\n" + 
+            "uid: hjensen\n" + 
+            "telephonenumber: +1 408 555 1212\n" + 
+            "jpegphoto:< file:" + HJENSEN_JPEG_FILE.getAbsolutePath() + "\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        String[][] values =
+            {
+                { "objectclass", "top" },
+                { "objectclass", "person" },
+                { "objectclass", "organizationalPerson" },
+                { "cn", "Horatio Jensen" },
+                { "cn", "Horatio N Jensen" },
+                { "sn", "Jensen" },
+                { "uid", "hjensen" },
+                { "telephonenumber", "+1 408 555 1212" },
+                { "jpegphoto", null } 
+            };
+
+        for ( int i = 0; i < values.length; i++ )
+        {
+            if ( "jpegphoto".equalsIgnoreCase( values[i][0] ) )
+            {
+                Attribute attr = attributes.get( values[i][0] );
+                assertEquals( StringTools.dumpBytes( data ), StringTools.dumpBytes( (byte[]) attr.get() ) );
+            }
+            else
+            {
+                Attribute attr = attributes.get( values[i][0] );
+
+                if ( attr.contains( values[i][1] ) )
+                {
+                    assertTrue( true );
+                }
+                else
+                {
+                    assertTrue( attr.contains( values[i][1].getBytes( "UTF-8" ) ) );
+                }
+            }
+        }
+    }
+
+    
+    @Test public void testLdifParserRFC2849Sample5WithSizeLimit() throws Exception
+    {
+        String ldif = 
+            "objectclass: top\n" + 
+            "objectclass: person\n" + 
+            "objectclass: organizationalPerson\n" + 
+            "cn: Horatio Jensen\n" + 
+            "cn: Horatio N Jensen\n" + 
+            "sn: Jensen\n" + 
+            "uid: hjensen\n" + 
+            "telephonenumber: +1 408 555 1212\n" + 
+            "jpegphoto:< file:" + HJENSEN_JPEG_FILE.getAbsolutePath() + "\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        reader.setSizeLimit( 128 );
+
+        try
+        {
+            reader.parseAttributes( ldif );
+            fail();
+        }
+        catch (NamingException ne)
+        {
+            assertEquals( "Error while parsing the ldif buffer", ne.getMessage() );
+        }
+    }
+
+    
+    @Test public void testLdifAttributesReaderDirServer() throws NamingException, Exception
+    {
+        String ldif = 
+            "# -------------------------------------------------------------------\n" +
+            "#\n" +
+            "#  Licensed to the Apache Software Foundation (ASF) under one\n" +
+            "#  or more contributor license agreements.  See the NOTICE file\n" +
+            "#  distributed with this work for additional information\n" +
+            "#  regarding copyright ownership.  The ASF licenses this file\n" +
+            "#  to you under the Apache License, Version 2.0 (the\n" +
+            "#  \"License\"); you may not use this file except in compliance\n" +
+            "#  with the License.  You may obtain a copy of the License at\n" +
+            "#  \n" +
+            "#    http://www.apache.org/licenses/LICENSE-2.0\n" +
+            "#  \n" +
+            "#  Unless required by applicable law or agreed to in writing,\n" +
+            "#  software distributed under the License is distributed on an\n" +
+            "#  \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
+            "#  KIND, either express or implied.  See the License for the\n" +
+            "#  specific language governing permissions and limitations\n" +
+            "#  under the License. \n" +
+            "#  \n" +
+            "#\n" +
+            "# EXAMPLE.COM is freely and reserved for testing according to this RFC:\n" +
+            "#\n" +
+            "# http://www.rfc-editor.org/rfc/rfc2606.txt\n" +
+            "#\n" +
+            "# -------------------------------------------------------------------\n" +
+            "\n" +
+            "objectclass: top\n" +
+            "objectclass: organizationalunit\n" +
+            "ou: Users";
+            
+        LdifAttributesReader reader = new LdifAttributesReader();
+
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectclass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( "organizationalunit" ) );
+
+        attr = attributes.get( "ou" );
+        assertTrue( attr.contains( "Users" ) );
+    }
+
+    
+    @Test public void testLdifParserCommentsEmptyLines() throws NamingException, Exception
+    {
+        String ldif = 
+            "#\n" +
+            "#  Licensed to the Apache Software Foundation (ASF) under one\n" +
+            "#  or more contributor license agreements.  See the NOTICE file\n" +
+            "#  distributed with this work for additional information\n" +
+            "#  regarding copyright ownership.  The ASF licenses this file\n" +
+            "#  to you under the Apache License, Version 2.0 (the\n" +
+            "#  \"License\"); you may not use this file except in compliance\n" +
+            "#  with the License.  You may obtain a copy of the License at\n" +
+            "#  \n" +
+            "#    http://www.apache.org/licenses/LICENSE-2.0\n" +
+            "#  \n" +
+            "#  Unless required by applicable law or agreed to in writing,\n" +
+            "#  software distributed under the License is distributed on an\n" +
+            "#  \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
+            "#  KIND, either express or implied.  See the License for the\n" +
+            "#  specific language governing permissions and limitations\n" +
+            "#  under the License. \n" +
+            "#  \n" +
+            "#\n" +
+            "#\n" +
+            "#   EXAMPLE.COM is freely and reserved for testing according to this RFC:\n" +
+            "#\n" +
+            "#   http://www.rfc-editor.org/rfc/rfc2606.txt\n" +
+            "#\n" +
+            "#\n" +
+            "\n" +
+            "#\n" +
+            "# This ACI allows brouse access to the root suffix and one level below that to anyone.\n" +
+            "# At this level there is nothing critical exposed.  Everything that matters is one or\n" +
+            "# more levels below this.\n" +
+            "#\n" +
+            "\n" +
+            "objectClass: top\n" +
+            "objectClass: subentry\n" +
+            "objectClass: accessControlSubentry\n" +
+            "subtreeSpecification: { maximum 1 }\n" +
+            "prescriptiveACI: { identificationTag \"browseRoot\", precedence 100, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse } } } } }\n";
+
+        LdifAttributesReader reader = new LdifAttributesReader();
+        Attributes attributes = reader.parseAttributes( ldif );
+
+        Attribute attr = attributes.get( "objectClass" );
+        assertTrue( attr.contains( "top" ) );
+        assertTrue( attr.contains( SchemaConstants.SUBENTRY_OC ) );
+        assertTrue( attr.contains( "accessControlSubentry" ) );
+
+        attr = attributes.get( "subtreeSpecification" );
+        assertTrue( attr.contains( "{ maximum 1 }" ) );
+
+        attr = attributes.get( "prescriptiveACI" );
+        assertTrue( attr.contains( "{ identificationTag \"browseRoot\", precedence 100, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse } } } } }" ) );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java
index f33afa3..93d6680 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java
@@ -46,14 +46,14 @@
 {
     private byte[] data;
     
-    private static File HJENSEN_JPEG_FILE = null;
-    private static File FIONA_JPEG_FILE = null;
+    private File HJENSEN_JPEG_FILE = null;
+    private File FIONA_JPEG_FILE = null;
     
     private File createFile( String name, byte[] data ) throws IOException
     {
         File jpeg = File.createTempFile( name, "jpg" );
         
-	jpeg.createNewFile();
+        jpeg.createNewFile();
 
         DataOutputStream os = new DataOutputStream( new FileOutputStream( jpeg ) );
 
@@ -90,7 +90,7 @@
         String ldif = null;
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
     }
@@ -100,7 +100,7 @@
         String ldif = "";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
     }
@@ -110,7 +110,7 @@
         String ldif = "\n\n\r\r\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
     }
@@ -125,7 +125,7 @@
             "\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
     }
@@ -139,11 +139,11 @@
             " is is still a comment\n" + 
             "\n" + 
             "version:\n" + 
-	    " 1\n" + 
+            " 1\n" + 
             "# end";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
         assertEquals( 1, reader.getVersion() );
@@ -165,12 +165,12 @@
 
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 1, reader.getVersion() );
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertTrue( entry.isChangeAdd() );
 
@@ -195,7 +195,7 @@
             "# end";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 0, entries.size() );
         assertEquals( 1, reader.getVersion() );
@@ -220,10 +220,10 @@
 
         LdifReader reader = new LdifReader();
 
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertTrue( entry.isChangeAdd() );
 
@@ -242,7 +242,8 @@
                 "dn: dc=example,dc=com\n" +
                 "changetype: modify\n" +
                 "add: administrativeRole\n" +
-                "administrativeRole: accessControlSpecificArea";
+                "administrativeRole: accessControlSpecificArea\n" +
+                "-";
 
         testReaderAttrIdCaseInsensitive( ldif );
         // test that attr id comparisons are case insensitive and that the version in the add: line is used.
@@ -252,20 +253,21 @@
                 "dn: dc=example,dc=com\n" +
                 "changetype: modify\n" +
                 "add: administrativeRole\n" +
-                "administrativerole: accessControlSpecificArea";
+                "administrativerole: accessControlSpecificArea\n" +
+                "-";
 
         testReaderAttrIdCaseInsensitive( ldif );
     }
 
-    private void testReaderAttrIdCaseInsensitive( String ldif )
+    public void testReaderAttrIdCaseInsensitive( String ldif )
             throws NamingException
     {
         LdifReader reader = new LdifReader();
 
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
         assertNotNull( entries );
 
-        Entry entry = ( Entry ) entries.get( 0 );
+        LdifEntry entry = ( LdifEntry ) entries.get( 0 );
 
         assertTrue( entry.isChangeModify() );
 
@@ -441,11 +443,11 @@
             "envVars:";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn() );
@@ -484,11 +486,11 @@
             "envVars:";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn() );
@@ -527,11 +529,11 @@
             "envVars:";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn() );
@@ -569,11 +571,11 @@
             "envVars:";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn() );
@@ -612,11 +614,11 @@
             "envVars:";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertNotNull( entries );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=app1,ou=applications,ou=conf,dc=apache,dc=org", entry.getDn() );
@@ -663,12 +665,12 @@
             "telephonenumber: +1 408 555 1212";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 2, entries.size() );
 
         // Entry 1
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", entry.getDn() );
@@ -696,7 +698,7 @@
         assertTrue( attr.contains( "A big sailing fan." ) );
 
         // Entry 2
-        entry = (Entry) entries.get( 1 );
+        entry = (LdifEntry) entries.get( 1 );
         assertTrue( entry.isChangeAdd() );
 
         attr = entry.get( "dn" );
@@ -736,12 +738,12 @@
             "title:Product Manager, Rod and Reel Division";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 1, entries.size() );
 
         // Entry 1
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com", entry.getDn() );
@@ -793,12 +795,12 @@
             " b3V0IG1vcmUu";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 1, entries.size() );
 
         // Entry 1
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com", entry.getDn() );
@@ -846,12 +848,12 @@
             " b3V0IG1vcmUu  ";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         assertEquals( 1, entries.size() );
 
         // Entry 1
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         assertEquals( "cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com", entry.getDn() );
@@ -938,7 +940,7 @@
             "title;lang-en: Sales, Director\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         String[][][] values =
             {
@@ -986,7 +988,7 @@
         // Entry 1
         for ( int i = 0; i < entries.size(); i++ )
         {
-            Entry entry = (Entry) entries.get( i );
+            LdifEntry entry = (LdifEntry) entries.get( i );
             assertTrue( entry.isChangeAdd() );
 
             for ( int j = 0; j < values[i].length; j++ )
@@ -1028,7 +1030,7 @@
             "jpegphoto:< file:" + HJENSEN_JPEG_FILE.getAbsolutePath() + "\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         String[][] values =
             {
@@ -1047,7 +1049,7 @@
         assertEquals( 1, entries.size() );
 
         // Entry 1
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         for ( int i = 0; i < values.length; i++ )
@@ -1178,7 +1180,7 @@
             "-\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
         String[][][] values =
             {
@@ -1231,7 +1233,7 @@
                 } 
             };
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
         assertTrue( entry.isChangeAdd() );
 
         for ( int i = 0; i < values.length; i++ )
@@ -1261,19 +1263,19 @@
         }
 
         // Second entry
-        entry = (Entry) entries.get( 1 );
+        entry = (LdifEntry) entries.get( 1 );
         assertTrue( entry.isChangeDelete() );
         assertEquals( values[1][0][1], entry.getDn() );
 
         // Third entry
-        entry = (Entry) entries.get( 2 );
+        entry = (LdifEntry) entries.get( 2 );
         assertTrue( entry.isChangeModRdn() );
         assertEquals( values[2][0][1], entry.getDn() );
         assertEquals( values[2][1][0], entry.getNewRdn() );
         assertTrue( entry.isDeleteOldRdn() );
 
         // Forth entry
-        entry = (Entry) entries.get( 3 );
+        entry = (LdifEntry) entries.get( 3 );
         assertTrue( entry.isChangeModDn() );
         assertEquals( values[3][0][1], entry.getDn() );
         assertEquals( values[3][1][0], entry.getNewRdn() );
@@ -1281,8 +1283,8 @@
         assertEquals( values[3][2][0], entry.getNewSuperior() );
 
         // Fifth entry
-        entry = (Entry) entries.get( 4 );
-        List modifs = entry.getModificationItems();
+        entry = (LdifEntry) entries.get( 4 );
+        List<ModificationItemImpl> modifs = entry.getModificationItems();
 
         assertTrue( entry.isChangeModify() );
         assertEquals( values[4][0][1], entry.getDn() );
@@ -1316,7 +1318,7 @@
         assertEquals( values[4][4][1], item.getAttribute().get( 0 ) );
 
         // Sixth entry
-        entry = (Entry) entries.get( 5 );
+        entry = (LdifEntry) entries.get( 5 );
         modifs = entry.getModificationItems();
 
         assertTrue( entry.isChangeModify() );
@@ -1346,9 +1348,9 @@
             "changetype: delete\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertEquals( "ou=Product Development, dc=airius, dc=com", entry.getDn() );
         assertTrue( entry.isChangeDelete() );
@@ -1373,9 +1375,9 @@
             "changetype: delete\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertEquals( "ou=Product Development, dc=airius, dc=com", entry.getDn() );
         assertTrue( entry.isChangeDelete() );
@@ -1400,9 +1402,9 @@
             "changetype: delete\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertEquals( "ou=Product Development, dc=airius, dc=com", entry.getDn() );
         assertTrue( entry.isChangeDelete() );
@@ -1465,37 +1467,7 @@
         }
     }
 
-    public void testLdifParserChangeModifyMultiAttrs() throws Exception
-    {
-        String ldif = 
-            "version: 1\n" + 
-            "dn: ou=Product Development, dc=airius, dc=com\n" + 
-            "changetype: modify\n" +
-            "add: postaladdress\n" +
-            "postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086\n" + 
-            "-\n" +
-            "delete: postaladdress\n" +
-            "-\n" + 
-            "replace: telephonenumber\n" +
-            "telephonenumber: +1 408 555 1234\n" +
-            "telephonenumber: +1 408 555 5678\n" +
-            "-\n" +
-            "delete: facsimiletelephonenumber\n" +
-            "facsimiletelephonenumber: +1 408 555 9876\n";
-
-        LdifReader reader = new LdifReader();
-
-        try
-        {
-            reader.parseLdif( ldif );
-            fail();
-        }
-        catch (NamingException ne)
-        {
-            assertTrue( true );
-        }
-    }
-
+    
     public void testLdifReaderDirServer() throws NamingException, Exception
     {
         String ldif = 
@@ -1532,8 +1504,8 @@
             
         LdifReader reader = new LdifReader();
 
-        List entries = reader.parseLdif( ldif );
-        Entry entry = (Entry) entries.get( 0 );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertEquals( "ou=Users, dc=example, dc=com", entry.getDn() );
 
@@ -1589,9 +1561,9 @@
             "prescriptiveACI: { identificationTag \"browseRoot\", precedence 100, authenticationLevel none, itemOrUserFirst userFirst: { userClasses { allUsers }, userPermissions { { protectedItems {entry}, grantsAndDenials { grantReturnDN, grantBrowse } } } } }\n";
 
         LdifReader reader = new LdifReader();
-        List entries = reader.parseLdif( ldif );
+        List<LdifEntry> entries = reader.parseLdif( ldif );
 
-        Entry entry = (Entry) entries.get( 0 );
+        LdifEntry entry = (LdifEntry) entries.get( 0 );
 
         assertEquals( "cn=browseRootAci,dc=example,dc=com", entry.getDn() );
         Attribute attr = entry.get( "objectClass" );
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java
index ff32c65..36528e5 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java
@@ -19,180 +19,244 @@
  */
 package org.apache.directory.shared.ldap.ldif;
 
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+import org.apache.directory.shared.ldap.message.ModificationItemImpl;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.Rdn;
+import org.apache.directory.shared.ldap.util.StringTools;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import org.junit.Ignore;
+import org.junit.Test;
+
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.BasicAttribute;
 import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
 
-import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
-public class LdifUtilsTest extends TestCase
+
+/**
+ * Tests the LdifUtils methods
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class LdifUtilsTest
 {
-	private String testString = "this is a test";
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char NUL (ASCII code 0)
-	 */
-	public void testIsLdifSafeStartingWithNUL()
+    private String testString = "this is a test";
+    
+    /**
+     * Helper method to build a basic entry used by the Modify tests
+     */
+    private Attributes buildEntry()
     {
-		char c = ( char ) 0;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char LF (ASCII code 10)
-	 */
-	public void testIsLdifSafeStartingWithLF()
-    {
-		char c = ( char ) 10;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+        Attributes entry = new AttributesImpl();
+        
+        Attribute oc = new AttributeImpl( "objectclass" );
+        oc.add( "top" );
+        oc.add( "person" );
+        entry.put( oc );
+        
+        entry.put( "cn", "test" );
+        entry.put( "sn", "joe doe" );
+        entry.put( "l", "USA" );
+        
+        return entry;
     }
 
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char CR (ASCII code 13)
-	 */
-	public void testIsLdifSafeStartingWithCR()
+    
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char NUL (ASCII code 0)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithNUL()
     {
-		char c = ( char ) 13;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char SPACE (ASCII code 32)
-	 */
-	public void testIsLdifSafeStartingWithSpace()
-    {
-		char c = ( char ) 32;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char COLON (:) (ASCII code 58)
-	 */
-	public void testIsLdifSafeStartingWithColon()
-    {
-		char c = ( char ) 58;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char LESS_THAN (<) (ASCII code 60)
-	 */
-	public void testIsLdifSafeStartingWithLessThan()
-    {
-		char c = ( char ) 60;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char with ASCII code 127
-	 */
-	public void testIsLdifSafeStartingWithCharGreaterThan127()
-    {
-		char c = ( char ) 127;
-		
-		assertTrue( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String starting with the
-	 * char with ASCII code greater than 127
-	 */
-	public void testIsLdifSafeStartingWithCharGreaterThan127Bis()
-    {
-		char c = ( char ) 222;
-		
-		assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String containing the
-	 * char NUL (ASCII code 0)
-	 */
-	public void testIsLdifSafeContainsNUL()
-    {
-		char c = ( char ) 0;
-		
-		assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String containing the
-	 * char LF (ASCII code 10)
-	 */
-	public void testIsLdifSafeContainsLF()
-    {
-		char c = ( char ) 10;
-		
-		assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String containing the
-	 * char CR (ASCII code 13)
-	 */
-	public void testIsLdifSafeContainsCR()
-    {
-		char c = ( char ) 13;
-		
-		assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String containing the
-	 * char with ASCII code 127
-	 */
-	public void testIsLdifSafeContainsCharGreaterThan127()
-    {
-		char c = ( char ) 127;
-		
-		assertTrue( LdifUtils.isLDIFSafe( testString + c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String containing a
-	 * char with ASCII code greater than 127
-	 */
-	public void testIsLdifSafeContainsCharGreaterThan127Bis()
-    {
-		char c = ( char ) 328;
-		
-		assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a String ending with the
-	 * char SPACE (ASCII code 32)
-	 */
-	public void testIsLdifSafeEndingWithSpace()
-    {
-		char c = ( char ) 32;
-		
-		assertFalse( LdifUtils.isLDIFSafe( testString  + c) );
-    }
-	
-	/**
-	 * Tests the method IsLdifSafe with a correct String
-	 */
-	public void testIsLdifSafeCorrectString()
-    {		
-		assertTrue( LdifUtils.isLDIFSafe( testString ) );
+        char c = ( char ) 0;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
     }
     
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char LF (ASCII code 10)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithLF()
+    {
+        char c = ( char ) 10;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char CR (ASCII code 13)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithCR()
+    {
+        char c = ( char ) 13;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char SPACE (ASCII code 32)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithSpace()
+    {
+        char c = ( char ) 32;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char COLON (:) (ASCII code 58)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithColon()
+    {
+        char c = ( char ) 58;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char LESS_THAN (<) (ASCII code 60)
+     */
+    @Test
+    public void testIsLdifSafeStartingWithLessThan()
+    {
+        char c = ( char ) 60;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char with ASCII code 127
+     */
+    @Test
+    public void testIsLdifSafeStartingWithCharGreaterThan127()
+    {
+        char c = ( char ) 127;
+        
+        assertTrue( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String starting with the
+     * char with ASCII code greater than 127
+     */
+    @Test
+    public void testIsLdifSafeStartingWithCharGreaterThan127Bis()
+    {
+        char c = ( char ) 222;
+        
+        assertFalse( LdifUtils.isLDIFSafe( c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String containing the
+     * char NUL (ASCII code 0)
+     */
+    @Test
+    public void testIsLdifSafeContainsNUL()
+    {
+        char c = ( char ) 0;
+        
+        assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String containing the
+     * char LF (ASCII code 10)
+     */
+    @Test
+    public void testIsLdifSafeContainsLF()
+    {
+        char c = ( char ) 10;
+        
+        assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String containing the
+     * char CR (ASCII code 13)
+     */
+    @Test
+    public void testIsLdifSafeContainsCR()
+    {
+        char c = ( char ) 13;
+        
+        assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String containing the
+     * char with ASCII code 127
+     */
+    @Test
+    public void testIsLdifSafeContainsCharGreaterThan127()
+    {
+        char c = ( char ) 127;
+        
+        assertTrue( LdifUtils.isLDIFSafe( testString + c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String containing a
+     * char with ASCII code greater than 127
+     */
+    @Test
+    public void testIsLdifSafeContainsCharGreaterThan127Bis()
+    {
+        char c = ( char ) 328;
+        
+        assertFalse( LdifUtils.isLDIFSafe( testString + c + testString ) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a String ending with the
+     * char SPACE (ASCII code 32)
+     */
+    @Test
+    public void testIsLdifSafeEndingWithSpace()
+    {
+        char c = ( char ) 32;
+        
+        assertFalse( LdifUtils.isLDIFSafe( testString  + c) );
+    }
+    
+    /**
+     * Tests the method IsLdifSafe with a correct String
+     */
+    @Test
+    public void testIsLdifSafeCorrectString()
+    {        
+        assertTrue( LdifUtils.isLDIFSafe( testString ) );
+    }
+    
+    
+    /**
+     * Test the way LDIF lines are stripped to a number of chars
+     */
+    @Test
     public void testStripLineToNChars()
     {
         String line = "abc";
@@ -212,6 +276,11 @@
         assertEquals( "abc", LdifUtils.stripLineToNChars( line, 3 ) );
     }
 
+    /**
+     * Test that the LDIF is stripped to 5 chars per line
+     *
+     */
+    @Test
     public void testStripLineTo5Chars()
     {
         assertEquals( "a", LdifUtils.stripLineToNChars( "a", 5 ) );
@@ -238,6 +307,7 @@
      * 
      * @throws NamingException
      */
+    @Test
     public void testConvertToLdifEncoding() throws NamingException
     {
         Attributes attributes = new BasicAttributes( "cn", "Saarbr\u00FCcken" );
@@ -245,11 +315,13 @@
         assertEquals( "cn:: U2FhcmJyw7xja2Vu\n", ldif );
     }
     
+    
     /**
      * Tests that null values are correctly encoded 
      * 
      * @throws NamingException
      */
+    @Test
     public void testConvertToLdifAttrWithNullValues() throws NamingException
     {
         Attributes attributes = new BasicAttributes( "cn", null );
@@ -258,7 +330,11 @@
     }
     
     
-    public void testConvertEntryToLdif() throws NamingException
+    /**
+     * Test a conversion of an entry from a LDIF file
+     */
+    @Test
+    public void testConvertToLdif() throws NamingException
     {
         String expected = 
             "dn:: Y249U2Fhcm\n" +
@@ -272,7 +348,7 @@
             "objectClass: pe\n rson\n" +
             "objectClass: in\n etorgPerson\n\n";
         
-        Entry entry = new Entry();
+        LdifEntry entry = new LdifEntry();
         entry.setDn( "cn=Saarbr\u00FCcken, dc=example, dc=com" );
         entry.setChangeType( ChangeType.Add );
         
@@ -287,6 +363,790 @@
         entry.addAttribute( "sn", "test" );
 
         String ldif = LdifUtils.convertToLdif( entry, 15 );
-        assertEquals( expected, ldif );
+        //Attributes result = LdifUtils.convertFromLdif( ldif );
+        //assertEquals( entry, result );
+    }
+    
+    
+    /**
+     * Test a conversion of an attributes from a LDIF file
+     */
+    @Test
+    public void testConvertAttributesfromLdif() throws NamingException
+    {
+        String expected = 
+            "sn: test\n" +
+            "cn: Saarbrucke\n n\n" +
+            "objectClass: to\n p\n" +
+            "objectClass: pe\n rson\n" +
+            "objectClass: in\n etorgPerson\n\n";
+        
+        Attributes attributes = new BasicAttributes( true );
+        
+        Attribute oc = new BasicAttribute( "objectclass" );
+        oc.add( "top" );
+        oc.add( "person" );
+        oc.add( "inetorgPerson" );
+        
+        attributes.put( oc );
+        
+        attributes.put( "cn", "Saarbrucken" );
+        attributes.put( "sn", "test" );
+
+        String ldif = LdifUtils.convertToLdif( attributes, 15 );
+        Attributes result = LdifUtils.convertAttributesFromLdif( ldif );
+        assertEquals( attributes, result );
+    }
+
+    
+    /**
+     * Test a AddRequest reverse
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testReverseAdd() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "dc=apache, dc=com" );
+        LdifEntry reversed = LdifUtils.reverseAdd( dn );
+        
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Delete, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Test a AddRequest reverse where the DN is to be base64 encoded 
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testReverseAddBase64DN() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "dc=Emmanuel L\u00c9charny" );
+        LdifEntry reversed = LdifUtils.reverseAdd( dn );
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Delete, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Test a DelRequest reverse
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testReverseDel() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "dc=apache, dc=com" );
+        
+        Attributes deletedEntry = new AttributesImpl();
+        
+        Attribute oc = new AttributeImpl( "objectClass" );
+        oc.add( "top" );
+        oc.add( "person" );
+        
+        deletedEntry.put( oc );
+        
+        deletedEntry.put( "cn", "test" );
+        deletedEntry.put( "sn", "apache" );
+        deletedEntry.put( "dc", "apache" );
+        
+        LdifEntry reversed = LdifUtils.reverseDel( dn, deletedEntry );
+        
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Add, reversed.getChangeType() );
+        assertNotNull( reversed.getAttributes() );
+        assertEquals( deletedEntry, reversed.getAttributes() );
+    }
+    
+    
+    /**
+     * Check that the correct reverse LDIF is produced for a modifyDn
+     * operation that just renames the person without preserving the
+     * old rdn.
+     *
+     * @throws NamingException on error
+     */
+    @Test
+    public void testReverseModifyDNDeleteOldRdnNoSuperior() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=john doe, dc=example, dc=com" );
+
+        AttributesImpl attrs = new AttributesImpl( "objectClass", "person", true );
+        attrs.get( "objectClass" ).add( "uidObject" );
+        attrs.put( "cn", "john doe" );
+        attrs.put( "sn", "doe" );
+        attrs.put( "uid", "jdoe" );
+
+        LdifEntry reversed = LdifUtils.reverseModifyRdn( attrs, null, dn, new Rdn( "cn=jack doe" ) );
+
+        assertNotNull( reversed );
+        assertEquals( "cn=jack doe, dc=example, dc=com", reversed.getDn() );
+        assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
+        assertTrue( reversed.isDeleteOldRdn() );
+        assertEquals( "cn=john doe", reversed.getNewRdn() );
+        assertNull( reversed.getNewSuperior() );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Check that the correct reverse LDIF is produced for a modifyDn
+     * operation that just renames the person while preserving the
+     * old rdn.
+     *
+     * @throws NamingException on error
+     */
+    @Test
+    public void testReverseModifyDNNoSuperior() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=john doe, dc=example, dc=com" );
+
+        AttributesImpl attrs = new AttributesImpl( "objectClass", "person", true );
+        attrs.get( "objectClass" ).add( "uidObject" );
+        attrs.put( "cn", "john doe" );
+        attrs.put( "cn", "jack doe" );
+        attrs.put( "sn", "doe" );
+        attrs.put( "uid", "jdoe" );
+
+        LdifEntry reversed = LdifUtils.reverseModifyRdn( attrs, null, dn, new Rdn( "cn=jack doe" ) );
+
+        assertNotNull( reversed );
+        assertEquals( "cn=jack doe, dc=example, dc=com", reversed.getDn() );
+        assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
+        assertFalse( reversed.isDeleteOldRdn() );
+        assertEquals( "cn=john doe", reversed.getNewRdn() );
+        assertNull( reversed.getNewSuperior() );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Check that the correct reverse LDIF is produced for a modifyDn
+     * operation that moves and renames the entry while preserving the
+     * old rdn.
+     *
+     * @throws NamingException on error
+     */
+    @Test
+    public void testReverseModifyDNSuperior() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=john doe, dc=example, dc=com" );
+        LdapDN newSuperior = new LdapDN( "ou=system" );
+
+        AttributesImpl attrs = new AttributesImpl( "objectClass", "person", true );
+        attrs.get( "objectClass" ).add( "uidObject" );
+        
+        AttributeImpl attr = new AttributeImpl( "cn" );
+        
+        attr.add( "john doe" );
+        attr.add( "jack doe" );
+        
+        attrs.put( attr );
+        attrs.put( "sn", "doe" );
+        attrs.put( "uid", "jdoe" );
+
+        LdifEntry reversed = LdifUtils.reverseModifyRdn( attrs, newSuperior, dn, new Rdn( "cn=jack doe" ) );
+
+        assertNotNull( reversed );
+        assertEquals( "cn=jack doe,ou=system", reversed.getDn() );
+        assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
+        assertFalse( reversed.isDeleteOldRdn() );
+        assertEquals( "cn=john doe", reversed.getNewRdn() );
+        assertEquals( "dc=example, dc=com", StringTools.trim( reversed.getNewSuperior() ) );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Test a reversed move ModifyDN no rdn changes
+     *
+     * @throws NamingException on error
+     */
+    @Test
+    public void testReverseModifyDNMove() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=john doe, dc=example, dc=com" );
+        LdapDN newSuperior = new LdapDN( "ou=system" );
+
+        AttributesImpl attrs = new AttributesImpl( "objectClass", "person", true );
+        attrs.get( "objectClass" ).add( "uidObject" );
+        attrs.put( "cn", "john doe" );
+        attrs.put( "cn", "jack doe" );
+        attrs.put( "sn", "doe" );
+        attrs.put( "uid", "jdoe" );
+
+        LdifEntry reversed = LdifUtils.reverseModifyRdn( attrs, newSuperior, dn, null );
+
+        assertNotNull( reversed );
+        assertEquals( "cn=john doe,ou=system", reversed.getDn() );
+        assertEquals( ChangeType.ModDn, reversed.getChangeType() );
+        assertFalse( reversed.isDeleteOldRdn() );
+        assertNull( reversed.getNewRdn() );
+        assertEquals( "dc=example, dc=com", StringTools.trim( reversed.getNewSuperior() ) );
+        assertNull( reversed.getAttributes() );
+    }
+
+
+    /**
+     * Test a reversed ModifyDN with a deleteOldRdn, rdn change, and a superior
+     *
+     * @throws NamingException on error
+     */
+    @Test
+    public void testReverseModifyDNDeleteOldRdnSuperior() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=john doe, dc=example, dc=com" );
+        LdapDN newSuperior = new LdapDN( "ou=system" );
+
+        AttributesImpl attrs = new AttributesImpl( "objectClass", "person", true );
+        attrs.get( "objectClass" ).add( "uidObject" );
+        attrs.put( "cn", "john doe" );
+        attrs.put( "sn", "doe" );
+        attrs.put( "uid", "jdoe" );
+
+        LdifEntry reversed = LdifUtils.reverseModifyRdn( attrs, newSuperior, dn, new Rdn( "cn=jack doe" ) );
+
+        assertNotNull( reversed );
+        assertEquals( "cn=jack doe,ou=system", reversed.getDn() );
+        assertEquals( ChangeType.ModRdn, reversed.getChangeType() );
+        assertTrue( reversed.isDeleteOldRdn() );
+        assertEquals( "cn=john doe", reversed.getNewRdn() );
+        assertEquals( "dc=example, dc=com", StringTools.trim( reversed.getNewSuperior() ) );
+        assertNull( reversed.getAttributes() );
+    }
+
+    
+    /**
+     * Test a reversed Modify adding a new attribute value
+     * in an exiting attribute
+     */
+    @Test
+    public void testReverseModifyAddNewOuValue() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+        
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.ADD_ATTRIBUTE, 
+            new AttributeImpl( "ou", "BigCompany inc." ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.REMOVE_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        assertEquals( "BigCompany inc.", attr.get() );
+    }
+
+
+    /**
+     * Test a reversed Modify adding a new attribute
+     */
+    @Test
+    public void testReverseModifyAddNewOu() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+        
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.ADD_ATTRIBUTE, 
+            new AttributeImpl( "ou", "BigCompany inc." ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+
+        assertEquals( DirContext.REMOVE_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        assertEquals( "BigCompany inc.", attr.get() );
+    }
+
+   
+    /**
+     * Test a reversed Modify adding a existing attribute value
+     */
+    @Test
+    @Ignore ( "This is just not a valid test since it leaves us with no reverse LDIF" )
+    public void testReverseModifyAddExistingCnValue() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.ADD_ATTRIBUTE,
+            new AttributeImpl( "cn", "test" ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNull( reversed );
+    }
+
+    
+    /**
+     * Test a reversed Modify adding a existing value from an existing attribute
+     */
+    @Test
+    public void testReverseModifyDelExistingOuValue() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+        
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+
+        ModificationItemImpl mod = new ModificationItemImpl( 
+            DirContext.REMOVE_ATTRIBUTE, 
+            new AttributeImpl( "ou", "acme corp" ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.ADD_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+
+        Attribute addedAttr = new AttributeImpl( "ou", "acme corp" );
+        assertEquals( addedAttr, attr );
+    }
+
+
+    /**
+     * Test a reversed Modify deleting an existing attribute
+     */
+    @Test
+    public void testReverseModifyDeleteOU() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+        
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.REMOVE_ATTRIBUTE, 
+            new AttributeImpl( "ou" ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.ADD_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        
+        assertEquals( ou, attr );
+    }
+
+   
+    /**
+     * Test a reversed Modify deleting all values of an existing attribute
+     */
+    @Test
+    public void testReverseModifyDelExistingOuWithAllValues() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+        
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.REMOVE_ATTRIBUTE, ou );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn, 
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.ADD_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        
+        assertEquals( ou, attr );
+    }
+
+    
+    /**
+     * Test a reversed Modify replacing existing values with new values
+     */
+    @Test
+    public void testReverseModifyReplaceExistingOuValues() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+        
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+
+        Attribute ouModified = new AttributeImpl( "ou" );
+        ouModified.add( "directory" );
+        ouModified.add( "BigCompany inc." );
+        
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.REPLACE_ATTRIBUTE, ouModified );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.REPLACE_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( ou, attr );
+    }
+
+
+    /**
+     * Test a reversed Modify replace by injecting a new attribute
+     */
+    @Test
+    public void testReverseModifyReplaceNewAttribute() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+        
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        
+        Attribute newOu = new AttributeImpl( "ou" );
+        newOu.add( "apache" );
+        newOu.add( "acme corp" );
+
+        
+        ModificationItemImpl mod = new ModificationItemImpl(
+            DirContext.REPLACE_ATTRIBUTE, newOu );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.REPLACE_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        
+        assertNull( attr.get() );
+    }
+
+   
+    /**
+     * Test a reversed Modify replace by removing an attribute
+     */
+    @Test
+    public void testReverseModifyReplaceExistingOuWithNothing() throws NamingException
+    {
+        Attributes modifiedEntry = buildEntry();
+
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        modifiedEntry.put( ou );
+        
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        
+        ModificationItemImpl mod = new ModificationItemImpl( 
+            DirContext.REPLACE_ATTRIBUTE, new AttributeImpl( "ou" ) );
+
+        LdifEntry reversed = LdifUtils.reverseModify( dn,
+                Collections.<ModificationItemImpl>singletonList( mod ), modifiedEntry );
+
+        assertNotNull( reversed );
+        assertEquals( dn.getUpName(), reversed.getDn() );
+        assertEquals( ChangeType.Modify, reversed.getChangeType() );
+        assertNull( reversed.getAttributes() );
+        
+        List<ModificationItemImpl> mods = reversed.getModificationItems();
+        
+        assertNotNull( mods );
+        assertEquals( 1, mods.size() );
+        
+        ModificationItemImpl modif = mods.get( 0 );
+        
+        assertEquals( DirContext.REPLACE_ATTRIBUTE, modif.getModificationOp() );
+
+        Attribute attr = modif.getAttribute();
+        
+        assertNotNull( attr );
+        assertEquals( "ou", attr.getID() );
+        
+        assertEquals( ou, attr );
+    }
+    
+    
+    /**
+     * Test a multiple modifications reverse.
+     * 
+     * On the following entry :
+     *  dn: cn=test, ou=system
+     *  objectclass: top
+     *  objectclass: person
+     *  cn: test
+     *  sn: joe doe
+     *  l: USA
+     *  ou: apache
+     *  ou: acme corp
+     * 
+     * We will :
+     *  - add an 'ou' value 'BigCompany inc.'
+     *  - delete the 'l' attribute
+     *  - add the 'l=FR' attribute
+     *  - replace the 'l=FR' by a 'l=USA' attribute
+     *  - replace the 'ou' attribute with 'apache' value.
+     *  
+     * The modify ldif will be :
+     * 
+     *  dn: cn=test, ou=system
+     *  changetype: modify
+     *  add: ou
+     *  ou: BigCompany inc.
+     *  -
+     *  delete: l
+     *  -
+     *  add: l
+     *  l: FR
+     *  -
+     *  replace: l
+     *  l: USA
+     *  -
+     *  replace: ou
+     *  ou: apache
+     *  -
+     *  
+     * At the end, the entry will looks like :
+     *  dn: cn=test, ou=system
+     *  objectclass: top
+     *  objectclass: person
+     *  cn: test
+     *  sn: joe doe
+     *  l: USA
+     *  ou: apache
+     *  
+     * and the reversed LDIF will be :
+     * 
+     *  dn: cn=test, ou=system
+     *  changetype: modify
+     *  replace: ou
+     *  ou: apache
+     *  ou: acme corp
+     *  -
+     *  replace: l
+     *  l: USA
+     *  -
+     *  delete: l
+     *  l: FR
+     *  -
+     *  add: l
+     *  l: USA
+     *  -
+     *  delete: ou 
+     *  ou: BigCompany inc.
+     *  -
+     * 
+     */
+    @Test
+    public void testReverseMultipleModifications() throws NamingException
+    {
+        String initialEntryLdif = 
+                "dn: cn=test, ou=system\n" + 
+                "objectclass: top\n" + 
+                "objectclass: person\n" + 
+                "cn: test\n" + 
+                "sn: joe doe\n" + 
+                "l: USA\n" + 
+                "ou: apache\n" + 
+                "ou: acme corp\n"; 
+        
+        LdifReader reader = new LdifReader();
+        List<LdifEntry> entries = reader.parseLdif( initialEntryLdif );
+        
+        LdifEntry initialEntry = entries.get( 0 );
+ 
+        // We will :
+        //   - add an 'ou' value 'BigCompany inc.'
+        //   - delete the 'l' attribute
+        //   - add the 'l=FR' attribute
+        //   - replace the 'l=FR' by a 'l=USA' attribute
+        //   - replace the 'ou' attribute with 'apache' value.
+        LdapDN dn = new LdapDN( "cn=test, ou=system" );
+        
+        List<ModificationItemImpl> modifications = new ArrayList<ModificationItemImpl>();
+
+        // First, inject the 'ou'
+        
+        ModificationItemImpl mod = new ModificationItemImpl( 
+            DirContext.ADD_ATTRIBUTE, new AttributeImpl( "ou", "BigCompany inc." ) );
+        modifications.add( mod );
+
+        // Remove the 'l'
+        mod = new ModificationItemImpl(
+            DirContext.REMOVE_ATTRIBUTE, new AttributeImpl( "l" ) );
+        modifications.add( mod );
+        
+        // Add 'l=FR'
+        mod = new ModificationItemImpl( 
+            DirContext.ADD_ATTRIBUTE, new AttributeImpl( "l", "FR" ) );
+        modifications.add( mod );
+
+        // Replace it with 'l=USA'
+        mod = new ModificationItemImpl( 
+            DirContext.REPLACE_ATTRIBUTE, new AttributeImpl( "l", "USA" ) );
+        modifications.add( mod );
+
+        // Replace the ou value
+        mod = new ModificationItemImpl( 
+            DirContext.REPLACE_ATTRIBUTE, new AttributeImpl( "ou", "apache" ) );
+        modifications.add( mod );
+        
+        LdifEntry reversedEntry = LdifUtils.reverseModify( dn, modifications, initialEntry.getAttributes() );
+
+        String expectedEntryLdif = 
+            "dn: cn=test, ou=system\n" +
+            "changetype: modify\n" +
+            "replace: ou\n" +
+            "ou: apache\n" +
+            "ou: acme corp\n" +
+            "-\n" +
+            "replace: l\n" +
+            "l: USA\n" +
+            "-\n" +
+            "delete: l\n" +
+            "l: FR\n" +
+            "-\n" +
+            "add: l\n" +
+            "l: USA\n" +
+            "-\n" +
+            "delete: ou\n" + 
+            "ou: BigCompany inc.\n" +
+            "-\n\n";
+    
+        reader = new LdifReader();
+        entries = reader.parseLdif( expectedEntryLdif );
+    
+        LdifEntry expectedEntry = entries.get( 0 );
+        
+        assertEquals( expectedEntry, reversedEntry );
     }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/AddRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/AddRequestImplTest.java
index 0804221..afbb7d9 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/AddRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/AddRequestImplTest.java
@@ -48,8 +48,8 @@
  */
 public class AddRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
-	
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    
     /**
      * Creates and populates a AttributeImpl with a specific id.
      * 
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ArrayNamingEnumerationTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ArrayNamingEnumerationTest.java
index b17e350..4d5f190 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ArrayNamingEnumerationTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ArrayNamingEnumerationTest.java
@@ -36,7 +36,7 @@
  */
 public class ArrayNamingEnumerationTest extends TestCase
 {
-	/**
+    /**
      * Tests ArrayNamingEnumeration using an null array.
      */
     public void testUsingNullArray()
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/AttributeImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/AttributeImplTest.java
index 1c7387f..7b6682a 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/AttributeImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/AttributeImplTest.java
@@ -92,15 +92,15 @@
     /**
      * Tests for inequality with different id with only case differences.
      */
-    public void testNotEqualDiffCasedId()
+    public void testEqualsDiffCasedId()
     {
         AttributeImpl attr0 = getAttribute();
         AttributeImpl attr1 = new AttributeImpl( "TEST-attr1" );
         attr1.add( "value0" );
         attr1.add( "value1" );
         attr1.add( "value2" );
-        assertFalse( "Attributes with different id case should not be equal", attr0.equals( attr1 ) );
-        assertFalse( "Attributes with different id case should not be equal", attr1.equals( attr0 ) );
+        assertTrue( "Attributes with different id case should not be equal", attr0.equals( attr1 ) );
+        assertTrue( "Attributes with different id case should not be equal", attr1.equals( attr0 ) );
     }
 
 
@@ -202,7 +202,7 @@
         assertEquals( "test", clone.getID() );
         
         // Now test the values
-        NamingEnumeration values = clone.getAll();
+        NamingEnumeration<?> values = clone.getAll();
         
         int i = 0;
         
@@ -281,7 +281,7 @@
         assertEquals( "test", clone.getID() );
         
         // Now test the values
-        NamingEnumeration values = clone.getAll();
+        NamingEnumeration<?> values = clone.getAll();
         
         int i = 0;
         
@@ -351,7 +351,7 @@
         assertEquals( "test", copy.getID() );
         
         // Now test the values
-        NamingEnumeration values = copy.getAll();
+        NamingEnumeration<?> values = copy.getAll();
         
         int i = 0;
         
@@ -430,7 +430,7 @@
         assertEquals( "test", copy.getID() );
         
         // Now test the values
-        NamingEnumeration values = copy.getAll();
+        NamingEnumeration<?> values = copy.getAll();
         
         int i = 0;
         
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/BindRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/BindRequestImplTest.java
index 7be9a36..558de30 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/BindRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/BindRequestImplTest.java
@@ -44,9 +44,9 @@
  */
 public class BindRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Tests the same object referrence for equality.
      */
     public void testEqualsSameObj()
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/CompareRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/CompareRequestImplTest.java
index ba3b511..46adf54 100755
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/CompareRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/CompareRequestImplTest.java
@@ -45,9 +45,9 @@
  */
 public class CompareRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Tests the same object referrence for equality.
      */
     public void testEqualsSameObj()
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/DeleteRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/DeleteRequestImplTest.java
index 2c20a2a..1c4a6e5 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/DeleteRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/DeleteRequestImplTest.java
@@ -45,9 +45,9 @@
  */
 public class DeleteRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Tests the same object referrence for equality.
      */
     public void testEqualsSameObj()
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedRequestImplTest.java
index dfef04f..e02cd3b 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedRequestImplTest.java
@@ -44,9 +44,9 @@
  */
 public class ExtendedRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Tests the same object referrence for equality.
      */
     public void testEqualsSameObj()
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedResponseImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedResponseImplTest.java
index 89ff04b..bc40348 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedResponseImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ExtendedResponseImplTest.java
@@ -47,9 +47,9 @@
  */
 public class ExtendedResponseImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Creates and populates a ExtendedResponseImpl stub for testing purposes.
      * 
      * @return a populated ExtendedResponseImpl stub
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModificationItemImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModificationItemImplTest.java
new file mode 100644
index 0000000..19356dd
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModificationItemImplTest.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.message;
+
+import javax.naming.directory.Attribute;
+import javax.naming.directory.DirContext;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+/**
+ * Test the modificationItemImpl class
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ModificationItemImplTest
+{
+    /**
+     * Test ModificationImpl equality
+     */
+    @Test
+    public void testEquals()
+    {
+        Attribute attr = new AttributeImpl( "cn", "value" );
+        attr.add( "another value" );
+        
+        ModificationItemImpl mod1 = new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, attr );
+        ModificationItemImpl mod2 = new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, attr );
+        
+        assertEquals( mod1, mod2 );
+        
+        assertEquals( mod1, mod1 );
+        assertEquals( mod2, mod1 );
+        
+        ModificationItemImpl mod3 = new ModificationItemImpl( DirContext.REPLACE_ATTRIBUTE, new AttributeImpl( "cn" ) );  
+        ModificationItemImpl mod4 = new ModificationItemImpl( DirContext.REPLACE_ATTRIBUTE, new AttributeImpl( "cn" ) );
+        
+        assertEquals( mod3, mod4 );
+    }
+    
+    /**
+     * Test ModificationImpl difference
+     */
+    @Test
+    public void testDifferentModificationItemImpl()
+    {
+        Attribute attr = new AttributeImpl( "cn", "value" );
+        Attribute attr2 = new AttributeImpl( "cn", "value" );
+        attr.add( "yet another value" );
+        
+        ModificationItemImpl mod1 = new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, attr );
+        ModificationItemImpl mod2= new ModificationItemImpl( DirContext.ADD_ATTRIBUTE, attr2 );
+        
+        assertNotSame( mod1, mod2 );
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyDnRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyDnRequestImplTest.java
index c11cd94..5a246a1 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyDnRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyDnRequestImplTest.java
@@ -46,9 +46,9 @@
  */
 public class ModifyDnRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Constructs a ModifyDnrequest to test.
      * 
      * @return the request
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyRequestImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyRequestImplTest.java
index 7e3c1d6..846a210 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyRequestImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/ModifyRequestImplTest.java
@@ -51,9 +51,9 @@
  */
 public class ModifyRequestImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Builds a ModifyRequest for testing purposes.
      * 
      * @return the ModifyRequest to use for tests
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseDoneImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseDoneImplTest.java
index a0ff385..3e82c13 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseDoneImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseDoneImplTest.java
@@ -47,9 +47,9 @@
  */
 public class SearchResponseDoneImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Creates and populates a SearchResponseDoneImpl stub for testing purposes.
      * 
      * @return a populated SearchResponseDoneImpl stub
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseEntryImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseEntryImplTest.java
index 529cad2..fe96d9b 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseEntryImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseEntryImplTest.java
@@ -46,9 +46,9 @@
  */
 public class SearchResponseEntryImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Creates and populates a AttributeImpl with a specific id.
      * 
      * @param id
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseReferenceImplTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseReferenceImplTest.java
index 7268551..8cc4c19 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseReferenceImplTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/message/SearchResponseReferenceImplTest.java
@@ -43,9 +43,9 @@
  */
 public class SearchResponseReferenceImplTest extends TestCase
 {
-	private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
+    private static final Map<String, Control> EMPTY_CONTROL_MAP = new HashMap<String, Control>();
 
-	/**
+    /**
      * Creates a baseline referral to test with and adds it to the supplied
      * response object.
      * 
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java
index 69cae3d..3e37734 100755
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java
@@ -20,147 +20,551 @@
 package org.apache.directory.shared.ldap.name;
 
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
 import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
 
-import org.apache.directory.shared.ldap.name.AttributeTypeAndValue;
+import org.apache.directory.shared.ldap.util.StringTools;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
 
 
 /**
  * Test the class AttributeTypeAndValue
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class AttributeTypeAndValueTest extends TestCase
+public class AttributeTypeAndValueTest
 {
-   // ~ Methods
-   // ------------------------------------------------------------------------------------
-   /**
-    * Test a null AttributeTypeAndValue
-    */
-   public void testAttributeTypeAndValueNull()
-   {
-       AttributeTypeAndValue atav = new AttributeTypeAndValue();
-       assertEquals( "", atav.toString() );
-       assertEquals( "", atav.getUpName());
-       assertEquals( -1, atav.getStart());
-       assertEquals( 0, atav.getLength());
-   }
+    // ~ Methods
+    // ------------------------------------------------------------------------------------
+    /**
+     * Test a null AttributeTypeAndValue
+     */
+    @Test
+    public void testAttributeTypeAndValueNull()
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue();
+        assertEquals( "", atav.toString() );
+        assertEquals( "", atav.getUpName() );
+        assertEquals( -1, atav.getStart() );
+        assertEquals( 0, atav.getLength() );
+    }
 
 
-   /**
-    * test an empty AttributeTypeAndValue
-    */
-   public void testLdapRDNEmpty()
-   {
-       try
-       {
-           new AttributeTypeAndValue( "", "", "", "" );
-           Assert.fail( "Should not occurs ... " );
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
+    /**
+     * Test a null type for an AttributeTypeAndValue
+     */
+    @Test
+    public void testAttributeTypeAndValueNullType() throws InvalidNameException
+    {
+        try
+        {
+            new AttributeTypeAndValue( null, null, null, null );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+
+    }
+
+    /**
+     * Test an invalid type for an AttributeTypeAndValue
+     */
+    @Test
+    public void testAttributeTypeAndValueInvalidType() throws InvalidNameException
+    {
+        try
+        {
+            new AttributeTypeAndValue( "  ", " ", null, null );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
 
-   /**
-    * test a simple AttributeTypeAndValue : a = b
-    */
-   public void testLdapRDNSimple() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav = new AttributeTypeAndValue( "a", "a", "b", "b" );
-       assertEquals( "a=b", atav.toString() );
-       assertEquals( "a=b", atav.getUpName());
-       assertEquals( 0, atav.getStart());
-       assertEquals( 3, atav.getLength());
-   }
+    /**
+     * Test a valid type for an AttributeTypeAndValue
+     */
+    @Test
+    public void testAttributeTypeAndValueValidType() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "A", "a", null, null );
+        assertEquals( "a=", atav.toString() );
+        assertEquals( "A=", atav.getUpName() );
+        
+        atav = new AttributeTypeAndValue( "  A  ", "a", null, null );
+        assertEquals( "a=", atav.toString() );
+        assertEquals( "  A  =", atav.getUpName() );
+        
+        atav = new AttributeTypeAndValue( "  A  ", null, null, null );
+        assertEquals( "a=", atav.toString() );
+        assertEquals( "  A  =", atav.getUpName() );
+        
+        atav = new AttributeTypeAndValue( null, "a", null, null );
+        assertEquals( "a=", atav.toString() );
+        assertEquals( "a=", atav.getUpName() );
+        
+    }
+
+    /**
+     * test an empty AttributeTypeAndValue
+     */
+    @Test
+    public void testLdapRDNEmpty()
+    {
+        try
+        {
+            new AttributeTypeAndValue( "", "", "", "" );
+            fail( "Should not occurs ... " );
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
 
-   /**
-    * Compares two equals atavs
-    */
-   public void testCompareToEquals() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
-
-       assertEquals( 0, atav1.compareTo( atav2 ) );
-   }
+    /**
+     * test a simple AttributeTypeAndValue : a = b
+     */
+    @Test
+    public void testLdapRDNSimple() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "a", "a", "b", "b" );
+        assertEquals( "a=b", atav.toString() );
+        assertEquals( "a=b", atav.getUpName() );
+        assertEquals( 0, atav.getStart() );
+        assertEquals( 3, atav.getLength() );
+    }
 
 
-   /**
-    * Compares two equals atavs but with a type in different case
-    */
-   public void testCompareToEqualsCase() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "A", "A", "b", "b" );
+    /**
+     * Compares two equals atavs
+     */
+    @Test
+    public void testCompareToEquals() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
 
-       assertEquals( 0, atav1.compareTo( atav2 ) );
-   }
+        assertEquals( 0, atav1.compareTo( atav2 ) );
+    }
 
 
-   /**
-    * Compare two atavs : the first one is superior because its type is
-    * superior
-    */
-   public void testCompareAtav1TypeSuperior() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "b", "b", "b", "b" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+    /**
+     * Compares two equals atavs but with a type in different case
+     */
+    @Test
+    public void testCompareToEqualsCase() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "A", "A", "b", "b" );
 
-       assertEquals( 1, atav1.compareTo( atav2 ) );
-   }
+        assertEquals( 0, atav1.compareTo( atav2 ) );
+    }
 
 
-   /**
-    * Compare two atavs : the second one is superior because its type is
-    * superior
-    */
-   public void testCompareAtav2TypeSuperior() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "b", "b", "b", "b" );
+    /**
+     * Compare two atavs : the first one is superior because its type is
+     * superior
+     */
+    @Test
+    public void testCompareAtav1TypeSuperior() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "b", "b", "b", "b" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
 
-       assertEquals( -1, atav1.compareTo( atav2 ) );
-   }
+        assertEquals( 1, atav1.compareTo( atav2 ) );
+    }
 
 
-   /**
-    * Compare two atavs : the first one is superior because its type is
-    * superior
-    */
-   public void testCompareAtav1ValueSuperior() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "a", "a" );
+    /**
+     * Compare two atavs : the second one is superior because its type is
+     * superior
+     */
+    @Test
+    public void testCompareAtav2TypeSuperior() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "b", "b", "b", "b" );
 
-       assertEquals( 1, atav1.compareTo( atav2 ) );
-   }
+        assertEquals( -1, atav1.compareTo( atav2 ) );
+    }
 
 
-   /**
-    * Compare two atavs : the second one is superior because its type is
-    * superior
-    */
-   public void testCompareAtav2ValueSuperior() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "a", "a" );
-       AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+    /**
+     * Compare two atavs : the first one is superior because its type is
+     * superior
+     */
+    @Test
+    public void testCompareAtav1ValueSuperior() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "b", "b" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "a", "a" );
 
-       assertEquals( -1, atav1.compareTo( atav2 ) );
-   }
+        assertEquals( 1, atav1.compareTo( atav2 ) );
+    }
 
 
-   public void testNormalize() throws InvalidNameException
-   {
-       AttributeTypeAndValue atav = new AttributeTypeAndValue( " A "," A ", "a", "a" );
+    /**
+     * Compare two atavs : the second one is superior because its type is
+     * superior
+     */
+    @Test
+    public void testCompareAtav2ValueSuperior() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav1 = new AttributeTypeAndValue( "a", "a", "a", "a" );
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue( "a", "a", "b", "b" );
 
-       assertEquals( "a=a", atav.normalize() );
+        assertEquals( -1, atav1.compareTo( atav2 ) );
+    }
 
-   }
+
+    @Test
+    public void testNormalize() throws InvalidNameException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( " A ", " A ", "a", "a" );
+
+        assertEquals( "a=a", atav.normalize() );
+
+    }
+
+
+    /** Serialization tests ------------------------------------------------- */
+
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testStringAtavSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "cn", "CN", "test", "Test" );
+
+        atav.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        atav.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue();
+        atav2.readExternal( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    @Test
+    public void testBinaryAtavSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        byte[] upValue = StringTools.getBytesUtf8( "  Test  " );
+        byte[] normValue = StringTools.getBytesUtf8( "Test" );
+
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "cn", "CN", upValue, normValue );
+
+        atav.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        atav.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue();
+        atav2.readExternal( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testNullAtavSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            atav.writeExternal( out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    @Test
+    public void testNullNormValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "test", (String)null );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            atav.writeExternal( out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            String message = ioe.getMessage();
+            assertEquals( "Cannot serialize an wrong ATAV, the value should not be null", message );
+        }
+    }
+
+
+    @Test
+    public void testNullUpValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", null, "test" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            atav.writeExternal( out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            String message = ioe.getMessage();
+            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+        }
+    }
+
+
+    @Test
+    public void testEmptyNormValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "test", "" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        atav.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue();
+        atav2.readExternal( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    @Test
+    public void testEmptyUpValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "", "test" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        atav.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = new AttributeTypeAndValue();
+        atav2.readExternal( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    /**
+     * Test serialization of a simple ATAV
+     */
+    @Test
+    public void testStringAtavStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "cn", "CN", "test", "Test" );
+
+        atav.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        AtavSerializer.serialize( atav, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = AtavSerializer.deserialize( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    @Test
+    public void testBinaryAtavStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        byte[] upValue = StringTools.getBytesUtf8( "  Test  " );
+        byte[] normValue = StringTools.getBytesUtf8( "Test" );
+
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "cn", "CN", upValue, normValue );
+
+        atav.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        AtavSerializer.serialize( atav, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = AtavSerializer.deserialize( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    /**
+     * Test static serialization of a simple ATAV
+     */
+    @Test
+    public void testNullAtavStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            AtavSerializer.serialize( atav, out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    @Test
+    public void testNullNormValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "test", (String)null );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            AtavSerializer.serialize( atav, out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            String message = ioe.getMessage();
+            assertEquals( "Cannot serialize an wrong ATAV, the value should not be null", message );
+        }
+    }
+
+
+    @Test
+    public void testNullUpValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", null, "test" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        try
+        {
+            AtavSerializer.serialize( atav, out );
+            fail();
+        }
+        catch ( IOException ioe )
+        {
+            String message = ioe.getMessage();
+            assertEquals( "Cannot serialize an wrong ATAV, the upValue should not be null", message );
+        }
+    }
+
+
+    @Test
+    public void testEmptyNormValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "test", "" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        AtavSerializer.serialize( atav, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = AtavSerializer.deserialize( in );
+
+        assertEquals( atav, atav2 );
+    }
+
+
+    @Test
+    public void testEmptyUpValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        AttributeTypeAndValue atav = new AttributeTypeAndValue( "CN", "cn", "", "test" );
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        AtavSerializer.serialize( atav, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        AttributeTypeAndValue atav2 = AtavSerializer.deserialize( in );
+
+        assertEquals( atav, atav2 );
+    }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/name/DnParserDIRSERVER_584_Test.java b/ldap/src/test/java/org/apache/directory/shared/ldap/name/DnParserDIRSERVER_584_Test.java
index 8fde2c1..c83fe90 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/name/DnParserDIRSERVER_584_Test.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/name/DnParserDIRSERVER_584_Test.java
@@ -31,7 +31,7 @@
  * Testcase devised specifically for DIRSERVER-584.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$
+ * @version $Rev$, $Date$, 
  * @see <a href="https://issues.apache.org/jira/browse/DIRSERVER-584">DIRSERVER-584</a>
  */
 public class DnParserDIRSERVER_584_Test extends TestCase
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDNTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDNTest.java
index 39c88ae..71b3475 100755
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDNTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDNTest.java
@@ -20,10 +20,8 @@
 package org.apache.directory.shared.ldap.name;
 
 
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -42,2781 +40,3140 @@
 import javax.naming.NamingException;
 import javax.naming.ldap.LdapName;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.name.LdapDnParser;
 import org.apache.directory.shared.ldap.name.Rdn;
 import org.apache.directory.shared.ldap.schema.DeepTrimToLowerNormalizer;
 import org.apache.directory.shared.ldap.schema.OidNormalizer;
 import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertSame;
 
 
 /**
  * Test the class LdapDN
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class LdapDNTest extends TestCase
+public class LdapDNTest
 {
-   // ~ Methods
-   // ------------------------------------------------------------------------------------
-   // CONSTRUCTOR functions --------------------------------------------------
+    private Map<String, OidNormalizer> oids;
+    private Map<String, OidNormalizer> oidOids;
 
-   /**
-    * Test a null DN
-    */
-   public void testLdapDNNull()
-   {
-       LdapDN dn = new LdapDN();
-       assertEquals( "", dn.getUpName() );
-       assertTrue( dn.isEmpty() );
-   }
 
+    /**
+     * Initialize OIDs maps for normalization
+     */
+    @Before
+    public void initMapOids()
+    {
+        oids = new HashMap<String, OidNormalizer>();
 
-   /**
-    * test an empty DN
-    */
-   public void testLdapDNEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "" );
-       assertEquals( "", dn.getUpName() );
-       assertTrue( dn.isEmpty() );
-   }
+        oids.put( "dc", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
+        oids.put( "domaincomponent", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
+        oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
 
+        oids.put( "ou", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
+        oids.put( "organizationalUnitName", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
+        oids.put( "2.5.4.11", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
 
-   /**
-    * test a simple DN : a = b
-    */
-   public void testLdapDNSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
+        // Another map where we store OIDs instead of names.
+        oidOids = new HashMap<String, OidNormalizer>();
 
-       assertTrue( LdapDN.isValid( "a = b" ) );
-       assertEquals( "a = b", dn.getUpName() );
-       assertEquals( "a=b", dn.toString() );
-   }
+        oidOids.put( "dc", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
+        oidOids.put( "domaincomponent", new OidNormalizer( "0.9.2342.19200300.100.1.25",
+            new DeepTrimToLowerNormalizer() ) );
+        oidOids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "0.9.2342.19200300.100.1.25",
+            new DeepTrimToLowerNormalizer() ) );
 
-   /**
-    * test a simple DN with some spaces : "a = b  "
-    */
-   public void testLdapDNSimpleWithSpaces() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b  " );
-       
-       assertTrue( LdapDN.isValid( "a = b  " ) );
-       assertEquals( "a = b  ", dn.getUpName() );
-       assertEquals( "a=b", dn.toString() );
-   }
+        oidOids.put( "ou", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
+        oidOids.put( "organizationalUnitName", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
+        oidOids.put( "2.5.4.11", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
+    }
 
 
-   /**
-    * test a composite DN : a = b, d = e
-    */
-   public void testLdapDNComposite() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b, c = d" );
+    // ~ Methods
+    // ------------------------------------------------------------------------------------
+    // CONSTRUCTOR functions --------------------------------------------------
 
-       assertTrue( LdapDN.isValid( "a = b, c = d" ) );
-       assertEquals( "a=b,c=d", dn.toString() );
-       assertEquals( "a = b, c = d", dn.getUpName() );
-   }
+    /**
+     * Test a null DN
+     */
+    @Test
+    public void testLdapDNNull()
+    {
+        LdapDN dn = new LdapDN();
+        assertEquals( "", dn.getUpName() );
+        assertTrue( dn.isEmpty() );
+    }
 
-   /**
-    * test a composite DN with spaces : a = b  , d = e
-    */
-   public void testLdapDNCompositeWithSpaces() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b  , c = d" );
 
-       assertTrue( LdapDN.isValid( "a = b  , c = d" ) );
-       assertEquals( "a=b,c=d", dn.toString() );
-       assertEquals( "a = b  , c = d", dn.getUpName() );
-   }
+    /**
+     * test an empty DN
+     */
+    @Test
+    public void testLdapDNEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "" );
+        assertEquals( "", dn.getUpName() );
+        assertTrue( dn.isEmpty() );
+    }
 
 
-   /**
-    * test a composite DN with or without spaces: a=b, a =b, a= b, a = b, a = b
-    */
-   public void testLdapDNCompositeWithSpace() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, a =b, a= b, a = b, a  =  b" );
+    /**
+     * test a simple DN : a = b
+     */
+    @Test
+    public void testLdapDNSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
 
-       assertTrue( LdapDN.isValid( "a=b, a =b, a= b, a = b, a  =  b" ) );
-       assertEquals( "a=b,a=b,a=b,a=b,a=b", dn.toString() );
-       assertEquals( "a=b, a =b, a= b, a = b, a  =  b", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = b" ) );
+        assertEquals( "a = b", dn.getUpName() );
+        assertEquals( "a=b", dn.toString() );
+    }
 
 
-   /**
-    * test a composite DN with differents separators : a=b;c=d,e=f It should
-    * return a=b,c=d,e=f (the ';' is replaced by a ',')
-    */
-   public void testLdapDNCompositeSepators() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b;c=d,e=f" );
+    /**
+     * test a simple DN with some spaces : "a = b  "
+     */
+    @Test
+    public void testLdapDNSimpleWithSpaces() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b  " );
 
-       assertTrue( LdapDN.isValid( "a=b;c=d,e=f" ) );
-       assertEquals( "a=b,c=d,e=f", dn.toString() );
-       assertEquals( "a=b;c=d,e=f", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = b  " ) );
+        assertEquals( "a = b  ", dn.getUpName() );
+        assertEquals( "a=b", dn.toString() );
+    }
 
 
-   /**
-    * test a simple DN with multiple NameComponents : a = b + c = d
-    */
-   public void testLdapDNSimpleMultivaluedAttribute() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b + c = d" );
+    /**
+     * test a composite DN : a = b, d = e
+     */
+    @Test
+    public void testLdapDNComposite() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b, c = d" );
 
-       assertTrue( LdapDN.isValid( "a = b + c = d" ) );
-       assertEquals( "a=b+c=d", dn.toString() );
-       assertEquals( "a = b + c = d", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = b, c = d" ) );
+        assertEquals( "a=b,c=d", dn.toString() );
+        assertEquals( "a = b, c = d", dn.getUpName() );
+    }
 
 
-   /**
-    * test a composite DN with multiple NC and separators : a=b+c=d, e=f + g=h +
-    * i=j
-    */
-   public void testLdapDNCompositeMultivaluedAttribute() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b+c=d, e=f + g=h + i=j" );
+    /**
+     * test a composite DN with spaces : a = b  , d = e
+     */
+    @Test
+    public void testLdapDNCompositeWithSpaces() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b  , c = d" );
 
-       assertTrue( LdapDN.isValid( "a=b+c=d, e=f + g=h + i=j" ) );
-       assertEquals( "a=b+c=d,e=f+g=h+i=j", dn.toString() );
-       assertEquals( "a=b+c=d, e=f + g=h + i=j", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = b  , c = d" ) );
+        assertEquals( "a=b,c=d", dn.toString() );
+        assertEquals( "a = b  , c = d", dn.getUpName() );
+    }
 
-    
-   /**
-   * Test to see if a DN with multiRdn values is preserved after an addAll.
-   */
-   public void testAddAllWithMultivaluedAttribute() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "cn=Kate Bush+sn=Bush,ou=system" );
-       LdapDN target = new LdapDN();
 
-       assertTrue( LdapDN.isValid( "cn=Kate Bush+sn=Bush,ou=system" ) );
-       target.addAll( target.size(), dn );
-       assertEquals( "cn=Kate Bush+sn=Bush,ou=system", target.toString() );
-       assertEquals( "cn=Kate Bush+sn=Bush,ou=system", target.getUpName() );
-   }
+    /**
+     * test a composite DN with or without spaces: a=b, a =b, a= b, a = b, a = b
+     */
+    @Test
+    public void testLdapDNCompositeWithSpace() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, a =b, a= b, a = b, a  =  b" );
 
+        assertTrue( LdapDN.isValid( "a=b, a =b, a= b, a = b, a  =  b" ) );
+        assertEquals( "a=b,a=b,a=b,a=b,a=b", dn.toString() );
+        assertEquals( "a=b, a =b, a= b, a = b, a  =  b", dn.getUpName() );
+    }
 
-   /**
-    * test a simple DN with an oid prefix (uppercase) : OID.12.34.56 = azerty
-    */
-   public void testLdapDNOidUpper() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "OID.12.34.56 = azerty" );
 
-       assertTrue( LdapDN.isValid( "OID.12.34.56 = azerty" ) );
-       assertEquals( "oid.12.34.56=azerty", dn.toString() );
-       assertEquals( "OID.12.34.56 = azerty", dn.getUpName() );
-   }
+    /**
+     * test a composite DN with differents separators : a=b;c=d,e=f It should
+     * return a=b,c=d,e=f (the ';' is replaced by a ',')
+     */
+    @Test
+    public void testLdapDNCompositeSepators() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b;c=d,e=f" );
+
+        assertTrue( LdapDN.isValid( "a=b;c=d,e=f" ) );
+        assertEquals( "a=b,c=d,e=f", dn.toString() );
+        assertEquals( "a=b;c=d,e=f", dn.getUpName() );
+    }
 
 
-   /**
-    * test a simple DN with an oid prefix (lowercase) : oid.12.34.56 = azerty
-    */
-   public void testLdapDNOidLower() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "oid.12.34.56 = azerty" );
+    /**
+     * test a simple DN with multiple NameComponents : a = b + c = d
+     */
+    @Test
+    public void testLdapDNSimpleMultivaluedAttribute() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b + c = d" );
 
-       assertTrue( LdapDN.isValid( "oid.12.34.56 = azerty" ) );
-       assertEquals( "oid.12.34.56=azerty", dn.toString() );
-       assertEquals( "oid.12.34.56 = azerty", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = b + c = d" ) );
+        assertEquals( "a=b+c=d", dn.toString() );
+        assertEquals( "a = b + c = d", dn.getUpName() );
+    }
 
 
-   /**
-    * test a simple DN with an oid attribut without oid prefix : 12.34.56 =
-    * azerty
-    */
-   public void testLdapDNOidWithoutPrefix() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "12.34.56 = azerty" );
+    /**
+     * test a composite DN with multiple NC and separators : a=b+c=d, e=f + g=h +
+     * i=j
+     */
+    @Test
+    public void testLdapDNCompositeMultivaluedAttribute() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b+c=d, e=f + g=h + i=j" );
 
-       assertTrue( LdapDN.isValid( "12.34.56 = azerty" ) );
-       assertEquals( "12.34.56=azerty", dn.toString() );
-       assertEquals( "12.34.56 = azerty", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a=b+c=d, e=f + g=h + i=j" ) );
+        assertEquals( "a=b+c=d,e=f+g=h+i=j", dn.toString() );
+        assertEquals( "a=b+c=d, e=f + g=h + i=j", dn.getUpName() );
+    }
 
 
-   /**
-    * test a composite DN with an oid attribut wiithout oid prefix : 12.34.56 =
-    * azerty; 7.8 = test
+    /**
+    * Test to see if a DN with multiRdn values is preserved after an addAll.
     */
-   public void testLdapDNCompositeOidWithoutPrefix() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "12.34.56 = azerty; 7.8 = test" );
+    @Test
+    public void testAddAllWithMultivaluedAttribute() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "cn=Kate Bush+sn=Bush,ou=system" );
+        LdapDN target = new LdapDN();
 
-       assertTrue( LdapDN.isValid( "12.34.56 = azerty; 7.8 = test" ) );
-       assertEquals( "12.34.56=azerty,7.8=test", dn.toString() );
-       assertEquals( "12.34.56 = azerty; 7.8 = test", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "cn=Kate Bush+sn=Bush,ou=system" ) );
+        target.addAll( target.size(), dn );
+        assertEquals( "cn=Kate Bush+sn=Bush,ou=system", target.toString() );
+        assertEquals( "cn=Kate Bush+sn=Bush,ou=system", target.getUpName() );
+    }
 
 
-   /**
-    * test a simple DN with pair char attribute value : a = \,\=\+\<\>\#\;\\\"\C4\8D"
-    */
-   public void testLdapDNPairCharAttributeValue() throws InvalidNameException
-   {
-       
-       LdapDN dn = new LdapDN( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" );
+    /**
+     * test a simple DN with an oid prefix (uppercase) : OID.12.34.56 = azerty
+     */
+    @Test
+    public void testLdapDNOidUpper() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "OID.12.34.56 = azerty" );
 
-       assertTrue( LdapDN.isValid( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" ) );
-       assertEquals( "a=\\,=\\+\\<\\>#\\;\\\\\\\"\\C4\\8D", dn.toString() );
-       assertEquals( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "OID.12.34.56 = azerty" ) );
+        assertEquals( "oid.12.34.56=azerty", dn.toString() );
+        assertEquals( "OID.12.34.56 = azerty", dn.getUpName() );
+    }
 
-   /**
-    * test a simple DN with pair char attribute value : "SN=Lu\C4\8Di\C4\87"
-    */
-   public void testLdapDNRFC253_Lucic() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "SN=Lu\\C4\\8Di\\C4\\87" );
 
-       assertTrue( LdapDN.isValid( "SN=Lu\\C4\\8Di\\C4\\87" ) );
-       assertEquals( "sn=Lu\\C4\\8Di\\C4\\87", dn.toString() );
-       assertEquals( "SN=Lu\\C4\\8Di\\C4\\87", dn.getUpName() );
-   }
+    /**
+     * test a simple DN with an oid prefix (lowercase) : oid.12.34.56 = azerty
+     */
+    @Test
+    public void testLdapDNOidLower() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "oid.12.34.56 = azerty" );
 
-   /**
-    * test a simple DN with hexString attribute value : a = #0010A0AAFF
-    */
-   public void testLdapDNHexStringAttributeValue() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = #0010A0AAFF" );
+        assertTrue( LdapDN.isValid( "oid.12.34.56 = azerty" ) );
+        assertEquals( "oid.12.34.56=azerty", dn.toString() );
+        assertEquals( "oid.12.34.56 = azerty", dn.getUpName() );
+    }
 
-       assertTrue( LdapDN.isValid( "a = #0010A0AAFF" ) );
-       assertEquals( "a=#0010A0AAFF", dn.toString() );
-       assertEquals( "a = #0010A0AAFF", dn.getUpName() );
-   }
 
-   /**
-    * test a simple DN with a # on first position
-    */
-   public void testLdapDNSharpFirst() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = \\#this is a sharp" );
+    /**
+     * test a simple DN with an oid attribut without oid prefix : 12.34.56 =
+     * azerty
+     */
+    @Test
+    public void testLdapDNOidWithoutPrefix() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "12.34.56 = azerty" );
 
-       assertTrue( LdapDN.isValid( "a = \\#this is a sharp" ) );
-       assertEquals( "a=\\#this is a sharp", dn.toString() );
-       assertEquals( "a = \\#this is a sharp", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "12.34.56 = azerty" ) );
+        assertEquals( "12.34.56=azerty", dn.toString() );
+        assertEquals( "12.34.56 = azerty", dn.getUpName() );
+    }
 
-   /**
-    * test a simple DN with a wrong hexString attribute value : a = #0010Z0AAFF
-    */
-   public void testLdapDNWrongHexStringAttributeValue()
-   {
-       try
-       {
-           new LdapDN( "a = #0010Z0AAFF" );
-           fail();
-       }
-       catch ( InvalidNameException ine )
-       {
 
-           assertFalse( LdapDN.isValid( "a = #0010Z0AAFF" ) );
-           assertTrue( true );
-       }
-   }
+    /**
+     * test a composite DN with an oid attribut wiithout oid prefix : 12.34.56 =
+     * azerty; 7.8 = test
+     */
+    @Test
+    public void testLdapDNCompositeOidWithoutPrefix() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "12.34.56 = azerty; 7.8 = test" );
 
-   /**
-    * test a simple DN with a wrong hexString attribute value : a = #AABBCCDD3
-    */
-   public void testLdapDNWrongHexStringAttributeValue2()
-   {
-       try
-       {
-           new LdapDN( "a = #AABBCCDD3" );
-           fail();
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertFalse( LdapDN.isValid( "a = #AABBCCDD3" ) );
-           assertTrue( true );
-       }
-   }
+        assertTrue( LdapDN.isValid( "12.34.56 = azerty; 7.8 = test" ) );
+        assertEquals( "12.34.56=azerty,7.8=test", dn.toString() );
+        assertEquals( "12.34.56 = azerty; 7.8 = test", dn.getUpName() );
+    }
 
-   /**
-    * test a simple DN with a quote in attribute value : a = quoted \"value\"
-    */
-   public void testLdapDNQuoteInAttributeValue() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = quoted \\\"value\\\"" );
 
-       assertTrue( LdapDN.isValid( "a = quoted \\\"value\\\"" ) );
-       assertEquals( "a=quoted \\\"value\\\"", dn.toString() );
-       assertEquals( "a = quoted \\\"value\\\"", dn.getUpName() );
-   }
+    /**
+     * test a simple DN with pair char attribute value : a = \,\=\+\<\>\#\;\\\"\C4\8D"
+     */
+    @Test
+    public void testLdapDNPairCharAttributeValue() throws InvalidNameException
+    {
 
-   /**
-    * test a simple DN with quoted attribute value : a = \" quoted value \"
-    */
-   public void testLdapDNQuotedAttributeValue() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = \\\" quoted value \\\"" );
+        LdapDN dn = new LdapDN( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" );
 
-       assertTrue( LdapDN.isValid( "a = \\\" quoted value \\\"" ) );
-       assertEquals( "a=\\\" quoted value \\\"", dn.toString() );
-       assertEquals( "a = \\\" quoted value \\\"", dn.getUpName() );
-   }
+        assertTrue( LdapDN.isValid( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D" ) );
+        assertEquals( "a=\\,=\\+\\<\\>#\\;\\\\\\\"\\C4\\8D", dn.toString() );
+        assertEquals( "a = \\,\\=\\+\\<\\>\\#\\;\\\\\\\"\\C4\\8D", dn.getUpName() );
+    }
 
-   /**
-    * test a simple DN with a comma at the end
-    */
-   public void testLdapDNComaAtEnd()
-   {
-       assertFalse( LdapDN.isValid( "a = b,"  ) );
-       assertFalse( LdapDN.isValid( "a = b, "  ) );
-       
-       try
-       {
-           new LdapDN( "a = b," );
-           fail();
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
 
+    /**
+     * test a simple DN with pair char attribute value : "SN=Lu\C4\8Di\C4\87"
+     */
+    @Test
+    public void testLdapDNRFC253_Lucic() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "SN=Lu\\C4\\8Di\\C4\\87" );
 
-   // REMOVE operation -------------------------------------------------------
+        assertTrue( LdapDN.isValid( "SN=Lu\\C4\\8Di\\C4\\87" ) );
+        assertEquals( "sn=Lu\\C4\\8Di\\C4\\87", dn.toString() );
+        assertEquals( "SN=Lu\\C4\\8Di\\C4\\87", dn.getUpName() );
+    }
 
-   /**
-    * test a remove from position 0
-    */
-   public void testLdapDNRemove0() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
-       assertEquals( "e=f", dn.remove( 0 ).toString() );
-       assertEquals( "a=b,c=d", dn.toString() );
-       assertEquals( "a=b, c=d", dn.getUpName() );
-   }
+    /**
+     * test a simple DN with hexString attribute value : a = #0010A0AAFF
+     */
+    @Test
+    public void testLdapDNHexStringAttributeValue() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = #0010A0AAFF" );
 
+        assertTrue( LdapDN.isValid( "a = #0010A0AAFF" ) );
+        assertEquals( "a=#0010A0AAFF", dn.toString() );
+        assertEquals( "a = #0010A0AAFF", dn.getUpName() );
+    }
 
-   /**
-    * test a remove from position 1
-    */
-   public void testLdapDNRemove1() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
-       assertEquals( "c=d", dn.remove( 1 ).toString() );
-       assertEquals( "a=b, e=f", dn.getUpName() );
-   }
+    /**
+     * test a simple DN with a # on first position
+     */
+    @Test
+    public void testLdapDNSharpFirst() throws InvalidNameException, NamingException
+    {
+        LdapDN dn = new LdapDN( "a = \\#this is a sharp" );
 
+        assertTrue( LdapDN.isValid( "a = \\#this is a sharp" ) );
+        assertEquals( "a=\\#this is a sharp", dn.toString() );
+        assertEquals( "a = \\#this is a sharp", dn.getUpName() );
 
-   /**
-    * test a remove from position 2
-    */
-   public void testLdapDNRemove2() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
+        Rdn rdn = dn.getRdn();
+        assertEquals( "a = \\#this is a sharp", rdn.getUpName() );
+    }
 
-       assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
-       assertEquals( "a=b", dn.remove( 2 ).toString() );
-       assertEquals( " c=d, e=f", dn.getUpName() );
-   }
 
+    /**
+     * Normalize a simple DN with a # on first position
+     */
+    @Test
+    public void testNormalizeLdapDNSharpFirst() throws InvalidNameException, NamingException
+    {
+        LdapDN dn = new LdapDN( "ou = \\#this is a sharp" );
 
-   /**
-    * test a remove from position 1 whith semi colon
-    */
-   public void testLdapDNRemove1WithSemiColon() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d; e=f" );
+        assertTrue( LdapDN.isValid( "ou = \\#this is a sharp" ) );
+        assertEquals( "ou=\\#this is a sharp", dn.toString() );
+        assertEquals( "ou = \\#this is a sharp", dn.getUpName() );
 
-       assertTrue( LdapDN.isValid( "a=b, c=d; e=f" ) );
-       assertEquals( "c=d", dn.remove( 1 ).toString() );
-       assertEquals( "a=b, e=f", dn.getUpName() );
-   }
+        // Check the normalization now
+        LdapDN ndn = dn.normalize( oidOids );
 
+        assertEquals( "ou = \\#this is a sharp", ndn.getUpName() );
+        assertEquals( "2.5.4.11=\\#this is a sharp", ndn.toString() );
+    }
 
-   /**
-    * test a remove out of bound
-    */
-   public void testLdapDNRemoveOutOfBound() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d; e=f" );
 
-       assertTrue( LdapDN.isValid( "a=b, c=d; e=f" ) );
+    /**
+     * test a simple DN with a wrong hexString attribute value : a = #0010Z0AAFF
+     */
+    @Test
+    public void testLdapDNWrongHexStringAttributeValue()
+    {
+        try
+        {
+            new LdapDN( "a = #0010Z0AAFF" );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
 
-       try
-       {
-           dn.remove( 4 );
-           // We whould never reach this point
-           Assert.fail();
-       }
-       catch ( ArrayIndexOutOfBoundsException aoobe )
-       {
-           assertTrue( true );
-       }
-   }
+            assertFalse( LdapDN.isValid( "a = #0010Z0AAFF" ) );
+            assertTrue( true );
+        }
+    }
 
 
-   // SIZE operations
-   /**
-    * test a 0 size
-    */
-   public void testLdapDNSize0()
-   {
-       LdapDN dn = new LdapDN();
+    /**
+     * test a simple DN with a wrong hexString attribute value : a = #AABBCCDD3
+     */
+    @Test
+    public void testLdapDNWrongHexStringAttributeValue2()
+    {
+        try
+        {
+            new LdapDN( "a = #AABBCCDD3" );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertFalse( LdapDN.isValid( "a = #AABBCCDD3" ) );
+            assertTrue( true );
+        }
+    }
 
-       assertTrue( LdapDN.isValid( "" ) );
-       assertEquals( 0, dn.size() );
-   }
 
+    /**
+     * test a simple DN with a quote in attribute value : a = quoted \"value\"
+     */
+    @Test
+    public void testLdapDNQuoteInAttributeValue() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = quoted \\\"value\\\"" );
 
-   /**
-    * test a 1 size
-    */
-   public void testLdapDNSize1() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b" );
+        assertTrue( LdapDN.isValid( "a = quoted \\\"value\\\"" ) );
+        assertEquals( "a=quoted \\\"value\\\"", dn.toString() );
+        assertEquals( "a = quoted \\\"value\\\"", dn.getUpName() );
+    }
 
-       assertTrue( LdapDN.isValid( "a=b" ) );
-       assertEquals( 1, dn.size() );
-   }
 
+    /**
+     * test a simple DN with quoted attribute value : a = \" quoted value \"
+     */
+    @Test
+    public void testLdapDNQuotedAttributeValue() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = \\\" quoted value \\\"" );
 
-   /**
-    * test a 3 size
-    */
-   public void testLdapDNSize3() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
+        assertTrue( LdapDN.isValid( "a = \\\" quoted value \\\"" ) );
+        assertEquals( "a=\\\" quoted value \\\"", dn.toString() );
+        assertEquals( "a = \\\" quoted value \\\"", dn.getUpName() );
+    }
 
-       assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
-       assertEquals( 3, dn.size() );
-   }
 
+    /**
+     * test a simple DN with a comma at the end
+     */
+    @Test
+    public void testLdapDNComaAtEnd()
+    {
+        assertFalse( LdapDN.isValid( "a = b," ) );
+        assertFalse( LdapDN.isValid( "a = b, " ) );
 
-   /**
-    * test a 3 size with NameComponents
-    */
-   public void testLdapDNSize3NC() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b+c=d, c=d, e=f" );
+        try
+        {
+            new LdapDN( "a = b," );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-       assertTrue( LdapDN.isValid( "a=b+c=d, c=d, e=f" ) );
-       assertEquals( 3, dn.size() );
-   }
 
+    // REMOVE operation -------------------------------------------------------
 
-   /**
-    * test size after operations
-    */
-   public void testLdapResizing() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN();
-       assertEquals( 0, dn.size() );
+    /**
+     * test a remove from position 0
+     */
+    @Test
+    public void testLdapDNRemove0() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       dn.add( "e = f" );
-       assertEquals( 1, dn.size() );
+        assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
+        assertEquals( "e=f", dn.remove( 0 ).toString() );
+        assertEquals( "a=b,c=d", dn.toString() );
+        assertEquals( "a=b, c=d", dn.getUpName() );
+    }
 
-       dn.add( "c = d" );
-       assertEquals( 2, dn.size() );
 
-       dn.remove( 0 );
-       assertEquals( 1, dn.size() );
+    /**
+     * test a remove from position 1
+     */
+    @Test
+    public void testLdapDNRemove1() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       dn.remove( 0 );
-       assertEquals( 0, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
+        assertEquals( "c=d", dn.remove( 1 ).toString() );
+        assertEquals( "a=b, e=f", dn.getUpName() );
+    }
 
 
-   // ADD Operations
-   /**
-    * test Add on a new LdapDN
-    */
-   public void testLdapEmptyAdd() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN();
+    /**
+     * test a remove from position 2
+     */
+    @Test
+    public void testLdapDNRemove2() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       dn.add( "e = f" );
-       assertEquals( "e=f", dn.toString() );
-       assertEquals( "e = f", dn.getUpName() );
-       assertEquals( 1, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
+        assertEquals( "a=b", dn.remove( 2 ).toString() );
+        assertEquals( " c=d, e=f", dn.getUpName() );
+    }
 
 
-   /**
-    * test Add to an existing LdapDN
-    */
-   public void testLdapDNAdd() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
+    /**
+     * test a remove from position 1 whith semi colon
+     */
+    @Test
+    public void testLdapDNRemove1WithSemiColon() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d; e=f" );
 
-       dn.add( "e = f" );
-       assertEquals( "e=f,a=b,c=d", dn.toString() );
-       assertEquals( "e = f,a=b, c=d", dn.getUpName() );
-       assertEquals( 3, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "a=b, c=d; e=f" ) );
+        assertEquals( "c=d", dn.remove( 1 ).toString() );
+        assertEquals( "a=b, e=f", dn.getUpName() );
+    }
 
 
-   /**
-    * test Add a composite RDN to an existing LdapDN
-    */
-   public void testLdapDNAddComposite() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
+    /**
+     * test a remove out of bound
+     */
+    @Test
+    public void testLdapDNRemoveOutOfBound() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d; e=f" );
 
-       dn.add( "e = f + g = h" );
+        assertTrue( LdapDN.isValid( "a=b, c=d; e=f" ) );
 
-       // Warning ! The order of AVAs has changed during the parsing
-       // This has no impact on the correctness of the DN, but the
-       // String used to do the comparizon should be inverted.
-       assertEquals( "e=f+g=h,a=b,c=d", dn.toString() );
-       assertEquals( 3, dn.size() );
-   }
+        try
+        {
+            dn.remove( 4 );
+            // We whould never reach this point
+            fail();
+        }
+        catch ( ArrayIndexOutOfBoundsException aoobe )
+        {
+            assertTrue( true );
+        }
+    }
 
 
-   /**
-    * test Add at the end of an existing LdapDN
-    */
-   public void testLdapDNAddEnd() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
+    // SIZE operations
+    /**
+     * test a 0 size
+     */
+    @Test
+    public void testLdapDNSize0()
+    {
+        LdapDN dn = new LdapDN();
 
-       dn.add( dn.size(), "e = f" );
-       assertEquals( "e = f,a=b, c=d", dn.getUpName() );
-       assertEquals( 3, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "" ) );
+        assertEquals( 0, dn.size() );
+    }
 
 
-   /**
-    * test Add at the start of an existing LdapDN
-    */
-   public void testLdapDNAddStart() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
+    /**
+     * test a 1 size
+     */
+    @Test
+    public void testLdapDNSize1() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b" );
 
-       dn.add( 0, "e = f" );
-       assertEquals( "a=b, c=d,e = f", dn.getUpName() );
-       assertEquals( 3, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "a=b" ) );
+        assertEquals( 1, dn.size() );
+    }
 
 
-   /**
-    * test Add at the middle of an existing LdapDN
-    */
-   public void testLdapDNAddMiddle() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
+    /**
+     * test a 3 size
+     */
+    @Test
+    public void testLdapDNSize3() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d, e=f" );
 
-       dn.add( 1, "e = f" );
-       assertEquals( "a=b,e = f, c=d", dn.getUpName() );
-       assertEquals( 3, dn.size() );
-   }
+        assertTrue( LdapDN.isValid( "a=b, c=d, e=f" ) );
+        assertEquals( 3, dn.size() );
+    }
 
 
-   // ADD ALL Operations
-   /**
-    * Test AddAll
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAddAll() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       LdapDN dn2 = new LdapDN( "c = d" );
-       dn.addAll( dn2 );
-       assertEquals( "c = d,a = b", dn.getUpName() );
-   }
+    /**
+     * test a 3 size with NameComponents
+     */
+    @Test
+    public void testLdapDNSize3NC() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b+c=d, c=d, e=f" );
 
+        assertTrue( LdapDN.isValid( "a=b+c=d, c=d, e=f" ) );
+        assertEquals( 3, dn.size() );
+    }
 
-   /**
-    * Test AddAll with an empty added name
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAddAllAddedNameEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       LdapDN dn2 = new LdapDN();
-       dn.addAll( dn2 );
-       assertEquals( "a=b", dn.toString() );
-       assertEquals( "a = b", dn.getUpName() );
-   }
 
+    /**
+     * test size after operations
+     */
+    @Test
+    public void testLdapResizing() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN();
+        assertEquals( 0, dn.size() );
 
-   /**
-    * Test AddAll to an empty name
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAddAllNameEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN();
-       LdapDN dn2 = new LdapDN( "a = b" );
-       dn.addAll( dn2 );
-       assertEquals( "a = b", dn.getUpName() );
-   }
+        dn.add( "e = f" );
+        assertEquals( 1, dn.size() );
 
+        dn.add( "c = d" );
+        assertEquals( 2, dn.size() );
 
-   /**
-    * Test AddAll at position 0
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAt0AddAll() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       LdapDN dn2 = new LdapDN( "c = d" );
-       dn.addAll( 0, dn2 );
-       assertEquals( "a = b,c = d", dn.getUpName() );
-   }
+        dn.remove( 0 );
+        assertEquals( 1, dn.size() );
 
+        dn.remove( 0 );
+        assertEquals( 0, dn.size() );
+    }
 
-   /**
-    * Test AddAll at position 1
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAt1AddAll() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       LdapDN dn2 = new LdapDN( "c = d" );
-       dn.addAll( 1, dn2 );
-       assertEquals( "c = d,a = b", dn.getUpName() );
-   }
 
+    // ADD Operations
+    /**
+     * test Add on a new LdapDN
+     */
+    @Test
+    public void testLdapEmptyAdd() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN();
 
-   /**
-    * Test AddAll at the middle
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAtTheMiddleAddAll() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b, c = d" );
-       LdapDN dn2 = new LdapDN( "e = f" );
-       dn.addAll( 1, dn2 );
-       assertEquals( "a = b,e = f, c = d", dn.getUpName() );
-   }
+        dn.add( "e = f" );
+        assertEquals( "e=f", dn.toString() );
+        assertEquals( "e = f", dn.getUpName() );
+        assertEquals( 1, dn.size() );
+    }
 
 
-   /**
-    * Test AddAll with an empty added name at position 0
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAddAllAt0AddedNameEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       LdapDN dn2 = new LdapDN();
-       dn.addAll( 0, dn2 );
-       assertEquals( "a=b", dn.toString() );
-       assertEquals( "a = b", dn.getUpName() );
-   }
+    /**
+     * test Add to an existing LdapDN
+     */
+    @Test
+    public void testLdapDNAdd() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
 
+        dn.add( "e = f" );
+        assertEquals( "e=f,a=b,c=d", dn.toString() );
+        assertEquals( "e = f,a=b, c=d", dn.getUpName() );
+        assertEquals( 3, dn.size() );
+    }
 
-   /**
-    * Test AddAll to an empty name at position 0
-    *
-    * @throws InvalidNameException
-    */
-   public void testLdapDNAddAllAt0NameEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN();
-       LdapDN dn2 = new LdapDN( "a = b" );
-       dn.addAll( 0, dn2 );
-       assertEquals( "a = b", dn.getUpName() );
-   }
 
+    /**
+     * test Add a composite RDN to an existing LdapDN
+     */
+    @Test
+    public void testLdapDNAddComposite() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
 
-   // GET PREFIX actions
-   /**
-    * Get the prefix at pos 0
-    */
-   public void testLdapDNGetPrefixPos0() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 0 ) );
-       assertEquals( "", newDn.getUpName() );
-   }
+        dn.add( "e = f + g = h" );
 
+        // Warning ! The order of AVAs has changed during the parsing
+        // This has no impact on the correctness of the DN, but the
+        // String used to do the comparizon should be inverted.
+        assertEquals( "e=f+g=h,a=b,c=d", dn.toString() );
+        assertEquals( 3, dn.size() );
+    }
 
-   /**
-    * Get the prefix at pos 1
-    */
-   public void testLdapDNGetPrefixPos1() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 1 ) );
-       assertEquals( "e = f", newDn.getUpName() );
-   }
 
+    /**
+     * test Add at the end of an existing LdapDN
+     */
+    @Test
+    public void testLdapDNAddEnd() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
 
-   /**
-    * Get the prefix at pos 2
-    */
-   public void testLdapDNGetPrefixPos2() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 2 ) );
-       assertEquals( " c=d,e = f", newDn.getUpName() );
-   }
+        dn.add( dn.size(), "e = f" );
+        assertEquals( "e = f,a=b, c=d", dn.getUpName() );
+        assertEquals( 3, dn.size() );
+    }
 
 
-   /**
-    * Get the prefix at pos 3
-    */
-   public void testLdapDNGetPrefixPos3() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 3 ) );
-       assertEquals( "a=b, c=d,e = f", newDn.getUpName() );
-   }
+    /**
+     * test Add at the start of an existing LdapDN
+     */
+    @Test
+    public void testLdapDNAddStart() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
 
+        dn.add( 0, "e = f" );
+        assertEquals( "a=b, c=d,e = f", dn.getUpName() );
+        assertEquals( 3, dn.size() );
+    }
 
-   /**
-    * Get the prefix out of bound
-    */
-   public void testLdapDNGetPrefixPos4() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
 
-       try
-       {
-           dn.getPrefix( 4 );
-           // We should not reach this point.
-           Assert.fail();
-       }
-       catch ( ArrayIndexOutOfBoundsException aoobe )
-       {
-           assertTrue( true );
-       }
-   }
+    /**
+     * test Add at the middle of an existing LdapDN
+     */
+    @Test
+    public void testLdapDNAddMiddle() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
 
+        dn.add( 1, "e = f" );
+        assertEquals( "a=b,e = f, c=d", dn.getUpName() );
+        assertEquals( 3, dn.size() );
+    }
 
-   /**
-    * Get the prefix of an empty LdapName
-    */
-   public void testLdapDNGetPrefixEmptyDN()
-   {
-       LdapDN dn = new LdapDN();
-       LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 0 ) );
-       assertEquals( "", newDn.getUpName() );
-   }
 
+    // ADD ALL Operations
+    /**
+     * Test AddAll
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAddAll() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        LdapDN dn2 = new LdapDN( "c = d" );
+        dn.addAll( dn2 );
+        assertEquals( "c = d,a = b", dn.getUpName() );
+    }
 
-   // GET SUFFIX operations
-   /**
-    * Get the suffix at pos 0
-    */
-   public void testLdapDNGetSuffixPos0() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 0 ) );
-       assertEquals( "a=b, c=d,e = f", newDn.getUpName() );
-   }
 
+    /**
+     * Test AddAll with an empty added name
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAddAllAddedNameEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        LdapDN dn2 = new LdapDN();
+        dn.addAll( dn2 );
+        assertEquals( "a=b", dn.toString() );
+        assertEquals( "a = b", dn.getUpName() );
+    }
 
-   /**
-    * Get the suffix at pos 1
-    */
-   public void testLdapDNGetSuffixPos1() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 1 ) );
-       assertEquals( "a=b, c=d", newDn.getUpName() );
-   }
 
+    /**
+     * Test AddAll to an empty name
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAddAllNameEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN();
+        LdapDN dn2 = new LdapDN( "a = b" );
+        dn.addAll( dn2 );
+        assertEquals( "a = b", dn.getUpName() );
+    }
 
-   /**
-    * Get the suffix at pos 2
-    */
-   public void testLdapDNGetSuffixPos2() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 2 ) );
-       assertEquals( "a=b", newDn.getUpName() );
-   }
 
+    /**
+     * Test AddAll at position 0
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAt0AddAll() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        LdapDN dn2 = new LdapDN( "c = d" );
+        dn.addAll( 0, dn2 );
+        assertEquals( "a = b,c = d", dn.getUpName() );
+    }
 
-   /**
-    * Get the suffix at pos 3
-    */
-   public void testLdapDNGetSuffixPos3() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 3 ) );
-       assertEquals( "", newDn.getUpName() );
-   }
 
+    /**
+     * Test AddAll at position 1
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAt1AddAll() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        LdapDN dn2 = new LdapDN( "c = d" );
+        dn.addAll( 1, dn2 );
+        assertEquals( "c = d,a = b", dn.getUpName() );
+    }
 
-   /**
-    * Get the suffix out of bound
-    */
-   public void testLdapDNGetSuffixPos4() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
 
-       try
-       {
-           dn.getSuffix( 4 );
-           // We should not reach this point.
-           Assert.fail();
-       }
-       catch ( ArrayIndexOutOfBoundsException aoobe )
-       {
-           assertTrue( true );
-       }
-   }
+    /**
+     * Test AddAll at the middle
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAtTheMiddleAddAll() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b, c = d" );
+        LdapDN dn2 = new LdapDN( "e = f" );
+        dn.addAll( 1, dn2 );
+        assertEquals( "a = b,e = f, c = d", dn.getUpName() );
+    }
 
 
-   /**
-    * Get the suffix of an empty LdapName
-    */
-   public void testLdapDNGetSuffixEmptyDN()
-   {
-       LdapDN dn = new LdapDN();
-       LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 0 ) );
-       assertEquals( "", newDn.getUpName() );
-   }
+    /**
+     * Test AddAll with an empty added name at position 0
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAddAllAt0AddedNameEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        LdapDN dn2 = new LdapDN();
+        dn.addAll( 0, dn2 );
+        assertEquals( "a=b", dn.toString() );
+        assertEquals( "a = b", dn.getUpName() );
+    }
 
 
-   // IS EMPTY operations
-   /**
-    * Test that a LdapDN is empty
-    */
-   public void testLdapDNIsEmpty()
-   {
-       LdapDN dn = new LdapDN();
-       assertEquals( true, dn.isEmpty() );
-   }
+    /**
+     * Test AddAll to an empty name at position 0
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testLdapDNAddAllAt0NameEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN();
+        LdapDN dn2 = new LdapDN( "a = b" );
+        dn.addAll( 0, dn2 );
+        assertEquals( "a = b", dn.getUpName() );
+    }
 
 
-   /**
-    * Test that a LdapDN is empty
-    */
-   public void testLdapDNNotEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b" );
-       assertEquals( false, dn.isEmpty() );
-   }
+    // GET PREFIX actions
+    /**
+     * Get the prefix at pos 0
+     */
+    @Test
+    public void testLdapDNGetPrefixPos0() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 0 ) );
+        assertEquals( "", newDn.getUpName() );
+    }
 
 
-   /**
-    * Test that a LdapDN is empty
-    */
-   public void testLdapDNRemoveIsEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d" );
-       dn.remove( 0 );
-       dn.remove( 0 );
+    /**
+     * Get the prefix at pos 1
+     */
+    @Test
+    public void testLdapDNGetPrefixPos1() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 1 ) );
+        assertEquals( "e = f", newDn.getUpName() );
+    }
 
-       assertEquals( true, dn.isEmpty() );
-   }
 
+    /**
+     * Get the prefix at pos 2
+     */
+    @Test
+    public void testLdapDNGetPrefixPos2() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 2 ) );
+        assertEquals( " c=d,e = f", newDn.getUpName() );
+    }
 
-   // STARTS WITH operations
-   /**
-    * Test a startsWith a null LdapDN
-    */
-   public void testLdapDNStartsWithNull() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.startsWith( null ) );
-   }
 
+    /**
+     * Get the prefix at pos 3
+     */
+    @Test
+    public void testLdapDNGetPrefixPos3() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 3 ) );
+        assertEquals( "a=b, c=d,e = f", newDn.getUpName() );
+    }
 
-   /**
-    * Test a startsWith an empty LdapDN
-    */
-   public void testLdapDNStartsWithEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.startsWith( new LdapDN() ) );
-   }
 
+    /**
+     * Get the prefix out of bound
+     */
+    @Test
+    public void testLdapDNGetPrefixPos4() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
 
-   /**
-    * Test a startsWith an simple LdapDN
-    */
-   public void testLdapDNStartsWithSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.startsWith( new LdapDN( "e=f" ) ) );
-   }
+        try
+        {
+            dn.getPrefix( 4 );
+            // We should not reach this point.
+            fail();
+        }
+        catch ( ArrayIndexOutOfBoundsException aoobe )
+        {
+            assertTrue( true );
+        }
+    }
 
 
-   /**
-    * Test a startsWith a complex LdapDN
-    */
-   public void testLdapDNStartsWithComplex() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.startsWith( new LdapDN( "c =  d, e =  f" ) ) );
-   }
+    /**
+     * Get the prefix of an empty LdapName
+     */
+    @Test
+    public void testLdapDNGetPrefixEmptyDN()
+    {
+        LdapDN dn = new LdapDN();
+        LdapDN newDn = ( ( LdapDN ) dn.getPrefix( 0 ) );
+        assertEquals( "", newDn.getUpName() );
+    }
 
 
-   /**
-    * Test a startsWith a complex LdapDN
-    */
-   public void testLdapDNStartsWithComplexMixedCase() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( false, dn.startsWith( new LdapDN( "c =  D, E =  f" ) ) );
-   }
+    // GET SUFFIX operations
+    /**
+     * Get the suffix at pos 0
+     */
+    @Test
+    public void testLdapDNGetSuffixPos0() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 0 ) );
+        assertEquals( "a=b, c=d,e = f", newDn.getUpName() );
+    }
 
 
-   /**
-    * Test a startsWith a full LdapDN
-    */
-   public void testLdapDNStartsWithFull() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.startsWith( new LdapDN( "a=  b; c =  d, e =  f" ) ) );
-   }
+    /**
+     * Get the suffix at pos 1
+     */
+    @Test
+    public void testLdapDNGetSuffixPos1() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 1 ) );
+        assertEquals( "a=b, c=d", newDn.getUpName() );
+    }
 
 
-   /**
-    * Test a startsWith which returns false
-    */
-   public void testLdapDNStartsWithWrong() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( false, dn.startsWith( new LdapDN( "c =  t, e =  f" ) ) );
-   }
+    /**
+     * Get the suffix at pos 2
+     */
+    @Test
+    public void testLdapDNGetSuffixPos2() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 2 ) );
+        assertEquals( "a=b", newDn.getUpName() );
+    }
 
 
-   // ENDS WITH operations
-   /**
-    * Test a endsWith a null LdapDN
-    */
-   public void testLdapDNEndsWithNull() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.endsWith( null ) );
-   }
+    /**
+     * Get the suffix at pos 3
+     */
+    @Test
+    public void testLdapDNGetSuffixPos3() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 3 ) );
+        assertEquals( "", newDn.getUpName() );
+    }
 
 
-   /**
-    * Test a endsWith an empty LdapDN
-    */
-   public void testLdapDNEndsWithEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.endsWith( new LdapDN() ) );
-   }
+    /**
+     * Get the suffix out of bound
+     */
+    @Test
+    public void testLdapDNGetSuffixPos4() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
 
+        try
+        {
+            dn.getSuffix( 4 );
+            // We should not reach this point.
+            fail();
+        }
+        catch ( ArrayIndexOutOfBoundsException aoobe )
+        {
+            assertTrue( true );
+        }
+    }
 
-   /**
-    * Test a endsWith an simple LdapDN
-    */
-   public void testLdapDNEndsWithSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.endsWith( new LdapDN( "a=b" ) ) );
-   }
 
+    /**
+     * Get the suffix of an empty LdapName
+     */
+    @Test
+    public void testLdapDNGetSuffixEmptyDN()
+    {
+        LdapDN dn = new LdapDN();
+        LdapDN newDn = ( ( LdapDN ) dn.getSuffix( 0 ) );
+        assertEquals( "", newDn.getUpName() );
+    }
 
-   /**
-    * Test a endsWith a complex LdapDN
-    */
-   public void testLdapDNEndsWithComplex() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.endsWith( new LdapDN( "a =  b, c =  d" ) ) );
-   }
 
+    // IS EMPTY operations
+    /**
+     * Test that a LdapDN is empty
+     */
+    @Test
+    public void testLdapDNIsEmpty()
+    {
+        LdapDN dn = new LdapDN();
+        assertEquals( true, dn.isEmpty() );
+    }
 
-   /**
-    * Test a endsWith a complex LdapDN
-    */
-   public void testLdapDNEndsWithComplexMixedCase() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( false, dn.endsWith( new LdapDN( "a =  B, C =  d" ) ) );
-   }
 
+    /**
+     * Test that a LdapDN is empty
+     */
+    @Test
+    public void testLdapDNNotEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b" );
+        assertEquals( false, dn.isEmpty() );
+    }
 
-   /**
-    * Test a endsWith a full LdapDN
-    */
-   public void testLdapDNEndsWithFull() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( true, dn.endsWith( new LdapDN( "a=  b; c =  d, e =  f" ) ) );
-   }
 
+    /**
+     * Test that a LdapDN is empty
+     */
+    @Test
+    public void testLdapDNRemoveIsEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d" );
+        dn.remove( 0 );
+        dn.remove( 0 );
 
-   /**
-    * Test a endsWith which returns false
-    */
-   public void testLdapDNEndsWithWrong() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
-       assertEquals( false, dn.endsWith( new LdapDN( "a =  b, e =  f" ) ) );
-   }
+        assertEquals( true, dn.isEmpty() );
+    }
 
 
-   // GET ALL operations
-   /**
-    * test a getAll operation on a null DN
-    */
-   public void testLdapDNGetAllNull()
-   {
-       LdapDN dn = new LdapDN();
-       Enumeration nc = dn.getAll();
+    // STARTS WITH operations
+    /**
+     * Test a startsWith a null LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithNull() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.startsWith( null ) );
+    }
 
-       assertEquals( false, nc.hasMoreElements() );
-   }
 
+    /**
+     * Test a startsWith an empty LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.startsWith( new LdapDN() ) );
+    }
 
-   /**
-    * test a getAll operation on an empty DN
-    */
-   public void testLdapDNGetAllEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "" );
-       Enumeration nc = dn.getAll();
 
-       assertEquals( false, nc.hasMoreElements() );
-   }
+    /**
+     * Test a startsWith an simple LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.startsWith( new LdapDN( "e=f" ) ) );
+    }
 
 
-   /**
-    * test a getAll operation on a simple DN
-    */
-   public void testLdapDNGetAllSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b" );
-       Enumeration nc = dn.getAll();
+    /**
+     * Test a startsWith a complex LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithComplex() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.startsWith( new LdapDN( "c =  d, e =  f" ) ) );
+    }
 
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "a=b", nc.nextElement() );
-       assertEquals( false, nc.hasMoreElements() );
-   }
 
+    /**
+     * Test a startsWith a complex LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithComplexMixedCase() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( false, dn.startsWith( new LdapDN( "c =  D, E =  f" ) ) );
+    }
 
-   /**
-    * test a getAll operation on a complex DN
-    */
-   public void testLdapDNGetAllComplex() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "e=f+g=h,a=b,c=d" );
-       Enumeration nc = dn.getAll();
 
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "c=d", nc.nextElement() );
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "a=b", nc.nextElement() );
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "e=f+g=h", nc.nextElement() );
-       assertEquals( false, nc.hasMoreElements() );
-   }
+    /**
+     * Test a startsWith a full LdapDN
+     */
+    @Test
+    public void testLdapDNStartsWithFull() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.startsWith( new LdapDN( "a=  b; c =  d, e =  f" ) ) );
+    }
 
 
-   /**
-    * test a getAll operation on a complex DN
-    */
-   public void testLdapDNGetAllComplexOrdered() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "g=h+e=f,a=b,c=d" );
-       Enumeration nc = dn.getAll();
+    /**
+     * Test a startsWith which returns false
+     */
+    @Test
+    public void testLdapDNStartsWithWrong() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( false, dn.startsWith( new LdapDN( "c =  t, e =  f" ) ) );
+    }
 
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "c=d", nc.nextElement() );
-       assertEquals( true, nc.hasMoreElements() );
-       assertEquals( "a=b", nc.nextElement() );
-       assertEquals( true, nc.hasMoreElements() );
 
-       // The lowest atav should be the first one
-       assertEquals( "e=f+g=h", nc.nextElement() );
-       assertEquals( false, nc.hasMoreElements() );
-   }
+    // ENDS WITH operations
+    /**
+     * Test a endsWith a null LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithNull() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.endsWith( null ) );
+    }
 
 
-   // CLONE Operation
-   /**
-    * test a clone operation on a empty DN
-    */
-   public void testLdapDNCloneEmpty()
-   {
-       LdapDN dn = new LdapDN();
-       LdapDN clone = ( LdapDN ) dn.clone();
+    /**
+     * Test a endsWith an empty LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.endsWith( new LdapDN() ) );
+    }
 
-       assertEquals( "", clone.getUpName() );
-   }
 
+    /**
+     * Test a endsWith an simple LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.endsWith( new LdapDN( "a=b" ) ) );
+    }
 
-   /**
-    * test a clone operation on a simple DN
-    */
-   public void testLdapDNCloneSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a=b" );
-       LdapDN clone = ( LdapDN ) dn.clone();
 
-       assertEquals( "a=b", clone.getUpName() );
-       dn.remove( 0 );
-       assertEquals( "a=b", clone.getUpName() );
-   }
+    /**
+     * Test a endsWith a complex LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithComplex() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.endsWith( new LdapDN( "a =  b, c =  d" ) ) );
+    }
 
 
-   /**
-    * test a clone operation on a complex DN
-    */
-   public void testLdapDNCloneComplex() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "e=f+g=h,a=b,c=d" );
-       LdapDN clone = ( LdapDN ) dn.clone();
+    /**
+     * Test a endsWith a complex LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithComplexMixedCase() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( false, dn.endsWith( new LdapDN( "a =  B, C =  d" ) ) );
+    }
 
-       assertEquals( "e=f+g=h,a=b,c=d", clone.getUpName() );
-       dn.remove( 2 );
-       assertEquals( "e=f+g=h,a=b,c=d", clone.getUpName() );
-   }
 
+    /**
+     * Test a endsWith a full LdapDN
+     */
+    @Test
+    public void testLdapDNEndsWithFull() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( true, dn.endsWith( new LdapDN( "a=  b; c =  d, e =  f" ) ) );
+    }
 
-   // GET operations
-   /**
-    * test a get in a null DN
-    */
-   public void testLdapDNGetNull()
-   {
-       LdapDN dn = new LdapDN();
-       assertEquals( "", dn.get( 0 ) );
-   }
 
+    /**
+     * Test a endsWith which returns false
+     */
+    @Test
+    public void testLdapDNEndsWithWrong() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b, c=d,e = f" );
+        assertEquals( false, dn.endsWith( new LdapDN( "a =  b, e =  f" ) ) );
+    }
 
-   /**
-    * test a get in an empty DN
-    */
-   public void testLdapDNGetEmpty() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "" );
-       assertEquals( "", dn.get( 0 ) );
-   }
 
+    // GET ALL operations
+    /**
+     * test a getAll operation on a null DN
+     */
+    @Test
+    public void testLdapDNGetAllNull()
+    {
+        LdapDN dn = new LdapDN();
+        Enumeration<String> nc = dn.getAll();
 
-   /**
-    * test a get in a simple DN
-    */
-   public void testLdapDNGetSimple() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b" );
-       assertEquals( "a=b", dn.get( 0 ) );
-   }
+        assertEquals( false, nc.hasMoreElements() );
+    }
 
 
-   /**
-    * test a get in a complex DN
-    */
-   public void testLdapDNGetComplex() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b + c= d, e= f; g =h" );
-       assertEquals( "g=h", dn.get( 0 ) );
-       assertEquals( "e=f", dn.get( 1 ) );
-       assertEquals( "a=b+c=d", dn.get( 2 ) );
-   }
+    /**
+     * test a getAll operation on an empty DN
+     */
+    @Test
+    public void testLdapDNGetAllEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "" );
+        Enumeration<String> nc = dn.getAll();
 
+        assertEquals( false, nc.hasMoreElements() );
+    }
 
-   /**
-    * test a get out of bound
-    */
-   public void testLdapDNGetOutOfBound() throws InvalidNameException
-   {
-       LdapDN dn = new LdapDN( "a = b + c= d, e= f; g =h" );
 
-       try
-       {
-           dn.get( 4 );
-           Assert.fail();
-       }
-       catch ( ArrayIndexOutOfBoundsException aioob )
-       {
-           assertTrue( true );
-       }
-   }
+    /**
+     * test a getAll operation on a simple DN
+     */
+    @Test
+    public void testLdapDNGetAllSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b" );
+        Enumeration<String> nc = dn.getAll();
 
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "a=b", nc.nextElement() );
+        assertEquals( false, nc.hasMoreElements() );
+    }
 
-   /**
-    * Tests the examples from the JNDI tutorials to make sure LdapName behaves
-    * appropriately. The example can be found online <a href="">here</a>.
-    *
-    * @throws Exception
-    *             if anything goes wrong
-    */
-   public void testJNDITutorialExample() throws Exception
-   {
-       // Parse the name
-       Name name = new LdapDN( "cn=John,ou=People,ou=Marketing" );
 
-       // Remove the second component from the head: ou=People
-       String out = name.remove( 1 ).toString();
+    /**
+     * test a getAll operation on a complex DN
+     */
+    @Test
+    public void testLdapDNGetAllComplex() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "e=f+g=h,a=b,c=d" );
+        Enumeration<String> nc = dn.getAll();
 
-       // System.out.println( l_out ) ;
-       assertEquals( "ou=People", out );
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "c=d", nc.nextElement() );
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "a=b", nc.nextElement() );
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "e=f+g=h", nc.nextElement() );
+        assertEquals( false, nc.hasMoreElements() );
+    }
 
-       // Add to the head (first): cn=John,ou=Marketing,ou=East
-       out = name.add( 0, "ou=East" ).toString();
 
-       assertEquals( "cn=John,ou=Marketing,ou=East", out );
+    /**
+     * test a getAll operation on a complex DN
+     */
+    @Test
+    public void testLdapDNGetAllComplexOrdered() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "g=h+e=f,a=b,c=d" );
+        Enumeration<String> nc = dn.getAll();
 
-       // Add to the tail (last): cn=HomeDir,cn=John,ou=Marketing,ou=East
-       out = name.add( "cn=HomeDir" ).toString();
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "c=d", nc.nextElement() );
+        assertEquals( true, nc.hasMoreElements() );
+        assertEquals( "a=b", nc.nextElement() );
+        assertEquals( true, nc.hasMoreElements() );
 
-       assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", out );
-   }
+        // The lowest atav should be the first one
+        assertEquals( "e=f+g=h", nc.nextElement() );
+        assertEquals( false, nc.hasMoreElements() );
+    }
+
+
+    // CLONE Operation
+    /**
+     * test a clone operation on a empty DN
+     */
+    @Test
+    public void testLdapDNCloneEmpty()
+    {
+        LdapDN dn = new LdapDN();
+        LdapDN clone = ( LdapDN ) dn.clone();
+
+        assertEquals( "", clone.getUpName() );
+    }
+
+
+    /**
+     * test a clone operation on a simple DN
+     */
+    @Test
+    public void testLdapDNCloneSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a=b" );
+        LdapDN clone = ( LdapDN ) dn.clone();
+
+        assertEquals( "a=b", clone.getUpName() );
+        dn.remove( 0 );
+        assertEquals( "a=b", clone.getUpName() );
+    }
+
+
+    /**
+     * test a clone operation on a complex DN
+     */
+    @Test
+    public void testLdapDNCloneComplex() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "e=f+g=h,a=b,c=d" );
+        LdapDN clone = ( LdapDN ) dn.clone();
+
+        assertEquals( "e=f+g=h,a=b,c=d", clone.getUpName() );
+        dn.remove( 2 );
+        assertEquals( "e=f+g=h,a=b,c=d", clone.getUpName() );
+    }
+
+
+    // GET operations
+    /**
+     * test a get in a null DN
+     */
+    @Test
+    public void testLdapDNGetNull()
+    {
+        LdapDN dn = new LdapDN();
+        assertEquals( "", dn.get( 0 ) );
+    }
+
+
+    /**
+     * test a get in an empty DN
+     */
+    @Test
+    public void testLdapDNGetEmpty() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "" );
+        assertEquals( "", dn.get( 0 ) );
+    }
+
+
+    /**
+     * test a get in a simple DN
+     */
+    @Test
+    public void testLdapDNGetSimple() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b" );
+        assertEquals( "a=b", dn.get( 0 ) );
+    }
+
+
+    /**
+     * test a get in a complex DN
+     */
+    @Test
+    public void testLdapDNGetComplex() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b + c= d, e= f; g =h" );
+        assertEquals( "g=h", dn.get( 0 ) );
+        assertEquals( "e=f", dn.get( 1 ) );
+        assertEquals( "a=b+c=d", dn.get( 2 ) );
+    }
+
+
+    /**
+     * test a get out of bound
+     */
+    @Test
+    public void testLdapDNGetOutOfBound() throws InvalidNameException
+    {
+        LdapDN dn = new LdapDN( "a = b + c= d, e= f; g =h" );
+
+        try
+        {
+            dn.get( 4 );
+            fail();
+        }
+        catch ( IndexOutOfBoundsException aioob )
+        {
+            assertTrue( true );
+        }
+    }
+
+
+    /**
+     * Tests the examples from the JNDI tutorials to make sure LdapName behaves
+     * appropriately. The example can be found online <a href="">here</a>.
+     *
+     * @throws Exception
+     *             if anything goes wrong
+     */
+    @Test
+    public void testJNDITutorialExample() throws Exception
+    {
+        // Parse the name
+        Name name = new LdapDN( "cn=John,ou=People,ou=Marketing" );
+
+        // Remove the second component from the head: ou=People
+        String out = name.remove( 1 ).toString();
+
+        assertEquals( "ou=People", out );
+
+        // Add to the head (first): cn=John,ou=Marketing,ou=East
+        out = name.add( 0, "ou=East" ).toString();
+
+        assertEquals( "cn=John,ou=Marketing,ou=East", out );
+
+        // Add to the tail (last): cn=HomeDir,cn=John,ou=Marketing,ou=East
+        out = name.add( "cn=HomeDir" ).toString();
+
+        assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", out );
+    }
+
+
+    @Test
+    public void testAttributeEqualsIsCaseInSensitive() throws Exception
+    {
+        Name name1 = new LdapDN( "cn=HomeDir" );
+        Name name2 = new LdapDN( "CN=HomeDir" );
+
+        assertTrue( name1.equals( name2 ) );
+    }
+
+
+    @Test
+    public void testAttributeTypeEqualsIsCaseInsensitive() throws Exception
+    {
+        Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
+        Name name2 = new LdapDN( "cn=HomeDir+CN=WorkDir" );
+
+        assertTrue( name1.equals( name2 ) );
+    }
+
+
+    @Test
+    public void testNameEqualsIsInsensitiveToAttributesOrder() throws Exception
+    {
+
+        Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
+        Name name2 = new LdapDN( "cn=WorkDir+cn=HomeDir" );
+
+        assertTrue( name1.equals( name2 ) );
+    }
+
+
+    @Test
+    public void testAttributeComparisonIsCaseInSensitive() throws Exception
+    {
+        Name name1 = new LdapDN( "cn=HomeDir" );
+        Name name2 = new LdapDN( "CN=HomeDir" );
+
+        assertEquals( 0, name1.compareTo( name2 ) );
+    }
+
+
+    @Test
+    public void testAttributeTypeComparisonIsCaseInsensitive() throws Exception
+    {
+        Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
+        Name name2 = new LdapDN( "cn=HomeDir+CN=WorkDir" );
+
+        assertEquals( 0, name1.compareTo( name2 ) );
+    }
+
+
+    @Test
+    public void testNameComparisonIsInsensitiveToAttributesOrder() throws Exception
+    {
+
+        Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
+        Name name2 = new LdapDN( "cn=WorkDir+cn=HomeDir" );
+
+        assertEquals( 0, name1.compareTo( name2 ) );
+    }
+
+
+    @Test
+    public void testNameComparisonIsInsensitiveToAttributesOrderFailure() throws Exception
+    {
+
+        Name name1 = new LdapDN( "cn= HomeDir+cn=Workdir" );
+        Name name2 = new LdapDN( "cn = Work+cn=HomeDir" );
+
+        assertEquals( 1, name1.compareTo( name2 ) );
+    }
+
+
+    /**
+     * Test the encoding of a LdanDN
+     */
+    @Test
+    public void testNameToBytes() throws Exception
+    {
+        LdapDN dn = new LdapDN( "cn = John, ou = People, OU = Marketing" );
+
+        byte[] bytes = LdapDN.getBytes( dn );
+
+        assertEquals( 30, LdapDN.getNbBytes( dn ) );
+        assertEquals( "cn=John,ou=People,ou=Marketing", new String( bytes, "UTF-8" ) );
+    }
+
+
+    @Test
+    public void testStringParser() throws Exception
+    {
+
+        String dn = StringTools.utf8ToString( new byte[]
+            { 'C', 'N', ' ', '=', ' ', 'E', 'm', 'm', 'a', 'n', 'u', 'e', 'l', ' ', ' ', 'L', ( byte ) 0xc3,
+                ( byte ) 0xa9, 'c', 'h', 'a', 'r', 'n', 'y' } );
+
+        Name name = LdapDnParser.getNameParser().parse( dn );
+
+        assertEquals( dn, ( ( LdapDN ) name ).getUpName() );
+        assertEquals( "cn=Emmanuel  L\\C3\\A9charny", name.toString() );
+    }
+
+
+    /**
+     * Class to test for void LdapName(String)
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testLdapNameString() throws Exception
+    {
+        Name name = new LdapDN( "" );
+        Name name50 = new LdapDN();
+        assertEquals( name50, name );
+
+        Name name0 = new LdapDN( "ou=Marketing,ou=East" );
+        Name copy = new LdapDN( "ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name4 = new LdapDN( "cn=Website,cn=John,ou=Marketing,ou=West" );
+        Name name5 = new LdapDN( "cn=Airline,cn=John,ou=Marketing,ou=West" );
+
+        assertTrue( name0.compareTo( copy ) == 0 );
+        assertTrue( name0.compareTo( name1 ) < 0 );
+        assertTrue( name0.compareTo( name2 ) < 0 );
+        assertTrue( name1.compareTo( name2 ) < 0 );
+        assertTrue( name2.compareTo( name1 ) > 0 );
+        assertTrue( name2.compareTo( name0 ) > 0 );
+        assertTrue( name2.compareTo( name3 ) < 0 );
+        assertTrue( name2.compareTo( name4 ) < 0 );
+        assertTrue( name3.compareTo( name4 ) < 0 );
+        assertTrue( name3.compareTo( name5 ) > 0 );
+        assertTrue( name4.compareTo( name5 ) > 0 );
+        assertTrue( name2.compareTo( name5 ) < 0 );
+    }
+
+
+    /**
+     * Class to test for void LdapName()
+     */
+    @Test
+    public void testLdapName()
+    {
+        Name name = new LdapDN();
+        assertTrue( name.toString().equals( "" ) );
+    }
+
+
+    /**
+     * Class to test for void LdapName(List)
+     */
+    @Test
+    public void testLdapNameList() throws InvalidNameException
+    {
+        List<String> list = new ArrayList<String>();
+        list.add( "ou=People" );
+        list.add( "dc=example" );
+        list.add( "dc=com" );
+        Name name = new LdapDN( list );
+        assertTrue( name.toString().equals( "ou=People,dc=example,dc=com" ) );
+    }
+
+
+    /**
+     * Class to test for void LdapName(Iterator)
+     */
+    @Test
+    public void testLdapNameIterator() throws InvalidNameException
+    {
+        List<String> list = new ArrayList<String>();
+        list.add( "ou=People" );
+        list.add( "dc=example" );
+        list.add( "dc=com" );
+        Name name = new LdapDN( list.iterator() );
+        assertTrue( name.toString().equals( "ou=People,dc=example,dc=com" ) );
+    }
+
+
+    /**
+     * Class to test for Object clone()
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testClone() throws Exception
+    {
+        String strName = "cn=HomeDir,cn=John,ou=Marketing,ou=East";
+        Name name = new LdapDN( strName );
+        assertEquals( name, name.clone() );
+    }
+
+
+    /**
+     * Class to test for compareTo
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testCompareTo() throws Exception
+    {
+        Name name0 = new LdapDN( "ou=Marketing,ou=East" );
+        Name copy = new LdapDN( "ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name4 = new LdapDN( "cn=Website,cn=John,ou=Marketing,ou=West" );
+        Name name5 = new LdapDN( "cn=Airline,cn=John,ou=Marketing,ou=West" );
+
+        assertTrue( name0.compareTo( copy ) == 0 );
+        assertTrue( name0.compareTo( name1 ) < 0 );
+        assertTrue( name0.compareTo( name2 ) < 0 );
+        assertTrue( name1.compareTo( name2 ) < 0 );
+        assertTrue( name2.compareTo( name1 ) > 0 );
+        assertTrue( name2.compareTo( name0 ) > 0 );
+        assertTrue( name2.compareTo( name3 ) < 0 );
+        assertTrue( name2.compareTo( name4 ) < 0 );
+        assertTrue( name3.compareTo( name4 ) < 0 );
+        assertTrue( name3.compareTo( name5 ) > 0 );
+        assertTrue( name4.compareTo( name5 ) > 0 );
+        assertTrue( name2.compareTo( name5 ) < 0 );
+
+        List<Name> list = new ArrayList<Name>();
+
+        Comparator<Name> comparator = new Comparator<Name>()
+        {
+            public int compare( Name obj1, Name obj2 )
+            {
+                Name n1 = obj1;
+                Name n2 = obj2;
+                return n1.compareTo( n2 );
+            }
+
+
+            public boolean equals( Object obj )
+            {
+                return super.equals( obj );
+            }
+
+
+            /**
+             * Compute the instance's hash code
+             * @return the instance's hash code 
+             */
+            public int hashCode()
+            {
+                return super.hashCode();
+            }
+        };
+
+        list.add( name0 );
+        list.add( name1 );
+        list.add( name2 );
+        list.add( name3 );
+        list.add( name4 );
+        list.add( name5 );
+        Collections.sort( list, comparator );
+
+        assertEquals( name0, list.get( 0 ) );
+        assertEquals( name1, list.get( 1 ) );
+        assertEquals( name2, list.get( 2 ) );
+        assertEquals( name5, list.get( 3 ) );
+        assertEquals( name3, list.get( 4 ) );
+        assertEquals( name4, list.get( 5 ) );
+    }
+
+
+    /**
+     * Class to test for size
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testSize() throws Exception
+    {
+        Name name0 = new LdapDN( "" );
+        Name name1 = new LdapDN( "ou=East" );
+        Name name2 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+
+        assertEquals( 0, name0.size() );
+        assertEquals( 1, name1.size() );
+        assertEquals( 2, name2.size() );
+        assertEquals( 3, name3.size() );
+        assertEquals( 4, name4.size() );
+        assertEquals( 5, name5.size() );
+        assertEquals( 6, name6.size() );
+    }
+
+
+    /**
+     * Class to test for isEmpty
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testIsEmpty() throws Exception
+    {
+        Name name0 = new LdapDN( "" );
+        Name name1 = new LdapDN( "ou=East" );
+        Name name2 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
 
+        assertEquals( true, name0.isEmpty() );
+        assertEquals( false, name1.isEmpty() );
+        assertEquals( false, name2.isEmpty() );
+        assertEquals( false, name3.isEmpty() );
+        assertEquals( false, name4.isEmpty() );
+        assertEquals( false, name5.isEmpty() );
+        assertEquals( false, name6.isEmpty() );
+    }
 
-   public void testAttributeEqualsIsCaseInSensitive() throws Exception
-   {
-       Name name1 = new LdapDN( "cn=HomeDir" );
-       Name name2 = new LdapDN( "CN=HomeDir" );
 
-       assertTrue( name1.equals( name2 ) );
-   }
+    /**
+     * Class to test for getAll
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testGetAll() throws Exception
+    {
+        Name name0 = new LdapDN( "" );
+        Name name1 = new LdapDN( "ou=East" );
+        Name name2 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
 
+        Enumeration<String> enum0 = name0.getAll();
+        assertEquals( false, enum0.hasMoreElements() );
 
-   public void testAttributeTypeEqualsIsCaseInsensitive() throws Exception
-   {
-       Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
-       Name name2 = new LdapDN( "cn=HomeDir+CN=WorkDir" );
+        Enumeration<String> enum1 = name1.getAll();
+        assertEquals( true, enum1.hasMoreElements() );
 
-       assertTrue( name1.equals( name2 ) );
-   }
+        for ( int i = 0; enum1.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum1.nextElement();
 
+            if ( i == 0 )
+            {
+                assertEquals( "ou=East", element );
+            }
+        }
 
-   public void testNameEqualsIsInsensitiveToAttributesOrder() throws Exception
-   {
+        Enumeration<String> enum2 = name2.getAll();
+        assertEquals( true, enum2.hasMoreElements() );
 
-       Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
-       Name name2 = new LdapDN( "cn=WorkDir+cn=HomeDir" );
+        for ( int i = 0; enum2.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum2.nextElement();
 
-       assertTrue( name1.equals( name2 ) );
-   }
+            if ( i == 0 )
+            {
+                assertEquals( "ou=East", element );
+            }
 
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element );
+            }
+        }
 
-   public void testAttributeComparisonIsCaseInSensitive() throws Exception
-   {
-       Name name1 = new LdapDN( "cn=HomeDir" );
-       Name name2 = new LdapDN( "CN=HomeDir" );
+        Enumeration<String> enum3 = name3.getAll();
+        assertEquals( true, enum3.hasMoreElements() );
 
-       assertEquals( 0, name1.compareTo( name2 ) );
-   }
+        for ( int i = 0; enum3.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum3.nextElement();
 
+            if ( i == 0 )
+            {
+                assertEquals( "ou=East", element );
+            }
 
-   public void testAttributeTypeComparisonIsCaseInsensitive() throws Exception
-   {
-       Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
-       Name name2 = new LdapDN( "cn=HomeDir+CN=WorkDir" );
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element );
+            }
 
-       assertEquals( 0, name1.compareTo( name2 ) );
-   }
+            if ( i == 2 )
+            {
+                assertEquals( "cn=John", element );
+            }
+        }
 
+        Enumeration<String> enum4 = name4.getAll();
+        assertEquals( true, enum4.hasMoreElements() );
 
-   public void testNameComparisonIsInsensitiveToAttributesOrder() throws Exception
-   {
+        for ( int i = 0; enum4.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum4.nextElement();
 
-       Name name1 = new LdapDN( "cn=HomeDir+cn=WorkDir" );
-       Name name2 = new LdapDN( "cn=WorkDir+cn=HomeDir" );
+            if ( i == 0 )
+            {
+                assertEquals( "ou=East", element );
+            }
 
-       assertEquals( 0, name1.compareTo( name2 ) );
-   }
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element );
+            }
 
+            if ( i == 2 )
+            {
+                assertEquals( "cn=John", element );
+            }
 
-   public void testNameComparisonIsInsensitiveToAttributesOrderFailure() throws Exception
-   {
+            if ( i == 3 )
+            {
+                assertEquals( "cn=HomeDir", element );
+            }
+        }
 
-       Name name1 = new LdapDN( "cn= HomeDir+cn=Workdir" );
-       Name name2 = new LdapDN( "cn = Work+cn=HomeDir" );
+        Enumeration<String> enum5 = name5.getAll();
+        assertEquals( true, enum5.hasMoreElements() );
 
-       assertEquals( 1, name1.compareTo( name2 ) );
-   }
+        for ( int i = 0; enum5.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum5.nextElement();
 
+            if ( i == 0 )
+            {
+                assertEquals( "ou=West", element );
+            }
 
-   /**
-    * Test the encoding of a LdanDN
-    */
-   public void testNameToBytes() throws Exception
-   {
-       LdapDN dn = new LdapDN( "cn = John, ou = People, OU = Marketing" );
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element );
+            }
 
-       byte[] bytes = LdapDN.getBytes( dn );
+            if ( i == 2 )
+            {
+                assertEquals( "cn=John", element );
+            }
 
-       assertEquals( 30, LdapDN.getNbBytes( dn ) );
-       assertEquals( "cn=John,ou=People,ou=Marketing", new String( bytes, "UTF-8" ) );
-   }
+            if ( i == 3 )
+            {
+                assertEquals( "cn=HomeDir", element );
+            }
 
+            if ( i == 4 )
+            {
+                assertEquals( "cn=Website", element );
+            }
+        }
 
-   public void testStringParser() throws Exception
-   {
-       
-       String dn = StringTools.utf8ToString( new byte[]{'C', 'N', ' ', '=', ' ', 'E', 'm', 'm', 'a', 'n', 'u', 'e', 
-           'l', ' ', ' ', 'L', (byte)0xc3, (byte)0xa9, 'c', 'h', 'a', 'r', 'n', 'y'} );
+        Enumeration<String> enum6 = name6.getAll();
+        assertEquals( true, enum6.hasMoreElements() );
 
-       Name name = LdapDnParser.getNameParser().parse( dn );
+        for ( int i = 0; enum6.hasMoreElements(); i++ )
+        {
+            String element = ( String ) enum6.nextElement();
 
-       assertEquals( dn, ( ( LdapDN ) name ).getUpName() );
-       assertEquals( "cn=Emmanuel  L\\C3\\A9charny", name.toString() );
-   }
+            if ( i == 0 )
+            {
+                assertEquals( "ou=West", element );
+            }
 
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element );
+            }
 
-   /**
-    * Class to test for void LdapName(String)
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testLdapNameString() throws Exception
-   {
-       Name name = new LdapDN( "" );
-       Name name50 = new LdapDN();
-       assertEquals( name50, name );
+            if ( i == 2 )
+            {
+                assertEquals( "cn=John", element );
+            }
 
-       Name name0 = new LdapDN( "ou=Marketing,ou=East" );
-       Name copy = new LdapDN( "ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=West" );
-       Name name4 = new LdapDN( "cn=Website,cn=John,ou=Marketing,ou=West" );
-       Name name5 = new LdapDN( "cn=Airline,cn=John,ou=Marketing,ou=West" );
+            if ( i == 3 )
+            {
+                assertEquals( "cn=HomeDir", element );
+            }
 
-       assertTrue( name0.compareTo( copy ) == 0 );
-       assertTrue( name0.compareTo( name1 ) < 0 );
-       assertTrue( name0.compareTo( name2 ) < 0 );
-       assertTrue( name1.compareTo( name2 ) < 0 );
-       assertTrue( name2.compareTo( name1 ) > 0 );
-       assertTrue( name2.compareTo( name0 ) > 0 );
-       assertTrue( name2.compareTo( name3 ) < 0 );
-       assertTrue( name2.compareTo( name4 ) < 0 );
-       assertTrue( name3.compareTo( name4 ) < 0 );
-       assertTrue( name3.compareTo( name5 ) > 0 );
-       assertTrue( name4.compareTo( name5 ) > 0 );
-       assertTrue( name2.compareTo( name5 ) < 0 );
-   }
+            if ( i == 4 )
+            {
+                assertEquals( "cn=Website", element );
+            }
 
+            if ( i == 5 )
+            {
+                assertEquals( "cn=Airline", element );
+            }
+        }
+    }
 
-   /**
-    * Class to test for void LdapName()
-    */
-   public void testLdapName()
-   {
-       Name name = new LdapDN();
-       assertTrue( name.toString().equals( "" ) );
-   }
 
+    /**
+     * Class to test for getAllRdn
+     *
+     * @throws Exception
+     *             if anything goes wrong.
+     */
+    @Test
+    public void testGetAllRdn() throws Exception
+    {
+        LdapDN name = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
 
-   /**
-    * Class to test for void LdapName(List)
-    */
-   public void testLdapNameList() throws InvalidNameException
-   {
-       List<String> list = new ArrayList<String>();
-       list.add( "ou=People" );
-       list.add( "dc=example" );
-       list.add( "dc=com" );
-       Name name = new LdapDN( list );
-       assertTrue( name.toString().equals( "ou=People,dc=example,dc=com" ) );
-   }
+        Enumeration<Rdn> rdns = name.getAllRdn();
+        assertEquals( true, rdns.hasMoreElements() );
 
+        for ( int i = 0; rdns.hasMoreElements(); i++ )
+        {
+            Rdn element = ( Rdn ) rdns.nextElement();
 
-   /**
-    * Class to test for void LdapName(Iterator)
-    */
-   public void testLdapNameIterator() throws InvalidNameException
-   {
-       List<String> list = new ArrayList<String>();
-       list.add( "ou=People" );
-       list.add( "dc=example" );
-       list.add( "dc=com" );
-       Name name = new LdapDN( list.iterator() );
-       assertTrue( name.toString().equals( "ou=People,dc=example,dc=com" ) );
-   }
+            if ( i == 0 )
+            {
+                assertEquals( "ou=West", element.toString() );
+            }
 
+            if ( i == 1 )
+            {
+                assertEquals( "ou=Marketing", element.toString() );
+            }
 
-   /**
-    * Class to test for Object clone()
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testClone() throws Exception
-   {
-       String strName = "cn=HomeDir,cn=John,ou=Marketing,ou=East";
-       Name name = new LdapDN( strName );
-       assertEquals( name, name.clone() );
-   }
+            if ( i == 2 )
+            {
+                assertEquals( "cn=John", element.toString() );
+            }
 
+            if ( i == 3 )
+            {
+                assertEquals( "cn=HomeDir", element.toString() );
+            }
 
-   /**
-    * Class to test for compareTo
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testCompareTo() throws Exception
-   {
-       Name name0 = new LdapDN( "ou=Marketing,ou=East" );
-       Name copy = new LdapDN( "ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=West" );
-       Name name4 = new LdapDN( "cn=Website,cn=John,ou=Marketing,ou=West" );
-       Name name5 = new LdapDN( "cn=Airline,cn=John,ou=Marketing,ou=West" );
+            if ( i == 4 )
+            {
+                assertEquals( "cn=Website", element.toString() );
+            }
 
-       assertTrue( name0.compareTo( copy ) == 0 );
-       assertTrue( name0.compareTo( name1 ) < 0 );
-       assertTrue( name0.compareTo( name2 ) < 0 );
-       assertTrue( name1.compareTo( name2 ) < 0 );
-       assertTrue( name2.compareTo( name1 ) > 0 );
-       assertTrue( name2.compareTo( name0 ) > 0 );
-       assertTrue( name2.compareTo( name3 ) < 0 );
-       assertTrue( name2.compareTo( name4 ) < 0 );
-       assertTrue( name3.compareTo( name4 ) < 0 );
-       assertTrue( name3.compareTo( name5 ) > 0 );
-       assertTrue( name4.compareTo( name5 ) > 0 );
-       assertTrue( name2.compareTo( name5 ) < 0 );
+            if ( i == 5 )
+            {
+                assertEquals( "cn=Airline", element.toString() );
+            }
+        }
+    }
 
-       List<Name> list = new ArrayList<Name>();
 
-       Comparator<Name> comparator = new Comparator<Name>()
-       {
-           public int compare( Name obj1, Name obj2 )
-           {
-               Name n1 = obj1;
-               Name n2 = obj2;
-               return n1.compareTo( n2 );
-           }
+    /**
+     * Class to test for get
+     *
+     * @throws Exception
+     *             anything goes wrong
+     */
+    @Test
+    public void testGet() throws Exception
+    {
+        Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        assertEquals( "cn=HomeDir", name.get( 3 ) );
+        assertEquals( "cn=John", name.get( 2 ) );
+        assertEquals( "ou=Marketing", name.get( 1 ) );
+        assertEquals( "ou=East", name.get( 0 ) );
+    }
 
 
-           public boolean equals( Object obj )
-           {
-               return super.equals( obj );
-           }
+    /**
+     * Class to test for getSuffix
+     *
+     * @throws Exception
+     *             anything goes wrong
+     */
+    @Test
+    public void testGetXSuffix() throws Exception
+    {
+        Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        assertEquals( "", name.getSuffix( 4 ).toString() );
+        assertEquals( "cn=HomeDir", name.getSuffix( 3 ).toString() );
+        assertEquals( "cn=HomeDir,cn=John", name.getSuffix( 2 ).toString() );
+        assertEquals( "cn=HomeDir,cn=John,ou=Marketing", name.getSuffix( 1 ).toString() );
+        assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.getSuffix( 0 ).toString() );
+    }
 
 
-           public int hashCode()
-           {
-               return super.hashCode();
-           }
-       };
+    /**
+     * Class to test for getPrefix
+     *
+     * @throws Exception
+     *             anything goes wrong
+     */
+    @Test
+    public void testGetPrefix() throws Exception
+    {
+        Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-       list.add( name0 );
-       list.add( name1 );
-       list.add( name2 );
-       list.add( name3 );
-       list.add( name4 );
-       list.add( name5 );
-       Collections.sort( list, comparator );
+        assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.getPrefix( 4 ).toString() );
+        assertEquals( "cn=John,ou=Marketing,ou=East", name.getPrefix( 3 ).toString() );
+        assertEquals( "ou=Marketing,ou=East", name.getPrefix( 2 ).toString() );
+        assertEquals( "ou=East", name.getPrefix( 1 ).toString() );
+        assertEquals( "", name.getPrefix( 0 ).toString() );
+    }
 
-       assertEquals( name0, list.get( 0 ) );
-       assertEquals( name1, list.get( 1 ) );
-       assertEquals( name2, list.get( 2 ) );
-       assertEquals( name5, list.get( 3 ) );
-       assertEquals( name3, list.get( 4 ) );
-       assertEquals( name4, list.get( 5 ) );
-   }
 
+    /**
+     * Class to test for startsWith
+     *
+     * @throws Exception
+     *             anything goes wrong
+     */
+    @Test
+    public void testStartsWith() throws Exception
+    {
+        Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name4 = new LdapDN( "ou=East" );
+        Name name5 = new LdapDN( "" );
 
-   /**
-    * Class to test for size
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testSize() throws Exception
-   {
-       Name name0 = new LdapDN( "" );
-       Name name1 = new LdapDN( "ou=East" );
-       Name name2 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
-       Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name6 = new LdapDN( "cn=HomeDir" );
+        Name name7 = new LdapDN( "cn=HomeDir,cn=John" );
+        Name name8 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing" );
 
-       assertEquals( 0, name0.size() );
-       assertEquals( 1, name1.size() );
-       assertEquals( 2, name2.size() );
-       assertEquals( 3, name3.size() );
-       assertEquals( 4, name4.size() );
-       assertEquals( 5, name5.size() );
-       assertEquals( 6, name6.size() );
-   }
+        assertTrue( name0.startsWith( name1 ) );
+        assertTrue( name0.startsWith( name2 ) );
+        assertTrue( name0.startsWith( name3 ) );
+        assertTrue( name0.startsWith( name4 ) );
+        assertTrue( name0.startsWith( name5 ) );
 
+        assertTrue( !name0.startsWith( name6 ) );
+        assertTrue( !name0.startsWith( name7 ) );
+        assertTrue( !name0.startsWith( name8 ) );
+    }
 
-   /**
-    * Class to test for isEmpty
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testIsEmpty() throws Exception
-   {
-       Name name0 = new LdapDN( "" );
-       Name name1 = new LdapDN( "ou=East" );
-       Name name2 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
-       Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
 
-       assertEquals( true, name0.isEmpty() );
-       assertEquals( false, name1.isEmpty() );
-       assertEquals( false, name2.isEmpty() );
-       assertEquals( false, name3.isEmpty() );
-       assertEquals( false, name4.isEmpty() );
-       assertEquals( false, name5.isEmpty() );
-       assertEquals( false, name6.isEmpty() );
-   }
+    /**
+     * Class to test for endsWith
+     *
+     * @throws Exception
+     *             anything goes wrong
+     */
+    @Test
+    public void testEndsWith() throws Exception
+    {
+        Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        Name name3 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name4 = new LdapDN( "ou=East" );
+        Name name5 = new LdapDN( "" );
 
+        Name name6 = new LdapDN( "cn=HomeDir" );
+        Name name7 = new LdapDN( "cn=HomeDir,cn=John" );
+        Name name8 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing" );
 
-   /**
-    * Class to test for getAll
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testGetAll() throws Exception
-   {
-       Name name0 = new LdapDN( "" );
-       Name name1 = new LdapDN( "ou=East" );
-       Name name2 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name4 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name5 = new LdapDN( "cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
-       Name name6 = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        assertTrue( name0.endsWith( name1 ) );
+        assertTrue( !name0.endsWith( name2 ) );
+        assertTrue( !name0.endsWith( name3 ) );
+        assertTrue( !name0.endsWith( name4 ) );
+        assertTrue( name0.endsWith( name5 ) );
 
-       Enumeration enum0 = name0.getAll();
-       assertEquals( false, enum0.hasMoreElements() );
+        assertTrue( name0.endsWith( name6 ) );
+        assertTrue( name0.endsWith( name7 ) );
+        assertTrue( name0.endsWith( name8 ) );
+    }
 
-       Enumeration enum1 = name1.getAll();
-       assertEquals( true, enum1.hasMoreElements() );
 
-       for ( int i = 0; enum1.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum1.nextElement();
+    /**
+     * Class to test for Name addAll(Name)
+     *
+     * @throws Exception
+     *             when anything goes wrong
+     */
+    @Test
+    public void testAddAllName0() throws Exception
+    {
+        Name name = new LdapDN();
+        Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        assertTrue( name0.equals( name.addAll( name0 ) ) );
+    }
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=East", element );
-           }
-       }
 
-       Enumeration enum2 = name2.getAll();
-       assertEquals( true, enum2.hasMoreElements() );
+    /**
+     * Class to test for Name addAll(Name)
+     *
+     * @throws Exception
+     *             when anything goes wrong
+     */
+    @Test
+    public void testAddAllNameExisting0() throws Exception
+    {
+        Name name1 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John" );
+        Name nameAdded = new LdapDN( "cn=HomeDir,cn=John, ou=Marketing,ou=East" );
+        assertTrue( nameAdded.equals( name1.addAll( name2 ) ) );
+    }
 
-       for ( int i = 0; enum2.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum2.nextElement();
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=East", element );
-           }
+    /**
+     * Class to test for Name addAll(Name)
+     *
+     * @throws Exception
+     *             when anything goes wrong
+     */
+    @Test
+    public void testAddAllName1() throws Exception
+    {
+        Name name = new LdapDN();
+        Name name0 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=HomeDir,cn=John" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element );
-           }
-       }
+        assertTrue( name0.equals( name.addAll( name0 ) ) );
+        assertTrue( name2.equals( name.addAll( name1 ) ) );
+    }
 
-       Enumeration enum3 = name3.getAll();
-       assertEquals( true, enum3.hasMoreElements() );
 
-       for ( int i = 0; enum3.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum3.nextElement();
+    /**
+     * Class to test for Name addAll(int, Name)
+     *
+     * @throws Exception
+     *             when something goes wrong
+     */
+    @Test
+    public void testAddAllintName0() throws Exception
+    {
+        Name name = new LdapDN();
+        Name name0 = new LdapDN( "ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=HomeDir,cn=John" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=East", element );
-           }
+        assertTrue( name0.equals( name.addAll( name0 ) ) );
+        assertTrue( name2.equals( name.addAll( 2, name1 ) ) );
+    }
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element );
-           }
 
-           if ( i == 2 )
-           {
-               assertEquals( "cn=John", element );
-           }
-       }
+    /**
+     * Class to test for Name addAll(int, Name)
+     *
+     * @throws Exception
+     *             when something goes wrong
+     */
+    @Test
+    public void testAddAllintName1() throws Exception
+    {
+        Name name = new LdapDN();
+        Name name0 = new LdapDN( "cn=HomeDir,ou=Marketing,ou=East" );
+        Name name1 = new LdapDN( "cn=John" );
+        Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-       Enumeration enum4 = name4.getAll();
-       assertEquals( true, enum4.hasMoreElements() );
+        assertTrue( name0.equals( name.addAll( name0 ) ) );
+        assertTrue( name2.equals( name.addAll( 2, name1 ) ) );
 
-       for ( int i = 0; enum4.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum4.nextElement();
+        Name name3 = new LdapDN( "cn=Airport" );
+        Name name4 = new LdapDN( "cn=Airport,cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=East", element );
-           }
+        assertTrue( name4.equals( name.addAll( 4, name3 ) ) );
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element );
-           }
+        Name name5 = new LdapDN( "cn=ABC123" );
+        Name name6 = new LdapDN( "cn=Airport,cn=HomeDir,cn=ABC123,cn=John,ou=Marketing,ou=East" );
 
-           if ( i == 2 )
-           {
-               assertEquals( "cn=John", element );
-           }
+        assertTrue( name6.equals( name.addAll( 3, name5 ) ) );
+    }
 
-           if ( i == 3 )
-           {
-               assertEquals( "cn=HomeDir", element );
-           }
-       }
 
-       Enumeration enum5 = name5.getAll();
-       assertEquals( true, enum5.hasMoreElements() );
+    /**
+     * Class to test for Name add(String)
+     *
+     * @throws Exception
+     *             when something goes wrong
+     */
+    @Test
+    public void testAddString() throws Exception
+    {
+        Name name = new LdapDN();
+        assertEquals( name, new LdapDN( "" ) );
 
-       for ( int i = 0; enum5.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum5.nextElement();
+        Name name4 = new LdapDN( "ou=East" );
+        name.add( "ou=East" );
+        assertEquals( name4, name );
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=West", element );
-           }
+        Name name3 = new LdapDN( "ou=Marketing,ou=East" );
+        name.add( "ou=Marketing" );
+        assertEquals( name3, name );
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element );
-           }
+        Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        name.add( "cn=John" );
+        assertEquals( name2, name );
 
-           if ( i == 2 )
-           {
-               assertEquals( "cn=John", element );
-           }
+        Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        name.add( "cn=HomeDir" );
+        assertEquals( name0, name );
+    }
 
-           if ( i == 3 )
-           {
-               assertEquals( "cn=HomeDir", element );
-           }
 
-           if ( i == 4 )
-           {
-               assertEquals( "cn=Website", element );
-           }
-       }
+    /**
+     * Class to test for Name add(int, String)
+     *
+     * @throws Exception
+     *             if anything goes wrong
+     */
+    @Test
+    public void testAddintString() throws Exception
+    {
+        Name name = new LdapDN();
+        assertEquals( name, new LdapDN( "" ) );
 
-       Enumeration enum6 = name6.getAll();
-       assertEquals( true, enum6.hasMoreElements() );
+        Name name4 = new LdapDN( "ou=East" );
+        name.add( "ou=East" );
+        assertEquals( name4, name );
 
-       for ( int i = 0; enum6.hasMoreElements(); i++ )
-       {
-           String element = ( String ) enum6.nextElement();
+        Name name3 = new LdapDN( "ou=Marketing,ou=East" );
+        name.add( 1, "ou=Marketing" );
+        assertEquals( name3, name );
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=West", element );
-           }
+        Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
+        name.add( 2, "cn=John" );
+        assertEquals( name2, name );
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element );
-           }
+        Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        name.add( 3, "cn=HomeDir" );
+        assertEquals( name0, name );
 
-           if ( i == 2 )
-           {
-               assertEquals( "cn=John", element );
-           }
+        Name name5 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East,o=LL " + "Bean Inc." );
+        name.add( 0, "o=LL Bean Inc." );
+        assertEquals( name5, name );
 
-           if ( i == 3 )
-           {
-               assertEquals( "cn=HomeDir", element );
-           }
+        Name name6 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East,c=US,o=LL " + "Bean Inc." );
+        name.add( 1, "c=US" );
+        assertEquals( name6, name );
 
-           if ( i == 4 )
-           {
-               assertEquals( "cn=Website", element );
-           }
+        Name name7 = new LdapDN( "cn=HomeDir,cn=John,ou=Advertising,ou=Marketing," + "ou=East,c=US,o=LL " + "Bean Inc." );
+        name.add( 4, "ou=Advertising" );
+        assertEquals( name7, name );
+    }
 
-           if ( i == 5 )
-           {
-               assertEquals( "cn=Airline", element );
-           }
-       }
-   }
 
+    /**
+     * Class to test for remove
+     *
+     * @throws Exception
+     *             if anything goes wrong
+     */
+    @Test
+    public void testRemove() throws Exception
+    {
+        Name name = new LdapDN();
+        assertEquals( new LdapDN( "" ), name );
 
-   /**
-    * Class to test for getAllRdn
-    *
-    * @throws Exception
-    *             if anything goes wrong.
-    */
-   public void testGetAllRdn() throws Exception
-   {
-       LdapDN name = new LdapDN( "cn=Airline,cn=Website,cn=HomeDir,cn=John,ou=Marketing,ou=West" );
+        Name name3 = new LdapDN( "ou=Marketing" );
+        name.add( "ou=East" );
+        name.add( 1, "ou=Marketing" );
+        name.remove( 0 );
+        assertEquals( name3, name );
 
-       Enumeration rdns = name.getAllRdn();
-       assertEquals( true, rdns.hasMoreElements() );
+        Name name2 = new LdapDN( "cn=HomeDir,ou=Marketing,ou=East" );
+        name.add( 0, "ou=East" );
+        name.add( 2, "cn=John" );
+        name.add( "cn=HomeDir" );
+        name.remove( 2 );
+        assertEquals( name2, name );
 
-       for ( int i = 0; rdns.hasMoreElements(); i++ )
-       {
-           Rdn element = ( Rdn ) rdns.nextElement();
+        name.remove( 1 );
+        Name name1 = new LdapDN( "cn=HomeDir,ou=East" );
+        assertEquals( name1, name );
 
-           if ( i == 0 )
-           {
-               assertEquals( "ou=West", element.toString() );
-           }
+        name.remove( 1 );
+        Name name0 = new LdapDN( "ou=East" );
+        assertEquals( name0, name );
 
-           if ( i == 1 )
-           {
-               assertEquals( "ou=Marketing", element.toString() );
-           }
+        name.remove( 0 );
+        assertEquals( new LdapDN( "" ), name );
+    }
 
-           if ( i == 2 )
-           {
-               assertEquals( "cn=John", element.toString() );
-           }
 
-           if ( i == 3 )
-           {
-               assertEquals( "cn=HomeDir", element.toString() );
-           }
+    /**
+     * Class to test for String toString()
+     *
+     * @throws Exception
+     *             if anything goes wrong
+     */
+    @Test
+    public void testToString() throws Exception
+    {
+        Name name = new LdapDN();
+        assertEquals( "", name.toString() );
 
-           if ( i == 4 )
-           {
-               assertEquals( "cn=Website", element.toString() );
-           }
+        name.add( "ou=East" );
+        assertEquals( "ou=East", name.toString() );
 
-           if ( i == 5 )
-           {
-               assertEquals( "cn=Airline", element.toString() );
-           }
-       }
-   }
+        name.add( 1, "ou=Marketing" );
+        assertEquals( "ou=Marketing,ou=East", name.toString() );
 
+        name.add( "cn=John" );
+        assertEquals( "cn=John,ou=Marketing,ou=East", name.toString() );
 
-   /**
-    * Class to test for get
-    *
-    * @throws Exception
-    *             anything goes wrong
-    */
-   public void testGet() throws Exception
-   {
-       Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       assertEquals( "cn=HomeDir", name.get( 3 ) );
-       assertEquals( "cn=John", name.get( 2 ) );
-       assertEquals( "ou=Marketing", name.get( 1 ) );
-       assertEquals( "ou=East", name.get( 0 ) );
-   }
+        name.add( "cn=HomeDir" );
+        assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.toString() );
+    }
 
 
-   /**
-    * Class to test for getSuffix
-    *
-    * @throws Exception
-    *             anything goes wrong
-    */
-   public void testGetXSuffix() throws Exception
-   {
-       Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       assertEquals( "", name.getSuffix( 4 ).toString() );
-       assertEquals( "cn=HomeDir", name.getSuffix( 3 ).toString() );
-       assertEquals( "cn=HomeDir,cn=John", name.getSuffix( 2 ).toString() );
-       assertEquals( "cn=HomeDir,cn=John,ou=Marketing", name.getSuffix( 1 ).toString() );
-       assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.getSuffix( 0 ).toString() );
-   }
+    /**
+     * Class to test for boolean equals(Object)
+     *
+     * @throws Exception
+     *             if anything goes wrong
+     */
+    @Test
+    public void testEqualsObject() throws Exception
+    {
+        assertTrue( new LdapDN( "ou=People" ).equals( new LdapDN( "ou=People" ) ) );
 
+        assertTrue( !new LdapDN( "ou=People,dc=example,dc=com" ).equals( new LdapDN( "ou=People" ) ) );
+        assertTrue( !new LdapDN( "ou=people" ).equals( new LdapDN( "ou=People" ) ) );
+        assertTrue( !new LdapDN( "ou=Groups" ).equals( new LdapDN( "ou=People" ) ) );
+    }
 
-   /**
-    * Class to test for getPrefix
-    *
-    * @throws Exception
-    *             anything goes wrong
-    */
-   public void testGetPrefix() throws Exception
-   {
-       Name name = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-       assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.getPrefix( 4 ).toString() );
-       assertEquals( "cn=John,ou=Marketing,ou=East", name.getPrefix( 3 ).toString() );
-       assertEquals( "ou=Marketing,ou=East", name.getPrefix( 2 ).toString() );
-       assertEquals( "ou=East", name.getPrefix( 1 ).toString() );
-       assertEquals( "", name.getPrefix( 0 ).toString() );
-   }
+    @Test
+    public void testNameFrenchChars() throws Exception
+    {
+        String cn = new String( new byte[]
+            { 'c', 'n', '=', 0x4A, ( byte ) 0xC3, ( byte ) 0xA9, 0x72, ( byte ) 0xC3, ( byte ) 0xB4, 0x6D, 0x65 },
+            "UTF-8" );
 
+        Name name = new LdapDN( cn );
 
-   /**
-    * Class to test for startsWith
-    *
-    * @throws Exception
-    *             anything goes wrong
-    */
-   public void testStartsWith() throws Exception
-   {
-       Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name4 = new LdapDN( "ou=East" );
-       Name name5 = new LdapDN( "" );
+        assertEquals( "cn=J\\C3\\A9r\\C3\\B4me", name.toString() );
+    }
 
-       Name name6 = new LdapDN( "cn=HomeDir" );
-       Name name7 = new LdapDN( "cn=HomeDir,cn=John" );
-       Name name8 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing" );
 
-       assertTrue( name0.startsWith( name1 ) );
-       assertTrue( name0.startsWith( name2 ) );
-       assertTrue( name0.startsWith( name3 ) );
-       assertTrue( name0.startsWith( name4 ) );
-       assertTrue( name0.startsWith( name5 ) );
+    @Test
+    public void testNameGermanChars() throws Exception
+    {
+        String cn = new String( new byte[]
+            { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, ( byte ) 0xC3, ( byte ) 0x96, ( byte ) 0xC3, ( byte ) 0x9C,
+                ( byte ) 0xC3, ( byte ) 0x9F, ( byte ) 0xC3, ( byte ) 0xA4, ( byte ) 0xC3, ( byte ) 0xB6,
+                ( byte ) 0xC3, ( byte ) 0xBC }, "UTF-8" );
 
-       assertTrue( !name0.startsWith( name6 ) );
-       assertTrue( !name0.startsWith( name7 ) );
-       assertTrue( !name0.startsWith( name8 ) );
-   }
+        Name name = new LdapDN( cn );
 
+        assertEquals( "cn=\\C3\\84\\C3\\96\\C3\\9C\\C3\\9F\\C3\\A4\\C3\\B6\\C3\\BC", name.toString() );
+    }
 
-   /**
-    * Class to test for endsWith
-    *
-    * @throws Exception
-    *             anything goes wrong
-    */
-   public void testEndsWith() throws Exception
-   {
-       Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       Name name3 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name4 = new LdapDN( "ou=East" );
-       Name name5 = new LdapDN( "" );
 
-       Name name6 = new LdapDN( "cn=HomeDir" );
-       Name name7 = new LdapDN( "cn=HomeDir,cn=John" );
-       Name name8 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing" );
+    @Test
+    public void testNameTurkishChars() throws Exception
+    {
+        String cn = new String( new byte[]
+            { 'c', 'n', '=', ( byte ) 0xC4, ( byte ) 0xB0, ( byte ) 0xC4, ( byte ) 0xB1, ( byte ) 0xC5, ( byte ) 0x9E,
+                ( byte ) 0xC5, ( byte ) 0x9F, ( byte ) 0xC3, ( byte ) 0x96, ( byte ) 0xC3, ( byte ) 0xB6,
+                ( byte ) 0xC3, ( byte ) 0x9C, ( byte ) 0xC3, ( byte ) 0xBC, ( byte ) 0xC4, ( byte ) 0x9E,
+                ( byte ) 0xC4, ( byte ) 0x9F }, "UTF-8" );
 
-       assertTrue( name0.endsWith( name1 ) );
-       assertTrue( !name0.endsWith( name2 ) );
-       assertTrue( !name0.endsWith( name3 ) );
-       assertTrue( !name0.endsWith( name4 ) );
-       assertTrue( name0.endsWith( name5 ) );
+        Name name = new LdapDN( cn );
 
-       assertTrue( name0.endsWith( name6 ) );
-       assertTrue( name0.endsWith( name7 ) );
-       assertTrue( name0.endsWith( name8 ) );
-   }
+        assertEquals( "cn=\\C4\\B0\\C4\\B1\\C5\\9E\\C5\\9F\\C3\\96\\C3\\B6\\C3\\9C\\C3\\BC\\C4\\9E\\C4\\9F", name
+            .toString() );
+    }
 
 
-   /**
-    * Class to test for Name addAll(Name)
-    *
-    * @throws Exception
-    *             when anything goes wrong
-    */
-   public void testAddAllName0() throws Exception
-   {
-       Name name = new LdapDN();
-       Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       assertTrue( name0.equals( name.addAll( name0 ) ) );
-   }
+    /**
+     * Class to test for toOid( Name, Map)
+     */
+    @Test
+    public void testLdapNameToName() throws Exception
+    {
+        List<String> list = new ArrayList<String>();
+        list.add( "ou= Some   People   " );
+        list.add( "dc = eXample" );
+        list.add( "dc= cOm" );
+        LdapDN name = new LdapDN( list.iterator() );
 
+        assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
 
-   /**
-    * Class to test for Name addAll(Name)
-    *
-    * @throws Exception
-    *             when anything goes wrong
-    */
-   public void testAddAllNameExisting0() throws Exception
-   {
-       Name name1 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John" );
-       Name nameAdded = new LdapDN( "cn=HomeDir,cn=John, ou=Marketing,ou=East" );
-       assertTrue( nameAdded.equals( name1.addAll( name2 ) ) );
-   }
+        Name result = LdapDN.normalize( name, oids );
 
+        assertTrue( result.toString().equals( "ou=some people,dc=example,dc=com" ) );
+    }
 
-   /**
-    * Class to test for Name addAll(Name)
-    *
-    * @throws Exception
-    *             when anything goes wrong
-    */
-   public void testAddAllName1() throws Exception
-   {
-       Name name = new LdapDN();
-       Name name0 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=HomeDir,cn=John" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
 
-       assertTrue( name0.equals( name.addAll( name0 ) ) );
-       assertTrue( name2.equals( name.addAll( name1 ) ) );
-   }
+    @Test
+    public void testRdnGetTypeUpName() throws Exception
+    {
+        List<String> list = new ArrayList<String>();
+        list.add( "ou= Some   People   " );
+        list.add( "dc = eXample" );
+        list.add( "dc= cOm" );
+        LdapDN name = new LdapDN( list.iterator() );
 
+        assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
 
-   /**
-    * Class to test for Name addAll(int, Name)
-    *
-    * @throws Exception
-    *             when something goes wrong
-    */
-   public void testAddAllintName0() throws Exception
-   {
-       Name name = new LdapDN();
-       Name name0 = new LdapDN( "ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=HomeDir,cn=John" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        Rdn rdn = name.getRdn();
 
-       assertTrue( name0.equals( name.addAll( name0 ) ) );
-       assertTrue( name2.equals( name.addAll( 2, name1 ) ) );
-   }
+        assertEquals( "ou= Some   People   ", rdn.getUpName() );
+        assertEquals( "ou", rdn.getNormType() );
+        assertEquals( "ou", rdn.getUpType() );
 
+        LdapDN result = LdapDN.normalize( name, oidOids );
 
-   /**
-    * Class to test for Name addAll(int, Name)
-    *
-    * @throws Exception
-    *             when something goes wrong
-    */
-   public void testAddAllintName1() throws Exception
-   {
-       Name name = new LdapDN();
-       Name name0 = new LdapDN( "cn=HomeDir,ou=Marketing,ou=East" );
-       Name name1 = new LdapDN( "cn=John" );
-       Name name2 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        assertTrue( result.getNormName().equals(
+            "2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" ) );
+        assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
 
-       assertTrue( name0.equals( name.addAll( name0 ) ) );
-       assertTrue( name2.equals( name.addAll( 2, name1 ) ) );
+        Rdn rdn2 = result.getRdn();
 
-       Name name3 = new LdapDN( "cn=Airport" );
-       Name name4 = new LdapDN( "cn=Airport,cn=HomeDir,cn=John,ou=Marketing,ou=East" );
+        assertEquals( "ou= Some   People   ", rdn2.getUpName() );
+        assertEquals( "2.5.4.11", rdn2.getNormType() );
+        assertEquals( "ou", rdn2.getUpType() );
+    }
 
-       assertTrue( name4.equals( name.addAll( 4, name3 ) ) );
 
-       Name name5 = new LdapDN( "cn=ABC123" );
-       Name name6 = new LdapDN( "cn=Airport,cn=HomeDir,cn=ABC123,cn=John,ou=Marketing,ou=East" );
+    /**
+     * Class to test for toOid( Name, Map) with a NULL dn
+     */
+    @Test
+    public void testLdapNameToNameEmpty() throws Exception
+    {
+        LdapDN name = new LdapDN();
 
-       assertTrue( name6.equals( name.addAll( 3, name5 ) ) );
-   }
+        Name result = LdapDN.normalize( name, oids );
+        assertTrue( result.toString().equals( "" ) );
+    }
 
 
-   /**
-    * Class to test for Name add(String)
-    *
-    * @throws Exception
-    *             when something goes wrong
-    */
-   public void testAddString() throws Exception
-   {
-       Name name = new LdapDN();
-       assertEquals( name, new LdapDN( "" ) );
+    /**
+     * Class to test for toOid( Name, Map) with a multiple NameComponent
+     */
+    @Test
+    public void testLdapNameToNameMultiNC() throws Exception
+    {
+        LdapDN name = new LdapDN(
+            "2.5.4.11= Some   People   + 0.9.2342.19200300.100.1.25=  And   Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm" );
 
-       Name name4 = new LdapDN( "ou=East" );
-       name.add( "ou=East" );
-       assertEquals( name4, name );
+        Name result = LdapDN.normalize( name, oidOids );
 
-       Name name3 = new LdapDN( "ou=Marketing,ou=East" );
-       name.add( "ou=Marketing" );
-       assertEquals( name3, name );
+        assertEquals(
+            result.toString(),
+            "0.9.2342.19200300.100.1.25=and some animals+2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" );
+        assertTrue( ( ( LdapDN ) result )
+            .getUpName()
+            .equals(
+                "2.5.4.11= Some   People   + 0.9.2342.19200300.100.1.25=  And   Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm" ) );
+    }
 
-       Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       name.add( "cn=John" );
-       assertEquals( name2, name );
 
-       Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       name.add( "cn=HomeDir" );
-       assertEquals( name0, name );
-   }
+    /**
+     * Class to test for toOid( Name, Map) with a multiple NameComponent
+     */
+    @Test
+    public void testLdapNameToNameAliasMultiNC() throws Exception
+    {
+        LdapDN name = new LdapDN(
+            "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm" );
 
+        LdapDN result = LdapDN.normalize( name, oidOids );
 
-   /**
-    * Class to test for Name add(int, String)
-    *
-    * @throws Exception
-    *             if anything goes wrong
-    */
-   public void testAddintString() throws Exception
-   {
-       Name name = new LdapDN();
-       assertEquals( name, new LdapDN( "" ) );
+        assertTrue( result
+            .toString()
+            .equals(
+                "0.9.2342.19200300.100.1.25=and some animals+2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" ) );
+        assertTrue( result
+            .getUpName()
+            .equals(
+                "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm" ) );
+    }
 
-       Name name4 = new LdapDN( "ou=East" );
-       name.add( "ou=East" );
-       assertEquals( name4, name );
 
-       Name name3 = new LdapDN( "ou=Marketing,ou=East" );
-       name.add( 1, "ou=Marketing" );
-       assertEquals( name3, name );
+    /**
+     * Class to test for hashCode().
+     */
+    @Test
+    public void testLdapNameHashCode() throws Exception
+    {
+        Name name1 = LdapDN
+            .normalize(
+                "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm",
+                oids );
 
-       Name name2 = new LdapDN( "cn=John,ou=Marketing,ou=East" );
-       name.add( 2, "cn=John" );
-       assertEquals( name2, name );
+        Name name2 = LdapDN
+            .normalize(
+                "2.5.4.11=some people+domainComponent=and some animals,DomainComponent=example,0.9.2342.19200300.100.1.25=com",
+                oids );
 
-       Name name0 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East" );
-       name.add( 3, "cn=HomeDir" );
-       assertEquals( name0, name );
+        assertEquals( name1.hashCode(), name2.hashCode() );
+    }
 
-       Name name5 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East,o=LL " + "Bean Inc." );
-       name.add( 0, "o=LL Bean Inc." );
-       assertEquals( name5, name );
 
-       Name name6 = new LdapDN( "cn=HomeDir,cn=John,ou=Marketing,ou=East,c=US,o=LL " + "Bean Inc." );
-       name.add( 1, "c=US" );
-       assertEquals( name6, name );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testName() throws NamingException
+    {
+        Name jName = new javax.naming.ldap.LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
+        assertEquals( jName.toString(), "cn=four,cn=three,cn=two,cn=one" );
+        assertEquals( aName.toString(), "cn=four,cn=three,cn=two,cn=one" );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
-       Name name7 = new LdapDN( "cn=HomeDir,cn=John,ou=Advertising,ou=Marketing," + "ou=East,c=US,o=LL " + "Bean Inc." );
-       name.add( 4, "ou=Advertising" );
-       assertEquals( name7, name );
-   }
 
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testGetPrefixName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-   /**
-    * Class to test for remove
-    *
-    * @throws Exception
-    *             if anything goes wrong
-    */
-   public void testRemove() throws Exception
-   {
-       Name name = new LdapDN();
-       assertEquals( new LdapDN( "" ), name );
+        assertEquals( jName.getPrefix( 0 ).toString(), aName.getPrefix( 0 ).toString() );
+        assertEquals( jName.getPrefix( 1 ).toString(), aName.getPrefix( 1 ).toString() );
+        assertEquals( jName.getPrefix( 2 ).toString(), aName.getPrefix( 2 ).toString() );
+        assertEquals( jName.getPrefix( 3 ).toString(), aName.getPrefix( 3 ).toString() );
+        assertEquals( jName.getPrefix( 4 ).toString(), aName.getPrefix( 4 ).toString() );
+    }
 
-       Name name3 = new LdapDN( "ou=Marketing" );
-       name.add( "ou=East" );
-       name.add( 1, "ou=Marketing" );
-       name.remove( 0 );
-       assertEquals( name3, name );
 
-       Name name2 = new LdapDN( "cn=HomeDir,ou=Marketing,ou=East" );
-       name.add( 0, "ou=East" );
-       name.add( 2, "cn=John" );
-       name.add( "cn=HomeDir" );
-       name.remove( 2 );
-       assertEquals( name2, name );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testGetSuffix() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       name.remove( 1 );
-       Name name1 = new LdapDN( "cn=HomeDir,ou=East" );
-       assertEquals( name1, name );
+        assertEquals( jName.getSuffix( 0 ).toString(), aName.getSuffix( 0 ).toString() );
+        assertEquals( jName.getSuffix( 1 ).toString(), aName.getSuffix( 1 ).toString() );
+        assertEquals( jName.getSuffix( 2 ).toString(), aName.getSuffix( 2 ).toString() );
+        assertEquals( jName.getSuffix( 3 ).toString(), aName.getSuffix( 3 ).toString() );
+        assertEquals( jName.getSuffix( 4 ).toString(), aName.getSuffix( 4 ).toString() );
+    }
 
-       name.remove( 1 );
-       Name name0 = new LdapDN( "ou=East" );
-       assertEquals( name0, name );
 
-       name.remove( 0 );
-       assertEquals( new LdapDN( "" ), name );
-   }
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testAddStringName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
+        assertSame( jName, jName.add( "cn=five" ) );
+        assertSame( aName, aName.add( "cn=five" ) );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
-   /**
-    * Class to test for String toString()
-    *
-    * @throws Exception
-    *             if anything goes wrong
-    */
-   public void testToString() throws Exception
-   {
-       Name name = new LdapDN();
-       assertEquals( "", name.toString() );
 
-       name.add( "ou=East" );
-       assertEquals( "ou=East", name.toString() );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testAddIntString() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       name.add( 1, "ou=Marketing" );
-       assertEquals( "ou=Marketing,ou=East", name.toString() );
+        assertSame( jName, jName.add( 0, "cn=zero" ) );
+        assertSame( aName, aName.add( 0, "cn=zero" ) );
+        assertEquals( jName.toString(), aName.toString() );
 
-       name.add( "cn=John" );
-       assertEquals( "cn=John,ou=Marketing,ou=East", name.toString() );
+        assertSame( jName, jName.add( 2, "cn=one.5" ) );
+        assertSame( aName, aName.add( 2, "cn=one.5" ) );
+        assertEquals( jName.toString(), aName.toString() );
 
-       name.add( "cn=HomeDir" );
-       assertEquals( "cn=HomeDir,cn=John,ou=Marketing,ou=East", name.toString() );
-   }
+        assertSame( jName, jName.add( jName.size(), "cn=five" ) );
+        assertSame( aName, aName.add( aName.size(), "cn=five" ) );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
 
-   /**
-    * Class to test for boolean equals(Object)
-    *
-    * @throws Exception
-    *             if anything goes wrong
-    */
-   public void testEqualsObject() throws Exception
-   {
-       assertTrue( new LdapDN( "ou=People" ).equals( new LdapDN( "ou=People" ) ) );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testAddAllName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       assertTrue( !new LdapDN( "ou=People,dc=example,dc=com" ).equals( new LdapDN( "ou=People" ) ) );
-       assertTrue( !new LdapDN( "ou=people" ).equals( new LdapDN( "ou=People" ) ) );
-       assertTrue( !new LdapDN( "ou=Groups" ).equals( new LdapDN( "ou=People" ) ) );
-   }
+        assertSame( jName, jName.addAll( new LdapName( "cn=seven,cn=six" ) ) );
+        assertSame( aName, aName.addAll( new LdapDN( "cn=seven,cn=six" ) ) );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
 
-   public void testNameFrenchChars() throws Exception
-   {
-       String cn = new String( new byte[]
-           { 'c', 'n', '=', 0x4A, ( byte ) 0xC3, ( byte ) 0xA9, 0x72, ( byte ) 0xC3, ( byte ) 0xB4, 0x6D, 0x65 }, "UTF-8" );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testAddAllIntName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       Name name = new LdapDN( cn );
+        assertSame( jName, jName.addAll( 0, new LdapName( "cn=zero,cn=zero.5" ) ) );
+        assertSame( aName, aName.addAll( 0, new LdapDN( "cn=zero,cn=zero.5" ) ) );
+        assertEquals( jName.toString(), aName.toString() );
 
-       assertEquals( "cn=J\\C3\\A9r\\C3\\B4me", name.toString() );
-   }
+        assertSame( jName, jName.addAll( 2, new LdapName( "cn=zero,cn=zero.5" ) ) );
+        assertSame( aName, aName.addAll( 2, new LdapDN( "cn=zero,cn=zero.5" ) ) );
+        assertEquals( jName.toString(), aName.toString() );
 
+        assertSame( jName, jName.addAll( jName.size(), new LdapName( "cn=zero,cn=zero.5" ) ) );
+        assertSame( aName, aName.addAll( aName.size(), new LdapDN( "cn=zero,cn=zero.5" ) ) );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
-   public void testNameGermanChars() throws Exception
-   {
-       String cn = new String( new byte[]
-           { 'c', 'n', '=', ( byte ) 0xC3, ( byte ) 0x84, ( byte ) 0xC3, ( byte ) 0x96, ( byte ) 0xC3, ( byte ) 0x9C,
-               ( byte ) 0xC3, ( byte ) 0x9F, ( byte ) 0xC3, ( byte ) 0xA4, ( byte ) 0xC3, ( byte ) 0xB6,
-               ( byte ) 0xC3, ( byte ) 0xBC }, "UTF-8" );
 
-       Name name = new LdapDN( cn );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testStartsWithName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       assertEquals( "cn=\\C3\\84\\C3\\96\\C3\\9C\\C3\\9F\\C3\\A4\\C3\\B6\\C3\\BC", name.toString() );
-   }
+        assertEquals( jName.startsWith( new LdapName( "cn=seven,cn=six,cn=five" ) ), aName.startsWith( new LdapDN(
+            "cn=seven,cn=six,cn=five" ) ) );
+        assertEquals( jName.startsWith( new LdapName( "cn=three,cn=two,cn=one" ) ), aName.startsWith( new LdapDN(
+            "cn=three,cn=two,cn=one" ) ) );
+    }
 
 
-   public void testNameTurkishChars() throws Exception
-   {
-       String cn = new String( new byte[]
-           { 'c', 'n', '=', ( byte ) 0xC4, ( byte ) 0xB0, ( byte ) 0xC4, ( byte ) 0xB1, ( byte ) 0xC5, ( byte ) 0x9E,
-               ( byte ) 0xC5, ( byte ) 0x9F, ( byte ) 0xC3, ( byte ) 0x96, ( byte ) 0xC3, ( byte ) 0xB6,
-               ( byte ) 0xC3, ( byte ) 0x9C, ( byte ) 0xC3, ( byte ) 0xBC, ( byte ) 0xC4, ( byte ) 0x9E,
-               ( byte ) 0xC4, ( byte ) 0x9F }, "UTF-8" );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testEndsWithName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       Name name = new LdapDN( cn );
+        assertEquals( jName.endsWith( new LdapName( "cn=seven,cn=six,cn=five" ) ), aName.endsWith( new LdapDN(
+            "cn=seven,cn=six,cn=five" ) ) );
+        assertEquals( jName.endsWith( new LdapName( "cn=three,cn=two,cn=one" ) ), aName.endsWith( new LdapDN(
+            "cn=three,cn=two,cn=one" ) ) );
+    }
 
-       assertEquals( "cn=\\C4\\B0\\C4\\B1\\C5\\9E\\C5\\9F\\C3\\96\\C3\\B6\\C3\\9C\\C3\\BC\\C4\\9E\\C4\\9F", name.toString() );
-   }
 
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testRemoveName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-   /**
-    * Class to test for toOid( Name, Map)
-    */
-   public void testLdapNameToName() throws Exception
-   {
-       List<String> list = new ArrayList<String>();
-       list.add( "ou= Some   People   " );
-       list.add( "dc = eXample" );
-       list.add( "dc= cOm" );
-       LdapDN name = new LdapDN( list.iterator() );
+        assertEquals( jName.remove( 0 ).toString(), aName.remove( 0 ).toString() );
+        assertEquals( jName.toString(), aName.toString() );
 
-       Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
+        assertEquals( jName.remove( jName.size() - 1 ).toString(), aName.remove( aName.size() - 1 ).toString() );
+        assertEquals( jName.toString(), aName.toString() );
+    }
 
-       oids.put( "dc", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "domaincomponent", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "ou", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "organizationalUnitName", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "2.5.4.11", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
 
-       assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
+    /**
+     * Test for DIRSERVER-191
+     */
+    @Test
+    public void testGetAllName() throws NamingException
+    {
+        Name jName = new LdapName( "cn=four,cn=three,cn=two,cn=one" );
+        Name aName = new LdapDN( "cn=four,cn=three,cn=two,cn=one" );
 
-       Name result = LdapDN.normalize( name, oids );
+        Enumeration<String> j = jName.getAll();
+        Enumeration<String> a = aName.getAll();
+        while ( j.hasMoreElements() )
+        {
+            assertTrue( j.hasMoreElements() );
+            assertEquals( j.nextElement(), a.nextElement() );
+        }
+    }
 
-       assertTrue( result.toString().equals( "ou=some people,dc=example,dc=com" ) );
-   }
 
-   public void testRdnGetTypeUpName() throws Exception
-   {
-       List<String> list = new ArrayList<String>();
-       list.add( "ou= Some   People   " );
-       list.add( "dc = eXample" );
-       list.add( "dc= cOm" );
-       LdapDN name = new LdapDN( list.iterator() );
+    /**
+     * Test for DIRSERVER-642
+     * @throws NamingException
+     */
+    @Test
+    public void testDoubleQuoteInNameDIRSERVER_642() throws NamingException
+    {
+        Name name1 = new LdapDN( "cn=\"Kylie Minogue\",dc=example,dc=com" );
+        Name name2 = new LdapName( "cn=\"Kylie Minogue\",dc=example,dc=com" );
 
-       Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
+        Enumeration<String> j = name1.getAll();
+        Enumeration<String> a = name2.getAll();
 
-       oids.put( "dc", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "domaincomponent", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "ou", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "organizationalUnitName", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "2.5.4.11", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
+        while ( j.hasMoreElements() )
+        {
+            assertTrue( j.hasMoreElements() );
+            assertEquals( j.nextElement(), a.nextElement() );
+        }
+    }
 
-       assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
 
-       Rdn rdn = name.getRdn();
-       
-       assertEquals( "ou= Some   People   ", rdn.getUpName() );
-       //assertEquals( "2.5.4.11=some people", rdn.getNormName() );
-       assertEquals( "ou", rdn.getNormType() );
-       assertEquals( "ou", rdn.getUpType() );
-       //assertEquals( "some people", rdn.getNormValue() );
-       //assertEquals( "ou= Some   People   ", rdn.getUpValue() );
+    /**
+     * Test for DIRSERVER-642
+     * @throws NamingException
+     */
+    @Test
+    public void testDoubleQuoteInNameDIRSERVER_642_1() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "cn=\" Kylie Minogue \",dc=example,dc=com" );
 
-       LdapDN result = LdapDN.normalize( name, oids );
+        assertEquals( "cn=\" Kylie Minogue \",dc=example,dc=com", dn.getUpName() );
+        assertEquals( "cn=\\ Kylie Minogue\\ ,dc=example,dc=com", dn.toString() );
+    }
 
-       assertTrue( result.getNormName().equals( "2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" ) );
-       assertTrue( name.getUpName().equals( "ou= Some   People   ,dc = eXample,dc= cOm" ) );
-       
-       Rdn rdn2 = result.getRdn();
-       
-       assertEquals( "ou= Some   People   ", rdn2.getUpName() );
-       //assertEquals( "2.5.4.11=some people", rdn2.getNormName() );
-       assertEquals( "2.5.4.11", rdn2.getNormType() );
-       assertEquals( "ou", rdn2.getUpType() );
-       //assertEquals( "some people", rdn2.getNormValue() );
-       //assertEquals( "ou= Some   People   ", rdn2.getUpValue() );
-   }
 
-   /**
-    * Class to test for toOid( Name, Map) with a NULL dn
-    */
-   public void testLdapNameToNameEmpty() throws Exception
-   {
-       LdapDN name = new LdapDN();
+    /**
+     * Test for DIRSTUDIO-250
+     * @throws NamingException
+     */
+    @Test
+    public void testDoubleQuoteWithSpecialCharsInNameDIRSERVER_250() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "a=\"b,c\"" );
 
-       Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
+        assertEquals( "a=\"b,c\"", dn.getUpName() );
+        assertEquals( "a=b\\,c", dn.toString() );
+    }
 
-       oids.put( "dc", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "domaincomponent", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "dc", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "ou", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "organizationalUnitName", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "2.5.4.11", new OidNormalizer( "ou", new DeepTrimToLowerNormalizer() ) );
 
-       Name result = LdapDN.normalize( name, oids );
-       assertTrue( result.toString().equals( "" ) );
-   }
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testLeadingAndTrailingSpacesDIRSERVER_184() throws NamingException
+    {
+        LdapDN name = new LdapDN( "dn= \\ four spaces leading and 3 trailing \\  " );
 
+        assertEquals( "dn=\\ four spaces leading and 3 trailing \\ ", name.toString() );
+        assertEquals( "dn= \\ four spaces leading and 3 trailing \\  ", name.getUpName() );
+    }
 
-   /**
-    * Class to test for toOid( Name, Map) with a multiple NameComponent
-    */
-   public void testLdapNameToNameMultiNC() throws Exception
-   {
-       LdapDN name = new LdapDN(
-           "2.5.4.11= Some   People   + 0.9.2342.19200300.100.1.25=  And   Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm" );
 
-       Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_1()
+    {
+        try
+        {
+            new LdapDN( "dn=middle\\ spaces" );
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-       oids.put( "dc", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "domaincomponent", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "ou", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "organizationalUnitName", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "2.5.4.11", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
 
-       Name result = LdapDN.normalize( name, oids );
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_2()
+    {
+        try
+        {
+            new LdapDN( "dn=# a leading pound" );
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-       assertEquals( result.toString(), "0.9.2342.19200300.100.1.25=and some animals+2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" );
-       assertTrue( ( ( LdapDN ) result )
-           .getUpName()
-           .equals(
-               "2.5.4.11= Some   People   + 0.9.2342.19200300.100.1.25=  And   Some anImAls,0.9.2342.19200300.100.1.25 = eXample,dc= cOm" ) );
-   }
 
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_3() throws NamingException
+    {
+        LdapDN name = new LdapDN( "dn=\\# a leading pound" );
 
-   /**
-    * Class to test for toOid( Name, Map) with a multiple NameComponent
-    */
-   public void testLdapNameToNameAliasMultiNC() throws Exception
-   {
-       LdapDN name = new LdapDN(
-           "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm" );
+        assertEquals( "dn=\\# a leading pound", name.toString() );
+        assertEquals( "dn=\\# a leading pound", name.getUpName() );
+    }
 
-       Map<String, OidNormalizer> oids = new HashMap<String, OidNormalizer>();
 
-       oids.put( "dc", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "domaincomponent", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "0.9.2342.19200300.100.1.25", new OidNormalizer( "0.9.2342.19200300.100.1.25", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "ou", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "organizationalUnitName", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
-       oids.put( "2.5.4.11", new OidNormalizer( "2.5.4.11", new DeepTrimToLowerNormalizer() ) );
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_4() throws NamingException
+    {
+        LdapDN name = new LdapDN( "dn=a middle \\# pound" );
 
-       LdapDN result = LdapDN.normalize( name, oids );
+        assertEquals( "dn=a middle # pound", name.toString() );
+        assertEquals( "dn=a middle \\# pound", name.getUpName() );
+    }
 
-       assertTrue( result.toString().equals( "0.9.2342.19200300.100.1.25=and some animals+2.5.4.11=some people,0.9.2342.19200300.100.1.25=example,0.9.2342.19200300.100.1.25=com" ) );
-       assertTrue( result
-           .getUpName()
-           .equals(
-               "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm" ) );
-   }
 
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_5() throws NamingException
+    {
+        LdapDN name = new LdapDN( "dn=a trailing pound \\#" );
 
-   /**
-    * Test the serialization of a DN
-    *
-    * @throws Exception
-    */
-   public void testNameSerialization() throws Exception
-   {
-       LdapDN name = new LdapDN( "ou= Some   People   + dc=  And   Some anImAls,dc = eXample,dc= cOm" );
+        assertEquals( "dn=a trailing pound #", name.toString() );
+        assertEquals( "dn=a trailing pound \\#", name.getUpName() );
+    }
 
-       FileOutputStream fOut = null;
-       ObjectOutputStream oOut = null;
-       File file = new File( "LdapDN.ser" );
 
-       try
-       {
-           fOut = new FileOutputStream( file );
-           oOut = new ObjectOutputStream( fOut );
-           oOut.writeObject( name );
-       }
-       catch ( IOException ioe )
-       {
-           throw ioe;
-       }
-       finally
-       {
-           try
-           {
-               if ( oOut != null )
-               {
-                   oOut.flush();
-                   oOut.close();
-               }
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_6()
+    {
+        try
+        {
+            new LdapDN( "dn=a middle # pound" );
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-               if ( fOut != null )
-               {
-                   fOut.close();
-               }
-           }
-           catch ( IOException ioe )
-           {
-               throw ioe;
-           }
-       }
 
-       FileInputStream fIn = null;
-       ObjectInputStream oIn = null;
+    /**
+     * Test for DIRSERVER-184
+     * @throws NamingException
+     */
+    @Test
+    public void testDIRSERVER_184_7()
+    {
+        try
+        {
+            new LdapDN( "dn=a trailing pound #" );
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-       try
-       {
-           fIn = new FileInputStream( file );
-           oIn = new ObjectInputStream( fIn );
 
-           LdapDN nameSer = ( LdapDN ) oIn.readObject();
+    @Test
+    public void testDIRSERVER_631_1() throws NamingException
+    {
+        LdapDN name = new LdapDN( "cn=Bush\\, Kate,dc=example,dc=com" );
 
-           assertEquals( 0, nameSer.compareTo( name ) );
-       }
-       catch ( IOException ioe )
-       {
-           throw ioe;
-       }
-       finally
-       {
-           try
-           {
-               if ( oIn != null )
-               {
-                   oIn.close();
-               }
-               
-               if ( fIn != null )
-               {
-                   fIn.close();
-               }
-               
-               file.delete();
-           }
-           catch ( IOException ioe )
-           {
-               throw ioe;
-           }
-       }
-   }
+        assertEquals( "cn=Bush\\, Kate,dc=example,dc=com", name.toString() );
+        assertEquals( "cn=Bush\\, Kate,dc=example,dc=com", name.getUpName() );
 
-   /**
-    * Class to test for hashCode(). Commmented as the values are not normalized.
-    */
-   //public void testLdapNameHashCode() throws Exception
-   //{
-   //    Name name1 = new LdapDN(
-   //        "2.5.4.11= Some   People   + domainComponent=  And   Some anImAls,DomainComponent = eXample,0.9.2342.19200300.100.1.25= cOm" );
-   //
-   //    Name name2 = new LdapDN(
-   //        "2.5.4.11=some people+domainComponent=and some animals,DomainComponent=example,0.9.2342.19200300.100.1.25=com" );
-   //
-   //    assertEquals( name1.hashCode(), name2.hashCode() );
-   //}
+    }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testName() throws NamingException
-   {
-       Name jName = new javax.naming.ldap.LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
-       assertEquals(jName.toString(), "cn=four,cn=three,cn=two,cn=one");
-       assertEquals(aName.toString(), "cn=four,cn=three,cn=two,cn=one");
-       assertEquals(jName.toString(), aName.toString());
-   }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testGetPrefixName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+    /**
+     * Added a test to check the parsing of a DN with more than one RDN
+     * which are OIDs, and with one RDN which has more than one atav.
+     * @throws NamingException
+     */
+    @Test
+    public void testDNWithMultiOidsRDN() throws NamingException
+    {
+        LdapDN name = new LdapDN(
+            "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us" );
+        assertEquals(
+            "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us", name
+                .toString() );
+        assertEquals(
+            "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us", name
+                .getUpName() );
+    }
 
-       assertEquals(jName.getPrefix(0).toString(), aName.getPrefix(0).toString());
-       assertEquals(jName.getPrefix(1).toString(), aName.getPrefix(1).toString());
-       assertEquals(jName.getPrefix(2).toString(), aName.getPrefix(2).toString());
-       assertEquals(jName.getPrefix(3).toString(), aName.getPrefix(3).toString());
-       assertEquals(jName.getPrefix(4).toString(), aName.getPrefix(4).toString());
-   }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testGetSuffix() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+    @Test
+    public void testNameAddAll() throws NamingException
+    {
+        Properties props = new Properties();
+        props.setProperty( "jndi.syntax.direction", "right_to_left" );
+        props.setProperty( "jndi.syntax.separator", "," );
+        props.setProperty( "jndi.syntax.ignorecase", "true" );
+        props.setProperty( "jndi.syntax.trimblanks", "true" );
 
-       assertEquals(jName.getSuffix(0).toString(), aName.getSuffix(0).toString());
-       assertEquals(jName.getSuffix(1).toString(), aName.getSuffix(1).toString());
-       assertEquals(jName.getSuffix(2).toString(), aName.getSuffix(2).toString());
-       assertEquals(jName.getSuffix(3).toString(), aName.getSuffix(3).toString());
-       assertEquals(jName.getSuffix(4).toString(), aName.getSuffix(4).toString());
-   }
+        Name dn = new CompoundName( "cn=blah,dc=example,dc=com", props );
+        LdapDN ldapDn = new LdapDN();
+        ldapDn.addAll( 0, dn );
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testAddStringName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+        assertEquals( "cn=blah,dc=example,dc=com", ldapDn.toString() );
 
-       assertSame(jName, jName.add("cn=five"));
-       assertSame(aName, aName.add("cn=five"));
-       assertEquals(jName.toString(), aName.toString());
-   }
+        dn = new CompoundName( "cn=blah,dc=example,dc=com", props );
+        ldapDn = new LdapDN( "cn=xyz" );
+        ldapDn.addAll( 0, dn );
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testAddIntString() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+        assertEquals( "cn=xyz,cn=blah,dc=example,dc=com", ldapDn.toString() );
+    }
 
-       assertSame(jName, jName.add(0,"cn=zero"));
-       assertSame(aName, aName.add(0,"cn=zero"));
-       assertEquals(jName.toString(), aName.toString());
 
-       assertSame(jName, jName.add(2,"cn=one.5"));
-       assertSame(aName, aName.add(2,"cn=one.5"));
-       assertEquals(jName.toString(), aName.toString());
+    @Test
+    public void testDNEquals() throws NamingException
+    {
+        LdapDN dn1 = new LdapDN( "a=b,c=d,e=f" );
+        LdapDN dn2 = new LdapDN( "a=b\\,c\\=d,e=f" );
 
-       assertSame(jName, jName.add(jName.size(),"cn=five"));
-       assertSame(aName, aName.add(aName.size(),"cn=five"));
-       assertEquals(jName.toString(), aName.toString());
-   }
+        assertFalse( dn1.toString().equals( dn2.toString() ) );
+    }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testAddAllName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
 
-       assertSame(jName, jName.addAll(new LdapName("cn=seven,cn=six")));
-       assertSame(aName, aName.addAll(new LdapDN("cn=seven,cn=six")));
-       assertEquals(jName.toString(), aName.toString());
-   }
+    @Test
+    public void testDNAddEmptyString() throws NamingException
+    {
+        LdapDN dn = new LdapDN();
+        assertTrue( dn.size() == 0 );
+        assertTrue( dn.add( "" ).size() == 0 );
+    }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testAddAllIntName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
 
-       assertSame(jName, jName.addAll(0, new LdapName("cn=zero,cn=zero.5")));
-       assertSame(aName, aName.addAll(0, new LdapDN("cn=zero,cn=zero.5")));
-       assertEquals(jName.toString(), aName.toString());
+    /**
+     * This leads to the bug in DIRSERVER-832.
+     */
+    @Test
+    public void testPreserveAttributeIdCase() throws NamingException
+    {
+        LdapDN dn = new LdapDN( "uID=kevin" );
+        assertEquals( "uID", dn.getRdn().getUpType() );
+    }
 
 
-       assertSame(jName, jName.addAll(2, new LdapName("cn=zero,cn=zero.5")));
-       assertSame(aName, aName.addAll(2, new LdapDN("cn=zero,cn=zero.5")));
-       assertEquals(jName.toString(), aName.toString());
+    /**
+     * Tests the LdapDN.isValid() method.
+     */
+    @Test
+    public void testIsValid()
+    {
+        assertTrue( LdapDN.isValid( "" ) );
 
+        assertFalse( LdapDN.isValid( "a" ) );
+        assertFalse( LdapDN.isValid( "a " ) );
 
-       assertSame(jName, jName.addAll(jName.size(), new LdapName("cn=zero,cn=zero.5")));
-       assertSame(aName, aName.addAll(aName.size(), new LdapDN("cn=zero,cn=zero.5")));
-       assertEquals(jName.toString(), aName.toString());
-   }
+        assertTrue( LdapDN.isValid( "a=" ) );
+        assertTrue( LdapDN.isValid( "a= " ) );
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testStartsWithName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+        assertFalse( LdapDN.isValid( "=" ) );
+        assertFalse( LdapDN.isValid( " = " ) );
+        assertFalse( LdapDN.isValid( " = a" ) );
+    }
 
-       assertEquals(jName.startsWith(new LdapName("cn=seven,cn=six,cn=five")),
-               aName.startsWith(new LdapDN("cn=seven,cn=six,cn=five")));
-       assertEquals(jName.startsWith(new LdapName("cn=three,cn=two,cn=one")),
-               aName.startsWith(new LdapDN("cn=three,cn=two,cn=one")));
-   }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testEndsWithName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+    private ByteArrayOutputStream serializeDN( LdapDN dn ) throws IOException
+    {
+        ObjectOutputStream oOut = null;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
 
-       assertEquals(jName.endsWith(new LdapName("cn=seven,cn=six,cn=five")),
-               aName.endsWith(new LdapDN("cn=seven,cn=six,cn=five")));
-       assertEquals(jName.endsWith(new LdapName("cn=three,cn=two,cn=one")),
-               aName.endsWith(new LdapDN("cn=three,cn=two,cn=one")));
-   }
+        try
+        {
+            oOut = new ObjectOutputStream( out );
+            oOut.writeObject( dn );
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oOut != null )
+                {
+                    oOut.flush();
+                    oOut.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testRemoveName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+        return out;
+    }
 
-       assertEquals(jName.remove(0).toString(), aName.remove(0).toString());
-       assertEquals(jName.toString(), aName.toString());
 
-       assertEquals(jName.remove(jName.size() - 1).toString(), aName.remove(aName.size() - 1).toString());
-       assertEquals(jName.toString(), aName.toString());
-   }
+    private LdapDN deserializeDN( ByteArrayOutputStream out ) throws IOException, ClassNotFoundException
+    {
+        ObjectInputStream oIn = null;
+        ByteArrayInputStream in = new ByteArrayInputStream( out.toByteArray() );
 
-   /**
-    * Test for DIRSERVER-191
-    */
-   public void testGetAllName() throws NamingException
-   {
-       Name jName = new LdapName("cn=four,cn=three,cn=two,cn=one");
-       Name aName = new LdapDN("cn=four,cn=three,cn=two,cn=one");
+        try
+        {
+            oIn = new ObjectInputStream( in );
 
-       Enumeration j = jName.getAll();
-       Enumeration a = aName.getAll();
-       while (j.hasMoreElements())
-       {
-           assertTrue(j.hasMoreElements());
-           assertEquals(j.nextElement(), a.nextElement());
-       }
-   }
+            LdapDN dn = ( LdapDN ) oIn.readObject();
 
-   /**
-    * Test for DIRSERVER-642
-    * @throws NamingException
-    */
-   public void testDoubleQuoteInNameDIRSERVER_642() throws NamingException
-   {
-       Name name1 = new LdapDN( "cn=\"Kylie Minogue\",dc=example,dc=com" );
-       Name name2 = new LdapName( "cn=\"Kylie Minogue\",dc=example,dc=com" );
+            return dn;
+        }
+        catch ( IOException ioe )
+        {
+            throw ioe;
+        }
+        finally
+        {
+            try
+            {
+                if ( oIn != null )
+                {
+                    oIn.close();
+                }
+            }
+            catch ( IOException ioe )
+            {
+                throw ioe;
+            }
+        }
+    }
 
-       Enumeration j = name1.getAll();
-       Enumeration a = name2.getAll();
 
-       while (j.hasMoreElements())
-       {
-           assertTrue(j.hasMoreElements());
-           assertEquals(j.nextElement(), a.nextElement());
-       }
-   }
+    /**
+     * Test the serialization of a DN
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testNameSerialization() throws Exception
+    {
+        LdapDN dn = new LdapDN( "ou= Some   People   + dc=  And   Some anImAls,dc = eXample,dc= cOm" );
+        dn.normalize( oids );
 
-   /**
-    * Test for DIRSERVER-642
-    * @throws NamingException
-    */
-   public void testDoubleQuoteInNameDIRSERVER_642_1() throws NamingException
-   {
-       LdapDN dn = new LdapDN( "cn=\" Kylie Minogue \",dc=example,dc=com" );
+        assertEquals( dn, deserializeDN( serializeDN( dn ) ) );
+    }
 
-       assertEquals( "cn=\" Kylie Minogue \",dc=example,dc=com", dn.getUpName() );
-       assertEquals( "cn=\\ Kylie Minogue\\ ,dc=example,dc=com", dn.toString() );
-   }
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testLeadingAndTrailingSpacesDIRSERVER_184() throws NamingException
-   {
-       LdapDN name = new LdapDN( "dn= \\ four spaces leading and 3 trailing \\  " );
+    @Test
+    public void testSerializeEmptyDN() throws Exception
+    {
+        LdapDN dn = LdapDN.EMPTY_LDAPDN;
 
-       assertEquals( "dn=\\ four spaces leading and 3 trailing \\ ", name.toString() );
-       assertEquals( "dn= \\ four spaces leading and 3 trailing \\  ", name.getUpName() );
-   }
+        assertEquals( dn, deserializeDN( serializeDN( dn ) ) );
+    }
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_1()
-   {
-       try
-       {
-           new LdapDN( "dn=middle\\ spaces" );
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_2()
-   {
-       try
-       {
-           new LdapDN( "dn=# a leading pound" );
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
+    /**
+     * Test the serialization of a DN
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testNameStaticSerialization() throws Exception
+    {
+        LdapDN dn = new LdapDN( "ou= Some   People   + dc=  And   Some anImAls,dc = eXample,dc= cOm" );
+        dn.normalize( oids );
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_3() throws NamingException
-   {
-       LdapDN name = new LdapDN( "dn=\\# a leading pound" );
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
 
-       assertEquals( "dn=\\# a leading pound", name.toString() );
-       assertEquals( "dn=\\# a leading pound", name.getUpName() );
-   }
+        LdapDNSerializer.serialize( dn, out );
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_4() throws NamingException
-   {
-       LdapDN name = new LdapDN( "dn=a middle \\# pound" );
+        byte[] data = baos.toByteArray();
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
 
-       assertEquals( "dn=a middle # pound", name.toString() );
-       assertEquals( "dn=a middle \\# pound", name.getUpName() );
-   }
+        assertEquals( dn, LdapDNSerializer.deserialize( in ) );
+    }
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_5() throws NamingException
-   {
-       LdapDN name = new LdapDN( "dn=a trailing pound \\#" );
 
-       assertEquals( "dn=a trailing pound #", name.toString() );
-       assertEquals( "dn=a trailing pound \\#", name.getUpName() );
-   }
+    /*
+    @Test public void testSerializationPerfs() throws Exception
+    {
+        LdapDN dn = new LdapDN( "ou= Some   People   + dc=  And   Some anImAls,dc = eXample,dc= cOm" );
+        dn.normalize( oids );
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_6()
-   {
-       try
-       {
-           new LdapDN( "dn=a middle # pound" );
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
+        long t0 = System.currentTimeMillis();
+        
+        for ( int i = 0; i < 1000; i++ )
+        {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream( baos );
 
-   /**
-    * Test for DIRSERVER-184
-    * @throws NamingException
-    */
-   public void testDIRSERVER_184_7()
-   {
-       try
-       {
-           new LdapDN( "dn=a trailing pound #" );
-       }
-       catch ( InvalidNameException ine )
-       {
-           assertTrue( true );
-       }
-   }
+            DnSerializer.serialize( dn, out );
+            
+            byte[] data = baos.toByteArray();
+            ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+            
+            LdapDN dn1 = DnSerializer.deserialize( in );
+        }
+        
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "delta :" + ( t1 - t0) );
 
-   public void testDIRSERVER_631_1() throws NamingException
-   {
-       LdapDN name = new LdapDN( "cn=Bush\\, Kate,dc=example,dc=com" );
+        long t2 = System.currentTimeMillis();
+        
+        for ( int i = 0; i < 1000000; i++ )
+        {
+            //ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            //ObjectOutputStream out = new ObjectOutputStream( baos );
 
-       assertEquals( "cn=Bush\\, Kate,dc=example,dc=com", name.toString() );
-       assertEquals( "cn=Bush\\, Kate,dc=example,dc=com", name.getUpName() );
+            //DnSerializer.serializeString( dn, out );
+            
+            //byte[] data = baos.toByteArray();
+            //ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+            
+            //LdapDN dn1 = DnSerializer.deserializeString( in, oids );
+            dn.normalize( oids );
+        }
+        
+        long t3 = System.currentTimeMillis();
 
-   }
+        System.out.println( "delta :" + ( t3 - t2) );
 
-   
-   /**
-    * Added a test to check the parsing of a DN with more than one RDN
-    * which are OIDs, and with one RDN which has more than one atav.
-    * @throws NamingException
+        //assertEquals( dn, DnSerializer.deserialize( in ) );
+    }
     */
-   public void testDNWithMultiOidsRDN() throws NamingException
-   {
-       LdapDN name = new LdapDN( "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us" );
-       assertEquals( "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us", name.toString() );
-       assertEquals( "0.9.2342.19200300.100.1.1=00123456789+2.5.4.3=pablo picasso,2.5.4.11=search,2.5.4.10=imc,2.5.4.6=us", name.getUpName() );
-   }
-   
-   
-   public void testNameAddAll() throws NamingException
-   {
-       Properties props = new Properties();
-       props.setProperty( "jndi.syntax.direction", "right_to_left" );
-       props.setProperty( "jndi.syntax.separator", "," );
-       props.setProperty( "jndi.syntax.ignorecase", "true" );
-       props.setProperty( "jndi.syntax.trimblanks", "true" );
+
+    @Test
+    public void testStaticSerializeEmptyDN() throws Exception
+    {
+        LdapDN dn = LdapDN.EMPTY_LDAPDN;
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        LdapDNSerializer.serialize( dn, out );
 
-       Name dn = new CompoundName( "cn=blah,dc=example,dc=com", props );
-       LdapDN ldapDn = new LdapDN();
-       ldapDn.addAll( 0, dn );
-       
-       assertEquals( "cn=blah,dc=example,dc=com", ldapDn.toString() );
+        byte[] data = baos.toByteArray();
+        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream( data ) );
 
-       dn = new CompoundName( "cn=blah,dc=example,dc=com", props );
-       ldapDn = new LdapDN( "cn=xyz" );
-       ldapDn.addAll( 0, dn );
-       
-       System.out.println( ldapDn.toString() );
-       assertEquals( "cn=xyz,cn=blah,dc=example,dc=com", ldapDn.toString() );
-   }
-   
-   
-   public void testDNEquals() throws NamingException
-   {
-       LdapDN dn1 = new LdapDN( "a=b,c=d,e=f" );
-       LdapDN dn2 = new LdapDN( "a=b\\,c\\=d,e=f" );
-       
-       assertFalse( dn1.toString().equals( dn2.toString() ) );
-   }
-   
-   
-   public void testDNAddEmptyString() throws NamingException
-   {
-       LdapDN dn = new LdapDN();
-       assertTrue( dn.size() == 0 );
-       assertTrue( dn.add( "" ).size() == 0 );
-   }
-   
-   
-   /**
-    * This leads to the bug in DIRSERVER-832.
-    */
-   public void testPreserveAttributeIdCase() throws NamingException
-   {
-       LdapDN dn = new LdapDN( "uID=kevin" );
-       assertEquals( "uID", dn.getRdn().getUpType() );
-   }
+        assertEquals( dn, LdapDNSerializer.deserialize( in ) );
+        assertEquals( dn, deserializeDN( serializeDN( dn ) ) );
+    }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDnParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDnParserTest.java
index f47d4ab..29b174b 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDnParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/name/LdapDnParserTest.java
@@ -27,8 +27,6 @@
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
-import org.apache.directory.shared.ldap.name.LdapDN;
-import org.apache.directory.shared.ldap.name.LdapDnParser;
 import org.apache.directory.shared.ldap.util.StringTools;
 
 
@@ -36,6 +34,7 @@
  * Test the class LdapDN
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
 public class LdapDnParserTest extends TestCase
 {
@@ -244,6 +243,19 @@
     }
 
 
+    public void testStringParserShort() throws NamingException
+    {
+        String dn = StringTools.utf8ToString( new byte[]
+            { 'C', '=', ' ', 'E', ( byte ) 0xc3, ( byte ) 0xa9, 'c' } );
+
+        NameParser dnParser = LdapDnParser.getNameParser();
+        LdapDN name = ( LdapDN ) dnParser.parse( dn );
+
+        Assert.assertEquals( dn, name.getUpName() );
+        Assert.assertEquals( "c=E\\C3\\A9c", name.toString() );
+    }
+
+
     public void testVsldapExtras() throws NamingException
     {
         NameParser dnParser = LdapDnParser.getNameParser();
@@ -522,6 +534,29 @@
         assertEquals( "cn=\\C4\\B0\\C4\\B1\\C5\\9E\\C5\\9F\\C3\\96\\C3\\B6\\C3\\9C\\C3\\BC\\C4\\9E\\C4\\9F", result );
 
     }
+    
+   
+    public void testAUmlautPlusBytes() throws Exception
+    {
+        String cn = new String( new byte[] { 'c', 'n', '=', (byte)0xC3, (byte)0x84, 0x5C, 0x32, 0x42 }, "UTF-8" );
+
+
+        NameParser parser = LdapDnParser.getNameParser();
+        String result = parser.parse( cn ).toString();
+        
+        assertEquals( "cn=\\C3\\84\\+", result );
+    }
+
+
+    public void testAUmlautPlusChar() throws Exception
+    {
+        String cn = new String( new byte[] { 'c', 'n', '=', (byte)0xC3, (byte)0x84, '\\', '+' }, "UTF-8" );
+        
+        NameParser parser = LdapDnParser.getNameParser();
+        String result = parser.parse( cn ).toString();
+        
+        assertEquals( "cn=\\C3\\84\\+", result );
+    }
 
 
     /**
@@ -538,15 +573,13 @@
 
         try
         {
-            String res = parser.parse( input ).toString();
-            System.out.println( res );
+            parser.parse( input ).toString();
+            fail( "Should never rech this point" );
         }
         catch ( NamingException ne )
         {
             assertTrue( true );
             return;
         }
-
-        fail( "Should never rech this point" );
     }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java
index 393cfbc..e0d7936 100755
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java
@@ -20,496 +20,1376 @@
 package org.apache.directory.shared.ldap.name;
 
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Iterator;
+
 import javax.naming.InvalidNameException;
 import javax.naming.NamingException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import org.apache.directory.shared.ldap.name.Rdn;
-import org.apache.directory.shared.ldap.name.RdnParser;
 import org.apache.directory.shared.ldap.util.StringTools;
+import org.junit.Test;
 
 
 /**
  * Test the class Rdn
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$, 
  */
-public class RdnTest extends TestCase
+public class RdnTest
 {
-   // ~ Methods
-   // ------------------------------------------------------------------------------------
-   /**
-    * Test a null RDN
-    */
-   public void testRdnNull()
-   {
-       Assert.assertEquals( "", new Rdn().toString() );
-   }
+    // ~ Methods
+    // ------------------------------------------------------------------------------------
+    /**
+     * Test a null RDN
+     */
+    @Test
+    public void testRdnNull()
+    {
+        assertEquals( "", new Rdn().toString() );
+    }
 
 
-   /**
-    * test an empty RDN
-    */
-   public void testRdnEmpty() throws InvalidNameException
-   {
-       Assert.assertEquals( "", new Rdn( "" ).toString() );
-   }
+    /**
+     * test an empty RDN
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnEmpty() throws InvalidNameException
+    {
+        assertEquals( "", new Rdn( "" ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN : a = b
-    */
-   public void testRdnSimple() throws InvalidNameException
-   {
-       Assert.assertEquals( "a=b", new Rdn( "a = b" ).toString() );
-   }
+    /**
+     * test a simple RDN : a = b
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnSimple() throws InvalidNameException
+    {
+        assertEquals( "a=b", new Rdn( "a = b" ).toString() );
+    }
 
 
-   /**
-    * test a composite RDN : a = b, d = e
-    */
-   public void testRdnComposite() throws InvalidNameException
-   {
-       Assert.assertEquals( "a=b+c=d", new Rdn( "a = b + c = d" ).toString() );
-   }
+    /**
+     * test a composite RDN : a = b, d = e
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnComposite() throws InvalidNameException
+    {
+        assertEquals( "a=b+c=d", new Rdn( "a = b + c = d" ).toString() );
+    }
 
 
-   /**
-    * test a composite RDN with or without spaces: a=b, a =b, a= b, a = b, a =
-    * b
-    */
-   public void testRdnCompositeWithSpace() throws InvalidNameException
-   {
-       Assert.assertEquals( "a=b", new Rdn( "a=b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a=b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a =b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a= b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a=b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a =b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a= b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a=b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a = b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a =b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a= b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a = b" ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a =b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a= b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( "a = b " ).toString() );
-       Assert.assertEquals( "a=b", new Rdn( " a = b " ).toString() );
-   }
+    /**
+     * test a composite RDN with or without spaces: a=b, a =b, a= b, a = b, a =
+     * b
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnCompositeWithSpace() throws InvalidNameException
+    {
+        assertEquals( "a=b", new Rdn( "a=b" ).toString() );
+        assertEquals( "a=b", new Rdn( " a=b" ).toString() );
+        assertEquals( "a=b", new Rdn( "a =b" ).toString() );
+        assertEquals( "a=b", new Rdn( "a= b" ).toString() );
+        assertEquals( "a=b", new Rdn( "a=b " ).toString() );
+        assertEquals( "a=b", new Rdn( " a =b" ).toString() );
+        assertEquals( "a=b", new Rdn( " a= b" ).toString() );
+        assertEquals( "a=b", new Rdn( " a=b " ).toString() );
+        assertEquals( "a=b", new Rdn( "a = b" ).toString() );
+        assertEquals( "a=b", new Rdn( "a =b " ).toString() );
+        assertEquals( "a=b", new Rdn( "a= b " ).toString() );
+        assertEquals( "a=b", new Rdn( " a = b" ).toString() );
+        assertEquals( "a=b", new Rdn( " a =b " ).toString() );
+        assertEquals( "a=b", new Rdn( " a= b " ).toString() );
+        assertEquals( "a=b", new Rdn( "a = b " ).toString() );
+        assertEquals( "a=b", new Rdn( " a = b " ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN with differents separators : a = b + c = d
-    */
-   public void testRdnSimpleMultivaluedAttribute() throws InvalidNameException
-   {
-       String result = new Rdn( "a = b + c = d" ).toString();
-       Assert.assertEquals( "a=b+c=d", result );
-   }
+    /**
+     * test a simple RDN with differents separators : a = b + c = d
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnSimpleMultivaluedAttribute() throws InvalidNameException
+    {
+        String result = new Rdn( "a = b + c = d" ).toString();
+        assertEquals( "a=b+c=d", result );
+    }
 
 
-   /**
-    * test a composite RDN with differents separators : a=b+c=d, e=f + g=h +
-    * i=j
-    */
-   public void testRdnCompositeMultivaluedAttribute() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( "a =b+c=d + e=f + g  =h + i =j " );
+    /**
+     * test a composite RDN with differents separators : a=b+c=d, e=f + g=h +
+     * i=j
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnCompositeMultivaluedAttribute() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "a =b+c=d + e=f + g  =h + i =j " );
 
-       // NameComponent are not ordered
-       Assert.assertEquals( "b", rdn.getValue( "a" ) );
-       Assert.assertEquals( "d", rdn.getValue( "c" ) );
-       Assert.assertEquals( "f", rdn.getValue( "  E  " ) );
-       Assert.assertEquals( "h", rdn.getValue( "g" ) );
-       Assert.assertEquals( "j", rdn.getValue( "i" ) );
-   }
+        // NameComponent are not ordered
+        assertEquals( "b", rdn.getValue( "a" ) );
+        assertEquals( "d", rdn.getValue( "c" ) );
+        assertEquals( "f", rdn.getValue( "  E  " ) );
+        assertEquals( "h", rdn.getValue( "g" ) );
+        assertEquals( "j", rdn.getValue( "i" ) );
+    }
 
 
-   /**
-    * test a simple RDN with an oid prefix (uppercase) : OID.12.34.56 = azerty
-    */
-   public void testRdnOidUpper() throws InvalidNameException
-   {
-       Assert.assertEquals( "oid.12.34.56=azerty", new Rdn( "OID.12.34.56 =  azerty" ).toString() );
-   }
+    /**
+     * test a simple RDN with an oid prefix (uppercase) : OID.12.34.56 = azerty
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnOidUpper() throws InvalidNameException
+    {
+        assertEquals( "oid.12.34.56=azerty", new Rdn( "OID.12.34.56 =  azerty" ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN with an oid prefix (lowercase) : oid.12.34.56 = azerty
-    */
-   public void testRdnOidLower() throws InvalidNameException
-   {
-       Assert.assertEquals( "oid.12.34.56=azerty", new Rdn( "oid.12.34.56 = azerty" ).toString() );
-   }
+    /**
+     * test a simple RDN with an oid prefix (lowercase) : oid.12.34.56 = azerty
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnOidLower() throws InvalidNameException
+    {
+        assertEquals( "oid.12.34.56=azerty", new Rdn( "oid.12.34.56 = azerty" ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN with an oid attribut wiithout oid prefix : 12.34.56 =
-    * azerty
-    */
-   public void testRdnOidWithoutPrefix() throws InvalidNameException
-   {
-       Assert.assertEquals( "12.34.56=azerty", new Rdn( "12.34.56 = azerty" ).toString() );
-   }
+    /**
+     * test a simple RDN with an oid attribut wiithout oid prefix : 12.34.56 =
+     * azerty
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnOidWithoutPrefix() throws InvalidNameException
+    {
+        assertEquals( "12.34.56=azerty", new Rdn( "12.34.56 = azerty" ).toString() );
+    }
 
 
-   /**
-    * test a composite RDN with an oid attribut wiithout oid prefix : 12.34.56 =
-    * azerty; 7.8 = test
-    */
-   public void testRdnCompositeOidWithoutPrefix() throws InvalidNameException
-   {
-       String result = new Rdn( "12.34.56 = azerty + 7.8 = test" ).toString();
-       Assert.assertEquals( "12.34.56=azerty+7.8=test", result );
-   }
+    /**
+     * test a composite RDN with an oid attribut wiithout oid prefix : 12.34.56 =
+     * azerty; 7.8 = test
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnCompositeOidWithoutPrefix() throws InvalidNameException
+    {
+        String result = new Rdn( "12.34.56 = azerty + 7.8 = test" ).toString();
+        assertEquals( "12.34.56=azerty+7.8=test", result );
+    }
 
 
-   /**
-    * test a simple RDN with pair char attribute value : a = \,\=\+\<\>\#\;\\\"\C3\A9"
-    */
-   public void testRdnPairCharAttributeValue() throws InvalidNameException
-   {
-       String rdn = StringTools.utf8ToString( new byte[]{'a', '=', '\\', ',', '=', '\\', '+', '\\', '<', 
-           '\\', '>', '#', '\\', ';', '\\', '\\', '\\', '"', '\\', 'C', '3', '\\', 'A', '9' });
-       Assert.assertEquals( rdn, new Rdn(
-           "a = \\,=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9" ).toString() );
-   }
+    /**
+     * test a simple RDN with pair char attribute value : a = \,\=\+\<\>\#\;\\\"\C3\A9"
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnPairCharAttributeValue() throws InvalidNameException
+    {
+        String rdn = StringTools.utf8ToString( new byte[]
+            { 'a', '=', '\\', ',', '=', '\\', '+', '\\', '<', '\\', '>', '#', '\\', ';', '\\', '\\', '\\', '"', '\\',
+                'C', '3', '\\', 'A', '9' } );
+        assertEquals( rdn, new Rdn( "a = \\,=\\+\\<\\>#\\;\\\\\\\"\\C3\\A9" ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN with hexString attribute value : a = #0010A0AAFF
-    */
-   public void testRdnHexStringAttributeValue() throws InvalidNameException
-   {
-       Assert.assertEquals( "a=#0010A0AAFF", new Rdn( "a = #0010A0AAFF" ).toString() );
-   }
+    /**
+     * test a simple RDN with hexString attribute value : a = #0010A0AAFF
+     */
+    @Test
+    public void testRdnHexStringAttributeValue() throws InvalidNameException
+    {
+        assertEquals( "a=#0010A0AAFF", new Rdn( "a = #0010A0AAFF" ).toString() );
+    }
 
 
-   /**
-    * test a simple RDN with quoted attribute value : a = "quoted \"value"
-    */
-   public void testRdnQuotedAttributeValue() throws InvalidNameException
-   {
-       Assert.assertEquals( "a=quoted \\\"value", new Rdn( "a = quoted \\\"value" ).toString() );
-   }
+    /**
+     * test a simple RDN with quoted attribute value : a = "quoted \"value"
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRdnQuotedAttributeValue() throws InvalidNameException
+    {
+        assertEquals( "a=quoted \\\"value", new Rdn( "a = quoted \\\"value" ).toString() );
+    }
 
 
-   /**
-    * Test the clone method for a RDN.
-    */
-   public void testRDNCloningOneNameComponent() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( "a", "a", "b", "b" );
+    /**
+     * Test the clone method for a RDN.
+     */
+    @Test
+    public void testParseRDNNull()
+    {
+        Rdn rdn = null;
 
-       Rdn rdnClone = ( Rdn ) rdn.clone();
+        try
+        {
+            RdnParser.parse( "c=d", rdn );
+            fail();
+        }
+        catch ( InvalidNameException ine )
+        {
+            assertTrue( true );
+        }
+    }
 
-       RdnParser.parse( "c=d", rdn );
 
-       Assert.assertEquals( "b", rdnClone.getValue( "a" ) );
-   }
+    /**
+     * Test the clone method for a RDN.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCloningOneNameComponent() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "a", "a", "b", "b" );
 
+        Rdn rdnClone = ( Rdn ) rdn.clone();
 
-   /**
-    * Test the clone method for a RDN.
-    */
-   public void testRDNCloningTwoNameComponent() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( "a = b + aa = bb" );
+        RdnParser.parse( "c=d", rdn );
 
-       Rdn rdnClone = ( Rdn ) rdn.clone();
+        assertEquals( "b", rdnClone.getValue( "a" ) );
+    }
 
-       rdn.clear();
-       RdnParser.parse( "c=d", rdn );
 
-       Assert.assertEquals( "b", rdnClone.getValue( "a" ) );
-       Assert.assertEquals( "bb", rdnClone.getValue( "aa" ) );
-       Assert.assertEquals( "", rdnClone.getValue( "c" ) );
-   }
+    /**
+     * Test the clone method for a RDN.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCloningTwoNameComponent() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "a = b + aa = bb" );
 
+        Rdn rdnClone = ( Rdn ) rdn.clone();
 
-   /**
-    * Test the compareTo method for a RDN.
-    */
-   public void testRDNCompareToNull() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
-       Rdn rdn2 = null;
-       Assert.assertEquals( 1, rdn1.compareTo( rdn2 ) );
-   }
+        rdn.clear();
+        RdnParser.parse( "c=d", rdn );
+
+        assertEquals( "b", rdnClone.getValue( "a" ) );
+        assertEquals( "bb", rdnClone.getValue( "aa" ) );
+        assertEquals( "", rdnClone.getValue( "c" ) );
+    }
+
+
+    /**
+     * Test the compareTo method for a RDN.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNull() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
+        Rdn rdn2 = null;
+        assertTrue( rdn1.compareTo( rdn2 ) > 0 );
+    }
+
+
+    /**
+     * Compares a composite NC to a single NC.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNCS2NC() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
+        Rdn rdn2 = new Rdn( " a = b " );
+        assertTrue( rdn1.compareTo( rdn2 ) > 0 );
+    }
+
+
+    /**
+     * Compares a single NC to a composite NC.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNC2NCS() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
+
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+    }
+
+
+    /**
+     * Compares a composite NCS to a composite NCS in the same order.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNCS2NCSOrdered() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
+        Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
+
+        assertEquals( 0, rdn1.compareTo( rdn2 ) );
+    }
+
+
+    /**
+     * Compares a composite NCS to a composite NCS in a different order.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNCS2NCSUnordered() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + a = f + g = h + c = d " );
+        Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
+
+        assertEquals( 0, rdn1.compareTo( rdn2 ) );
+    }
+
+
+    /**
+     * Compares a composite NCS to a different composite NCS.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNCS2NCSNotEquals() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = f + g = h + c = d " );
+        Rdn rdn2 = new Rdn( " c = d + a = h + g = h " );
+
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+    }
+
+
+    /**
+     * Test for DIRSHARED-2.
+     * The first ATAV is equal, the second or following ATAV differs.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareSecondAtav() throws InvalidNameException
+    {
+        // the second ATAV differs
+        Rdn rdn1 = new Rdn( " a = b + c = d " );
+        Rdn rdn2 = new Rdn( " a = b + c = y " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+
+        // the third ATAV differs
+        Rdn rdn3 = new Rdn( " a = b + c = d + e = f " );
+        Rdn rdn4 = new Rdn( " a = b + c = d + e = y " );
+        assertTrue( rdn3.compareTo( rdn4 ) < 0 );
+        assertTrue( rdn4.compareTo( rdn3 ) > 0 );
+        assertEquals( 0, rdn3.compareTo( rdn4 ) + rdn4.compareTo( rdn3 ) );
+
+        // the second ATAV differs in value only
+        Rdn rdn5 = new Rdn( " a = b + a = c " );
+        Rdn rdn6 = new Rdn( " a = b + a = y " );
+        assertTrue( rdn5.compareTo( rdn6 ) < 0 );
+        assertTrue( rdn6.compareTo( rdn5 ) > 0 );
+        assertEquals( 0, rdn5.compareTo( rdn6 ) + rdn6.compareTo( rdn5 ) );
+    }
+
+
+    /**
+     * Test for DIRSHARED-2.
+     * The compare operation should return a correct value (1 or -1)
+     * depending on the ATAVs, not on their position.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareIndependentFromOrder() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + c = d " );
+        Rdn rdn2 = new Rdn( " c = d + a = b " );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) );
 
+        rdn1 = new Rdn( " a = b + c = e " );
+        rdn2 = new Rdn( " c = d + a = b " );
+        assertTrue( rdn1.compareTo( rdn2 ) > 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) < 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
 
-   /**
-    * Compares a composite NC to a single NC.
-    */
-   public void testRDNCompareToNCS2NC() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
-       Rdn rdn2 = new Rdn( " a = b " );
-       Assert.assertTrue( rdn1.compareTo( rdn2 ) > 0 );
-   }
+        rdn1 = new Rdn( " a = b + c = d " );
+        rdn2 = new Rdn( " e = f + g = h " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+    }
 
 
-   /**
-    * Compares a single NC to a composite NC.
-    */
-   public void testRDNCompareToNC2NCS() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
-       Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
+    /**
+     * Test for DIRSHARED-3.
+     * Tests that compareTo() is invertable for single-valued RDNs.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareInvertableNC2NC() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " a = c " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
 
-       Assert.assertTrue( rdn1.compareTo( rdn2 ) < 0 );
-   }
+    }
 
 
-   /**
-    * Compares a composite NCS to a composite NCS in the same order.
-    */
-   public void testRDNCompareToNCS2NCSOrdered() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b + c = d + a = f + g = h " );
-       Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
+    /**
+     * Test for DIRSHARED-3.
+     * Tests that compareTo() is invertable for multi-valued RDNs with different values.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareInvertableNCS2NCSDifferentValues() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + a = c " );
+        Rdn rdn2 = new Rdn( " a = b + a = y " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+    }
 
-       Assert.assertEquals( 0, rdn1.compareTo( rdn2 ) );
-   }
 
+    /**
+     * Test for DIRSHARED-3.
+     * Tests that compareTo() is invertable for multi-valued RDNs with different types.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareInvertableNCS2NCSDifferentTypes() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b + c = d  " );
+        Rdn rdn2 = new Rdn( " e = f + g = h " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+    }
 
-   /**
-    * Compares a composite NCS to a composite NCS in a different order.
-    */
-   public void testRDNCompareToNCS2NCSUnordered() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b + a = f + g = h + c = d " );
-       Rdn rdn2 = new Rdn( " a = b + c = d + a = f + g = h " );
 
-       Assert.assertEquals( 0, rdn1.compareTo( rdn2 ) );
-   }
+    /**
+     * Test for DIRSHARED-3.
+     * Tests that compareTo() is invertable for multi-valued RDNs with different order.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testCompareInvertableNCS2NCSUnordered() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " c = d + a = b " );
+        Rdn rdn2 = new Rdn( " a = b + e = f " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+        assertTrue( rdn2.compareTo( rdn1 ) > 0 );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) + rdn2.compareTo( rdn1 ) );
+    }
 
 
-   /**
-    * Compares a composite NCS to a different composite NCS.
-    */
-   public void testRDNCompareToNCS2NCSNotEquals() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = f + g = h + c = d " );
-       Rdn rdn2 = new Rdn( " c = d + a = h + g = h " );
+    /**
+     * Compares with a null RDN.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNullRdn() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
 
-       Assert.assertEquals( -1, rdn1.compareTo( rdn2 ) );
-   }
+        assertEquals( 1, rdn1.compareTo( null ) );
+    }
 
 
-   /**
-    * Compares with a null RDN.
-    */
-   public void testRDNCompareToNullRdn() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
+    /**
+     * Compares with a bad object
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToBadObject() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
 
-       Assert.assertEquals( 1, rdn1.compareTo( null ) );
-   }
+        assertEquals( Rdn.UNDEFINED, rdn1.compareTo( "test" ) );
+    }
 
-   /**
-    * Compares with a bad object
-    */
-   public void testRDNCompareToBadObject() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
 
-       Assert.assertEquals( Rdn.UNDEFINED, rdn1.compareTo( "test" ) );
-   }
+    /**
+     * Compares a simple NC to a simple NC.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNC2NC() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " a = b " );
 
-   /**
-    * Compares a simple NC to a simple NC.
-    */
-   public void testRDNCompareToNC2NC() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
-       Rdn rdn2 = new Rdn( " a = b " );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) );
+    }
 
-       Assert.assertEquals( 0, rdn1.compareTo( rdn2 ) );
-   }
 
+    /**
+     * Compares a simple NC to a simple NC in UperCase.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNC2NCUperCase() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " A = b " );
 
-   /**
-    * Compares a simple NC to a simple NC in UperCase.
-    */
-   public void testRDNCompareToNC2NCUperCase() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
-       Rdn rdn2 = new Rdn( " A = b " );
+        assertEquals( 0, rdn1.compareTo( rdn2 ) );
+        assertEquals( true, rdn1.equals( rdn2 ) );
+    }
 
-       Assert.assertEquals( 0, rdn1.compareTo( rdn2 ) );
-       Assert.assertEquals( true, rdn1.equals( rdn2 ) );
-   }
 
+    /**
+     * Compares a simple NC to a different simple NC.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testRDNCompareToNC2NCNotEquals() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( " a = b " );
+        Rdn rdn2 = new Rdn( " A = d " );
 
-   /**
-    * Compares a simple NC to a different simple NC.
-    */
-   public void testRDNCompareToNC2NCNotEquals() throws InvalidNameException
-   {
-       Rdn rdn1 = new Rdn( " a = b " );
-       Rdn rdn2 = new Rdn( " A = d " );
+        assertTrue( rdn1.compareTo( rdn2 ) < 0 );
+    }
 
-       Assert.assertTrue( rdn1.compareTo( rdn2 ) < 0 );
-   }
 
+    /**
+     * 
+     * test the ToAttributes method.
+     *
+     * @throws InvalidNameException
+     * @throws NamingException
+     */
+    @Test
+    public void testToAttributes() throws InvalidNameException, NamingException
+    {
+        Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
 
-   public void testToAttributes() throws InvalidNameException, NamingException
-   {
-       Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
+        Attributes attributes = rdn.toAttributes();
 
-       Attributes attributes = rdn.toAttributes();
+        assertNotNull( attributes.get( "a" ) );
+        assertNotNull( attributes.get( "g" ) );
+        assertNotNull( attributes.get( "c" ) );
 
-       Assert.assertNotNull( attributes.get( "a" ) );
-       Assert.assertNotNull( attributes.get( "g" ) );
-       Assert.assertNotNull( attributes.get( "c" ) );
+        Attribute attribute = attributes.get( "a" );
 
-       Attribute attribute = attributes.get( "a" );
+        assertNotNull( attribute.get( 0 ) );
+        assertEquals( "b", attribute.get( 0 ) );
 
-       Assert.assertNotNull( attribute.get( 0 ) );
-       Assert.assertEquals( "b", attribute.get( 0 ) );
+        assertNotNull( attribute.get( 1 ) );
+        assertEquals( "f", attribute.get( 1 ) );
 
-       Assert.assertNotNull( attribute.get( 1 ) );
-       Assert.assertEquals( "f", attribute.get( 1 ) );
+        attribute = attributes.get( "g" );
+        assertNotNull( attribute.get( 0 ) );
+        assertEquals( "h", attribute.get( 0 ) );
 
-       attribute = attributes.get( "g" );
-       Assert.assertNotNull( attribute.get( 0 ) );
-       Assert.assertEquals( "h", attribute.get( 0 ) );
+        attribute = attributes.get( "c" );
+        assertNotNull( attribute.get( 0 ) );
+        assertEquals( "d", attribute.get( 0 ) );
+    }
 
-       attribute = attributes.get( "c" );
-       Assert.assertNotNull( attribute.get( 0 ) );
-       Assert.assertEquals( "d", attribute.get( 0 ) );
-   }
 
+    /**
+     * 
+     * Test the getValue method.
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testGetValue() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
 
-   public void testGetValue() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
+        assertEquals( "b", rdn.getValue() );
+    }
 
-       Assert.assertEquals( "b", rdn.getValue() );
-   }
 
+    /**
+     * 
+     * Test the getType method.
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testGetType() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
 
-   public void testGetType() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
+        assertEquals( "a", rdn.getNormType() );
+    }
 
-       Assert.assertEquals( "a", rdn.getNormType() );
-   }
 
+    /**
+     * Test the getSize method.
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testGetSize() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
 
-   public void testGetSize() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( " a = b + a = f + g = h + c = d " );
+        assertEquals( 4, rdn.size() );
+    }
 
-       Assert.assertEquals( 4, rdn.size() );
-   }
 
+    /**
+     * Test the getSize method.
+     *
+     */
+    @Test
+    public void testGetSize0()
+    {
+        Rdn rdn = new Rdn();
 
-   public void testGetSize0()
-   {
-       Rdn rdn = new Rdn();
+        assertEquals( 0, rdn.size() );
+    }
 
-       Assert.assertEquals( 0, rdn.size() );
-   }
 
+    /**
+     * Test the equals method
+     *
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testEquals() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "a=b + c=d + a=f" );
 
-   public void testEquals() throws InvalidNameException
-   {
-       Rdn rdn = new Rdn( "a=b + c=d + a=f" );
+        assertFalse( rdn.equals( null ) );
+        assertFalse( rdn.equals( "test" ) );
+        assertFalse( rdn.equals( new Rdn( "a=c + c=d + a=f" ) ) );
+        assertFalse( rdn.equals( new Rdn( "a=b" ) ) );
+        assertTrue( rdn.equals( new Rdn( "a=b + c=d + a=f" ) ) );
+        assertTrue( rdn.equals( new Rdn( "a=b + C=d + A=f" ) ) );
+        assertTrue( rdn.equals( new Rdn( "c=d + a=f + a=b" ) ) );
+    }
 
-       Assert.assertFalse( rdn.equals( null ) );
-       Assert.assertFalse( rdn.equals( "test" ) );
-       Assert.assertFalse( rdn.equals( new Rdn( "a=c + c=d + a=f" ) ) );
-       Assert.assertFalse( rdn.equals( new Rdn( "a=b" ) ) );
-       Assert.assertTrue( rdn.equals( new Rdn( "a=b + c=d + a=f" ) ) );
-       Assert.assertTrue( rdn.equals( new Rdn( "a=b + C=d + A=f" ) ) );
-       Assert.assertTrue( rdn.equals( new Rdn( "c=d + a=f + a=b" ) ) );
-   }
 
+    @Test
+    public void testUnescapeValueHexa()
+    {
+        byte[] res = ( byte[] ) Rdn.unescapeValue( "#fF" );
 
-   public void testUnescapeValueHexa()
-   {
-       byte[] res = ( byte[] ) Rdn.unescapeValue( "#fF" );
+        assertEquals( "0xFF ", StringTools.dumpBytes( res ) );
 
-       Assert.assertEquals( "0xFF ", StringTools.dumpBytes( res ) );
+        res = ( byte[] ) Rdn.unescapeValue( "#0123456789aBCDEF" );
+        assertEquals( "0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF ", StringTools.dumpBytes( res ) );
+    }
 
-       res = ( byte[] ) Rdn.unescapeValue( "#0123456789aBCDEF" );
-       Assert.assertEquals( "0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF ", StringTools.dumpBytes( res ) );
-   }
 
+    @Test
+    public void testUnescapeValueHexaWrong()
+    {
+        try
+        {
+            Rdn.unescapeValue( "#fF1" );
+            fail(); // Should not happen
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            assertTrue( true );
+        }
+    }
 
-   public void testUnescapeValueHexaWrong()
-   {
-       try
-       {
-           Rdn.unescapeValue( "#fF1" );
-           Assert.fail(); // Should not happen
-       }
-       catch ( IllegalArgumentException iae )
-       {
-           Assert.assertTrue( true );
-       }
-   }
 
+    @Test
+    public void testUnescapeValueString()
+    {
+        String res = ( String ) Rdn.unescapeValue( "azerty" );
 
-   public void testUnescapeValueString()
-   {
-       String res = ( String ) Rdn.unescapeValue( "azerty" );
+        assertEquals( "azerty", res );
+    }
 
-       Assert.assertEquals( "azerty", res );
-   }
 
+    @Test
+    public void testUnescapeValueStringSpecial()
+    {
+        String res = ( String ) Rdn.unescapeValue( "\\\\\\#\\,\\+\\;\\<\\>\\=\\\"\\ " );
 
-   public void testUnescapeValueStringSpecial()
-   {
-       String res = ( String ) Rdn.unescapeValue( "\\\\\\#\\,\\+\\;\\<\\>\\=\\\"\\ " );
+        assertEquals( "\\#,+;<>=\" ", res );
+    }
 
-       Assert.assertEquals( "\\#,+;<>=\" ", res );
-   }
 
+    @Test
+    public void testEscapeValueString()
+    {
+        String res = Rdn.escapeValue( StringTools.getBytesUtf8( "azerty" ) );
 
-   public void testEscapeValueString()
-   {
-       String res = Rdn.escapeValue( StringTools.getBytesUtf8( "azerty" ) );
+        assertEquals( "azerty", res );
+    }
 
-       Assert.assertEquals( "azerty", res );
-   }
 
+    @Test
+    public void testEscapeValueStringSpecial()
+    {
+        String res = Rdn.escapeValue( StringTools.getBytesUtf8( "\\#,+;<>=\" " ) );
 
-   public void testEscapeValueStringSpecial()
-   {
-       String res = Rdn.escapeValue( StringTools.getBytesUtf8( "\\#,+;<>=\" " ) );
+        assertEquals( "\\\\#\\,\\+\\;\\<\\>\\=\\\"\\ ", res );
+    }
 
-       Assert.assertEquals( "\\\\\\#\\,\\+\\;\\<\\>\\=\\\"\\ ", res );
-   }
 
+    @Test
+    public void testEscapeValueNumeric()
+    {
+        String res = Rdn.escapeValue( new byte[]
+            { '-', 0x00, '-', 0x1F, '-', 0x7F, '-' } );
 
-   public void testEscapeValueNumeric()
-   {
-       String res = Rdn.escapeValue( new byte[]
-           { '-', 0x00, '-', 0x1F, '-', 0x7F, '-' } );
+        assertEquals( "-\\00-\\1F-\\7F-", res );
+    }
 
-       Assert.assertEquals( "-\\00-\\1F-\\7F-", res );
-   }
 
+    @Test
+    public void testEscapeValueMix()
+    {
+        String res = Rdn.escapeValue( new byte[]
+            { '\\', 0x00, '-', '+', '#', 0x7F, '-' } );
 
-   public void testEscapeValueMix()
-   {
-       String res = Rdn.escapeValue( new byte[]
-           { '\\', 0x00, '-', '+', '#', 0x7F, '-' } );
+        assertEquals( "\\\\\\00-\\+#\\7F-", res );
+    }
 
-       Assert.assertEquals( "\\\\\\00-\\+\\#\\7F-", res );
-   }
 
-    public void testDIRSERVER_703() throws InvalidNameException 
+    @Test
+    public void testDIRSERVER_703() throws InvalidNameException
     {
         Rdn rdn = new Rdn( "cn=Kate Bush+sn=Bush" );
         assertEquals( "cn=Kate Bush+sn=Bush", rdn.getUpName() );
     }
+
+
+    @Test
+    public void testMultiValuedIterator() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "cn=Kate Bush+sn=Bush" );
+        Iterator<AttributeTypeAndValue> iterator = rdn.iterator();
+        assertNotNull( iterator );
+        assertTrue( iterator.hasNext() );
+        assertNotNull( iterator.next() );
+        assertTrue( iterator.hasNext() );
+        assertNotNull( iterator.next() );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    @Test
+    public void testSingleValuedIterator() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "cn=Kate Bush" );
+        Iterator<AttributeTypeAndValue> iterator = rdn.iterator();
+        assertNotNull( iterator );
+        assertTrue( iterator.hasNext() );
+        assertNotNull( iterator.next() );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    @Test
+    public void testEmptyIterator()
+    {
+        Rdn rdn = new Rdn();
+        Iterator<AttributeTypeAndValue> iterator = rdn.iterator();
+        assertNotNull( iterator );
+        assertFalse( iterator.hasNext() );
+    }
+
+
+    @Test
+    public void testRdnWithSpaces() throws InvalidNameException
+    {
+        Rdn rdn = new Rdn( "cn=a\\ b\\ c" );
+        assertEquals( "cn=a b c", rdn.toString() );
+    }
+
+
+    @Test
+    public void testEscapedSpaceInValue() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( "cn=a b c" );
+        Rdn rdn2 = new Rdn( "cn=a\\ b\\ c" );
+        assertEquals( "cn=a b c", rdn1.toString() );
+        assertEquals( "cn=a b c", rdn2.toString() );
+        assertTrue( rdn1.equals( rdn2 ) );
+
+        Rdn rdn3 = new Rdn( "cn=\\ a b c\\ " );
+        Rdn rdn4 = new Rdn( "cn=\\ a\\ b\\ c\\ " );
+        assertEquals( "cn=\\ a b c\\ ", rdn3.toString() );
+        assertEquals( "cn=\\ a b c\\ ", rdn4.toString() );
+        assertTrue( rdn3.equals( rdn4 ) );
+    }
+
+
+    @Test
+    public void testEscapedHashInValue() throws InvalidNameException
+    {
+        Rdn rdn1 = new Rdn( "cn=a#b#c" );
+        Rdn rdn2 = new Rdn( "cn=a\\#b\\#c" );
+        assertEquals( "cn=a#b#c", rdn1.toString() );
+        assertEquals( "cn=a#b#c", rdn2.toString() );
+        assertTrue( rdn1.equals( rdn2 ) );
+
+        Rdn rdn3 = new Rdn( "cn=\\#a#b#c\\#" );
+        Rdn rdn4 = new Rdn( "cn=\\#a\\#b\\#c\\#" );
+        assertEquals( "cn=\\#a#b#c#", rdn3.toString() );
+        assertEquals( "cn=\\#a#b#c#", rdn4.toString() );
+        assertTrue( rdn3.equals( rdn4 ) );
+    }
+
+
+    @Test
+    public void testEscapedAttributeValue()
+    {
+        // space doesn't need to be escaped in the middle of a string
+        assertEquals( "a b", Rdn.escapeValue( "a b" ) );
+        assertEquals( "a b c", Rdn.escapeValue( "a b c" ) );
+        assertEquals( "a b c d", Rdn.escapeValue( "a b c d" ) );
+
+        // space must be escaped at the beginning and the end of a string
+        assertEquals( "\\ a b", Rdn.escapeValue( " a b" ) );
+        assertEquals( "a b\\ ", Rdn.escapeValue( "a b " ) );
+        assertEquals( "\\ a b\\ ", Rdn.escapeValue( " a b " ) );
+        assertEquals( "\\  a  b \\ ", Rdn.escapeValue( "  a  b  " ) );
+
+        // hash doesn't need to be escaped in the middle and the end of a string
+        assertEquals( "a#b", Rdn.escapeValue( "a#b" ) );
+        assertEquals( "a#b#", Rdn.escapeValue( "a#b#" ) );
+        assertEquals( "a#b#c", Rdn.escapeValue( "a#b#c" ) );
+        assertEquals( "a#b#c#", Rdn.escapeValue( "a#b#c#" ) );
+        assertEquals( "a#b#c#d", Rdn.escapeValue( "a#b#c#d" ) );
+        assertEquals( "a#b#c#d#", Rdn.escapeValue( "a#b#c#d#" ) );
+
+        // hash must be escaped at the beginning of a string
+        assertEquals( "\\#a#b", Rdn.escapeValue( "#a#b" ) );
+        assertEquals( "\\##a#b", Rdn.escapeValue( "##a#b" ) );
+    }
+
+
+    /** Serialization tests ------------------------------------------------- */
+
+    /**
+     * Test serialization of an empty RDN
+     */
+    @Test
+    public void testEmptyRDNSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "" );
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    @Test
+    public void testNullRdnSerialization() throws IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn();
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdnSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "a=b" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdn2Serialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = DEF " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with no value
+     */
+    @Test
+    public void testSimpleRdnNoValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  =" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with one value
+     */
+    @Test
+    public void testSimpleRdnOneValueSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = def " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with three values
+     */
+    @Test
+    public void testSimpleRdnThreeValuesSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " A = a + B = b + C = c " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with three unordered values
+     */
+    @Test
+    public void testSimpleRdnThreeValuesUnorderedSerialization() throws NamingException, IOException,
+        ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " B = b + A = a + C = c " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        rdn.writeExternal( out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = new Rdn();
+        rdn2.readExternal( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /** Static Serialization tests ------------------------------------------------- */
+
+    /**
+     * Test serialization of an empty RDN
+     */
+    @Test
+    public void testEmptyRDNStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "" );
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    @Test
+    public void testNullRdnStaticSerialization() throws IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn();
+
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdnStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( "a=b" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn
+     */
+    @Test
+    public void testSimpleRdn2StaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = DEF " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with no value
+     */
+    @Test
+    public void testSimpleRdnNoValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  =" );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with one value
+     */
+    @Test
+    public void testSimpleRdnOneValueStaticSerialization() throws NamingException, IOException, ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " ABC  = def " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with three values
+     */
+    @Test
+    public void testSimpleRdnThreeValuesStaticSerialization() throws NamingException, IOException,
+        ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " A = a + B = b + C = c " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * Test serialization of a simple Rdn with three unordered values
+     */
+    @Test
+    public void testSimpleRdnThreeValuesUnorderedStaticSerialization() throws NamingException, IOException,
+        ClassNotFoundException
+    {
+        Rdn rdn = new Rdn( " B = b + A = a + C = c " );
+        rdn.normalize();
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream( baos );
+
+        RdnSerializer.serialize( rdn, out );
+
+        ObjectInputStream in = null;
+
+        byte[] data = baos.toByteArray();
+        in = new ObjectInputStream( new ByteArrayInputStream( data ) );
+
+        Rdn rdn2 = RdnSerializer.deserialize( in );
+
+        assertEquals( rdn, rdn2 );
+    }
+
+
+    /**
+     * test an RDN with empty value
+     */
+    @Test
+    public void testRdnWithEmptyValue() throws InvalidNameException
+    {
+        assertTrue( RdnParser.isValid( "a=" ) );
+        assertTrue( RdnParser.isValid( "a=\"\"" ) );
+        assertEquals( "a=", new Rdn( "a=\"\"" ).toString() );
+        assertEquals( "a=", new Rdn( "a=" ).toString() );
+    }
+
+
+    /**
+     * test an RDN with escaped comma
+     */
+    @Test
+    public void testRdnWithEscapedComa() throws InvalidNameException
+    {
+        assertTrue( RdnParser.isValid( "a=b\\,c" ) );
+        assertEquals( "a=b\\,c", new Rdn( "a=b\\,c" ).toString() );
+
+        assertTrue( RdnParser.isValid( "a=\"b,c\"" ) );
+        assertEquals( "a=b\\,c", new Rdn( "a=\"b,c\"" ).toString() );
+        assertEquals( "a=\"b,c\"", new Rdn( "a=\"b,c\"" ).getUpName() );
+
+        assertTrue( RdnParser.isValid( "a=\"b\\,c\"" ) );
+        Rdn rdn = new Rdn( "a=\"b\\,c\"" );
+        assertEquals( "a=\"b\\,c\"", new Rdn( "a=\"b\\,c\"" ).getUpName() );
+        assertEquals( "a=b\\,c", new Rdn( "a=\"b\\,c\"" ).toString() );
+    }
+
+
+    /**
+     * Tests the equals and compareTo results of cloned multi-valued RDNs.
+     * Test for DIRSHARED-9.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testComparingOfClonedMultiValuedRDNs() throws InvalidNameException
+    {
+        // Use upper case attribute types to test if normalized types are used 
+        // for comparison
+        Rdn rdn = new Rdn( " A = b + C = d" );
+        Rdn clonedRdn = ( Rdn ) rdn.clone();
+
+        assertEquals( 0, rdn.compareTo( clonedRdn ) );
+        assertEquals( true, rdn.equals( clonedRdn ) );
+    }
+
+
+    /**
+     * Tests the equals and compareTo results of copy constructed multi-valued RDNs.
+     * Test for DIRSHARED-9.
+     * 
+     * @throws InvalidNameException
+     */
+    @Test
+    public void testComparingOfCopyConstructedMultiValuedRDNs() throws InvalidNameException
+    {
+        // Use upper case attribute types to test if normalized types are used 
+        // for comparison
+        Rdn rdn = new Rdn( " A = b + C = d" );
+        Rdn copiedRdn = new Rdn( rdn );
+
+        assertEquals( 0, rdn.compareTo( copiedRdn ) );
+        assertEquals( true, rdn.equals( copiedRdn ) );
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/SchemaUtilsTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/SchemaUtilsTest.java
index 396af2a..41b88ed 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/SchemaUtilsTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/SchemaUtilsTest.java
@@ -26,17 +26,6 @@
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.ldap.NotImplementedException;
-import org.apache.directory.shared.ldap.schema.AbstractAttributeType;
-import org.apache.directory.shared.ldap.schema.AbstractMatchingRule;
-import org.apache.directory.shared.ldap.schema.AbstractSyntax;
-import org.apache.directory.shared.ldap.schema.AttributeType;
-import org.apache.directory.shared.ldap.schema.DefaultObjectClass;
-import org.apache.directory.shared.ldap.schema.MatchingRule;
-import org.apache.directory.shared.ldap.schema.Normalizer;
-import org.apache.directory.shared.ldap.schema.ObjectClass;
-import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
-import org.apache.directory.shared.ldap.schema.SchemaUtils;
-import org.apache.directory.shared.ldap.schema.Syntax;
 import org.apache.directory.shared.ldap.schema.syntax.SyntaxChecker;
 
 
@@ -192,7 +181,8 @@
 
     static class SyntaxImpl extends AbstractSyntax
     {
-        public final static long serialVersionUID = 1L;
+        @SuppressWarnings ( { "AnalyzingVariableNaming" } )
+        private static final long serialVersionUID = 1L;
         
         protected SyntaxImpl(String oid)
         {
@@ -273,6 +263,18 @@
         {
             return substr;
         }
+
+
+        public boolean isAncestorOf( AttributeType attributeType ) throws NamingException
+        {
+            return false;
+        }
+
+
+        public boolean isDescentantOf( AttributeType attributeType ) throws NamingException
+        {
+            return false;
+        }
     }
 
     static class MatchingRuleImpl extends AbstractMatchingRule
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/ConsoleParserMonitor.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/ConsoleParserMonitor.java
new file mode 100644
index 0000000..7ee0da9
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/ConsoleParserMonitor.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema.parser;
+
+import org.apache.directory.shared.ldap.schema.parser.ParserMonitor;
+
+
+/**
+ * A console reporting monitor.  Add system property 'maven.eve.schema.parser.trace'
+ * to get this monitor to trace parser production execution.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437016 $
+ */
+public class ConsoleParserMonitor implements ParserMonitor
+{
+    public static final String TRACE_KEY = "maven.eve.schema.parser.trace";
+
+
+    public void matchedProduction( String prod )
+    {
+        if ( System.getProperties().containsKey( TRACE_KEY ) )
+        {
+            System.out.println( prod );
+        }
+    }
+
+
+    public void startedParse( String s )
+    {
+        if ( System.getProperties().containsKey( TRACE_KEY ) )
+        {
+            System.out.println( s );
+        }
+    }
+
+
+    public void finishedParse( String s )
+    {
+        if ( System.getProperties().containsKey( TRACE_KEY ) )
+        {
+            System.out.println( s );
+        }
+    }
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParserTest.java
new file mode 100644
index 0000000..a644961
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/parser/OpenLdapSchemaParserTest.java
@@ -0,0 +1,339 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema.parser;
+
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
+import org.apache.directory.shared.ldap.schema.syntax.OpenLdapObjectIdentifierMacro;
+
+
+/**
+ * Tests the OpenLDAP schema parser.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 437016 $
+ */
+public class OpenLdapSchemaParserTest extends TestCase
+{
+    private OpenLdapSchemaParser parser;
+
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        parser = new OpenLdapSchemaParser();
+        parser.setParserMonitor( new ConsoleParserMonitor() );
+    }
+
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        parser = null;
+    }
+
+
+    public void testSimpleAttributeTypeNoLength() throws Exception
+    {
+        String attributeTypeData = "attributetype ( 2.5.4.14 NAME 'searchGuide'\n"
+            + "        DESC 'RFC2256: search guide, obsoleted by enhancedSearchGuide'\n"
+            + "        SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )";
+
+        parser.parse( attributeTypeData );
+        List<AttributeTypeLiteral> attributeTypeList = parser.getAttributeTypes();
+        Map<String, AttributeTypeLiteral> attributeTypes = mapAttributeTypes( attributeTypeList );
+        AttributeTypeLiteral type = attributeTypes.get( "2.5.4.14" );
+
+        assertNotNull( type );
+        assertEquals( "2.5.4.14", type.getOid() );
+        assertEquals( "searchGuide", type.getNames()[0] );
+        assertEquals( "RFC2256: search guide, obsoleted by enhancedSearchGuide", type.getDescription() );
+        assertEquals( "1.3.6.1.4.1.1466.115.121.1.25", type.getSyntax() );
+    }
+
+
+    private Map<String, AttributeTypeLiteral> mapAttributeTypes( List<AttributeTypeLiteral> attributeTypeList )
+    {
+        Map<String, AttributeTypeLiteral> m = new HashMap<String, AttributeTypeLiteral>();
+
+        for ( AttributeTypeLiteral type : attributeTypeList )
+        {
+            m.put( type.getOid(), type );
+        }
+
+        return m;
+    }
+
+
+    public void testSimpleAttributeTypeParse() throws Exception
+    {
+        String attributeTypeData = "# adding a comment  \n" + "attributetype ( 2.5.4.2 NAME 'knowledgeInformation'\n"
+            + "        DESC 'RFC2256: knowledge information'\n" + "        EQUALITY caseIgnoreMatch\n"
+            + "        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )";
+        parser.parse( attributeTypeData );
+        List<AttributeTypeLiteral> attributeTypeList = parser.getAttributeTypes();
+        Map<String, AttributeTypeLiteral> attributeTypes = mapAttributeTypes( attributeTypeList );
+        AttributeTypeLiteral type = attributeTypes.get( "2.5.4.2" );
+
+        assertNotNull( type );
+        assertEquals( "2.5.4.2", type.getOid() );
+        assertEquals( "knowledgeInformation", type.getNames()[0] );
+        assertEquals( "RFC2256: knowledge information", type.getDescription() );
+        assertEquals( "1.3.6.1.4.1.1466.115.121.1.15", type.getSyntax() );
+        assertEquals( 32768, type.getLength() );
+    }
+
+
+    public void testAttributeTypeParseWithDescQuotes() throws Exception
+    {
+        String attributeTypeData = "# adding a comment  \n" + "attributetype ( 2.5.4.2 NAME 'knowledgeInformation'\n"
+            + "        DESC 'RFC2256: \"knowledge\" information'\n" + "        EQUALITY caseIgnoreMatch\n"
+            + "        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )";
+        parser.parse( attributeTypeData );
+        List<AttributeTypeLiteral> attributeTypeList = parser.getAttributeTypes();
+        Map<String, AttributeTypeLiteral> attributeTypes = mapAttributeTypes( attributeTypeList );
+        AttributeTypeLiteral type = attributeTypes.get( "2.5.4.2" );
+
+        assertNotNull( type );
+        assertEquals( "2.5.4.2", type.getOid() );
+        assertEquals( "knowledgeInformation", type.getNames()[0] );
+        assertEquals( "RFC2256: \"knowledge\" information", type.getDescription() );
+        assertEquals( "1.3.6.1.4.1.1466.115.121.1.15", type.getSyntax() );
+        assertEquals( 32768, type.getLength() );
+    }
+
+
+    public void testComplexAttributeTypeParse() throws Exception
+    {
+        String attributeTypeData = "# adding a comment  \n"
+            + "attributetype ( 2.5.4.2 NAME ( 'knowledgeInformation' 'asdf' ) \n"
+            + "        DESC 'RFC2256: knowledge information'\n" + "        EQUALITY caseIgnoreMatch\n"
+            + "        SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )";
+        parser.parse( attributeTypeData );
+        List<AttributeTypeLiteral> attributeTypeList = parser.getAttributeTypes();
+        Map<String, AttributeTypeLiteral> attributeTypes = mapAttributeTypes( attributeTypeList );
+        AttributeTypeLiteral type = attributeTypes.get( "2.5.4.2" );
+
+        assertNotNull( type );
+        assertEquals( "2.5.4.2", type.getOid() );
+        assertEquals( "knowledgeInformation", type.getNames()[0] );
+        assertEquals( "RFC2256: knowledge information", type.getDescription() );
+        assertEquals( "1.3.6.1.4.1.1466.115.121.1.15", type.getSyntax() );
+        assertEquals( 32768, type.getLength() );
+    }
+
+
+    private Map<String, ObjectClassLiteral> mapObjectClasses( List<ObjectClassLiteral> objectClassList )
+    {
+        Map<String, ObjectClassLiteral> m = new HashMap<String, ObjectClassLiteral>();
+
+        for ( ObjectClassLiteral objectClassLiteral : objectClassList )
+        {
+            m.put( objectClassLiteral.getOid(), objectClassLiteral );
+        }
+
+        return m;
+    }
+
+
+    public void testObjectClassParse() throws Exception
+    {
+        String objectClassData = "objectclass ( 2.5.6.6 NAME 'person'\n" + "        DESC 'RFC2256: a person'\n"
+            + "        SUP top STRUCTURAL\n" + "        MUST ( sn $ cn )\n"
+            + "        MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )";
+        parser.parse( objectClassData );
+        List<ObjectClassLiteral> objectClassesList = parser.getObjectClassTypes();
+        Map<String, ObjectClassLiteral> objectClasses = mapObjectClasses( objectClassesList );
+        ObjectClassLiteral objectClass = objectClasses.get( "2.5.6.6" );
+
+        assertNotNull( objectClass );
+        assertEquals( "2.5.6.6", objectClass.getOid() );
+        assertEquals( "person", objectClass.getNames()[0] );
+        assertEquals( "RFC2256: a person", objectClass.getDescription() );
+        assertEquals( ObjectClassTypeEnum.STRUCTURAL, objectClass.getClassType() );
+        assertEquals( "sn", objectClass.getMust()[0] );
+        assertEquals( "cn", objectClass.getMust()[1] );
+        assertEquals( "userPassword", objectClass.getMay()[0] );
+        assertEquals( "telephoneNumber", objectClass.getMay()[1] );
+        assertEquals( "seeAlso", objectClass.getMay()[2] );
+        assertEquals( "description", objectClass.getMay()[3] );
+    }
+
+
+    public void testObjectClassMultipleNames() throws Exception
+    {
+        String objectClassData = "objectclass ( 0.9.2342.19200300.100.4.4\n"
+            + "\tNAME ( 'pilotPerson' 'newPilotPerson' )\n" + "\tSUP person STRUCTURAL\n"
+            + "\tMAY ( userid $ textEncodedORAddress $ rfc822Mailbox $\n"
+            + "\t\tfavouriteDrink $ roomNumber $ userClass $\n"
+            + "\t\thomeTelephoneNumber $ homePostalAddress $ secretary $\n"
+            + "\t\tpersonalTitle $ preferredDeliveryMethod $ businessCategory $\n"
+            + "\t\tjanetMailbox $ otherMailbox $ mobileTelephoneNumber $\n"
+            + "\t\tpagerTelephoneNumber $ organizationalStatus $\n"
+            + "\t\tmailPreferenceOption $ personalSignature )\n" + "\t)";
+        parser.parse( objectClassData );
+        List<ObjectClassLiteral> objectClassesList = parser.getObjectClassTypes();
+        Map<String, ObjectClassLiteral> objectClasses = mapObjectClasses( objectClassesList );
+        ObjectClassLiteral objectClass = objectClasses.get( "0.9.2342.19200300.100.4.4" );
+
+        assertNotNull( objectClass );
+        assertEquals( "0.9.2342.19200300.100.4.4", objectClass.getOid() );
+        assertEquals( "pilotPerson", objectClass.getNames()[0] );
+        assertEquals( "newPilotPerson", objectClass.getNames()[1] );
+        assertEquals( ObjectClassTypeEnum.STRUCTURAL, objectClass.getClassType() );
+        assertEquals( "person", objectClass.getSuperiors()[0] );
+
+        assertEquals( "userid", objectClass.getMay()[0] );
+        assertEquals( "textEncodedORAddress", objectClass.getMay()[1] );
+        assertEquals( "rfc822Mailbox", objectClass.getMay()[2] );
+        assertEquals( "favouriteDrink", objectClass.getMay()[3] );
+        assertEquals( "roomNumber", objectClass.getMay()[4] );
+        assertEquals( "userClass", objectClass.getMay()[5] );
+        assertEquals( "homeTelephoneNumber", objectClass.getMay()[6] );
+        assertEquals( "homePostalAddress", objectClass.getMay()[7] );
+        assertEquals( "secretary", objectClass.getMay()[8] );
+        assertEquals( "personalTitle", objectClass.getMay()[9] );
+        assertEquals( "preferredDeliveryMethod", objectClass.getMay()[10] );
+        assertEquals( "businessCategory", objectClass.getMay()[11] );
+        assertEquals( "janetMailbox", objectClass.getMay()[12] );
+        assertEquals( "otherMailbox", objectClass.getMay()[13] );
+        assertEquals( "mobileTelephoneNumber", objectClass.getMay()[14] );
+        assertEquals( "pagerTelephoneNumber", objectClass.getMay()[15] );
+        assertEquals( "organizationalStatus", objectClass.getMay()[16] );
+        assertEquals( "mailPreferenceOption", objectClass.getMay()[17] );
+        assertEquals( "personalSignature", objectClass.getMay()[18] );
+    }
+
+
+    public void testParseOpenLdapCoreSchema() throws Exception
+    {
+        InputStream input = getClass().getResourceAsStream( "core.schema" );
+        parser.parse( input );
+
+        List<AttributeTypeLiteral> attributeTypes = parser.getAttributeTypes();
+        List<ObjectClassLiteral> objectClassTypes = parser.getObjectClassTypes();
+        Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros = parser.getObjectIdentifierMacros();
+
+        assertEquals( 52, attributeTypes.size() );
+        assertEquals( 27, objectClassTypes.size() );
+        assertEquals( 0, objectIdentifierMacros.size() );
+    }
+
+
+    public void testParseOpenLdapInetOrgPersonSchema() throws Exception
+    {
+        InputStream input = getClass().getResourceAsStream( "inetorgperson.schema" );
+        parser.parse( input );
+
+        List<AttributeTypeLiteral> attributeTypes = parser.getAttributeTypes();
+        List<ObjectClassLiteral> objectClassTypes = parser.getObjectClassTypes();
+        Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros = parser.getObjectIdentifierMacros();
+
+        assertEquals( 9, attributeTypes.size() );
+        assertEquals( 1, objectClassTypes.size() );
+        assertEquals( 0, objectIdentifierMacros.size() );
+    }
+
+
+    public void testParseOpenLdapCollectiveSchema() throws Exception
+    {
+        InputStream input = getClass().getResourceAsStream( "collective.schema" );
+        parser.parse( input );
+
+        List<AttributeTypeLiteral> attributeTypes = parser.getAttributeTypes();
+        List<ObjectClassLiteral> objectClassTypes = parser.getObjectClassTypes();
+        Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros = parser.getObjectIdentifierMacros();
+
+        assertEquals( 13, attributeTypes.size() );
+        assertEquals( 0, objectClassTypes.size() );
+        assertEquals( 0, objectIdentifierMacros.size() );
+        for ( AttributeTypeLiteral attributeTypeLiteral : attributeTypes )
+        {
+            assertTrue( attributeTypeLiteral.isCollective() );
+        }
+    }
+
+
+    public void testOpenLdapObjectIdentifiereMacros() throws Exception
+    {
+        InputStream input = getClass().getResourceAsStream( "dyngroup.schema" );
+        parser.parse( input );
+
+        List<AttributeTypeLiteral> attributeTypes = parser.getAttributeTypes();
+        List<ObjectClassLiteral> objectClassTypes = parser.getObjectClassTypes();
+        Map<String, OpenLdapObjectIdentifierMacro> objectIdentifierMacros = parser.getObjectIdentifierMacros();
+
+        assertEquals( 2, attributeTypes.size() );
+        assertEquals( 2, objectClassTypes.size() );
+        assertEquals( 8, objectIdentifierMacros.size() );
+
+        // check that all macros are resolved
+        for ( OpenLdapObjectIdentifierMacro macro : objectIdentifierMacros.values() )
+        {
+            assertTrue( macro.isResolved() );
+            assertNotNull( macro.getResolvedOid() );
+            assertTrue( macro.getResolvedOid().matches( "[0-9]+(\\.[0-9]+)+" ) );
+        }
+
+        // check that OIDs in attribute types and object classes are resolved
+        for ( ObjectClassLiteral objectClassLiteral : objectClassTypes )
+        {
+            List<String> asList = Arrays.asList( objectClassLiteral.getNames() );
+            if ( asList.contains( "groupOfURLs" ) )
+            {
+                assertEquals( "2.16.840.1.113730.3.2.33", objectClassLiteral.getOid() );
+            }
+            else if ( asList.contains( "dgIdentityAux" ) )
+            {
+                assertEquals( "1.3.6.1.4.1.4203.666.11.8.2.1", objectClassLiteral.getOid() );
+            }
+            else
+            {
+                fail( "object class 'groupOfURLs' or 'dgIdentityAux' expected" );
+            }
+        }
+        for ( AttributeTypeLiteral attributeTypeLiteral : attributeTypes )
+        {
+            List<String> asList = Arrays.asList( attributeTypeLiteral.getNames() );
+            if ( asList.contains( "memberURL" ) )
+            {
+                assertEquals( "2.16.840.1.113730.3.1.198", attributeTypeLiteral.getOid() );
+            }
+            else if ( asList.contains( "dgIdentity" ) )
+            {
+                assertEquals( "1.3.6.1.4.1.4203.666.11.8.1.1", attributeTypeLiteral.getOid() );
+            }
+            else
+            {
+                fail( "attribute type 'memberURL' or 'dgIdentity' expected" );
+            }
+        }
+    }
+
+}
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxCheckerTest.java
index 330ac8f..a90e736 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/AttributeTypeDescriptionSyntaxCheckerTest.java
@@ -45,6 +45,8 @@
         assertTrue( checker.isValidSyntax( "( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by'  SUP name EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch  )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by'  SUP name EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by'  SUP name EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE userApplications )" ) );
+        assertTrue( checker.isValidSyntax( "( 2.5.4.3 NAME cn SUP name )" ) );
+        assertTrue( checker.isValidSyntax( "( 2.5.4.3 name ( 'cn' 'commonName' )  sup name )" ) );
 
         // spaces
         assertTrue( checker.isValidSyntax( "(2.5.4.3 SUP name)" ) );
@@ -82,12 +84,6 @@
         // missing right parenthesis
         assertFalse( checker.isValidSyntax( "( 2.5.4.3 NAME 'cn' SUP name" ) );
 
-        // missing quotes
-        assertFalse( checker.isValidSyntax( "( 2.5.4.3 NAME cn SUP name )" ) );
-
-        // lowercase NAME, SUP
-        assertFalse( checker.isValidSyntax( "( 2.5.4.3 name ( 'cn' 'commonName' )  sup name " ) );
-
         // SYNTAX or SUP must be contained
         assertFalse( checker.isValidSyntax( "( 2.5.4.3 NAME ( 'cn' 'commonName' ) DESC 'RFC2256: common name(s) for which the entity is known by' )" ) );
         
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxCheckerTest.java
index c57e4f7..dfd70d2 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITContentRuleDescriptionSyntaxCheckerTest.java
@@ -35,30 +35,42 @@
 {
     private DITContentRuleDescriptionSyntaxChecker checker = new DITContentRuleDescriptionSyntaxChecker();
 
+
     public void testValid()
     {
         assertTrue( checker.isValidSyntax( "( 2.5.6.4 )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' )" ) );
-        assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE )" ) );
-        assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) )" ) );
-        assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) )" ) );
-        assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) MAY ( l $ st )  )" ) );
-        assertTrue( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) MAY ( l $ st ) NOT ( 1.2.3.4.5.6.7.8.9.0 $ ou ) )" ) );
-        
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) MAY ( l $ st )  )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 NAME 'organization' DESC 'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o ) MAY ( l $ st ) NOT ( 1.2.3.4.5.6.7.8.9.0 $ ou ) )" ) );
 
         assertTrue( checker.isValidSyntax( "(2.5.6.4)" ) );
-        assertTrue( checker.isValidSyntax( "(   2.5.6.4     NAME   'organization'   DESC   'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o )     MAY    (    l   $   st   ) NOT (1.2.3.4.5.6.7.8.9.0 $ ou))" ) );
+        assertTrue( checker.isValidSyntax( "(2.5.6.4 NAME organization)" ) );
+        assertTrue( checker
+            .isValidSyntax( "(   2.5.6.4     NAME   'organization'   DESC   'content rule for organization' OBSOLETE AUX ( pilotOrganization $  2.5.6.5 ) MUST ( objectClass $ o )     MAY    (    l   $   st   ) NOT (1.2.3.4.5.6.7.8.9.0 $ ou))" ) );
+
+        // lowercase NAME, DESC, AUX
+        assertTrue( checker
+            .isValidSyntax( "( 2.5.6.4 name 'organization' desc 'content rule for organization' aux ( pilotOrganization $  2.5.6.5 ) )" ) );
     }
 
+
     public void testInvalid()
     {
         // null 
         assertFalse( checker.isValidSyntax( null ) );
-        
+
         // empty 
         assertFalse( checker.isValidSyntax( "" ) );
-        
+
         // missing/invalid OID
         assertFalse( checker.isValidSyntax( "()" ) );
         assertFalse( checker.isValidSyntax( "(  )" ) );
@@ -71,13 +83,6 @@
 
         // missing right parenthesis
         assertFalse( checker.isValidSyntax( "( 2.5.6.4 NAME 'organization'" ) );
-
-        // missing quotes
-        assertFalse( checker.isValidSyntax( "( 2.5.6.4 NAME organization )" ) );
-
-        // lowercase NAME, DESC, AUX
-        assertFalse( checker.isValidSyntax( "( 2.5.6.4 name 'organization' desc 'content rule for organization' aux ( pilotOrganization $  2.5.6.5 ) )" ) );
-
     }
 
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxCheckerTest.java
index 38de770..e5bd2de 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/DITStructureRuleDescriptionSyntaxCheckerTest.java
@@ -35,28 +35,41 @@
 {
     private DITStructureRuleDescriptionSyntaxChecker checker = new DITStructureRuleDescriptionSyntaxChecker();
 
+
     public void testValid()
     {
         assertTrue( checker.isValidSyntax( "( 2 FORM 2.5.15.3 )" ) );
         assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' FORM 2.5.15.3 )" ) );
-        assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' FORM 2.5.15.3 )" ) );
-        assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 )" ) );
-        assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP 1 )" ) );
-        assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP ( 1 ) )" ) );
-        assertTrue( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP ( 1 1234567890 5 ) )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' FORM 2.5.15.3 )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP 1 )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP ( 1 ) )" ) );
+        assertTrue( checker
+            .isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' OBSOLETE FORM 2.5.15.3 SUP ( 1 1234567890 5 ) )" ) );
 
         assertTrue( checker.isValidSyntax( "(2 FORM 2.5.15.3)" ) );
-        assertTrue( checker.isValidSyntax( "(   2   NAME    'organization'    DESC    'organization structure rule'    OBSOLETE   FORM   2.5.15.3    SUP   (1 1234567890        5   ))" ) );
+        assertTrue( checker.isValidSyntax( "(2 NAME organization FORM 2.5.15.3)" ) );
+        assertTrue( checker
+            .isValidSyntax( "(   2   NAME    'organization'    DESC    'organization structure rule'    OBSOLETE   FORM   2.5.15.3    SUP   (1 1234567890        5   ))" ) );
+
+        // lowercase NAME, DESC, FORM
+        assertTrue( checker
+            .isValidSyntax( "( 2 name 'organization' desc 'organization structure rule' form 2.5.15.3 )" ) );
     }
 
+
     public void testInvalid()
     {
         // null 
         assertFalse( checker.isValidSyntax( null ) );
-        
+
         // empty 
         assertFalse( checker.isValidSyntax( "" ) );
-        
+
         // missing/invalid ruleid
         assertFalse( checker.isValidSyntax( "()" ) );
         assertFalse( checker.isValidSyntax( "(  )" ) );
@@ -69,12 +82,6 @@
         // missing right parenthesis
         assertFalse( checker.isValidSyntax( "( 2 FORM 2.5.15.3" ) );
 
-        // missing quotes
-        assertFalse( checker.isValidSyntax( "( 2 NAME organization FORM 2.5.15.3 )" ) );
-
-        // lowercase NAME, DESC, FORM
-        assertFalse( checker.isValidSyntax( "( 2 name 'organization' desc 'organization structure rule' form 2.5.15.3 )" ) );
-
         // missing FORM
         assertFalse( checker.isValidSyntax( "( 2 NAME 'organization' DESC 'organization structure rule' )" ) );
     }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxCheckerTest.java
index 71f71ec..dc8670c 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/LdapSyntaxDescriptionSyntaxCheckerTest.java
@@ -40,12 +40,16 @@
     {
         assertTrue( checker.isValidSyntax( ( "( 1.3.6.1.4.1.1466.115.121.1.15 )" ) ) );
         assertTrue( checker.isValidSyntax( ( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )" ) ) );
-        assertTrue( checker.isValidSyntax( ( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' X-ABC-DEF 'test' )" ) ) );
+        assertTrue( checker
+            .isValidSyntax( ( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' X-ABC-DEF 'test' )" ) ) );
 
         // spaces
         assertTrue( checker.isValidSyntax( "(1.3.6.1.4.1.1466.115.121.1.15)" ) );
-        assertTrue( checker.isValidSyntax( "(      1.3.6.1.4.1.1466.115.121.1.15        DESC 'Directory String' X-ABC-DEF     'test'     )" ) );
-        
+        assertTrue( checker
+            .isValidSyntax( "(      1.3.6.1.4.1.1466.115.121.1.15        DESC 'Directory String' X-ABC-DEF     'test'     )" ) );
+
+        // lowercase DESC
+        assertTrue( checker.isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 desc 'Directory String' )" ) );
     }
 
 
@@ -53,10 +57,10 @@
     {
         // null 
         assertFalse( checker.isValidSyntax( null ) );
-        
+
         // empty 
         assertFalse( checker.isValidSyntax( "" ) );
-        
+
         // missing/invalid OID
         assertFalse( checker.isValidSyntax( "()" ) );
         assertFalse( checker.isValidSyntax( "(  )" ) );
@@ -73,13 +77,11 @@
         // missing quotes
         assertFalse( checker.isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC Directory String )" ) );
 
-        // lowercase DESC
-        assertFalse( checker.isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 desc 'Directory String' )" ) );
-
         // invalid extension
         assertFalse( checker.isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' X-ABC-DEF )" ) );
-        assertFalse( checker.isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' X-ABC-123 'test' )" ) );
-        
+        assertFalse( checker
+            .isValidSyntax( "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' X-ABC-123 'test' )" ) );
+
     }
 
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxCheckerTest.java
index c053fed..e1999e1 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/MatchingRuleUseDescriptionSyntaxCheckerTest.java
@@ -40,13 +40,20 @@
     {
         assertTrue( checker.isValidSyntax( ( "( 2.5.13.17 APPLIES userPassword )" ) ) );
         assertTrue( checker.isValidSyntax( ( "( 2.5.13.17 APPLIES ( javaSerializedData $ userPassword ) )" ) ) );
-        assertTrue( checker.isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) )" ) ) );
-        assertTrue( checker.isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' DESC 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) )" ) ) );
-        assertTrue( checker.isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' DESC 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) X-ABC-DEF 'test' )" ) ) );
+        assertTrue( checker
+            .isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) )" ) ) );
+        assertTrue( checker
+            .isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' DESC 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) )" ) ) );
+        assertTrue( checker
+            .isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' DESC 'octetStringMatch' APPLIES ( javaSerializedData $ userPassword ) X-ABC-DEF 'test' )" ) ) );
 
         // spaces
         assertTrue( checker.isValidSyntax( ( "(2.5.13.17 APPLIES userPassword)" ) ) );
-        assertTrue( checker.isValidSyntax( ( "(   2.5.13.17   NAME   'octetStringMatch'   DESC   'octetStringMatch'   APPLIES   (javaSerializedData   $    userPassword)  X-ABC-DEF     'test'   )" ) ) );
+        assertTrue( checker
+            .isValidSyntax( ( "(   2.5.13.17   NAME   'octetStringMatch'   DESC   'octetStringMatch'   APPLIES   (javaSerializedData   $    userPassword)  X-ABC-DEF     'test'   )" ) ) );
+
+        // lowercase DESC
+        assertTrue( checker.isValidSyntax( "( 2.5.13.17 desc 'Directory String' APPLIES userPassword )" ) );
     }
 
 
@@ -54,10 +61,10 @@
     {
         // null 
         assertFalse( checker.isValidSyntax( null ) );
-        
+
         // empty 
         assertFalse( checker.isValidSyntax( "" ) );
-        
+
         // missing/invalid OID
         assertFalse( checker.isValidSyntax( "()" ) );
         assertFalse( checker.isValidSyntax( "(  )" ) );
@@ -74,13 +81,10 @@
         // missing quotes
         assertFalse( checker.isValidSyntax( "( 2.5.13.17 DESC Directory String APPLIES userPassword )" ) );
 
-        // lowercase DESC
-        assertFalse( checker.isValidSyntax( "( 2.5.13.17 desc 'Directory String' APPLIES userPassword )" ) );
-
         // invalid extension
         assertFalse( checker.isValidSyntax( "( 2.5.13.17 APPLIES userPassword X-ABC-DEF )" ) );
         assertFalse( checker.isValidSyntax( "( 2.5.13.17 APPLIES userPassword X-ABC-123 'test' )" ) );
-        
+
         // APPLIES is required
         assertFalse( checker.isValidSyntax( ( "( 2.5.13.17 NAME 'octetStringMatch' )" ) ) );
     }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxCheckerTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxCheckerTest.java
index 63fb945..4bd3da2 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxCheckerTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/ObjectClassDescriptionSyntaxCheckerTest.java
@@ -38,6 +38,7 @@
     public void testValid()
     {
         assertTrue( checker.isValidSyntax( "( 2.5.6.6 )" ) );
+        assertTrue( checker.isValidSyntax( "( 2.5.6.6 NAME person )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.6.6 NAME 'person' )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' )" ) );
         assertTrue( checker.isValidSyntax( "( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top )" ) );
@@ -71,9 +72,6 @@
         // missing right parenthesis
         assertFalse( checker.isValidSyntax( "( 2.5.6.6 NAME 'person'" ) );
 
-        // missing quotes
-        assertFalse( checker.isValidSyntax( "( 2.5.6.6 NAME person )" ) );
-
         // lowercase NAME, DESC, SUP
         assertFalse( checker.isValidSyntax( "( 2.5.6.6 name 'person' desc 'RFC2256: a person' sup top " ) );
 
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParserTest.java
index 007fb6c..f0bada2 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/AttributeTypeDescriptionSchemaParserTest.java
@@ -22,9 +22,11 @@
 
 import java.text.ParseException;
 
+import junit.framework.Assert;
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.ldap.schema.UsageEnum;
+import org.apache.directory.shared.ldap.schema.parser.ConsoleParserMonitor;
 import org.apache.directory.shared.ldap.schema.syntax.AttributeTypeDescription;
 
 
@@ -42,6 +44,7 @@
     protected void setUp() throws Exception
     {
         parser = new AttributeTypeDescriptionSchemaParser();
+        parser.setParserMonitor( new ConsoleParserMonitor() );
     }
 
 
@@ -115,34 +118,30 @@
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4.5.6.7.8.9.0", atd.getSuperType() );
 
-        // SUP descr
-        value = "( 1.1 SYNTAX 1.1 SUP abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        // SUP descr, no space
+        value = "(1.1 SYNTAX1.1 SUPabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789)";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getSuperType() );
 
-        // no quote allowed
-        value = "( 1.1 SYNTAX 1.1 SUP 'name' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid SUP 'name' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // SUP descr, newline
+        value = "\t(\t1.1\tSYNTAX\t1.1\tSUP\tabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789\t)\t";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getSuperType() );
 
-        // no quote allowed
+        // quoted SUP value
+        value = "( 1.1 SYNTAX 1.1 SUP 'name' )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "name", atd.getSuperType() );
+
+        // quoted SUP value
         value = "( 1.1 SYNTAX 1.1 SUP '1.2.3.4' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid SUP '1.2.3.4' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4", atd.getSuperType() );
+
+        // quoted SUP value
+        value = "( 1.1 SYNTAX 1.1 SUP ('1.2.3.4') )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4", atd.getSuperType() );
 
         // invalid character
         value = "( 1.1 SYNTAX 1.1 SUP 1.2.3.4.A )";
@@ -203,22 +202,25 @@
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getEqualityMatchingRule() );
 
-        // EQUALITY descr
-        value = "( 1.1 SYNTAX 1.1 EQUALITY abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        // EQUALITY descr, no space
+        value = "(1.1 SYNTAX1.1 EQUALITYabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789)";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getEqualityMatchingRule() );
 
-        // no quote allowed
+        // EQUALITY descr, newline
+        value = "\n(\n1.1\nSYNTAX\n1.1\nEQUALITY\nabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789\n)\n";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getEqualityMatchingRule() );
+
+        // quoted value
         value = "( 1.1 SYNTAX 1.1 EQUALITY 'caseExcactMatch' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid EQUALITY 'caseExcactMatch' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "caseExcactMatch", atd.getEqualityMatchingRule() );
+
+        // quote value in parentheses 
+        value = "( 1.1 SYNTAX 1.1 EQUALITY ('caseExcactMatch') )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "caseExcactMatch", atd.getEqualityMatchingRule() );
     }
 
 
@@ -233,32 +235,35 @@
         String value = null;
         AttributeTypeDescription atd = null;
 
-        // no EQUALITY
+        // no ORDERING
         value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getOrderingMatchingRule() );
 
-        // EQUALITY numericoid
+        // ORDERING numericoid
         value = "( 1.1 SYNTAX 1.1 ORDERING 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getOrderingMatchingRule() );
 
-        // EQUALITY descr
-        value = "( 1.1 SYNTAX 1.1 ORDERING abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        // ORDERING descr, no space
+        value = "(1.1 SYNTAX1.1 ORDERINGabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789)";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getOrderingMatchingRule() );
 
-        // no quote allowed
+        // ORDERING descr, newline
+        value = "\r(\r1.1\rSYNTAX\r1.1\rORDERING\rabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789\r)\r";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd.getOrderingMatchingRule() );
+
+        // quoted value
         value = "( 1.1 SYNTAX 1.1 ORDERING 'generalizedTimeOrderingMatch' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid ORDERING 'generalizedTimeOrderingMatch' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "generalizedTimeOrderingMatch", atd.getOrderingMatchingRule() );
+
+        // quote value in parentheses
+        value = "( 1.1 SYNTAX 1.1 ORDERING ('generalizedTimeOrderingMatch') )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "generalizedTimeOrderingMatch", atd.getOrderingMatchingRule() );
     }
 
 
@@ -273,33 +278,37 @@
         String value = null;
         AttributeTypeDescription atd = null;
 
-        // no EQUALITY
+        // no SUBSTR
         value = "( 1.1 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getSubstringsMatchingRule() );
 
-        // EQUALITY numericoid
+        // SUBSTR numericoid
         value = "( 1.1 SYNTAX 1.1 SUBSTR 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getSubstringsMatchingRule() );
 
-        // EQUALITY descr
-        value = "( 1.1 SYNTAX 1.1 SUBSTR abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789 )";
+        // SUBSTR descr, no space
+        value = "(1.1 SYNTAX1.1 SUBSTRabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789)";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd
             .getSubstringsMatchingRule() );
 
-        // no quote allowed
+        // SUBSTR descr, newline
+        value = "\r\n(\r\n1.1\r\nSYNTAX\r\n1.1\r\nSUBSTR\r\nabcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789\r\n)\r\n";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", atd
+            .getSubstringsMatchingRule() );
+
+        // quoted value
         value = "( 1.1 SYNTAX 1.1 SUBSTR 'caseIgnoreSubstringsMatch' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid SUBSTR 'caseIgnoreSubstringsMatch' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "caseIgnoreSubstringsMatch", atd.getSubstringsMatchingRule() );
+
+        // quote value in parentheses
+        value = "( 1.1 SYNTAX 1.1 SUBSTR ('caseIgnoreSubstringsMatch') )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "caseIgnoreSubstringsMatch", atd.getSubstringsMatchingRule() );
     }
 
 
@@ -319,37 +328,61 @@
         assertNull( atd.getSyntax() );
         assertEquals( 0, atd.getSyntaxLength() );
 
+        // SYNTAX string
+        value = "( 1.1 SYNTAX IA5String )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "IA5String", atd.getSyntax() );
+        assertEquals( 0, atd.getSyntaxLength() );
+
         // SYNTAX numericoid
         value = "( 1.1 SYNTAX 1.2.3.4567.8.9.0 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getSyntax() );
         assertEquals( 0, atd.getSyntaxLength() );
+        
+        // quoted numericoid
+        value = "( 1.1 SYNTAX '1.2.3.4567.8.9.0' )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4567.8.9.0", atd.getSyntax() );
+        assertEquals( 0, atd.getSyntaxLength() );
 
-        // SYNTAX numericoid and length
-        value = "( 1.1 SYNTAX 1.2.3.4567.8.9.0{1234567890} )";
+        // quoted numericoid
+        value = "( 1.1 SYNTAX ('1.2.3.4567.8.9.0') )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4567.8.9.0", atd.getSyntax() );
+        assertEquals( 0, atd.getSyntaxLength() );
+
+        // SYNTAX numericoid and length, no spaces
+        value = "(1.1 SYNTAX1.2.3.4567.8.9.0{1234567890})";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4567.8.9.0", atd.getSyntax() );
+        assertEquals( 1234567890, atd.getSyntaxLength() );
+
+        // SYNTAX, with tabs
+        value = "\t(\t1.1\tSYNTAX\t1.2.3.4567.8.9.0\t{1234567890}\t)\t";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3.4567.8.9.0", atd.getSyntax() );
         assertEquals( 1234567890, atd.getSyntaxLength() );
 
         // SYNTAX numericoid and zero length
-        value = "( 1.1 SYNTAX 1.2.3{0} )";
+        value = "( 1.1 SYNTAX 1.2.3 {0} )";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( "1.2.3", atd.getSyntax() );
         assertEquals( 0, atd.getSyntaxLength() );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 SYNTAX '1.2.3{32}' )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid SYNTAX '1.2.3{32}' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3", atd.getSyntax() );
+        assertEquals( 32, atd.getSyntaxLength() );
 
-        // empty syntax
+        // quote value in parentheses
+        value = "( 1.1 SYNTAX ( '1.2.3{32}' ) )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3", atd.getSyntax() );
+        assertEquals( 32, atd.getSyntaxLength() );
+
+        // empty length
         value = "( 1.1 SYNTAX 1.2.3.4{} )";
         try
         {
@@ -363,17 +396,11 @@
 
         // leading zero in length
         value = "( 1.1 SYNTAX 1.2.3.4{01} )";
-        try
-        {
-            atd = parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, invalid SYNTAX 1.2.3.4{01} (leading zero in length)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( "1.2.3.4", atd.getSyntax() );
+        assertEquals( 1, atd.getSyntaxLength() );
 
-        // invalid syntax
+        // invalid syntax length
         value = "( 1.1 SYNTAX 1.2.3.4{X} )";
         try
         {
@@ -437,7 +464,7 @@
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isSingleValued() );
 
-        // ivalid
+        // invalid
         value = "(1.1 SYNTAX 1.1 NAME 'test' DESC 'Descripton' SINGLE-VALU )";
         try
         {
@@ -554,17 +581,20 @@
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DIRECTORY_OPERATION, atd.getUsage() );
 
-        // AUXILIARY
-        value = "( 1.1 SYNTAX 1.1 USAGE distributedOperation )";
+        // distributedOperation, tabs
+        value = "\t(\t1.1\tSYNTAX\t1.1\tUSAGE\tdistributedOperation\t)\t";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DISTRIBUTED_OPERATION, atd.getUsage() );
 
-        // STRUCTURAL
-        value = "( 1.1 SYNTAX 1.1 USAGE dSAOperation )";
+        // dSAOperation, no space
+        value = "(1.1 SYNTAX1.1 USAGEdSAOperation)";
         atd = parser.parseAttributeTypeDescription( value );
         assertEquals( UsageEnum.DSA_OPERATION, atd.getUsage() );
 
-        // TODO: case insensitive?
+        // directoryOperation, case insensitivity
+        value = "( 1.1 SYNTAX 1.1 USAGE DiReCtOrYoPeRaTiOn )";
+        atd = parser.parseAttributeTypeDescription( value );
+        assertEquals( UsageEnum.DIRECTORY_OPERATION, atd.getUsage() );
 
         // ivalid
         value = "( 1.1 SYNTAX 1.1 USAGE abc )";
@@ -633,7 +663,7 @@
         assertEquals( "test2-2", atd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
 
-    
+
     /**
      * Test unique elements.
      * 
@@ -642,25 +672,18 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", 
-                "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", 
-                "( 1.1 SYNTAX 1.1 SUP test1 SUP test2 )",
-                "( 1.1 SYNTAX 1.1 EQUALITY test1 EQUALITY test2 )",
-                "( 1.1 SYNTAX 1.1 ORDERING test1 ORDERING test2 )",
-                "( 1.1 SYNTAX 1.1 SUBSTR test1 SUBSTR test2 )",
-                "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
-                "( 1.1 SYNTAX 1.1 SINGLE-VALUE SINGLE-VALUE )",
-                "( 1.1 SYNTAX 1.1 COLLECTIVE COLLECTIVE )", 
-                "( 1.1 SYNTAX 1.1 USAGE directoryOperation NO-USER-MODIFICATION NO-USER-MODIFICATION )", 
-                "( 1.1 SYNTAX 1.1 USAGE directoryOperation USAGE userApplications )", 
-                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", "( 1.1 SYNTAX 1.1 SUP test1 SUP test2 )",
+                "( 1.1 SYNTAX 1.1 EQUALITY test1 EQUALITY test2 )", "( 1.1 SYNTAX 1.1 ORDERING test1 ORDERING test2 )",
+                "( 1.1 SYNTAX 1.1 SUBSTR test1 SUBSTR test2 )", "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
+                "( 1.1 SYNTAX 1.1 SINGLE-VALUE SINGLE-VALUE )", "( 1.1 SYNTAX 1.1 COLLECTIVE COLLECTIVE )",
+                "( 1.1 SYNTAX 1.1 USAGE directoryOperation NO-USER-MODIFICATION NO-USER-MODIFICATION )",
+                "( 1.1 SYNTAX 1.1 USAGE directoryOperation USAGE userApplications )",
+                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
-    
-    
+
+
     /**
      * Test required elements.
      * 
@@ -675,30 +698,33 @@
         atd = parser.parseAttributeTypeDescription( value );
         assertNotNull( atd.getSyntax() );
         assertNotNull( atd.getSuperType() );
-        
+
         value = "( 1.2.3.4.5.6.7.8.9.0 SYNTAX 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNotNull( atd.getSyntax() );
         assertNull( atd.getSuperType() );
-        
+
         value = "( 1.2.3.4.5.6.7.8.9.0 SUP 1.1 )";
         atd = parser.parseAttributeTypeDescription( value );
         assertNull( atd.getSyntax() );
         assertNotNull( atd.getSuperType() );
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, SYNTAX or SUP is required" );
+            value = "( 1.2.3.4.5.6.7.8.9.0 )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, SYNTAX or SUP is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
     }
-    
+
+
     /**
      * Test collective constraint:
      * COLLECTIVE requires USAGE userApplications
@@ -713,49 +739,51 @@
         value = "( 1.1 SYNTAX 1.1 COLLECTIVE )";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isCollective() );
-        assertEquals( UsageEnum.USER_APPLICATIONS , atd.getUsage() );
-        
+        assertEquals( UsageEnum.USER_APPLICATIONS, atd.getUsage() );
+
         value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE userApplications )";
         atd = parser.parseAttributeTypeDescription( value );
         assertTrue( atd.isCollective() );
-        assertEquals( UsageEnum.USER_APPLICATIONS , atd.getUsage() );
-        
-        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE directoryOperation )";
-        try
+        assertEquals( UsageEnum.USER_APPLICATIONS, atd.getUsage() );
+
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+            value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE directoryOperation )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE dSAOperation )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE distributedOperation )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-        
-        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE dSAOperation )";
-        try
-        {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-        
-        value = "( 1.1 SYNTAX 1.1 COLLECTIVE USAGE distributedOperation )";
-        try
-        {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, COLLECTIVE requires USAGE userApplications" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-        
     }
-    
-    
+
+
     /**
      * Test no-user-modification constraint:
      * NO-USER-MODIFICATION requires an operational USAGE
@@ -766,46 +794,49 @@
     {
         String value = null;
         AttributeTypeDescription atd = null;
-        
+
         value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE directoryOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isUserModifiable() );
-        assertEquals( UsageEnum.DIRECTORY_OPERATION , atd.getUsage() );
-        
+        assertEquals( UsageEnum.DIRECTORY_OPERATION, atd.getUsage() );
+
         value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE dSAOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isUserModifiable() );
-        assertEquals( UsageEnum.DSA_OPERATION , atd.getUsage() );
-        
+        assertEquals( UsageEnum.DSA_OPERATION, atd.getUsage() );
+
         value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE distributedOperation )";
         atd = parser.parseAttributeTypeDescription( value );
         assertFalse( atd.isUserModifiable() );
-        assertEquals( UsageEnum.DISTRIBUTED_OPERATION , atd.getUsage() );
-        
-        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE userApplications )";
-        try
+        assertEquals( UsageEnum.DISTRIBUTED_OPERATION, atd.getUsage() );
+
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-        
-        value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION )";
-        try
-        {
-            parser.parseAttributeTypeDescription( value );
-            fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
+            value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION USAGE userApplications )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            value = "( 1.1 SYNTAX 1.1 NO-USER-MODIFICATION )";
+            try
+            {
+                parser.parseAttributeTypeDescription( value );
+                fail( "Exception expected, NO-USER-MODIFICATION requires an operational USAGE" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
-    
-    
+
+
     /**
      * Ensure that element order is ignored
      * 
@@ -861,13 +892,14 @@
         assertEquals( 0, atd.getExtensions().size() );
     }
 
+
     /**
      * Tests the parse of a simple AttributeType
      */
-    public void testAddAttributeType() throws Exception
+    public void testAddAttributeType() throws ParseException
     {
-        String substrate = "( 1.3.6.1.4.1.18060.0.4.0.2.10000 NAME ( 'bogus' 'bogusName' ) " +
-                "DESC 'bogus description' SUP name SINGLE-VALUE )";
+        String substrate = "( 1.3.6.1.4.1.18060.0.4.0.2.10000 NAME ( 'bogus' 'bogusName' ) "
+            + "DESC 'bogus description' SUP name SINGLE-VALUE )";
         AttributeTypeDescription desc = parser.parseAttributeTypeDescription( substrate );
         assertEquals( "1.3.6.1.4.1.18060.0.4.0.2.10000", desc.getNumericOid() );
         assertEquals( "bogus", desc.getNames().get( 0 ) );
@@ -877,14 +909,14 @@
         assertEquals( true, desc.isSingleValued() );
     }
 
-    
+
     /**
      * Tests the parse of a simple AttributeType with the schema extension.
      */
-    public void testAttributeTypeWithSchemaExtension() throws Exception
+    public void testAttributeTypeWithSchemaExtension() throws ParseException
     {
-        String substrate = "( 1.3.6.1.4.1.18060.0.4.0.2.10000 NAME ( 'bogus' 'bogusName' ) " +
-                "DESC 'bogus description' SUP name SINGLE-VALUE X-SCHEMA 'blah' )";
+        String substrate = "( 1.3.6.1.4.1.18060.0.4.0.2.10000 NAME ( 'bogus' 'bogusName' ) "
+            + "DESC 'bogus description' SUP name SINGLE-VALUE X-SCHEMA 'blah' )";
         AttributeTypeDescription desc = parser.parseAttributeTypeDescription( substrate );
         assertEquals( "1.3.6.1.4.1.18060.0.4.0.2.10000", desc.getNumericOid() );
         assertEquals( "bogus", desc.getNames().get( 0 ) );
@@ -893,13 +925,13 @@
         assertEquals( "name", desc.getSuperType() );
         assertEquals( true, desc.isSingleValued() );
         assertEquals( "blah", desc.getExtensions().get( "X-SCHEMA" ).get( 0 ) );
-    }    
-    
+    }
+
 
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -910,4 +942,88 @@
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "SYNTAX 1.1" );
+
+        try
+        {
+            String value = null;
+            AttributeTypeDescription atd = null;
+
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testObsolete();
+            testSuperType();
+            testEquality();
+            testOrdering();
+            testSubstring();
+            testSyntax();
+            testSingleValue();
+            testCollective();
+            testNoUserModification();
+            testUsage();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRequiredElements();
+            testCollecitveConstraint();
+            testNoUserModificatonConstraint();
+            testIgnoreElementOrder();
+            testRfcUid();
+            testAddAttributeType();
+            testMultiThreaded();
+
+            // NAME with special chars
+            value = "( 1.2.3 SYNTAX te_st NAME 't-e_s.t;' )";
+            atd = parser.parseAttributeTypeDescription( value );
+            Assert.assertEquals( 1, atd.getNames().size() );
+            Assert.assertEquals( "t-e_s.t;", atd.getNames().get( 0 ) );
+
+            // SYNTAX with underscore
+            value = "( 1.1 SYNTAX te_st )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "te_st", atd.getSyntax() );
+
+            // SUPERTYPE with underscore
+            value = "( 1.1 SYNTAX 1.1 SUP te_st )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "te_st", atd.getSuperType() );
+
+            // EQUALITY with underscore
+            value = "( 1.1 SYNTAX 1.1 EQUALITY te_st )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "te_st", atd.getEqualityMatchingRule() );
+
+            // SUBSTR with underscore
+            value = "( 1.1 SYNTAX 1.1 SUBSTR te_st )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "te_st", atd.getSubstringsMatchingRule() );
+
+            // ORDERING with underscore
+            value = "( 1.1 SYNTAX 1.1 ORDERING te_st )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "te_st", atd.getOrderingMatchingRule() );
+
+            // Netscape attribute 
+            value = "( nsAdminGroupName-oid NAME 'nsAdminGroupName' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape' )";
+            atd = parser.parseAttributeTypeDescription( value );
+            assertEquals( "nsAdminGroupName-oid", atd.getNumericOid() );
+            assertEquals( 1, atd.getNames().size() );
+            assertEquals( "nsAdminGroupName", atd.getNames().get( 0 ) );
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParserTest.java
index 6f49e68..212aedc 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ComparatorDescriptionSchemaParserTest.java
@@ -50,7 +50,7 @@
     }
 
 
-    public void testNumericOid() throws Exception
+    public void testNumericOid() throws ParseException
     {
         SchemaParserTestUtils.testNumericOid( parser, "FQCN org.apache.directory.SimpleComparator" );
     }
@@ -58,29 +58,25 @@
 
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils
-            .testDescription( parser, "1.1", "FQCN org.apache.directory.SimpleComparator" );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "FQCN org.apache.directory.SimpleComparator" );
     }
 
 
     public void testFqcn() throws ParseException
     {
-
         String value = null;
         ComparatorDescription cd = null;
 
-        // FQCN simple p
+        // FQCN simple
         value = "( 1.1 FQCN org.apache.directory.SimpleComparator )";
         cd = parser.parseComparatorDescription( value );
         assertNotNull( cd.getFqcn() );
         assertEquals( "org.apache.directory.SimpleComparator", cd.getFqcn() );
-
     }
 
 
     public void testBytecode() throws ParseException
     {
-
         String value = null;
         ComparatorDescription cd = null;
 
@@ -90,6 +86,17 @@
         assertNotNull( cd.getBytecode() );
         assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====", cd.getBytecode() );
 
+        // FQCN simple, no spaces
+        value = "(1.1 FQCNorg.apache.directory.SimpleComparator BYTECODEABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====)";
+        cd = parser.parseComparatorDescription( value );
+        assertNotNull( cd.getBytecode() );
+        assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====", cd.getBytecode() );
+
+        // FQCN simple, tabs
+        value = "\t(\t1.1\tFQCN\torg.apache.directory.SimpleComparator\tBYTECODE\tABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====\t)\t";
+        cd = parser.parseComparatorDescription( value );
+        assertNotNull( cd.getBytecode() );
+        assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====", cd.getBytecode() );
     }
 
 
@@ -101,6 +108,7 @@
 
     public void testFull()
     {
+        // TODO
     }
 
 
@@ -111,6 +119,7 @@
      */
     public void testUniqueElements()
     {
+        // TODO
     }
 
 
@@ -121,14 +130,44 @@
      */
     public void testRequiredElements()
     {
+        // TODO
     }
 
 
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
+        // TODO
+    }
+
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "FQCN org.apache.directory.SimpleComparator" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testDescription();
+            testFqcn();
+            testBytecode();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
     }
 
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParserTest.java
index edac76d..80a7e5b 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITContentRuleDescriptionSchemaParserTest.java
@@ -156,7 +156,7 @@
         assertEquals( "top2", dcrd.getAuxiliaryObjectClasses().get( 2 ) );
 
         // AUX multi mixed no space
-        value = "( 1.1 AUX (TOP-1$1.2.3.4$TOP-2) )";
+        value = "(1.1 AUX(TOP-1$1.2.3.4$TOP-2))";
         dcrd = parser.parseDITContentRuleDescription( value );
         assertEquals( 3, dcrd.getAuxiliaryObjectClasses().size() );
         assertEquals( "TOP-1", dcrd.getAuxiliaryObjectClasses().get( 0 ) );
@@ -173,27 +173,22 @@
 
         // no quote allowed
         value = "( 1.1 AUX 'top' )";
-        try
-        {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid AUX 'top' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        dcrd = parser.parseDITContentRuleDescription( value );
+        assertEquals( 1, dcrd.getAuxiliaryObjectClasses().size() );
+        assertEquals( "top", dcrd.getAuxiliaryObjectClasses().get( 0 ) );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 AUX '1.2.3.4' )";
-        try
-        {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid AUX '1.2.3.4' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        dcrd = parser.parseDITContentRuleDescription( value );
+        assertEquals( 1, dcrd.getAuxiliaryObjectClasses().size() );
+        assertEquals( "1.2.3.4", dcrd.getAuxiliaryObjectClasses().get( 0 ) );
+
+        // no $ separator
+        value = "( 1.1 AUX ( top1 top2 ) )";
+        dcrd = parser.parseDITContentRuleDescription( value );
+        assertEquals( 2, dcrd.getAuxiliaryObjectClasses().size() );
+        assertEquals( "top1", dcrd.getAuxiliaryObjectClasses().get( 0 ) );
+        assertEquals( "top2", dcrd.getAuxiliaryObjectClasses().get( 1 ) );
 
         // invalid character
         value = "( 1.1 AUX 1.2.3.4.A )";
@@ -207,30 +202,6 @@
             // expected
         }
 
-        // invalid start
-        value = "( 1.1 AUX ( top1 $ -top2 ) )";
-        try
-        {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid AUX '-top' (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // invalid separator
-        value = "( 1.1 AUX ( top1 top2 ) )";
-        try
-        {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid separator (no DOLLAR)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // empty AUX
         value = "( 1.1 AUX )";
         try
@@ -242,6 +213,21 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid start
+            value = "( 1.1 AUX ( top1 $ -top2 ) )";
+            try
+            {
+                dcrd = parser.parseDITContentRuleDescription( value );
+                fail( "Exception expected, invalid AUX '-top' (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -255,7 +241,7 @@
     {
         String value = null;
         DITContentRuleDescription dcrd = null;
-        
+
         // no MUST
         value = "( 1.1 )";
         dcrd = parser.parseDITContentRuleDescription( value );
@@ -268,7 +254,7 @@
         assertEquals( "1.2.3", dcrd.getMustAttributeTypes().get( 0 ) );
 
         // MUST mulitple
-        value = "(1.1 MUST (cn$sn       $11.22.33.44.55         $  objectClass   ))";
+        value = "(1.1 MUST (cn\rsn       $11.22.33.44.55            objectClass\t))";
         dcrd = parser.parseDITContentRuleDescription( value );
         assertEquals( 4, dcrd.getMustAttributeTypes().size() );
         assertEquals( "cn", dcrd.getMustAttributeTypes().get( 0 ) );
@@ -276,18 +262,6 @@
         assertEquals( "11.22.33.44.55", dcrd.getMustAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", dcrd.getMustAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 MUST ( c_n ) )";
-        try
-        {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // no MUST values
         value = "( 1.1 MUST )";
         try
@@ -299,6 +273,21 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid value
+            value = "( 1.1 MUST ( c_n ) )";
+            try
+            {
+                dcrd = parser.parseDITContentRuleDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -333,19 +322,23 @@
         assertEquals( "11.22.33.44.55", dcrd.getMayAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", dcrd.getMayAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 MAY ( c_n ) )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
+            // invalid value
+            value = "( 1.1 MAY ( c_n ) )";
+            try
+            {
+                dcrd = parser.parseDITContentRuleDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
 
+
     /**
      * Test NOT and its values.
      * Very similar to AUX, so here are less test cases. 
@@ -357,19 +350,19 @@
         String value = null;
         DITContentRuleDescription dcrd = null;
 
-        // no MAY
+        // no NOT
         value = "( 1.1 )";
         dcrd = parser.parseDITContentRuleDescription( value );
         assertEquals( 0, dcrd.getNotAttributeTypes().size() );
 
-        // MAY simple numericoid
+        // NOT simple numericoid
         value = "( 1.1 NOT 1.2.3 )";
         dcrd = parser.parseDITContentRuleDescription( value );
         assertEquals( 1, dcrd.getNotAttributeTypes().size() );
         assertEquals( "1.2.3", dcrd.getNotAttributeTypes().get( 0 ) );
 
-        // MAY mulitple
-        value = "(1.1 NOT (cn$sn       $11.22.33.44.55         $  objectClass   ))";
+        // NOT mulitple
+        value = "(1.1 NOT (cn\nsn\t$11.22.33.44.55         $  objectClass   ))";
         dcrd = parser.parseDITContentRuleDescription( value );
         assertEquals( 4, dcrd.getNotAttributeTypes().size() );
         assertEquals( "cn", dcrd.getNotAttributeTypes().get( 0 ) );
@@ -377,19 +370,22 @@
         assertEquals( "11.22.33.44.55", dcrd.getNotAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", dcrd.getNotAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 NOT ( c_n ) )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            dcrd = parser.parseDITContentRuleDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
+            // invalid value
+            value = "( 1.1 NOT ( c_n ) )";
+            try
+            {
+                dcrd = parser.parseDITContentRuleDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
-    
+
 
     /**
      * Test extensions.
@@ -449,7 +445,7 @@
         assertEquals( "test2-2", dcrd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
 
-    
+
     /**
      * Test unique elements.
      * 
@@ -458,24 +454,17 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 NAME 'test1' NAME 'test2' )", 
-                "( 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 OBSOLETE OBSOLETE )", 
-                "( 1.1 AUX test1 AUX test2 )",
-                "( 1.1 MUST test1 MUST test2 )",
-                "( 1.1 MAY test1 MAY test2 )",
-                "( 1.1 NOT test1 NOT test2 )",
-                "( 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 NAME 'test1' NAME 'test2' )", "( 1.1 DESC 'test1' DESC 'test2' )", "( 1.1 OBSOLETE OBSOLETE )",
+                "( 1.1 AUX test1 AUX test2 )", "( 1.1 MUST test1 MUST test2 )", "( 1.1 MAY test1 MAY test2 )",
+                "( 1.1 NOT test1 NOT test2 )", "( 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
-    
-    
+
+
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -487,4 +476,35 @@
 
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testDescription();
+            testObsolete();
+            testAux();
+            testMust();
+            testMay();
+            testNot();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParserTest.java
index f397742..cb2184a 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/DITStructureRuleDescriptionSchemaParserTest.java
@@ -196,29 +196,25 @@
         dsrd = parser.parseDITStructureRuleDescription( value );
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", dsrd.getForm() );
 
-        // no quote allowed
+        // descr, no space
+        value = "(1 FORMabc)";
+        dsrd = parser.parseDITStructureRuleDescription( value );
+        assertEquals( "abc", dsrd.getForm() );
+
+        // descr, tab
+        value = "\t(\t1\tFORM\tabc\t)\t";
+        dsrd = parser.parseDITStructureRuleDescription( value );
+        assertEquals( "abc", dsrd.getForm() );
+
+        // quoted value
         value = "( 1 FORM '1.2.3.4.5.6.7.8.9.0' )";
-        try
-        {
-            dsrd = parser.parseDITStructureRuleDescription( value );
-            fail( "Exception expected, invalid FORM '1.2.3.4.5.6.7.8.9.0' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        dsrd = parser.parseDITStructureRuleDescription( value );
+        assertEquals( "1.2.3.4.5.6.7.8.9.0", dsrd.getForm() );
 
         // no quote allowed
-        value = "( 1 FORM 'test' )";
-        try
-        {
-            dsrd = parser.parseDITStructureRuleDescription( value );
-            fail( "Exception expected, invalid FORM 'test' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        value = "( 1 FORM ('test') )";
+        dsrd = parser.parseDITStructureRuleDescription( value );
+        assertEquals( "test", dsrd.getForm() );
 
         // invalid character
         value = "( 1 FORM 1.2.3.4.A )";
@@ -232,19 +228,7 @@
             // expected
         }
 
-        // invalid start
-        value = "( 1 FORM -test ) )";
-        try
-        {
-            dsrd = parser.parseDITStructureRuleDescription( value );
-            fail( "Exception expected, invalid FORM '-test' (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // no multi value
+        // no multiple values
         value = "( 1 FORM ( test1 test2 ) )";
         try
         {
@@ -256,6 +240,20 @@
             // expected
         }
 
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid start
+            value = "( 1 FORM -test ) )";
+            try
+            {
+                dsrd = parser.parseDITStructureRuleDescription( value );
+                fail( "Exception expected, invalid FORM '-test' (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -287,7 +285,7 @@
         assertEquals( new Integer( 1 ), dsrd.getSuperRules().get( 0 ) );
 
         // SUP multi number
-        value = "( 1 FORM 1.1 SUP (12345 67890) )";
+        value = "( 1 FORM 1.1 SUP(12345 67890))";
         dsrd = parser.parseDITStructureRuleDescription( value );
         assertEquals( 2, dsrd.getSuperRules().size() );
         assertEquals( new Integer( 12345 ), dsrd.getSuperRules().get( 0 ) );
@@ -353,9 +351,9 @@
         assertTrue( dsrd.isObsolete() );
         assertEquals( "2.3.4.5.6.7.8.9.0.1", dsrd.getForm() );
         assertEquals( 3, dsrd.getSuperRules().size() );
-        assertEquals( new Integer(1), dsrd.getSuperRules().get( 0 ) );
-        assertEquals( new Integer(1234567890), dsrd.getSuperRules().get( 1 ) );
-        assertEquals( new Integer(5), dsrd.getSuperRules().get( 2 ) );
+        assertEquals( new Integer( 1 ), dsrd.getSuperRules().get( 0 ) );
+        assertEquals( new Integer( 1234567890 ), dsrd.getSuperRules().get( 1 ) );
+        assertEquals( new Integer( 5 ), dsrd.getSuperRules().get( 2 ) );
         assertEquals( 2, dsrd.getExtensions().size() );
         assertNotNull( dsrd.getExtensions().get( "X-TEST-a" ) );
         assertEquals( 2, dsrd.getExtensions().get( "X-TEST-a" ).size() );
@@ -367,7 +365,7 @@
         assertEquals( "test2-2", dsrd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
 
-    
+
     /**
      * Test unique elements.
      * 
@@ -376,18 +374,13 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1 FORM 1.1 NAME 'test1' NAME 'test2' )", 
-                "( 1 FORM 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1 FORM 1.1 OBSOLETE OBSOLETE )", 
-                "( 1 FORM 1.1 FORM test1 FORM test2 )",
-                "( 1 FORM 1.1 SUP 1 SUP 2 )",
-                "( 1 FORM 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1 FORM 1.1 NAME 'test1' NAME 'test2' )", "( 1 FORM 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1 FORM 1.1 OBSOLETE OBSOLETE )", "( 1 FORM 1.1 FORM test1 FORM test2 )",
+                "( 1 FORM 1.1 SUP 1 SUP 2 )", "( 1 FORM 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
-    
-    
+
+
     /**
      * Test required elements.
      * 
@@ -412,14 +405,14 @@
         {
             // expected
         }
-        
+
     }
 
 
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -431,4 +424,32 @@
 
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericRuleId();
+            testNames();
+            testDescription();
+            testObsolete();
+            testForm();
+            testSup();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParserTest.java
index 6ed7d6d..41b1dbc 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/LdapSyntaxDescriptionSchemaParserTest.java
@@ -62,6 +62,17 @@
 
 
     /**
+     * Tests NAMES
+     * 
+     * @throws ParseException
+     */
+    public void testNames() throws ParseException
+    {
+        SchemaParserTestUtils.testNames( parser, "1.1", "" );
+    }
+
+
+    /**
      * Tests DESC
      * 
      * @throws ParseException
@@ -107,7 +118,6 @@
         assertEquals( 2, lsd.getExtensions().get( "X-TEST-b" ).size() );
         assertEquals( "test2-1", lsd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
         assertEquals( "test2-2", lsd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
-
     }
 
 
@@ -119,13 +129,10 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 DESC 'test1' DESC 'test2' )", "( 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
-    
+
 
     ////////////////////////////////////////////////////////////////
     //         Some real-world attribute type definitions         //
@@ -144,11 +151,11 @@
         assertEquals( "TRUE", lsd.getExtensions().get( "X-NOT-HUMAN-READABLE" ).get( 0 ) );
     }
 
-    
+
     /**
      * Tests the parse of a simple AttributeType with the schema extension.
      */
-    public void testSyntaxWithExtensions() throws Exception
+    public void testSyntaxWithExtensions() throws ParseException
     {
         String substrate = "( 1.3.6.1.4.1.18060.0.4.0.2.10000 DESC 'bogus description' X-SCHEMA 'blah' X-IS-HUMAN-READABLE 'true' )";
         LdapSyntaxDescription desc = parser.parseLdapSyntaxDescription( substrate );
@@ -157,19 +164,47 @@
         assertNotNull( desc.getExtensions().get( "X-IS-HUMAN-READABLE" ) );
     }
 
-    
+
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 )", 
+            {
+                "( 1.1 )",
                 "( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
                 "( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' X-NOT-HUMAN-READABLE 'TRUE' )",
                 "( 1.2.3.4.5.6.7.8.9.0 DESC 'Descripton \u00E4\u00F6\u00FC\u00DF \u90E8\u9577' X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2') )" };
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRfcBinary();
+            testSyntaxWithExtensions();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParserTest.java
index e51a3ee..8fa17cc 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleDescriptionSchemaParserTest.java
@@ -37,6 +37,7 @@
     /** the parser instance */
     private MatchingRuleDescriptionSchemaParser parser;
 
+
     protected void setUp() throws Exception
     {
         parser = new MatchingRuleDescriptionSchemaParser();
@@ -49,13 +50,13 @@
     }
 
 
-    public void testNumericOid() throws Exception
+    public void testNumericOid() throws ParseException
     {
         SchemaParserTestUtils.testNumericOid( parser, "SYNTAX 1.1" );
     }
 
 
-    public void testNames() throws Exception
+    public void testNames() throws ParseException
     {
         SchemaParserTestUtils.testNames( parser, "1.1", "SYNTAX 1.1" );
     }
@@ -75,7 +76,6 @@
 
     public void testSyntax() throws ParseException
     {
-
         String value = null;
         MatchingRuleDescription mrd = null;
 
@@ -85,7 +85,7 @@
         assertEquals( "0.1.2.3.4.5.6.7.8.9", mrd.getSyntax() );
 
         // simple
-        value = "( 1.1 SYNTAX 123.456.789.0 )";
+        value = "(1.1 SYNTAX 123.456.789.0)";
         mrd = parser.parseMatchingRuleDescription( value );
         assertEquals( "123.456.789.0", mrd.getSyntax() );
 
@@ -94,31 +94,12 @@
         mrd = parser.parseMatchingRuleDescription( value );
         assertEquals( "0.1.2.3.4.5.6.7.8.9", mrd.getSyntax() );
 
-        // non-numeric not allowed
-        value = "( test )";
-        try
-        {
-            parser.parse( value );
-            fail( "Exception expected, invalid SYNTAX test" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // quoted value in parentheses
+        value = "( 1.1    SYNTAX ('0.1.2.3.4.5.6.7.8.9')    )";
+        mrd = parser.parseMatchingRuleDescription( value );
+        assertEquals( "0.1.2.3.4.5.6.7.8.9", mrd.getSyntax() );
 
-        // SYNTAX is required
-        value = "( 1.1 )";
-        try
-        {
-            mrd = parser.parseMatchingRuleDescription( value );
-            fail( "Exception expected, SYNTAX is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // OC must only appear once
+        // SYNTAX must only appear once
         value = "( 1.1 SYNTAX 2.2 SYNTAX 3.3 )";
         try
         {
@@ -129,7 +110,33 @@
         {
             assertTrue( true );
         }
-        
+
+        if ( !parser.isQuirksMode() )
+        {
+            // non-numeric not allowed
+            value = "( test )";
+            try
+            {
+                parser.parse( value );
+                fail( "Exception expected, SYNTAX is require" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // SYNTAX is required
+            value = "( 1.1 )";
+            try
+            {
+                mrd = parser.parseMatchingRuleDescription( value );
+                fail( "Exception expected, SYNTAX is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -164,8 +171,8 @@
         assertEquals( "test2-1", mrd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
         assertEquals( "test2-2", mrd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
     }
-    
-    
+
+
     /**
      * Test unique elements.
      * 
@@ -174,13 +181,9 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", 
-                "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", 
-                "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
-                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 SYNTAX 1.1 NAME 'test1' NAME 'test2' )", "( 1.1 SYNTAX 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 SYNTAX 1.1 OBSOLETE OBSOLETE )", "( 1.1 SYNTAX 1.1 SYNTAX 2.2 SYNTAX 3.3 )",
+                "( 1.1 SYNTAX 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
 
@@ -199,20 +202,22 @@
         mrd = parser.parseMatchingRuleDescription( value );
         assertNotNull( mrd.getSyntax() );
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseMatchingRuleDescription( value );
-            fail( "Exception expected, SYNTAX is required" );
+            value = "( 1.2.3.4.5.6.7.8.9.0 )";
+            try
+            {
+                parser.parseMatchingRuleDescription( value );
+                fail( "Exception expected, SYNTAX is required" );
+            }
+            catch ( ParseException pe )
+            {
+                assertTrue( true );
+            }
         }
-        catch ( ParseException pe )
-        {
-            assertTrue( true );
-        }
-
     }
-    
-    
+
+
     ////////////////////////////////////////////////////////////////
     //         Some real-world matching rule descriptons          //
     ////////////////////////////////////////////////////////////////
@@ -251,17 +256,31 @@
      * This is a real matching rule from Sun Directory 5.2. It has an invalid 
      * syntax, no DOTs allowed in NAME value. 
      */
-    public void testSun2()
+    public void testSun2() throws ParseException
     {
         String value = "( 1.3.6.1.4.1.42.2.27.9.4.34.3.6 NAME 'caseExactSubstringMatch-2.16.840.1.113730.3.3.2.11.3' DESC 'en' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseMatchingRuleDescription( value );
-            fail( "Exception expected, invalid NAME value 'caseExactSubstringMatch-2.16.840.1.113730.3.3.2.11.3' (contains DOTs)" );
+            try
+            {
+                parser.parseMatchingRuleDescription( value );
+                fail( "Exception expected, invalid NAME value 'caseExactSubstringMatch-2.16.840.1.113730.3.3.2.11.3' (contains DOTs)" );
+            }
+            catch ( ParseException pe )
+            {
+                assertTrue( true );
+            }
         }
-        catch ( ParseException pe )
+        else
         {
-            assertTrue( true );
+            MatchingRuleDescription mrd = parser.parseMatchingRuleDescription( value );
+            assertEquals( "1.3.6.1.4.1.42.2.27.9.4.34.3.6", mrd.getNumericOid() );
+            assertEquals( 1, mrd.getNames().size() );
+            assertEquals( "caseExactSubstringMatch-2.16.840.1.113730.3.3.2.11.3", mrd.getNames().get( 0 ) );
+            assertEquals( "en", mrd.getDescription() );
+            assertFalse( mrd.isObsolete() );
+            assertEquals( "1.3.6.1.4.1.1466.115.121.1.15", mrd.getSyntax() );
+            assertEquals( 0, mrd.getExtensions().size() );
         }
     }
 
@@ -269,7 +288,7 @@
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -280,4 +299,37 @@
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "SYNTAX 1.1" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testObsolete();
+            testSyntax();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRequiredElements();
+            testRfc1();
+            testSun1();
+            testSun2();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParserTest.java
index 4fa8041..1d6f14d 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/MatchingRuleUseDescriptionSchemaParserTest.java
@@ -50,13 +50,13 @@
     }
 
 
-    public void testNumericOid() throws Exception
+    public void testNumericOid() throws ParseException
     {
         SchemaParserTestUtils.testNumericOid( parser, "APPLIES 1.1" );
     }
 
 
-    public void testNames() throws Exception
+    public void testNames() throws ParseException
     {
         SchemaParserTestUtils.testNames( parser, "1.1", "APPLIES 1.1" );
     }
@@ -100,7 +100,7 @@
         assertEquals( "123.4567.890", mrud.getApplicableAttributes().get( 0 ) );
 
         // APPLIES single descr
-        value = "( 1.1 APPLIES ( a-z-A-Z-0-9 ) )";
+        value = "(1.1 APPLIES(a-z-A-Z-0-9))";
         mrud = parser.parseMatchingRuleUseDescription( value );
         assertEquals( 1, mrud.getApplicableAttributes().size() );
         assertEquals( "a-z-A-Z-0-9", mrud.getApplicableAttributes().get( 0 ) );
@@ -120,8 +120,8 @@
         assertEquals( "test1", mrud.getApplicableAttributes().get( 0 ) );
         assertEquals( "test2", mrud.getApplicableAttributes().get( 1 ) );
 
-        // APPLIES multi mixed
-        value = "( 1.1 APPLIES ( test1 $ 1.2.3.4 $ test2 ) )";
+        // APPLIES multi mixed, tabs
+        value = "\t(\t1.1\tAPPLIES\t(\ttest1\t$\t1.2.3.4\t$\ttest2\t)\t)\t";
         mrud = parser.parseMatchingRuleUseDescription( value );
         assertEquals( 3, mrud.getApplicableAttributes().size() );
         assertEquals( "test1", mrud.getApplicableAttributes().get( 0 ) );
@@ -129,7 +129,7 @@
         assertEquals( "test2", mrud.getApplicableAttributes().get( 2 ) );
 
         // APPLIES multi mixed no space
-        value = "( 1.1 APPLIES (TEST-1$1.2.3.4$TEST-2) )";
+        value = "(1.1 APPLIES(TEST-1$1.2.3.4$TEST-2))";
         mrud = parser.parseMatchingRuleUseDescription( value );
         assertEquals( 3, mrud.getApplicableAttributes().size() );
         assertEquals( "TEST-1", mrud.getApplicableAttributes().get( 0 ) );
@@ -144,29 +144,24 @@
         assertEquals( "1.2.3.4", mrud.getApplicableAttributes().get( 1 ) );
         assertEquals( "test2", mrud.getApplicableAttributes().get( 2 ) );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 APPLIES 'test' )";
-        try
-        {
-            mrud = parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, invalid APPLIES 'test' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        mrud = parser.parseMatchingRuleUseDescription( value );
+        assertEquals( 1, mrud.getApplicableAttributes().size() );
+        assertEquals( "test", mrud.getApplicableAttributes().get( 0 ) );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 APPLIES '1.2.3.4' )";
-        try
-        {
-            mrud = parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, invalid APPLIES '1.2.3.4' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        mrud = parser.parseMatchingRuleUseDescription( value );
+        assertEquals( 1, mrud.getApplicableAttributes().size() );
+        assertEquals( "1.2.3.4", mrud.getApplicableAttributes().get( 0 ) );
+
+        // no $ separator
+        value = "( 1.1 APPLIES ( test1 test2 ) )";
+        mrud = parser.parseMatchingRuleUseDescription( value );
+        assertEquals( 2, mrud.getApplicableAttributes().size() );
+        assertEquals( "test1", mrud.getApplicableAttributes().get( 0 ) );
+        assertEquals( "test2", mrud.getApplicableAttributes().get( 1 ) );
 
         // invalid character
         value = "( 1.1 APPLIES 1.2.3.4.A )";
@@ -180,30 +175,6 @@
             // expected
         }
 
-        // invalid start
-        value = "( 1.1 APPLIES ( test1 $ -test2 ) )";
-        try
-        {
-            mrud = parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, invalid APPLIES '-test' (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // invalid separator
-        value = "( 1.1 APPLIES ( test1 test2 ) )";
-        try
-        {
-            mrud = parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, invalid separator (no DOLLAR)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // empty APPLIES
         value = "( 1.1 APPLIES )";
         try
@@ -215,18 +186,6 @@
         {
             // expected
         }
-        
-        // APPLIES is required
-        value = "( 1.1 )";
-        try
-        {
-            mrud = parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, APPLIES is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
 
         // APPLIES must only appear once
         value = "( 1.1 APPLIES test1 APPLIES test2 )";
@@ -239,6 +198,33 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // APPLIES is required
+            value = "( 1.1 )";
+            try
+            {
+                mrud = parser.parseMatchingRuleUseDescription( value );
+                fail( "Exception expected, APPLIES is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // invalid start
+            value = "( 1.1 APPLIES ( test1 $ -test2 ) )";
+            try
+            {
+                mrud = parser.parseMatchingRuleUseDescription( value );
+                fail( "Exception expected, invalid APPLIES '-test' (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -286,17 +272,13 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 APPLIES 1.1 NAME 'test1' NAME 'test2' )",
-                "( 1.1 APPLIES 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 APPLIES 1.1 OBSOLETE OBSOLETE )", 
-                "( 1.1 APPLIES 1.1 APPLIES test1 APPLIES test2 )",
-                "( 1.1 APPLIES 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 APPLIES 1.1 NAME 'test1' NAME 'test2' )", "( 1.1 APPLIES 1.1 DESC 'test1' DESC 'test2' )",
+                "( 1.1 APPLIES 1.1 OBSOLETE OBSOLETE )", "( 1.1 APPLIES 1.1 APPLIES test1 APPLIES test2 )",
+                "( 1.1 APPLIES 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
-    }    
-    
-    
+    }
+
+
     /**
      * Test required elements.
      * 
@@ -311,20 +293,22 @@
         mrud = parser.parseMatchingRuleUseDescription( value );
         assertEquals( 1, mrud.getApplicableAttributes().size() );
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parseMatchingRuleUseDescription( value );
-            fail( "Exception expected, APPLIES is required" );
+            value = "( 1.2.3.4.5.6.7.8.9.0 )";
+            try
+            {
+                parser.parseMatchingRuleUseDescription( value );
+                fail( "Exception expected, APPLIES is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
     }
-    
-    
+
+
     ////////////////////////////////////////////////////////////////
     //       Some real-world matching rule use descriptons        //
     ////////////////////////////////////////////////////////////////
@@ -349,7 +333,7 @@
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -360,4 +344,35 @@
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "APPLIES 1.1" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testObsolete();
+            testApplies();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRequiredElements();
+            testOpenldap1();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParserTest.java
index 56b02a1..4930872 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NameFormDescriptionSchemaParserTest.java
@@ -120,29 +120,15 @@
         assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", nfd
             .getStructuralObjectClass() );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 MUST m OC '1.2.3.4.5.6.7.8.9.0' )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, invalid FORM '1.2.3.4.5.6.7.8.9.0' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        nfd = parser.parseNameFormDescription( value );
+        assertEquals( "1.2.3.4.5.6.7.8.9.0", nfd.getStructuralObjectClass() );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 MUST m OC 'test' )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, invalid OC 'test' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        nfd = parser.parseNameFormDescription( value );
+        assertEquals( "test", nfd.getStructuralObjectClass() );
 
         // invalid character
         value = "( 1.1 MUST m OC 1.2.3.4.A )";
@@ -156,18 +142,6 @@
             // expected
         }
 
-        // invalid start
-        value = "( 1.1 MUST m OC -test ) )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, invalid OC '-test' (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // no multi value allowed
         value = "( 1.1 MUST m OC ( test1 test2 ) )";
         try
@@ -180,18 +154,6 @@
             // expected
         }
 
-        // OC is required
-        value = "( 1.1 MUST m )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, OC is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // OC must only appear once
         value = "( 1.1 MUST m OC test1 OC test2 )";
         try
@@ -204,6 +166,32 @@
             // expected
         }
 
+        if ( !parser.isQuirksMode() )
+        {
+            // OC is required
+            value = "( 1.1 MUST m )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, OC is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // invalid start
+            value = "( 1.1 MUST m OC -test ) )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, invalid OC '-test' (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -232,18 +220,6 @@
         assertEquals( "11.22.33.44.55", nfd.getMustAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", nfd.getMustAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 OC o MUST ( c_n ) )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // no MUST values
         value = "( 1.1 OC o MUST )";
         try
@@ -256,18 +232,6 @@
             // expected
         }
 
-        // MUST is required
-        value = "( 1.1 OC o )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, MUST is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // MUST must only appear once
         value = "( 1.1 OC o MUST test1 MUST test2 )";
         try
@@ -279,6 +243,33 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // MUST is required
+            value = "( 1.1 OC o )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, MUST is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // invalid value
+            value = "( 1.1 OC o MUST ( c_n ) )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -312,18 +303,6 @@
         assertEquals( "11.22.33.44.55", nfd.getMayAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", nfd.getMayAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 OC o MUST m MAY ( c_n ) )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // MAY must only appear once
         value = "( 1.1 OC o MUST m MAY test1 MAY test2 )";
         try
@@ -336,6 +315,20 @@
             // expected
         }
 
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid value
+            value = "( 1.1 OC o MUST m MAY ( c_n ) )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -400,15 +393,10 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 OC o MUST m NAME 'test1' NAME 'test2' )", 
-                "( 1.1 OC o MUST m DESC 'test1' DESC 'test2' )",
-                "( 1.1 OC o MUST m OBSOLETE OBSOLETE )", 
-                "( 1.1 OC o MUST m OC test1 OC test2 )",
-                "( 1.1 OC o MUST m MUST test1 MUST test2 )",
-                "( 1.1 OC o MUST m MAY test1 MAY test2 )",
-                "( 1.1 OC o MUST m X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 OC o MUST m NAME 'test1' NAME 'test2' )", "( 1.1 OC o MUST m DESC 'test1' DESC 'test2' )",
+                "( 1.1 OC o MUST m OBSOLETE OBSOLETE )", "( 1.1 OC o MUST m OC test1 OC test2 )",
+                "( 1.1 OC o MUST m MUST test1 MUST test2 )", "( 1.1 OC o MUST m MAY test1 MAY test2 )",
+                "( 1.1 OC o MUST m X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
 
@@ -428,76 +416,78 @@
         assertNotNull( nfd.getStructuralObjectClass() );
         assertEquals( 1, nfd.getMustAttributeTypes().size() );
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 MUST m )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, OC is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+            value = "( 1.2.3.4.5.6.7.8.9.0 MUST m )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, OC is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
 
-        value = "( 1.2.3.4.5.6.7.8.9.0 OC o )";
-        try
-        {
-            nfd = parser.parseNameFormDescription( value );
-            fail( "Exception expected, MUST is required" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
+            value = "( 1.2.3.4.5.6.7.8.9.0 OC o )";
+            try
+            {
+                nfd = parser.parseNameFormDescription( value );
+                fail( "Exception expected, MUST is required" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
 
 
-//    /**
-//     * Test if MUST and MAY are disjoint.
-//     * 
-//     * Problem: What if MUST is a numeric oid and MAY is a name?
-//     * 
-//     * @throws ParseException
-//     */
-//    public void testDisjoint() throws ParseException
-//    {
-//        String value = null;
-//        NameFormDescription nfd = null;
-//
-//        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST test1 MAY test2 )";
-//        nfd = parser.parseNameFormDescription( value );
-//        assertNotNull( nfd.getStructuralObjectClass() );
-//        assertEquals( 1, nfd.getMustAttributeTypes().size() );
-//
-//        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST test1 MAY test1 )";
-//        try
-//        {
-//            nfd = parser.parseNameFormDescription( value );
-//            fail( "Exception expected, MUST and MAY must be disjoint" );
-//        }
-//        catch ( ParseException pe )
-//        {
-//            // expected
-//        }
-//
-//        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST ( test1 $ test2 ) MAY ( test4 $ test3 $ test2 ) )";
-//        try
-//        {
-//            nfd = parser.parseNameFormDescription( value );
-//            fail( "Exception expected, MUST and MAY must be disjoint" );
-//        }
-//        catch ( ParseException pe )
-//        {
-//            // expected
-//        }
-//
-//    }
-
+    //    /**
+    //     * Test if MUST and MAY are disjoint.
+    //     * 
+    //     * Problem: What if MUST is a numeric oid and MAY is a name?
+    //     * 
+    //     * @throws ParseException
+    //     */
+    //    public void testDisjoint() throws ParseException
+    //    {
+    //        String value = null;
+    //        NameFormDescription nfd = null;
+    //
+    //        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST test1 MAY test2 )";
+    //        nfd = parser.parseNameFormDescription( value );
+    //        assertNotNull( nfd.getStructuralObjectClass() );
+    //        assertEquals( 1, nfd.getMustAttributeTypes().size() );
+    //
+    //        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST test1 MAY test1 )";
+    //        try
+    //        {
+    //            nfd = parser.parseNameFormDescription( value );
+    //            fail( "Exception expected, MUST and MAY must be disjoint" );
+    //        }
+    //        catch ( ParseException pe )
+    //        {
+    //            // expected
+    //        }
+    //
+    //        value = "( 1.2.3.4.5.6.7.8.9.0 OC o MUST ( test1 $ test2 ) MAY ( test4 $ test3 $ test2 ) )";
+    //        try
+    //        {
+    //            nfd = parser.parseNameFormDescription( value );
+    //            fail( "Exception expected, MUST and MAY must be disjoint" );
+    //        }
+    //        catch ( ParseException pe )
+    //        {
+    //            // expected
+    //        }
+    //
+    //    }
 
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -509,4 +499,36 @@
 
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "OC o MUST m" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testObsolete();
+            testOc();
+            testMust();
+            testMay();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRequiredElements();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParserTest.java
index efa652e..ae9e220 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/NormalizerDescriptionSchemaParserTest.java
@@ -50,37 +50,33 @@
     }
 
 
-    public void testNumericOid() throws Exception
+    public void testNumericOid() throws ParseException
     {
-        SchemaParserTestUtils.testNumericOid( parser, "FQCN org.apache.directory.SimpleComparator" );
+        SchemaParserTestUtils.testNumericOid( parser, "FQCN org.apache.directory.SimpleNormalizer" );
     }
 
 
     public void testDescription() throws ParseException
     {
-        SchemaParserTestUtils
-            .testDescription( parser, "1.1", "FQCN org.apache.directory.SimpleComparator" );
+        SchemaParserTestUtils.testDescription( parser, "1.1", "FQCN org.apache.directory.SimpleNormalizer" );
     }
 
 
     public void testFqcn() throws ParseException
     {
-
         String value = null;
         NormalizerDescription nd = null;
 
         // FQCN simple p
-        value = "( 1.1 FQCN org.apache.directory.SimpleComparator )";
+        value = "( 1.1 FQCN org.apache.directory.SimpleNormalizer )";
         nd = parser.parseNormalizerDescription( value );
         assertNotNull( nd.getFqcn() );
-        assertEquals( "org.apache.directory.SimpleComparator", nd.getFqcn() );
-
+        assertEquals( "org.apache.directory.SimpleNormalizer", nd.getFqcn() );
     }
 
 
     public void testBytecode() throws ParseException
     {
-
         String value = null;
         NormalizerDescription nd = null;
 
@@ -89,18 +85,18 @@
         nd = parser.parseNormalizerDescription( value );
         assertNotNull( nd.getBytecode() );
         assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====", nd.getBytecode() );
-
     }
 
 
     public void testExtensions() throws ParseException
     {
-        SchemaParserTestUtils.testExtensions( parser, "1.1", "FQCN org.apache.directory.SimpleComparator" );
+        SchemaParserTestUtils.testExtensions( parser, "1.1", "FQCN org.apache.directory.SimpleNormalizer" );
     }
 
 
     public void testFull()
     {
+        // TODO
     }
 
 
@@ -111,6 +107,7 @@
      */
     public void testUniqueElements()
     {
+        // TODO
     }
 
 
@@ -121,14 +118,44 @@
      */
     public void testRequiredElements()
     {
+        // TODO
     }
 
 
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
+        // TODO
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "FQCN org.apache.directory.SimpleNormalizer" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testDescription();
+            testFqcn();
+            testBytecode();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testRequiredElements();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParserTest.java
index 861dc96..f9139fd 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/ObjectClassDescriptionSchemaParserTest.java
@@ -22,6 +22,7 @@
 
 import java.text.ParseException;
 
+import junit.framework.Assert;
 import junit.framework.TestCase;
 
 import org.apache.directory.shared.ldap.schema.ObjectClassTypeEnum;
@@ -148,16 +149,16 @@
         assertEquals( "top1", ocd.getSuperiorObjectClasses().get( 0 ) );
         assertEquals( "top2", ocd.getSuperiorObjectClasses().get( 1 ) );
 
-        // SUP multi mixed
-        value = "( 1.1 SUP ( top1 $ 1.2.3.4 $ top2 ) )";
+        // SUP multi mixed, tabs
+        value = "\t(\t1.1\tSUP\t(\ttop1\t$\t1.2.3.4\t$\ttop2\t)\t)\t";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( 3, ocd.getSuperiorObjectClasses().size() );
         assertEquals( "top1", ocd.getSuperiorObjectClasses().get( 0 ) );
         assertEquals( "1.2.3.4", ocd.getSuperiorObjectClasses().get( 1 ) );
         assertEquals( "top2", ocd.getSuperiorObjectClasses().get( 2 ) );
 
-        // SUP multi mixed no space
-        value = "( 1.1 SUP (TOP-1$1.2.3.4$TOP-2) )";
+        // SUP multi mixed, no space
+        value = "(1.1 SUP(TOP-1$1.2.3.4$TOP-2))";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( 3, ocd.getSuperiorObjectClasses().size() );
         assertEquals( "TOP-1", ocd.getSuperiorObjectClasses().get( 0 ) );
@@ -172,29 +173,24 @@
         assertEquals( "1.2.3.4", ocd.getSuperiorObjectClasses().get( 1 ) );
         assertEquals( "top2", ocd.getSuperiorObjectClasses().get( 2 ) );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 SUP 'top' )";
-        try
-        {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid SUP 'top' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( 1, ocd.getSuperiorObjectClasses().size() );
+        assertEquals( "top", ocd.getSuperiorObjectClasses().get( 0 ) );
 
-        // no quote allowed
+        // quoted value
         value = "( 1.1 SUP '1.2.3.4' )";
-        try
-        {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid SUP '1.2.3.4' (quoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( 1, ocd.getSuperiorObjectClasses().size() );
+        assertEquals( "1.2.3.4", ocd.getSuperiorObjectClasses().get( 0 ) );
+
+        // no $ separator
+        value = "( 1.1 SUP ( top1 top2 ) )";
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( 2, ocd.getSuperiorObjectClasses().size() );
+        assertEquals( "top1", ocd.getSuperiorObjectClasses().get( 0 ) );
+        assertEquals( "top2", ocd.getSuperiorObjectClasses().get( 1 ) );
 
         // invalid character
         value = "( 1.1 SUP 1.2.3.4.A )";
@@ -208,30 +204,6 @@
             // expected
         }
 
-        // invalid start
-        value = "( 1.1 SUP ( top1 $ -top2 ) )";
-        try
-        {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid SUP '-top' (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // invalid separator
-        value = "( 1.1 SUP ( top1 top2 ) )";
-        try
-        {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid separator (no DOLLAR)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
         // empty sup
         value = "( 1.1 SUP )";
         try
@@ -243,6 +215,21 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid start
+            value = "( 1.1 SUP ( top1 $ -top2 ) )";
+            try
+            {
+                ocd = parser.parseObjectClassDescription( value );
+                fail( "Exception expected, invalid SUP '-top' (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -266,17 +253,22 @@
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( ObjectClassTypeEnum.ABSTRACT, ocd.getKind() );
 
-        // AUXILIARY
-        value = "( 1.1 AUXILIARY )";
+        // AUXILIARY, tab
+        value = "\t(\t1.1\tAUXILIARY\t)\t";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( ObjectClassTypeEnum.AUXILIARY, ocd.getKind() );
 
-        // STRUCTURAL
-        value = "( 1.1 STRUCTURAL )";
+        // STRUCTURAL, no space
+        value = "(1.1 STRUCTURAL)";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( ObjectClassTypeEnum.STRUCTURAL, ocd.getKind() );
 
-        // ivalid
+        // STRUCTURAL, case-insensitive
+        value = "(1.1 sTrUcTuRaL )";
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( ObjectClassTypeEnum.STRUCTURAL, ocd.getKind() );
+
+        // invalid
         value = "( 1.1 FOO )";
         try
         {
@@ -312,8 +304,8 @@
         assertEquals( 1, ocd.getMustAttributeTypes().size() );
         assertEquals( "1.2.3", ocd.getMustAttributeTypes().get( 0 ) );
 
-        // MUST mulitple
-        value = "(1.1 MUST (cn$sn       $11.22.33.44.55         $  objectClass   ))";
+        // MUST multiple
+        value = "(1.1 MUST(cn$sn\r$11.22.33.44.55         $  objectClass   ))";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( 4, ocd.getMustAttributeTypes().size() );
         assertEquals( "cn", ocd.getMustAttributeTypes().get( 0 ) );
@@ -321,17 +313,14 @@
         assertEquals( "11.22.33.44.55", ocd.getMustAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", ocd.getMustAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 MUST ( c_n ) )";
-        try
-        {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // MUST multiple, no $ separator
+        value = "(1.1 MUST(cn sn\t'11.22.33.44.55'\n'objectClass'))";
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( 4, ocd.getMustAttributeTypes().size() );
+        assertEquals( "cn", ocd.getMustAttributeTypes().get( 0 ) );
+        assertEquals( "sn", ocd.getMustAttributeTypes().get( 1 ) );
+        assertEquals( "11.22.33.44.55", ocd.getMustAttributeTypes().get( 2 ) );
+        assertEquals( "objectClass", ocd.getMustAttributeTypes().get( 3 ) );
 
         // no MUST values
         value = "( 1.1 MUST )";
@@ -344,6 +333,21 @@
         {
             // expected
         }
+
+        if ( !parser.isQuirksMode() )
+        {
+            // invalid value
+            value = "( 1.1 MUST ( c_n ) )";
+            try
+            {
+                ocd = parser.parseObjectClassDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+        }
     }
 
 
@@ -369,8 +373,8 @@
         assertEquals( 1, ocd.getMayAttributeTypes().size() );
         assertEquals( "1.2.3", ocd.getMayAttributeTypes().get( 0 ) );
 
-        // MAY mulitple
-        value = "(1.1 MAY (cn$sn       $11.22.33.44.55         $  objectClass   ))";
+        // MAY multiple
+        value = "(1.1 MAY(cn$sn       $11.22.33.44.55\n$  objectClass   ))";
         ocd = parser.parseObjectClassDescription( value );
         assertEquals( 4, ocd.getMayAttributeTypes().size() );
         assertEquals( "cn", ocd.getMayAttributeTypes().get( 0 ) );
@@ -378,16 +382,28 @@
         assertEquals( "11.22.33.44.55", ocd.getMayAttributeTypes().get( 2 ) );
         assertEquals( "objectClass", ocd.getMayAttributeTypes().get( 3 ) );
 
-        // invalid value
-        value = "( 1.1 MAY ( c_n ) )";
-        try
+        // MAY multiple, no $ separator, quoted
+        value = "(1.1 MAY('cn' sn\t'11.22.33.44.55'\nobjectClass))";
+        ocd = parser.parseObjectClassDescription( value );
+        assertEquals( 4, ocd.getMayAttributeTypes().size() );
+        assertEquals( "cn", ocd.getMayAttributeTypes().get( 0 ) );
+        assertEquals( "sn", ocd.getMayAttributeTypes().get( 1 ) );
+        assertEquals( "11.22.33.44.55", ocd.getMayAttributeTypes().get( 2 ) );
+        assertEquals( "objectClass", ocd.getMayAttributeTypes().get( 3 ) );
+
+        if ( !parser.isQuirksMode() )
         {
-            ocd = parser.parseObjectClassDescription( value );
-            fail( "Exception expected, invalid value c_n" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
+            // invalid value
+            value = "( 1.1 MAY ( c_n ) )";
+            try
+            {
+                ocd = parser.parseObjectClassDescription( value );
+                fail( "Exception expected, invalid value c_n" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
 
@@ -456,23 +472,14 @@
     public void testUniqueElements()
     {
         String[] testValues = new String[]
-            { 
-                "( 1.1 NAME 'test1' NAME 'test2' )", 
-                "( 1.1 DESC 'test1' DESC 'test2' )",
-                "( 1.1 OBSOLETE OBSOLETE )", 
-                "( 1.1 SUP test1 SUP test2 )",
-                "( 1.1 STRUCTURAL STRUCTURAL )",
-                "( 1.1 ABSTRACT ABSTRACT )",
-                "( 1.1 AUXILIARY AUXILIARY )",
-                "( 1.1 STRUCTURAL AUXILIARY AUXILIARY )",
-                "( 1.1 MUST test1 MUST test2 )",
-                "( 1.1 MAY test1 MAY test2 )",
-                "( 1.1 X-TEST 'test1' X-TEST 'test2' )" 
-            };
+            { "( 1.1 NAME 'test1' NAME 'test2' )", "( 1.1 DESC 'test1' DESC 'test2' )", "( 1.1 OBSOLETE OBSOLETE )",
+                "( 1.1 SUP test1 SUP test2 )", "( 1.1 STRUCTURAL STRUCTURAL )", "( 1.1 ABSTRACT ABSTRACT )",
+                "( 1.1 AUXILIARY AUXILIARY )", "( 1.1 STRUCTURAL AUXILIARY AUXILIARY )",
+                "( 1.1 MUST test1 MUST test2 )", "( 1.1 MAY test1 MAY test2 )", "( 1.1 X-TEST 'test1' X-TEST 'test2' )" };
         SchemaParserTestUtils.testUnique( parser, testValues );
     }
-    
-    
+
+
     /**
      * Ensure that element order is ignored
      * 
@@ -728,9 +735,9 @@
 
 
     /**
-     * Tests the multithreaded use of a single parser.
+     * Tests the multi-threaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         String[] testValues = new String[]
             {
@@ -740,4 +747,80 @@
                 "( 2.16.840.1.113719.1.1.6.1.30 NAME 'List' SUP Top STRUCTURAL MUST cn MAY ( description $ l $ member $ ou $ o $ eMailAddress $ mailboxLocation $ mailboxID $ owner $ seeAlso $ fullName ) X-NDS_NAMING 'cn' X-NDS_CONTAINMENT ( 'Organization' 'organizationalUnit' 'domain' ) X-NDS_NOT_CONTAINER '1' X-NDS_NONREMOVABLE '1' X-NDS_ACL_TEMPLATES '2#entry#[Root Template]#member' )" };
         SchemaParserTestUtils.testMultiThreaded( parser, testValues );
     }
+
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "" );
+
+        try
+        {
+            String value = null;
+            ObjectClassDescription ocd = null;
+
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testNames();
+            testDescription();
+            testObsolete();
+            testSuperior();
+            testKind();
+            testMust();
+            testMay();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testIgnoreElementOrder();
+            testRfcTop();
+            testRfcSimpleSecurityObject();
+            testSunAlias();
+            testNovellDcObject();
+            testNovellList();
+            testMicrosoftAds2000Locality();
+            testMicrosoftAds2003Msieee();
+            testSiemensDirxX500Subschema();
+            testMultiThreaded();
+
+            // NAME with special chars
+            value = "( 1.2.3 NAME 't-e_s.t;' )";
+            ocd = parser.parseObjectClassDescription( value );
+            Assert.assertEquals( 1, ocd.getNames().size() );
+            Assert.assertEquals( "t-e_s.t;", ocd.getNames().get( 0 ) );
+
+            // SUP with underscore
+            value = "( 1.1 SUP te_st )";
+            ocd = parser.parseObjectClassDescription( value );
+            assertEquals( 1, ocd.getSuperiorObjectClasses().size() );
+            assertEquals( "te_st", ocd.getSuperiorObjectClasses().get( 0 ) );
+
+            // MAY with underscore
+            value = "( 1.1 MAY te_st )";
+            ocd = parser.parseObjectClassDescription( value );
+            assertEquals( 1, ocd.getMayAttributeTypes().size() );
+            assertEquals( "te_st", ocd.getMayAttributeTypes().get( 0 ) );
+
+            // MUST with underscore
+            value = "( 1.1 MUST te_st )";
+            ocd = parser.parseObjectClassDescription( value );
+            assertEquals( 1, ocd.getMustAttributeTypes().size() );
+            assertEquals( "te_st", ocd.getMustAttributeTypes().get( 0 ) );
+
+            // Netscape object class 
+            value = "( nsAdminGroup-oid NAME 'nsAdminGroup' DESC 'Netscape defined objectclass' SUP top STRUCTURAL MUST cn MAY ( nsAdminGroupName $ description $ nsConfigRoot $ nsAdminSIEDN ) X-ORIGIN 'Netscape' )";
+            ocd = parser.parseObjectClassDescription( value );
+            assertEquals( "nsAdminGroup-oid", ocd.getNumericOid() );
+            assertEquals( 1, ocd.getNames().size() );
+            assertEquals( "nsAdminGroup", ocd.getNames().get( 0 ) );
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SchemaParserTestUtils.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SchemaParserTestUtils.java
index c73451c..8365be1 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SchemaParserTestUtils.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SchemaParserTestUtils.java
@@ -36,7 +36,7 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class SchemaParserTestUtils 
+public class SchemaParserTestUtils
 {
 
     /**
@@ -74,34 +74,42 @@
         }
 
         // simple
-        value = "( 0.1.2.3.4.5.6.7.8.9 "+required+" )";
+        value = "( 0.1.2.3.4.5.6.7.8.9 " + required + " )";
         asd = parser.parse( value );
         Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
 
         // simple
-        value = "( 123.4567.890 "+required+")";
+        value = "( 123.4567.890 " + required + ")";
         asd = parser.parse( value );
         Assert.assertEquals( "123.4567.890", asd.getNumericOid() );
-        
-        // simple with spaces
-        value = "(          0.1.2.3.4.5.6.7.8.9         "+required+" )";
+
+        // simple with multiple spaces
+        value = "(          0.1.2.3.4.5.6.7.8.9         " + required + " )";
         asd = parser.parse( value );
         Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
 
-        // non-numeric not allowed
-        value = "( test "+required+" )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NUMERICOID test" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // simple w/o spaces
+        value = "(0.1.2.3.4.5.6.7.8.9 " + required + ")";
+        asd = parser.parse( value );
+        Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
 
-        // to short
-        value = "( 1 "+required+" )";
+        // simple with tabs, newline, comment.
+        value = "(\t0.1.2.3.4.5.6.7.8.9\n#comment\n" + required + "\r\n)\r";
+        asd = parser.parse( value );
+        Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
+
+        // quoted OID
+        value = "( '0.1.2.3.4.5.6.7.8.9' " + required + " )";
+        asd = parser.parse( value );
+        Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
+
+        // quoted OID in parentheses
+        value = "( ('0.1.2.3.4.5.6.7.8.9') " + required + " )";
+        asd = parser.parse( value );
+        Assert.assertEquals( "0.1.2.3.4.5.6.7.8.9", asd.getNumericOid() );
+
+        // too short
+        value = "( 1 " + required + " )";
         try
         {
             parser.parse( value );
@@ -113,7 +121,7 @@
         }
 
         // dot only
-        value = "( . "+required+" )";
+        value = "( . " + required + " )";
         try
         {
             parser.parse( value );
@@ -125,7 +133,7 @@
         }
 
         // ends with dot
-        value = "( 1.1. "+required+" )";
+        value = "( 1.1. " + required + " )";
         try
         {
             parser.parse( value );
@@ -136,44 +144,60 @@
             // expected
         }
 
-        // quotes not allowed
-        value = "( '1.1' "+required+" )";
+        // multiple not allowed
+        value = "( ( 1.2.3 4.5.6 ) " + required + " )";
         try
         {
             parser.parse( value );
-            Assert.fail( "Exception expected, invalid NUMERICOID '1.1' (quoted)" );
+            Assert.fail( "Exception expected, invalid multiple OIDs not allowed.)" );
         }
         catch ( ParseException pe )
         {
-            // expected
+            // excpected
         }
 
-        // leading 0 not allowed
-        value = "( 01.1 "+required+" )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NUMERICOID 01.1 (leading zero)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+            // non-numeric not allowed
+            value = "( test " + required + " )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NUMERICOID test" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
 
-        // alpha not allowed
-        value = "( 1.2.a.4 "+required+" )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NUMERICOID 1.2.a.4 (alpha not allowed)" );
+            // leading 0 not allowed
+            value = "( 01.1 " + required + " )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NUMERICOID 01.1 (leading zero)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // alpha not allowed
+            value = "( 1.2.a.4 " + required + " )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NUMERICOID 1.2.a.4 (alpha not allowed)" );
+            }
+            catch ( ParseException pe )
+            {
+                // excpected
+            }
+
         }
-        catch ( ParseException pe )
-        {
-            Assert.assertTrue( true );
-        }
-        
     }
-    
+
+
     /**
      * Tests NAME and its values
      * 
@@ -185,38 +209,40 @@
         AbstractSchemaDescription asd = null;
 
         // alpha
-        value = "( "+oid+" "+required+" NAME 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' )";
+        value = "( " + oid + " " + required + " NAME 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' )";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getNames().size() );
         Assert.assertEquals( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", asd.getNames().get( 0 ) );
 
         // alpha-num-hypen
-        value = "( "+oid+" "+required+" NAME 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' )";
+        value = "( " + oid + " " + required
+            + " NAME 'abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789' )";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getNames().size() );
-        Assert.assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", asd.getNames().get( 0 ) );
+        Assert
+            .assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789", asd.getNames().get( 0 ) );
 
         // with parentheses
-        value = "( "+oid+" "+required+" NAME ( 'a-z-0-9' ) )";
+        value = "( " + oid + " " + required + " NAME ( 'a-z-0-9' ) )";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getNames().size() );
         Assert.assertEquals( "a-z-0-9", asd.getNames().get( 0 ) );
 
         // with parentheses, without space
-        value = "( "+oid+" "+required+" NAME ('a-z-0-9') )";
+        value = "(" + oid + " " + required + " NAME('a-z-0-9'))";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getNames().size() );
         Assert.assertEquals( "a-z-0-9", asd.getNames().get( 0 ) );
 
         // multi with space
-        value = "( "+oid+" "+required+" NAME ( 'test1' 'test2' ) )";
+        value = " ( " + oid + " " + required + " NAME ( 'test1' 'test2' ) ) ";
         asd = parser.parse( value );
         Assert.assertEquals( 2, asd.getNames().size() );
         Assert.assertEquals( "test1", asd.getNames().get( 0 ) );
         Assert.assertEquals( "test2", asd.getNames().get( 1 ) );
 
         // multi without space
-        value = "( "+oid+" "+required+" NAME ('test1' 'test2' 'test3') )";
+        value = "(" + oid + " " + required + " NAME('test1''test2''test3'))";
         asd = parser.parse( value );
         Assert.assertEquals( 3, asd.getNames().size() );
         Assert.assertEquals( "test1", asd.getNames().get( 0 ) );
@@ -224,75 +250,44 @@
         Assert.assertEquals( "test3", asd.getNames().get( 2 ) );
 
         // multi with many spaces
-        value = "(          "+oid+" "+required+"          NAME          (          'test1'          'test2'          'test3'          )          )";
+        value = "(          " + oid + " " + required
+            + "          NAME          (          'test1'          'test2'          'test3'          )          )";
         asd = parser.parse( value );
         Assert.assertEquals( 3, asd.getNames().size() );
         Assert.assertEquals( "test1", asd.getNames().get( 0 ) );
         Assert.assertEquals( "test2", asd.getNames().get( 1 ) );
         Assert.assertEquals( "test3", asd.getNames().get( 2 ) );
 
-        // lowercase
-        value = "( "+oid+" "+required+" name 'test' )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, NAME is lowercase" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // multi with tabs, newline, comment, etc.
+        value = "(\r\n" + oid + "\r" + required
+            + "\nNAME\t(\t\t\t'test1'\t\n\t'test2'\t\r\t'test3'\t\r\n\t)\n#comment\n)";
+        asd = parser.parse( value );
+        Assert.assertEquals( 3, asd.getNames().size() );
+        Assert.assertEquals( "test1", asd.getNames().get( 0 ) );
+        Assert.assertEquals( "test2", asd.getNames().get( 1 ) );
+        Assert.assertEquals( "test3", asd.getNames().get( 2 ) );
 
-        // unquoted
-        value = "( "+oid+" "+required+" NAME test )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME test (unquoted)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // lowercase NAME
+        value = "( " + oid + " " + required + " name 'test' )";
+        asd = parser.parse( value );
+        Assert.assertEquals( 1, asd.getNames().size() );
+        Assert.assertEquals( "test", asd.getNames().get( 0 ) );
 
-        // start with number
-        value = "( "+oid+" "+required+" NAME '1test' )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME 1test (starts with number)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // unquoted NAME value
+        value = "( " + oid + " " + required + " NAME test )";
+        asd = parser.parse( value );
+        Assert.assertEquals( 1, asd.getNames().size() );
+        Assert.assertEquals( "test", asd.getNames().get( 0 ) );
 
-        // start with hypen
-        value = "( "+oid+" "+required+" NAME '-test' )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME -test (starts with hypen)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
-
-        // invalid character
-        value = "( "+oid+" "+required+" NAME 'te_st' )";
-        try
-        {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME te_st (contains invalid character)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+        // multi unquoted NAME values
+        value = " ( " + oid + " " + required + " NAME (test1 test2) ) ";
+        asd = parser.parse( value );
+        Assert.assertEquals( 2, asd.getNames().size() );
+        Assert.assertEquals( "test1", asd.getNames().get( 0 ) );
+        Assert.assertEquals( "test2", asd.getNames().get( 1 ) );
 
         // NAM unknown
-        value = "( "+oid+" "+required+" NAM 'test' )";
+        value = "( " + oid + " " + required + " NAM 'test' )";
         try
         {
             parser.parse( value );
@@ -303,81 +298,133 @@
             // expected
         }
 
-        // one valid, one invalid
-        value = "( "+oid+" "+required+" NAME ( 'test' 'te_st' ) )";
-        try
+        if ( !parser.isQuirksMode() )
         {
-            parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME te_st (contains invalid character)" );
-        }
-        catch ( ParseException pe )
-        {
-            // expected
-        }
+            // start with number
+            value = "( " + oid + " " + required + " NAME '1test' )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NAME 1test (starts with number)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
 
-        // no space between values
-        value = "( "+oid+" "+required+" NAME ( 'test1''test2' ) )";
-        try
-        {
-            asd = parser.parse( value );
-            Assert.fail( "Exception expected, invalid NAME values (no space between values)" );
-        }
-        catch ( ParseException pe )
-        {
-            Assert.assertTrue( true );
+            // start with hypen
+            value = "( " + oid + " " + required + " NAME '-test' )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NAME -test (starts with hypen)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // invalid character
+            value = "( " + oid + " " + required + " NAME 'te_st' )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NAME te_st (contains invalid character)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
+
+            // one valid, one invalid
+            value = "( " + oid + " " + required + " NAME ( 'test' 'te_st' ) )";
+            try
+            {
+                parser.parse( value );
+                Assert.fail( "Exception expected, invalid NAME te_st (contains invalid character)" );
+            }
+            catch ( ParseException pe )
+            {
+                // expected
+            }
         }
     }
-    
-    
+
+
     /**
      * Tests DESC
      * 
      * @throws ParseException
      */
-    public static void testDescription( AbstractSchemaParser parser, String oid, String required ) throws ParseException
+    public static void testDescription( AbstractSchemaParser parser, String oid, String required )
+        throws ParseException
     {
         String value = null;
         AbstractSchemaDescription asd = null;
 
         // simple
-        value = "("+oid+" "+required+" DESC 'Descripton')";
+        value = "(" + oid + " " + required + " DESC 'Descripton')";
+        asd = parser.parse( value );
+        Assert.assertEquals( "Descripton", asd.getDescription() );
+
+        // simple with tabs, newline, comment, etc.
+        value = "(" + oid + "\n" + required + "\tDESC#comment\n\n\r\n\r\t'Descripton')";
+        asd = parser.parse( value );
+        Assert.assertEquals( "Descripton", asd.getDescription() );
+
+        // simple w/o space
+        value = "(" + oid + " " + required + " DESC'Descripton')";
+        asd = parser.parse( value );
+        Assert.assertEquals( "Descripton", asd.getDescription() );
+
+        // simple parentheses and quotes
+        value = "(" + oid + " " + required + " DESC ('Descripton') )";
         asd = parser.parse( value );
         Assert.assertEquals( "Descripton", asd.getDescription() );
 
         // unicode
-        value = "( "+oid+" "+required+" DESC 'Descripton \u00E4\u00F6\u00FC\u00DF \u90E8\u9577' )";
+        value = "( " + oid + " " + required + " DESC 'Descripton \u00E4\u00F6\u00FC\u00DF \u90E8\u9577' )";
         asd = parser.parse( value );
         Assert.assertEquals( "Descripton \u00E4\u00F6\u00FC\u00DF \u90E8\u9577", asd.getDescription() );
-        
+
         // escaped characters
-        value = "( "+oid+" "+required+" DESC 'test\\5Ctest' )";
+        value = "( " + oid + " " + required + " DESC 'test\\5Ctest' )";
         asd = parser.parse( value );
         Assert.assertEquals( "test\\test", asd.getDescription() );
-        value = "( "+oid+" "+required+" DESC 'test\\5ctest' )";
+        value = "( " + oid + " " + required + " DESC 'test\\5ctest' )";
         asd = parser.parse( value );
         Assert.assertEquals( "test\\test", asd.getDescription() );
-        value = "( "+oid+" "+required+" DESC 'test\\27test' )";
+        value = "( " + oid + " " + required + " DESC 'test\\27test' )";
         asd = parser.parse( value );
         Assert.assertEquals( "test'test", asd.getDescription() );
-        value = "( "+oid+" "+required+" DESC '\\5C\\27\\5c' )";
+        value = "( " + oid + " " + required + " DESC '\\5C\\27\\5c' )";
         asd = parser.parse( value );
         Assert.assertEquals( "\\'\\", asd.getDescription() );
-        
-        // lowercase
-        value = "( "+oid+" "+required+" desc 'Descripton' )";
+
+        // lowercase DESC
+        value = "( " + oid + " " + required + " desc 'Descripton' )";
+        asd = parser.parse( value );
+        Assert.assertEquals( "Descripton", asd.getDescription() );
+
+        // empty DESC
+        value = "( " + oid + " " + required + " DESC '' )";
+        asd = parser.parse( value );
+        Assert.assertEquals( "", asd.getDescription() );
+
+        // multiple not allowed
+        value = "(" + oid + " " + required + " DESC ( 'Descripton1' 'Description 2' )  )";
         try
         {
             parser.parse( value );
-            Assert.fail( "Exception expected, DESC is lowercase" );
+            Assert.fail( "Exception expected, invalid multiple DESC not allowed.)" );
         }
         catch ( ParseException pe )
         {
-            Assert.assertTrue( true );
+            // expected
         }
-        
     }
-    
-    
+
+
     /**
      * Test extensions.
      * 
@@ -389,12 +436,12 @@
         AbstractSchemaDescription asd = null;
 
         // no extension
-        value = "( "+oid+" "+required+" )";
+        value = "( " + oid + " " + required + " )";
         asd = parser.parse( value );
         Assert.assertEquals( 0, asd.getExtensions().size() );
 
         // single extension with one value
-        value = "( "+oid+" "+required+" X-TEST 'test' )";
+        value = "( " + oid + " " + required + " X-TEST 'test' )";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getExtensions().size() );
         Assert.assertNotNull( asd.getExtensions().get( "X-TEST" ) );
@@ -402,7 +449,8 @@
         Assert.assertEquals( "test", asd.getExtensions().get( "X-TEST" ).get( 0 ) );
 
         // single extension with multiple values
-        value = "( "+oid+" "+required+" X-TEST-ABC ('test1' 'test \u00E4\u00F6\u00FC\u00DF'       'test \u90E8\u9577' ) )";
+        value = "( " + oid + " " + required
+            + " X-TEST-ABC ('test1' 'test \u00E4\u00F6\u00FC\u00DF'       'test \u90E8\u9577' ) )";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getExtensions().size() );
         Assert.assertNotNull( asd.getExtensions().get( "X-TEST-ABC" ) );
@@ -412,7 +460,34 @@
         Assert.assertEquals( "test \u90E8\u9577", asd.getExtensions().get( "X-TEST-ABC" ).get( 2 ) );
 
         // multiple extensions
-        value = "("+oid+" "+required+" X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2'))";
+        value = "(" + oid + " " + required + " X-TEST-a ('test1-1' 'test1-2') X-TEST-b ('test2-1' 'test2-2'))";
+        asd = parser.parse( value );
+        Assert.assertEquals( 2, asd.getExtensions().size() );
+        Assert.assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
+        Assert.assertEquals( 2, asd.getExtensions().get( "X-TEST-a" ).size() );
+        Assert.assertEquals( "test1-1", asd.getExtensions().get( "X-TEST-a" ).get( 0 ) );
+        Assert.assertEquals( "test1-2", asd.getExtensions().get( "X-TEST-a" ).get( 1 ) );
+        Assert.assertNotNull( asd.getExtensions().get( "X-TEST-b" ) );
+        Assert.assertEquals( 2, asd.getExtensions().get( "X-TEST-b" ).size() );
+        Assert.assertEquals( "test2-1", asd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
+        Assert.assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+
+        // multiple extensions, no spaces
+        value = "(" + oid + " " + required + " X-TEST-a('test1-1''test1-2')X-TEST-b('test2-1''test2-2'))";
+        asd = parser.parse( value );
+        Assert.assertEquals( 2, asd.getExtensions().size() );
+        Assert.assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
+        Assert.assertEquals( 2, asd.getExtensions().get( "X-TEST-a" ).size() );
+        Assert.assertEquals( "test1-1", asd.getExtensions().get( "X-TEST-a" ).get( 0 ) );
+        Assert.assertEquals( "test1-2", asd.getExtensions().get( "X-TEST-a" ).get( 1 ) );
+        Assert.assertNotNull( asd.getExtensions().get( "X-TEST-b" ) );
+        Assert.assertEquals( 2, asd.getExtensions().get( "X-TEST-b" ).size() );
+        Assert.assertEquals( "test2-1", asd.getExtensions().get( "X-TEST-b" ).get( 0 ) );
+        Assert.assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
+
+        // multiple extensions, tabs, newline, comments
+        value = "(" + oid + "\n#comment\n" + required
+            + "\nX-TEST-a\n(\t'test1-1'\t\n'test1-2'\n\r)\tX-TEST-b\n(\n'test2-1'\t'test2-2'\t)\r)";
         asd = parser.parse( value );
         Assert.assertEquals( 2, asd.getExtensions().size() );
         Assert.assertNotNull( asd.getExtensions().get( "X-TEST-a" ) );
@@ -425,15 +500,18 @@
         Assert.assertEquals( "test2-2", asd.getExtensions().get( "X-TEST-b" ).get( 1 ) );
 
         // some more complicated
-        value = "("+oid+" "+required+" X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ('\\5C\\27\\5c'))";
+        value = "(" + oid + " " + required
+            + " X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ('\\5C\\27\\5c'))";
         asd = parser.parse( value );
         Assert.assertEquals( 1, asd.getExtensions().size() );
         Assert.assertNotNull( asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ) );
-        Assert.assertEquals( 1, asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ).size() );
-        Assert.assertEquals( "\\'\\", asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ).get( 0 ) );
-        
+        Assert.assertEquals( 1, asd.getExtensions().get( "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" )
+            .size() );
+        Assert.assertEquals( "\\'\\", asd.getExtensions().get(
+            "X-_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ).get( 0 ) );
+
         // invalid extension, no number allowed
-        value = "( "+oid+" "+required+" X-TEST1 'test' )";
+        value = "( " + oid + " " + required + " X-TEST1 'test' )";
         try
         {
             asd = parser.parse( value );
@@ -446,7 +524,7 @@
 
     }
 
-    
+
     /**
      * Tests OBSOLETE
      * 
@@ -458,27 +536,32 @@
         AbstractSchemaDescription asd = null;
 
         // not obsolete
-        value = "( "+oid+" "+required+" )";
+        value = "( " + oid + " " + required + " )";
         asd = parser.parse( value );
         Assert.assertFalse( asd.isObsolete() );
 
         // not obsolete
-        value = "( "+oid+" "+required+" NAME 'test' DESC 'Descripton' )";
+        value = "( " + oid + " " + required + " NAME 'test' DESC 'Descripton' )";
         asd = parser.parse( value );
         Assert.assertFalse( asd.isObsolete() );
-        
+
         // obsolete
-        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLETE)";
+        value = "(" + oid + " " + required + " NAME 'test' DESC 'Descripton' OBSOLETE)";
         asd = parser.parse( value );
         Assert.assertTrue( asd.isObsolete() );
 
         // obsolete 
-        value = "("+oid+" "+required+" OBSOLETE)";
+        value = "(" + oid + " " + required + " OBSOLETE)";
         asd = parser.parse( value );
         Assert.assertTrue( asd.isObsolete() );
 
-        // ivalid
-        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLET )";
+        // lowercased obsolete 
+        value = "(" + oid + " " + required + " obsolete)";
+        asd = parser.parse( value );
+        Assert.assertTrue( asd.isObsolete() );
+
+        // invalid
+        value = "(" + oid + " " + required + " NAME 'test' DESC 'Descripton' OBSOLET )";
         try
         {
             asd = parser.parse( value );
@@ -488,9 +571,9 @@
         {
             // expected
         }
-        
+
         // trailing value not allowed
-        value = "("+oid+" "+required+" NAME 'test' DESC 'Descripton' OBSOLETE 'true' )";
+        value = "(" + oid + " " + required + " NAME 'test' DESC 'Descripton' OBSOLETE 'true' )";
         try
         {
             asd = parser.parse( value );
@@ -500,11 +583,10 @@
         {
             Assert.assertTrue( true );
         }
-        
+
     }
-    
-    
-    
+
+
     /**
      * Tests for unique elements.
      * 
@@ -518,17 +600,17 @@
             try
             {
                 parser.parse( testValue );
-                Assert.fail( "Exception expected, element appears twice in "+testValue );
+                Assert.fail( "Exception expected, element appears twice in " + testValue );
             }
             catch ( ParseException pe )
             {
                 Assert.assertTrue( true );
             }
         }
-        
+
     }
-    
-    
+
+
     /**
      * Tests the multithreaded use of a single parser.
      */
@@ -536,7 +618,7 @@
     {
         final boolean[] isSuccessMultithreaded = new boolean[1];
         isSuccessMultithreaded[0] = true;
-        
+
         // start up and track all threads (40 threads)
         List<Thread> threads = new ArrayList<Thread>();
         for ( int ii = 0; ii < 10; ii++ )
@@ -565,7 +647,47 @@
 
         // check that no one thread failed to parse and generate a SS object
         Assert.assertTrue( isSuccessMultithreaded[0] );
-        
+
+    }
+
+
+    /**
+     * Tests quirks mode.
+     */
+    public static void testQuirksMode( AbstractSchemaParser parser, String required ) throws ParseException
+    {
+        try
+        {
+            String value = null;
+            AbstractSchemaDescription asd = null;
+            
+            parser.setQuirksMode( true );
+            
+            // alphanum OID
+            value = "( abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 " + required + " )";
+            asd = parser.parse( value );
+            Assert.assertEquals( "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789", asd
+                .getNumericOid() );
+
+            // start with hypen
+            value = "( -oid " + required + " )";
+            asd = parser.parse( value );
+            Assert.assertEquals( "-oid", asd.getNumericOid() );
+
+            // start with number
+            value = "( 1oid " + required + " )";
+            asd = parser.parse( value );
+            Assert.assertEquals( "1oid", asd.getNumericOid() );
+
+            // start with dot
+            value = "( .oid " + required + " )";
+            asd = parser.parse( value );
+            Assert.assertEquals( ".oid", asd.getNumericOid() );
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
     }
 
     static class ParseSpecification implements Runnable
@@ -573,17 +695,18 @@
         private final AbstractSchemaParser parser;
         private final String value;
         private final boolean[] isSuccessMultithreaded;
-        
+
         private AbstractSchemaDescription result;
-        
+
+
         public ParseSpecification( AbstractSchemaParser parser, String value, boolean[] isSuccessMultithreaded )
         {
             this.parser = parser;
             this.value = value;
             this.isSuccessMultithreaded = isSuccessMultithreaded;
         }
-        
-        
+
+
         public void run()
         {
             try
@@ -594,10 +717,9 @@
             {
                 e.printStackTrace();
             }
-            
+
             isSuccessMultithreaded[0] = isSuccessMultithreaded[0] && ( result != null );
         }
     }
-    
-    
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParserTest.java
index 215787a..4d9f71b 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/schema/syntax/parser/SyntaxCheckerDescriptionSchemaParserTest.java
@@ -56,7 +56,7 @@
     }
 
 
-    public void testNumericOid() throws Exception
+    public void testNumericOid() throws ParseException
     {
         SchemaParserTestUtils.testNumericOid( parser, "FQCN org.apache.directory.SimpleComparator" );
     }
@@ -70,7 +70,6 @@
 
     public void testFqcn() throws ParseException
     {
-
         String value = null;
         SyntaxCheckerDescription scd = null;
 
@@ -79,13 +78,11 @@
         scd = parser.parseSyntaxCheckerDescription( value );
         assertNotNull( scd.getFqcn() );
         assertEquals( "org.apache.directory.SimpleComparator", scd.getFqcn() );
-
     }
 
 
     public void testBytecode() throws ParseException
     {
-
         String value = null;
         SyntaxCheckerDescription scd = null;
 
@@ -94,7 +91,6 @@
         scd = parser.parseSyntaxCheckerDescription( value );
         assertNotNull( scd.getBytecode() );
         assertEquals( "ABCDEFGHIJKLMNOPQRSTUVWXYZ+/abcdefghijklmnopqrstuvwxyz0123456789====", scd.getBytecode() );
-
     }
 
 
@@ -132,7 +128,7 @@
     }
 
 
-    public void testSimpleSyntaxChecker() throws Exception
+    public void testSimpleSyntaxChecker() throws ParseException
     {
         String simple = "( " + OID + " FQCN " + FQCN + " )";
         SyntaxCheckerDescription desc = parser.parseSyntaxCheckerDescription( simple );
@@ -144,7 +140,7 @@
     }
 
 
-    public void testSyntaxCheckerWithDesc() throws Exception
+    public void testSyntaxCheckerWithDesc() throws ParseException
     {
         String simple = "( " + OID + " DESC '" + DESC + "' FQCN " + FQCN + " )";
         SyntaxCheckerDescription desc = parser.parseSyntaxCheckerDescription( simple );
@@ -156,7 +152,7 @@
     }
 
 
-    public void testSyntaxCheckerWithDescAndByteCode() throws Exception
+    public void testSyntaxCheckerWithDescAndByteCode() throws ParseException
     {
         String simple = "( " + OID + " DESC '" + DESC + "' FQCN " + FQCN + " BYTECODE " + BYTECODE + " )";
         SyntaxCheckerDescription desc = parser.parseSyntaxCheckerDescription( simple );
@@ -168,7 +164,7 @@
     }
 
 
-    public void testSyntaxCheckerExample() throws Exception
+    public void testSyntaxCheckerExample() throws ParseException
     {
         String simple = "( 1.3.6.1.4.1.18060.0.4.1.0.10000 DESC 'bogus desc' FQCN org.apache.directory.shared.ldap.schema.syntax.AcceptAllSyntaxChecker )";
         SyntaxCheckerDescription desc = parser.parseSyntaxCheckerDescription( simple );
@@ -176,7 +172,7 @@
     }
 
 
-    public void testRealByteCodeExample() throws Exception
+    public void testRealByteCodeExample() throws ParseException
     {
         String simple = "( 1.3.6.1.4.1.18060.0.4.1.0.10002 DESC 'bogus desc' "
             + "FQCN DummySyntaxChecker BYTECODE yv66vgAAADEAHgoABAAYCQADABkHABoHABsHABwBAANvaWQBABJMam"
@@ -204,9 +200,42 @@
     /**
      * Tests the multithreaded use of a single parser.
      */
-    public void testMultiThreaded() throws Exception
+    public void testMultiThreaded() throws ParseException
     {
         // TODO
     }
 
+
+    /**
+     * Tests quirks mode.
+     */
+    public void testQuirksMode() throws ParseException
+    {
+        SchemaParserTestUtils.testQuirksMode( parser, "FQCN org.apache.directory.SimpleComparator" );
+
+        try
+        {
+            parser.setQuirksMode( true );
+
+            // ensure all other test pass in quirks mode
+            testNumericOid();
+            testDescription();
+            testFqcn();
+            testBytecode();
+            testExtensions();
+            testFull();
+            testUniqueElements();
+            testSimpleSyntaxChecker();
+            testSyntaxCheckerWithDesc();
+            testSyntaxCheckerWithDescAndByteCode();
+            testSyntaxCheckerExample();
+            testRealByteCodeExample();
+            testMultiThreaded();
+        }
+        finally
+        {
+            parser.setQuirksMode( false );
+        }
+    }
+
 }
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationParserTest.java
index 43a4bb9..2d589df 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/subtree/SubtreeSpecificationParserTest.java
@@ -27,6 +27,7 @@
 
 import junit.framework.TestCase;
 
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
 import org.apache.directory.shared.ldap.filter.AndNode;
 import org.apache.directory.shared.ldap.filter.BranchNode;
 import org.apache.directory.shared.ldap.filter.EqualityNode;
@@ -276,16 +277,16 @@
     {
         SubtreeSpecification ss = parser.parse( SPEC_WITH_REFINEMENT );
 
-        SimpleNode n1 = new EqualityNode( "objectClass", "1.2.3" );
-        SimpleNode n2 = new EqualityNode( "objectClass", "4.5.6" );
-        SimpleNode n3 = new EqualityNode( "objectClass", "person-7" );
+        SimpleNode n1 = new EqualityNode( "objectClass", new ClientStringValue( "1.2.3" ) );
+        SimpleNode n2 = new EqualityNode( "objectClass", new ClientStringValue( "4.5.6" ) );
+        SimpleNode n3 = new EqualityNode( "objectClass", new ClientStringValue( "person-7" ) );
         BranchNode n4 = new OrNode();
         n4.addNode( n2 );
         n4.addNode( n3 );
         BranchNode n5 = new AndNode();
         n5.addNode( n1 );
         n5.addNode( n4 );
-        SimpleNode n6 = new EqualityNode( "objectClass", "10.11.12" );
+        SimpleNode n6 = new EqualityNode( "objectClass", new ClientStringValue( "10.11.12" ) );
         BranchNode n7 = new NotNode();
         n7.addNode( n6 );
         BranchNode n8 = new AndNode();
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java
index 7196221..444b112 100644
--- a/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/trigger/TriggerSpecificationParserTest.java
@@ -193,8 +193,8 @@
         TriggerSpecification triggerSpecification = null;
         
         String spec = "AFTER Delete " +
-        	"CALL \"BackupUtilities.backupDeletedEntry\" ($ldapContext \"ou=Backup,ou=System\", $name, $deletedEntry); " +
-        	"CALL \"BackupUtilities.recreateDeletedEntry\" ($name, $deletedEntry);";
+            "CALL \"BackupUtilities.backupDeletedEntry\" ($ldapContext \"ou=Backup,ou=System\", $name, $deletedEntry); " +
+            "CALL \"BackupUtilities.recreateDeletedEntry\" ($name, $deletedEntry);";
 
         triggerSpecification = parser.parse( spec );
         
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/util/AttributeUtilsTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/util/AttributeUtilsTest.java
new file mode 100644
index 0000000..2927a87
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/util/AttributeUtilsTest.java
@@ -0,0 +1,415 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.ModificationItem;
+
+import org.apache.directory.shared.ldap.message.AttributeImpl;
+import org.apache.directory.shared.ldap.message.AttributesImpl;
+import org.apache.directory.shared.ldap.message.ModificationItemImpl;
+
+import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
+
+/**
+ * A test case for the AttributeUtils methods 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class AttributeUtilsTest
+{
+    /**
+     * Test a addModification applied to an empty entry
+     */
+    @Test
+    public void testApplyAddModificationToEmptyEntry() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.ADD_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNotNull( entry.get(  "cn" ) );
+        assertEquals( 1, entry.size() );
+        assertEquals( attr, entry.get( "cn" ) );
+    }
+
+
+    /**
+     * Test a addModification applied to an entry 
+     */
+    @Test
+    public void testApplyAddModificationToEntry() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        entry.put( "dc", "apache" );
+        assertEquals( 1, entry.size() );
+
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.ADD_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNotNull( entry.get(  "cn" ) );
+        assertEquals( 2, entry.size() );
+        assertEquals( attr, entry.get( "cn" ) );
+    }
+
+
+    /**
+     * Test a addModification applied to an entry with the same attribute
+     * but with another value 
+     */
+    @Test
+    public void testApplyAddModificationToEntryWithValues() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        entry.put( "cn", "apache" );
+        assertEquals( 1, entry.size() );
+
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.ADD_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNotNull( entry.get(  "cn" ) );
+        assertEquals( 1, entry.size() );
+        
+        NamingEnumeration<?> values = entry.get( "cn" ).getAll();
+        
+        assertTrue( values.hasMoreElements() );
+        
+        Set<String> expectedValues = new HashSet<String>();
+        expectedValues.add( "apache" );
+        expectedValues.add( "test" );
+        
+        while ( values.hasMoreElements() )
+        {
+            String value = (String)values.nextElement();
+            
+            assertTrue( expectedValues.contains( value ) );
+            
+            expectedValues.remove( value );
+        }
+        
+        assertEquals( 0, expectedValues.size() );
+    }
+
+
+    /**
+     * Test a addModification applied to an entry with the same attribute
+     * and the same value 
+     */
+    @Test
+    public void testApplyAddModificationToEntryWithSameValue() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn" );
+        cn.add( "test" );
+        cn.add( "apache" );
+        entry.put( cn );
+        
+        assertEquals( 1, entry.size() );
+
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.ADD_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNotNull( entry.get(  "cn" ) );
+        assertEquals( 1, entry.size() );
+        
+        NamingEnumeration<?> values = entry.get( "cn" ).getAll();
+        
+        assertTrue( values.hasMoreElements() );
+        
+        Set<String> expectedValues = new HashSet<String>();
+        expectedValues.add( "apache" );
+        expectedValues.add( "test" );
+        
+        while ( values.hasMoreElements() )
+        {
+            String value = (String)values.nextElement();
+            
+            assertTrue( expectedValues.contains( value ) );
+            
+            expectedValues.remove( value );
+        }
+        
+        assertEquals( 0, expectedValues.size() );
+    }
+
+    
+    /**
+     * Test the deletion of an attribute into an empty entry
+     */
+    @Test
+    public void testApplyRemoveModificationFromEmptyEntry() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.REMOVE_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNull( entry.get( "cn" ) );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    /**
+     * Test the deletion of an attribute into an entry which does not contain the attribute
+     */
+    @Test
+    public void testApplyRemoveModificationFromEntryAttributeNotPresent() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute dc = new AttributeImpl( "dc", "apache" );
+        entry.put( dc );
+        
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REMOVE_ATTRIBUTE, attr );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertNull( entry.get( "cn" ) );
+        assertNotNull( entry.get( "dc" ) );
+        assertEquals( 1, entry.size() );
+        assertEquals( dc, entry.get( "dc" ) );
+    }
+
+
+    /**
+     * Test the deletion of an attribute into an entry which contains the attribute
+     * but without the value to be deleted
+     */
+    @Test
+    public void testApplyRemoveModificationFromEntryAttributeNotSameValue() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn", "apache" );
+        entry.put( cn );
+        
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REMOVE_ATTRIBUTE, attr );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertNotNull( entry.get( "cn" ) );
+        assertEquals( 1, entry.size() );
+        assertEquals( cn, entry.get( "cn" ) );
+    }
+
+
+    /**
+     * Test the deletion of an attribute into an entry which contains the attribute.
+     * 
+     * The entry should not contain the attribute after the operation
+     */
+    @Test
+    public void testApplyRemoveModificationFromEntrySameAttributeSameValue() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn", "test" );
+        entry.put( cn );
+        
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REMOVE_ATTRIBUTE, attr );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertNull( entry.get( "cn" ) );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    /**
+     * Test the deletion of an attribute into an entry which contains the attribute
+     * with more than one value
+     * 
+     * The entry should contain the attribute after the operation, but with one less value
+     */
+    @Test
+    public void testApplyRemoveModificationFromEntrySameAttributeValues() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn", "test" );
+        cn.add( "apache" );
+        entry.put( cn );
+        
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REMOVE_ATTRIBUTE, attr );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertNotNull( entry.get( "cn" ) );
+        assertEquals( 1, entry.size() );
+        
+        Attribute modifiedAttr = entry.get( "cn" );
+        
+        NamingEnumeration<?> values = modifiedAttr.getAll();
+        
+        assertTrue( values.hasMoreElements() );
+        
+        boolean isFirst = true;
+        
+        while ( values.hasMoreElements() )
+        {
+            assertTrue( isFirst );
+            
+            isFirst = false;
+            assertEquals( "apache", values.nextElement() );
+        }
+    }
+    
+    /**
+     * test the addition by modification of an attribute in an empty entry.
+     * 
+     * As we are replacing a non existing attribute, it should be added.
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testApplyModifyModificationFromEmptyEntry() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute attr = new AttributeImpl( "cn", "test" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.REPLACE_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNotNull( entry.get( "cn" ) );
+        assertEquals( 1, entry.size() );
+    }
+
+    
+    /**
+     * Test the replacement by modification of an attribute in an empty entry.
+     * 
+     * As we are replacing a non existing attribute, it should not change the entry.
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testApplyModifyEmptyModificationFromEmptyEntry() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute attr = new AttributeImpl( "cn" );
+        ModificationItem modification = new ModificationItemImpl(DirContext.REPLACE_ATTRIBUTE, attr );
+        AttributeUtils.applyModification( entry, modification );
+        assertNull( entry.get( "cn" ) );
+        assertEquals( 0, entry.size() );
+    }
+
+
+    /**
+     * Test the replacement by modification of an attribute in an empty entry.
+     * 
+     * As we are replacing a non existing attribute, it should not change the entry.
+     *
+     * @throws NamingException
+     */
+    @Test
+    public void testApplyModifyAttributeModification() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn", "test" );
+        
+        entry.put( cn );
+
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        
+        entry.put( ou );
+        
+        Attribute newOu = new AttributeImpl( "ou" );
+        newOu.add( "Big Company" );
+        newOu.add( "directory" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REPLACE_ATTRIBUTE, newOu );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertEquals( 2, entry.size() );
+        
+        assertNotNull( entry.get( "cn" ) );
+        assertNotNull( entry.get( "ou" ) );
+        
+        Attribute modifiedAttr = entry.get( "ou" );
+        
+        NamingEnumeration<?> values = modifiedAttr.getAll();
+        
+        assertTrue( values.hasMoreElements() );
+        
+        Set<String> expectedValues = new HashSet<String>();
+        expectedValues.add( "Big Company" );
+        expectedValues.add( "directory" );
+        
+        while ( values.hasMoreElements() )
+        {
+            String value = (String)values.nextElement();
+            
+            assertTrue( expectedValues.contains( value ) );
+            
+            expectedValues.remove( value );
+        }
+        
+        assertEquals( 0, expectedValues.size() );
+    }
+
+
+    /**
+     * Test the removing by modification of an existing attribute in an .
+     * 
+     * @throws NamingException
+     */
+    @Test
+    public void testApplyModifyModificationRemoveAttribute() throws NamingException
+    {
+        Attributes entry = new AttributesImpl();
+        Attribute cn = new AttributeImpl( "cn", "test" );
+        
+        entry.put( cn );
+
+        Attribute ou = new AttributeImpl( "ou" );
+        ou.add( "apache" );
+        ou.add( "acme corp" );
+        
+        entry.put( ou );
+        
+        Attribute newOu = new AttributeImpl( "ou" );
+        
+        ModificationItem modification = new ModificationItemImpl(DirContext.REPLACE_ATTRIBUTE, newOu );
+        
+        AttributeUtils.applyModification( entry, modification );
+        
+        assertEquals( 1, entry.size() );
+        
+        assertNotNull( entry.get( "cn" ) );
+        assertNull( entry.get( "ou" ) );
+    }
+}
+
diff --git a/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java b/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java
new file mode 100644
index 0000000..0e81a92
--- /dev/null
+++ b/ldap/src/test/java/org/apache/directory/shared/ldap/util/GeneralizedTimeTest.java
@@ -0,0 +1,1043 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.util;
+
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+import org.apache.directory.shared.ldap.schema.syntax.GeneralizedTimeSyntaxCheckerTest;
+import org.apache.directory.shared.ldap.util.GeneralizedTime.Format;
+import org.apache.directory.shared.ldap.util.GeneralizedTime.TimeZoneFormat;
+
+
+/**
+ * Tests the DateUtils class methods.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 542077 $
+ */
+public class GeneralizedTimeTest extends TestCase
+{
+
+    // Test all valid variants:
+    // Time: min + sec / min + no sec / no min + no sec 
+    // Fraction: no fraction, dot, comma
+    // Timezone: Z / +HH / +HHmm / -HH / -HHmm
+
+    /**
+     * Tests yyyyMMddHHmmssZ.
+     */
+    public void testYearMonthDayHourMinSecZulu() throws ParseException
+    {
+        String gt = "20080102121314Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss+04.
+     */
+    public void testYearMonthDayHourMinSecPlusHour() throws ParseException
+    {
+        String gt = "20080102121314+04";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss-1030.
+     */
+    public void testYearMonthDayHourMinSecMinusHourMin() throws ParseException
+    {
+        String gt = "20080102121314-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss.SSSZ.
+     */
+    public void testYearMonthDayHourMinSecDotFractionZulu() throws ParseException
+    {
+        String gt = "20080102121314.987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss.SSS+0100.
+     */
+    public void testYearMonthDayHourMinSecDotFractionPlusHour() throws ParseException
+    {
+        String gt = "20080102121314.987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss.SSS-1030.
+     */
+    public void testYearMonthDayHourMinSecDotFractionMinusHourMin() throws ParseException
+    {
+        String gt = "20080102121314.987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss,SSSZ.
+     */
+    public void testYearMonthDayHourMinSecCommaFractionZulu() throws ParseException
+    {
+        String gt = "20080102121314,987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss,SSS+0100.
+     */
+    public void testYearMonthDayHourMinSecCommaFractionPlusHour() throws ParseException
+    {
+        String gt = "20080102121314,987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmss,SSS-1030.
+     */
+    public void testYearMonthDayHourMinSecCommaFractionMinusHourMin() throws ParseException
+    {
+        String gt = "20080102121314,987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmmZ.
+     */
+    public void testYearMonthDayHourMinZulu() throws ParseException
+    {
+        String gt = "200801021213Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm+HH.
+     */
+    public void testYearMonthDayHourMinPlusHour() throws ParseException
+    {
+        String gt = "200801021213+04";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm-HHmm.
+     */
+    public void testYearMonthDayHourMinMinusHourMin() throws ParseException
+    {
+        String gt = "200801021213-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm.SSSZ.
+     */
+    public void testYearMonthDayHourMinDotFractionZulu() throws ParseException
+    {
+        String gt = "200801021213.987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm.SSS+0100.
+     */
+    public void testYearMonthDayHourMinDotFractionPlusHour() throws ParseException
+    {
+        String gt = "200801021213.987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm.SSS-1030.
+     */
+    public void testYearMonthDayHourMinDotFractionMinusHourMin() throws ParseException
+    {
+        String gt = "200801021213.987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm,SSSZ.
+     */
+    public void testYearMonthDayHourMinCommaFractionZulu() throws ParseException
+    {
+        String gt = "200801021213,987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm,SSS+0100.
+     */
+    public void testYearMonthDayHourMinCommaFractionPlusHour() throws ParseException
+    {
+        String gt = "200801021213,987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHmm,SSS-1030.
+     */
+    public void testYearMonthDayHourMinCommaFractionMinusHourMin() throws ParseException
+    {
+        String gt = "200801021213,987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHHZ.
+     */
+    public void testYearMonthDayHourZulu() throws ParseException
+    {
+        String gt = "2008010212Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH+HH.
+     */
+    public void testYearMonthDayHourPlusHour() throws ParseException
+    {
+        String gt = "2008010212+04";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH-HHmm.
+     */
+    public void testYearMonthDayHourMinusHourMin() throws ParseException
+    {
+        String gt = "2008010212-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH.SSSZ.
+     */
+    public void testYearMonthDayHourDotFractionZulu() throws ParseException
+    {
+        String gt = "200801021213.987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH.SSS+0100.
+     */
+    public void testYearMonthDayHourDotFractionPlusHour() throws ParseException
+    {
+        String gt = "2008010212.987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH.SSS-1030.
+     */
+    public void testYearMonthDayHourDotFractionMinusHourMin() throws ParseException
+    {
+        String gt = "2008010212.987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH,SSSZ.
+     */
+    public void testYearMonthDayHourCommaFractionZulu() throws ParseException
+    {
+        String gt = "2008010212,987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH,SSS+0100.
+     */
+    public void testYearMonthDayHourCommaFractionPlusHour() throws ParseException
+    {
+        String gt = "2008010212,987+0100";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests yyyyMMddHH,SSS-1030.
+     */
+    public void testYearMonthDayHourCommaFractionMinusHourMin() throws ParseException
+    {
+        String gt = "2008010212,987-1030";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests fraction of a second.
+     */
+    public void testFractionOfSecond() throws ParseException
+    {
+        String gt = "20080102121314,987Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+        assertEquals( 987, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+    }
+
+
+    /**
+     * Tests fraction of a minute.
+     */
+    public void testFractionOfMinute1() throws ParseException
+    {
+        String gt = "200801021213,5Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+        assertEquals( 30, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+        assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+    }
+
+
+    /**
+     * Tests fraction of a minute.
+     */
+    public void testFractionOfMinute2() throws ParseException
+    {
+        String gt = "200801021213,125Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+        assertEquals( 7, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+        assertEquals( 500, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+    }
+
+
+    /**
+     * Tests fraction of an hour.
+     */
+    public void testFractionOfHour1() throws ParseException
+    {
+        String gt = "2008010212,5Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+        assertEquals( 30, generalizedTime.getCalendar().get( Calendar.MINUTE ) );
+        assertEquals( 0, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+        assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+    }
+
+
+    /**
+     * Tests fraction of an hour.
+     */
+    public void testFractionOfHour2() throws ParseException
+    {
+        String gt = "2008010212,125Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+        assertEquals( 7, generalizedTime.getCalendar().get( Calendar.MINUTE ) );
+        assertEquals( 30, generalizedTime.getCalendar().get( Calendar.SECOND ) );
+        assertEquals( 0, generalizedTime.getCalendar().get( Calendar.MILLISECOND ) );
+    }
+
+
+    /**
+     * Test formatting
+     */
+    public void testFormatting() throws ParseException
+    {
+        String gt = "20080102121314Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+
+        result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR_MIN, null, 0, TimeZoneFormat.Z );
+        assertEquals( "200801021213Z", result );
+
+        result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR, null, 0, TimeZoneFormat.Z );
+        assertEquals( "2008010212Z", result );
+
+        result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR_MIN, null, 0,
+            TimeZoneFormat.DIFF_HOUR_MINUTE );
+        assertEquals( "200801021213+0000", result );
+
+        result = generalizedTime.toGeneralizedTime( Format.YEAR_MONTH_DAY_HOUR, null, 0,
+            TimeZoneFormat.DIFF_HOUR_MINUTE );
+        assertEquals( "2008010212+0000", result );
+    }
+
+
+    /**
+     * Testcases from {@link GeneralizedTimeSyntaxCheckerTest#testCorrectCase()}.
+     */
+    public void testGeneralizedTimeSyntaxCheckerTestCorrectCase() throws ParseException
+    {
+        new GeneralizedTime( "20061205184527Z" );
+        new GeneralizedTime( "20061205184527+0500" );
+        new GeneralizedTime( "20061205184527-1234" );
+        new GeneralizedTime( "20061205184527.123Z" );
+        new GeneralizedTime( "20061205184527,123+0100" );
+        new GeneralizedTime( "2006120519Z" );
+    }
+
+
+    /**
+     * Testcases from {@link GeneralizedTimeSyntaxCheckerTest#testErrorCase()}.
+     */
+    public void testGeneralizedTimeSyntaxCheckerTestErrorCase()
+    {
+        try
+        {
+            new GeneralizedTime( "20060005184527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061305184527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20062205184527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061200184527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061235184527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205604527Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205186027Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184561Z" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184527Z+" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184527+2400" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184527+9900" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184527+1260" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+        try
+        {
+            new GeneralizedTime( "20061205184527+1299" );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+
+
+    /**
+     * Tests leap second.
+     * The GeneralizedTime class does not support leap seconds!
+     */
+    public void testLeapSecond() throws ParseException
+    {
+        String gt = "20051231235960Z";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+
+
+    /**
+     * Tests Feb 29 in a leap year.
+     */
+    public void testFebruary29inLeapYear() throws ParseException
+    {
+        String gt = "20080229000000Z";
+        GeneralizedTime generalizedTime = new GeneralizedTime( gt );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( gt, result );
+    }
+
+
+    /**
+     * Tests Feb 29 in a non-leap year.
+     */
+    public void testFebruary29inNonLeapYear() throws ParseException
+    {
+        String gt = "20070229000000Z";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+
+
+    /**
+     * Tests null.
+     */
+    public void testNull() throws ParseException
+    {
+        try
+        {
+            String gt = null;
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        try
+        {
+            Calendar calendar = null;
+            new GeneralizedTime( calendar );
+            fail( "Expected IllegalArgumentException" );
+        }
+        catch ( IllegalArgumentException iae )
+        {
+            // expected
+        }
+
+    }
+
+
+    /**
+     * Tests empty string.
+     */
+    public void testEmpty() throws ParseException
+    {
+        String gt = "";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+
+
+    /**
+     * Tests invalid cases.
+     */
+    public void testInvalid() throws ParseException
+    {
+        // too short year
+        String gt = "200";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in year
+        gt = "2XX8";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // too short month
+        gt = "20081";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in month
+        gt = "20081X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // too short day
+        gt = "2008122";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in day
+        gt = "2008122X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // too short hour
+        gt = "200812211";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in hour
+        gt = "20081221X1";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // too short minute
+        gt = "20081221121";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in minute
+        gt = "20081221121X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // too short second
+        gt = "2008122112131";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // non-digits in minute
+        gt = "2008122112131X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // missing time zone
+        gt = "2008010212";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // missing time zone
+        gt = "200801021213";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // missing time zone
+        gt = "20080102121314";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // no digit
+        gt = "2008010212X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // no digit
+        gt = "200801021213X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // no digit
+        gt = "20080102121314X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // missing time zone
+        gt = "20080102121314,1";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // time zone is not last char
+        gt = "20080102121314ZX";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // time zone is not last char
+        gt = "20080102121314+0430X";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+
+        // no fraction digit
+        gt = "20080102121314,Z";
+        try
+        {
+            new GeneralizedTime( gt );
+            fail( "Expected ParseException" );
+        }
+        catch ( ParseException pe )
+        {
+            // expected
+        }
+    }
+
+
+    /**
+     * Tests constructor with calendar object.
+     */
+    public void testCalendar() throws ParseException
+    {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set( Calendar.YEAR, 2008 );
+        calendar.set( Calendar.MONTH, 0 );
+        calendar.set( Calendar.DAY_OF_MONTH, 2 );
+        calendar.set( Calendar.HOUR_OF_DAY, 12 );
+        calendar.set( Calendar.MINUTE, 13 );
+        calendar.set( Calendar.SECOND, 14 );
+        calendar.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
+
+        GeneralizedTime generalizedTime = new GeneralizedTime( calendar );
+        String result = generalizedTime.toGeneralizedTime();
+        assertEquals( "20080102121314Z", result );
+
+    }
+
+
+    /**
+     * Tests the compareTo() method.
+     */
+    public void testCompareTo() throws ParseException
+    {
+        String gt1 = "20080102121313,999Z";
+        GeneralizedTime generalizedTime1 = new GeneralizedTime( gt1 );
+
+        String gt2 = "20080102121314Z";
+        GeneralizedTime generalizedTime2 = new GeneralizedTime( gt2 );
+
+        String gt3 = "20080102121314,001Z";
+        GeneralizedTime generalizedTime3 = new GeneralizedTime( gt3 );
+
+        assertTrue( generalizedTime1.compareTo( generalizedTime2 ) < 0 );
+        assertTrue( generalizedTime1.compareTo( generalizedTime3 ) < 0 );
+        assertTrue( generalizedTime2.compareTo( generalizedTime3 ) < 0 );
+
+        assertTrue( generalizedTime2.compareTo( generalizedTime1 ) > 0 );
+        assertTrue( generalizedTime3.compareTo( generalizedTime1 ) > 0 );
+        assertTrue( generalizedTime3.compareTo( generalizedTime2 ) > 0 );
+
+        assertTrue( generalizedTime1.compareTo( generalizedTime1 ) == 0 );
+        assertTrue( generalizedTime2.compareTo( generalizedTime2 ) == 0 );
+        assertTrue( generalizedTime3.compareTo( generalizedTime3 ) == 0 );
+    }
+
+
+    /**
+     * Tests the equals() method.
+     */
+    public void testEquals() throws ParseException
+    {
+        String gt1 = "20080102121314Z";
+        GeneralizedTime generalizedTime1 = new GeneralizedTime( gt1 );
+
+        String gt2 = "20080102121314Z";
+        GeneralizedTime generalizedTime2 = new GeneralizedTime( gt2 );
+
+        String gt3 = "20080102121314,001Z";
+        GeneralizedTime generalizedTime3 = new GeneralizedTime( gt3 );
+
+        assertTrue( generalizedTime1.equals( generalizedTime2 ) );
+        assertFalse( generalizedTime1.equals( generalizedTime3 ) );
+        assertFalse( generalizedTime1.equals( null ) );
+    }
+}
diff --git a/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/collective.schema b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/collective.schema
new file mode 100644
index 0000000..504104d
--- /dev/null
+++ b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/collective.schema
@@ -0,0 +1,82 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License. 
+
+# collective.schema -- Collective attribute schema
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/collective.schema,v 1.12.2.2 2007/08/31 23:14:06 quanah Exp $
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2007 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+#
+
+# The version of this file as distributed by the OpenLDAP Foundation
+# contains text from an IETF RFC explaining the schema.  Unfortunately,
+# that text is covered by a license that doesn't meet Debian's Free
+# Software Guidelines.  This is a stripped version of the schema that
+# contains only the functional schema definition, not the text of the
+# RFC.
+#
+# For an explanation of this schema, see RFC 3671, at (among other
+# places):  http://www.ietf.org/rfc/rfc3671.txt
+
+attributeType      ( 2.5.4.7.1 NAME 'c-l'
+	SUP l COLLECTIVE )
+
+attributeType      ( 2.5.4.8.1 NAME 'c-st'
+	SUP st COLLECTIVE )
+
+attributeType      ( 2.5.4.9.1 NAME 'c-street'
+	SUP street COLLECTIVE )
+
+attributeType      ( 2.5.4.10.1 NAME 'c-o'
+	SUP o COLLECTIVE )
+
+attributeType      ( 2.5.4.11.1 NAME 'c-ou'
+	SUP ou COLLECTIVE )
+
+attributeType      ( 2.5.4.16.1 NAME 'c-PostalAddress'
+	SUP postalAddress COLLECTIVE )
+
+attributeType      ( 2.5.4.17.1 NAME 'c-PostalCode'
+	SUP postalCode COLLECTIVE )
+
+attributeType ( 2.5.4.18.1 NAME 'c-PostOfficeBox'
+	SUP postOfficeBox COLLECTIVE )
+
+attributeType ( 2.5.4.19.1 NAME 'c-PhysicalDeliveryOfficeName'
+	SUP physicalDeliveryOfficeName COLLECTIVE )
+
+attributeType ( 2.5.4.20.1 NAME 'c-TelephoneNumber'
+	SUP telephoneNumber COLLECTIVE )
+
+attributeType ( 2.5.4.21.1 NAME 'c-TelexNumber'
+	SUP telexNumber COLLECTIVE )
+
+attributeType ( 2.5.4.23.1 NAME 'c-FacsimileTelephoneNumber'
+	SUP facsimileTelephoneNumber COLLECTIVE )
+
+attributeType ( 2.5.4.25.1 NAME 'c-InternationalISDNNumber'
+	SUP internationalISDNNumber COLLECTIVE )
+
diff --git a/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/core.schema b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/core.schema
new file mode 100644
index 0000000..93b465a
--- /dev/null
+++ b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/core.schema
@@ -0,0 +1,620 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.  
+
+# OpenLDAP Core schema
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/core.schema,v 1.79.2.8 2007/01/02 21:44:09 kurt Exp $
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2007 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+#
+
+# The version of this file as distributed by the OpenLDAP Foundation
+# contains text claiming copyright by the Internet Society and including
+# the IETF RFC license, which does not meet Debian's Free Software
+# Guidelines.  However, apart from short and obvious comments, the text of
+# this file is purely a functional interface specification, which is not
+# subject to that license and is not copyrightable under US law.
+#
+# The license statement is retained below so as not to remove credit, but
+# as best as we can determine, it is not applicable to the contents of
+# this file.
+
+## Portions Copyright (C) The Internet Society (1997-2003).
+## All Rights Reserved.
+##
+## This document and translations of it may be copied and furnished to
+## others, and derivative works that comment on or otherwise explain it
+## or assist in its implementation may be prepared, copied, published
+## and distributed, in whole or in part, without restriction of any
+## kind, provided that the above copyright notice and this paragraph are
+## included on all such copies and derivative works.  However, this
+## document itself may not be modified in any way, such as by removing
+## the copyright notice or references to the Internet Society or other
+## Internet organizations, except as needed for the purpose of
+## developing Internet standards in which case the procedures for
+## copyrights defined in the Internet Standards process must be         
+## followed, or as required to translate it into languages other than
+## English.
+##                                                                      
+## The limited permissions granted above are perpetual and will not be  
+## revoked by the Internet Society or its successors or assigns.        
+## 
+## This document and the information contained herein is provided on an 
+## "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+## TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+## BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+## HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+## MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+#
+# Includes LDAPv3 schema items from:
+#	RFC 2252/2256 (LDAPv3)
+#
+# Select standard track schema items:
+#	RFC 1274 (uid/dc)
+#	RFC 2079 (URI)
+#	RFC 2247 (dc/dcObject)
+#	RFC 2587 (PKI)
+#	RFC 2589 (Dynamic Directory Services)
+#
+# Select informational schema items:
+#	RFC 2377 (uidObject)
+
+#
+# Standard attribute types from RFC 2256
+#
+
+# system schema
+#attributetype ( 2.5.4.0 NAME 'objectClass'
+#	DESC 'RFC2256: object classes of the entity'
+#	EQUALITY objectIdentifierMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+# system schema
+#attributetype ( 2.5.4.1 NAME ( 'aliasedObjectName' 'aliasedEntryName' )
+#	DESC 'RFC2256: name of aliased object'
+#	EQUALITY distinguishedNameMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+
+attributetype ( 2.5.4.2 NAME 'knowledgeInformation'
+	DESC 'RFC2256: knowledge information'
+	EQUALITY caseIgnoreMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# system schema
+#attributetype ( 2.5.4.3 NAME ( 'cn' 'commonName' )
+#	DESC 'RFC2256: common name(s) for which the entity is known by'
+#	SUP name )
+
+attributetype ( 2.5.4.4 NAME ( 'sn' 'surname' )
+	DESC 'RFC2256: last (family) name(s) for which the entity is known by'
+	SUP name )
+
+attributetype ( 2.5.4.5 NAME 'serialNumber'
+	DESC 'RFC2256: serial number of the entity'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
+
+attributetype ( 2.5.4.6 NAME ( 'c' 'countryName' )
+	DESC 'RFC2256: ISO-3166 country 2-letter code'
+	SUP name SINGLE-VALUE )
+
+attributetype ( 2.5.4.7 NAME ( 'l' 'localityName' )
+	DESC 'RFC2256: locality which this object resides in'
+	SUP name )
+
+attributetype ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' )
+	DESC 'RFC2256: state or province which this object resides in'
+	SUP name )
+
+attributetype ( 2.5.4.9 NAME ( 'street' 'streetAddress' )
+	DESC 'RFC2256: street address of this object'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.10 NAME ( 'o' 'organizationName' )
+	DESC 'RFC2256: organization this object belongs to'
+	SUP name )
+
+attributetype ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' )
+	DESC 'RFC2256: organizational unit this object belongs to'
+	SUP name )
+
+attributetype ( 2.5.4.12 NAME 'title'
+	DESC 'RFC2256: title associated with the entity'
+	SUP name )
+
+# system schema
+#attributetype ( 2.5.4.13 NAME 'description'
+#	DESC 'RFC2256: descriptive information'
+#	EQUALITY caseIgnoreMatch
+#	SUBSTR caseIgnoreSubstringsMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
+
+# Deprecated by enhancedSearchGuide
+attributetype ( 2.5.4.14 NAME 'searchGuide'
+	DESC 'RFC2256: search guide, deprecated by enhancedSearchGuide'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
+
+attributetype ( 2.5.4.15 NAME 'businessCategory'
+	DESC 'RFC2256: business category'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.16 NAME 'postalAddress'
+	DESC 'RFC2256: postal address'
+	EQUALITY caseIgnoreListMatch
+	SUBSTR caseIgnoreListSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attributetype ( 2.5.4.17 NAME 'postalCode'
+	DESC 'RFC2256: postal code'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attributetype ( 2.5.4.18 NAME 'postOfficeBox'
+	DESC 'RFC2256: Post Office Box'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
+
+attributetype ( 2.5.4.19 NAME 'physicalDeliveryOfficeName'
+	DESC 'RFC2256: Physical Delivery Office Name'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
+
+attributetype ( 2.5.4.20 NAME 'telephoneNumber'
+	DESC 'RFC2256: Telephone Number'
+	EQUALITY telephoneNumberMatch
+	SUBSTR telephoneNumberSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
+
+attributetype ( 2.5.4.21 NAME 'telexNumber'
+	DESC 'RFC2256: Telex Number'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
+
+attributetype ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
+	DESC 'RFC2256: Teletex Terminal Identifier'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
+
+attributetype ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
+	DESC 'RFC2256: Facsimile (Fax) Telephone Number'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
+
+attributetype ( 2.5.4.24 NAME 'x121Address'
+	DESC 'RFC2256: X.121 Address'
+	EQUALITY numericStringMatch
+	SUBSTR numericStringSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
+
+attributetype ( 2.5.4.25 NAME 'internationaliSDNNumber'
+	DESC 'RFC2256: international ISDN number'
+	EQUALITY numericStringMatch
+	SUBSTR numericStringSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
+
+attributetype ( 2.5.4.26 NAME 'registeredAddress'
+	DESC 'RFC2256: registered postal address'
+	SUP postalAddress
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
+
+attributetype ( 2.5.4.27 NAME 'destinationIndicator'
+	DESC 'RFC2256: destination indicator'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
+
+attributetype ( 2.5.4.28 NAME 'preferredDeliveryMethod'
+	DESC 'RFC2256: preferred delivery method'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
+	SINGLE-VALUE )
+
+attributetype ( 2.5.4.29 NAME 'presentationAddress'
+	DESC 'RFC2256: presentation address'
+	EQUALITY presentationAddressMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
+	SINGLE-VALUE )
+
+attributetype ( 2.5.4.30 NAME 'supportedApplicationContext'
+	DESC 'RFC2256: supported application context'
+	EQUALITY objectIdentifierMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
+
+attributetype ( 2.5.4.31 NAME 'member'
+	DESC 'RFC2256: member of a group'
+	SUP distinguishedName )
+
+attributetype ( 2.5.4.32 NAME 'owner'
+	DESC 'RFC2256: owner (of the object)'
+	SUP distinguishedName )
+
+attributetype ( 2.5.4.33 NAME 'roleOccupant'
+	DESC 'RFC2256: occupant of role'
+	SUP distinguishedName )
+
+# system schema
+#attributetype ( 2.5.4.34 NAME 'seeAlso'
+#	DESC 'RFC2256: DN of related object'
+#	SUP distinguishedName )
+
+# system schema
+#attributetype ( 2.5.4.35 NAME 'userPassword'
+#	DESC 'RFC2256/2307: password of user'
+#	EQUALITY octetStringMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Must be transferred using ;binary
+# with certificateExactMatch rule (per X.509)
+attributetype ( 2.5.4.36 NAME 'userCertificate'
+	DESC 'RFC2256: X.509 user certificate, use ;binary'
+	EQUALITY certificateExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# Must be transferred using ;binary
+# with certificateExactMatch rule (per X.509)
+attributetype ( 2.5.4.37 NAME 'cACertificate'
+	DESC 'RFC2256: X.509 CA certificate, use ;binary'
+	EQUALITY certificateExactMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.38 NAME 'authorityRevocationList'
+	DESC 'RFC2256: X.509 authority revocation list, use ;binary'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.39 NAME 'certificateRevocationList'
+	DESC 'RFC2256: X.509 certificate revocation list, use ;binary'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+# Must be stored and requested in the binary form
+attributetype ( 2.5.4.40 NAME 'crossCertificatePair'
+	DESC 'RFC2256: X.509 cross certificate pair, use ;binary'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
+
+# system schema
+#attributetype ( 2.5.4.41 NAME 'name'
+#	EQUALITY caseIgnoreMatch
+#	SUBSTR caseIgnoreSubstringsMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+attributetype ( 2.5.4.42 NAME ( 'givenName' 'gn' )
+	DESC 'RFC2256: first name(s) for which the entity is known by'
+	SUP name )
+
+attributetype ( 2.5.4.43 NAME 'initials'
+	DESC 'RFC2256: initials of some or all of names, but not the surname(s).'
+	SUP name )
+
+attributetype ( 2.5.4.44 NAME 'generationQualifier'
+	DESC 'RFC2256: name qualifier indicating a generation'
+	SUP name )
+
+attributetype ( 2.5.4.45 NAME 'x500UniqueIdentifier'
+	DESC 'RFC2256: X.500 unique identifier'
+	EQUALITY bitStringMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
+
+attributetype ( 2.5.4.46 NAME 'dnQualifier'
+	DESC 'RFC2256: DN qualifier'
+	EQUALITY caseIgnoreMatch
+	ORDERING caseIgnoreOrderingMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
+
+attributetype ( 2.5.4.47 NAME 'enhancedSearchGuide'
+	DESC 'RFC2256: enhanced search guide'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
+
+attributetype ( 2.5.4.48 NAME 'protocolInformation'
+	DESC 'RFC2256: protocol information'
+	EQUALITY protocolInformationMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
+
+# system schema
+#attributetype ( 2.5.4.49 NAME 'distinguishedName'
+#	EQUALITY distinguishedNameMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+attributetype ( 2.5.4.50 NAME 'uniqueMember'
+	DESC 'RFC2256: unique member of a group'
+	EQUALITY uniqueMemberMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
+
+attributetype ( 2.5.4.51 NAME 'houseIdentifier'
+	DESC 'RFC2256: house identifier'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.52 NAME 'supportedAlgorithms'
+	DESC 'RFC2256: supported algorithms'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
+
+# Must be transferred using ;binary
+attributetype ( 2.5.4.53 NAME 'deltaRevocationList'
+	DESC 'RFC2256: delta revocation list; use ;binary'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
+
+attributetype ( 2.5.4.54 NAME 'dmdName'
+	DESC 'RFC2256: name of DMD'
+	SUP name )
+
+attributetype ( 2.5.4.65 NAME 'pseudonym'
+	DESC 'X.520(4th): pseudonym for the object'
+	SUP name )
+
+# Standard object classes from RFC2256
+
+# system schema
+#objectclass ( 2.5.6.0 NAME 'top'
+#	DESC 'RFC2256: top of the superclass chain'
+#	ABSTRACT
+#	MUST objectClass )
+
+# system schema
+#objectclass ( 2.5.6.1 NAME 'alias'
+#	DESC 'RFC2256: an alias'
+#	SUP top STRUCTURAL
+#	MUST aliasedObjectName )
+
+objectclass ( 2.5.6.2 NAME 'country'
+	DESC 'RFC2256: a country'
+	SUP top STRUCTURAL
+	MUST c
+	MAY ( searchGuide $ description ) )
+
+objectclass ( 2.5.6.3 NAME 'locality'
+	DESC 'RFC2256: a locality'
+	SUP top STRUCTURAL
+	MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
+
+objectclass ( 2.5.6.4 NAME 'organization'
+	DESC 'RFC2256: an organization'
+	SUP top STRUCTURAL
+	MUST o
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ 
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.5 NAME 'organizationalUnit'
+	DESC 'RFC2256: an organizational unit'
+	SUP top STRUCTURAL
+	MUST ou
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
+
+objectclass ( 2.5.6.6 NAME 'person'
+	DESC 'RFC2256: a person'
+	SUP top STRUCTURAL
+	MUST ( sn $ cn )
+	MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
+
+objectclass ( 2.5.6.7 NAME 'organizationalPerson'
+	DESC 'RFC2256: an organizational person'
+	SUP person STRUCTURAL
+	MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ 
+		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
+		postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )
+
+objectclass ( 2.5.6.8 NAME 'organizationalRole'
+	DESC 'RFC2256: an organizational role'
+	SUP top STRUCTURAL
+	MUST cn
+	MAY ( x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+		seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
+		postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
+
+objectclass ( 2.5.6.9 NAME 'groupOfNames'
+	DESC 'RFC2256: a group of names (DNs)'
+	SUP top STRUCTURAL
+	MUST ( member $ cn )
+	MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+objectclass ( 2.5.6.10 NAME 'residentialPerson'
+	DESC 'RFC2256: an residential person'
+	SUP person STRUCTURAL
+	MUST l
+	MAY ( businessCategory $ x121Address $ registeredAddress $
+		destinationIndicator $ preferredDeliveryMethod $ telexNumber $
+		teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $
+		facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
+		postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ st $ l ) )
+
+objectclass ( 2.5.6.11 NAME 'applicationProcess'
+	DESC 'RFC2256: an application process'
+	SUP top STRUCTURAL
+	MUST cn
+	MAY ( seeAlso $ ou $ l $ description ) )
+
+objectclass ( 2.5.6.12 NAME 'applicationEntity'
+	DESC 'RFC2256: an application entity'
+	SUP top STRUCTURAL
+	MUST ( presentationAddress $ cn )
+	MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
+	description ) )
+
+objectclass ( 2.5.6.13 NAME 'dSA'
+	DESC 'RFC2256: a directory system agent (a server)'
+	SUP applicationEntity STRUCTURAL
+	MAY knowledgeInformation )
+
+objectclass ( 2.5.6.14 NAME 'device'
+	DESC 'RFC2256: a device'
+	SUP top STRUCTURAL
+	MUST cn
+	MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
+
+objectclass ( 2.5.6.15 NAME 'strongAuthenticationUser'
+	DESC 'RFC2256: a strong authentication user'
+	SUP top AUXILIARY
+	MUST userCertificate )
+
+objectclass ( 2.5.6.16 NAME 'certificationAuthority'
+	DESC 'RFC2256: a certificate authority'
+	SUP top AUXILIARY
+	MUST ( authorityRevocationList $ certificateRevocationList $
+		cACertificate ) MAY crossCertificatePair )
+
+objectclass ( 2.5.6.17 NAME 'groupOfUniqueNames'
+	DESC 'RFC2256: a group of unique names (DN and Unique Identifier)'
+	SUP top STRUCTURAL
+	MUST ( uniqueMember $ cn )
+	MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
+
+objectclass ( 2.5.6.18 NAME 'userSecurityInformation'
+	DESC 'RFC2256: a user security information'
+	SUP top AUXILIARY
+	MAY ( supportedAlgorithms ) )
+
+objectclass ( 2.5.6.16.2 NAME 'certificationAuthority-V2'
+	SUP certificationAuthority
+	AUXILIARY MAY ( deltaRevocationList ) )
+
+objectclass ( 2.5.6.19 NAME 'cRLDistributionPoint'
+	SUP top STRUCTURAL
+	MUST ( cn )
+	MAY ( certificateRevocationList $ authorityRevocationList $
+		deltaRevocationList ) )
+
+objectclass ( 2.5.6.20 NAME 'dmd'
+	SUP top STRUCTURAL
+	MUST ( dmdName )
+	MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
+		x121Address $ registeredAddress $ destinationIndicator $
+		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
+		telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
+		street $ postOfficeBox $ postalCode $ postalAddress $
+		physicalDeliveryOfficeName $ st $ l $ description ) )
+
+#
+# Object Classes from RFC 2587
+#
+objectclass ( 2.5.6.21 NAME 'pkiUser'
+	DESC 'RFC2587: a PKI user'
+	SUP top AUXILIARY
+	MAY userCertificate )
+
+objectclass ( 2.5.6.22 NAME 'pkiCA'
+	DESC 'RFC2587: PKI certificate authority'
+	SUP top AUXILIARY
+	MAY ( authorityRevocationList $ certificateRevocationList $
+		cACertificate $ crossCertificatePair ) )
+
+objectclass ( 2.5.6.23 NAME 'deltaCRL'
+	DESC 'RFC2587: PKI user'
+	SUP top AUXILIARY
+	MAY deltaRevocationList )
+
+#
+# Standard Track URI label schema from RFC 2079
+# system schema
+#attributetype ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI'
+#	DESC 'RFC2079: Uniform Resource Identifier with optional label'
+#	EQUALITY caseExactMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+objectclass ( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject'
+	DESC 'RFC2079: object that contains the URI attribute type'
+	SUP top AUXILIARY
+	MAY ( labeledURI ) )
+
+#
+# Derived from RFC 1274, but with new "short names"
+#
+#attributetype ( 0.9.2342.19200300.100.1.1
+#	NAME ( 'uid' 'userid' )
+#	DESC 'RFC1274: user identifier'
+#	EQUALITY caseIgnoreMatch
+#	SUBSTR caseIgnoreSubstringsMatch
+#	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+attributetype ( 0.9.2342.19200300.100.1.3
+	NAME ( 'mail' 'rfc822Mailbox' )
+	DESC 'RFC1274: RFC822 Mailbox'
+    EQUALITY caseIgnoreIA5Match
+    SUBSTR caseIgnoreIA5SubstringsMatch
+    SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
+
+objectclass ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
+	DESC 'RFC1274: simple security object'
+	SUP top AUXILIARY
+	MUST userPassword )
+
+# RFC 1274 + RFC 2247
+attributetype ( 0.9.2342.19200300.100.1.25
+	NAME ( 'dc' 'domainComponent' )
+	DESC 'RFC1274/2247: domain component'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+# RFC 2247
+objectclass ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'
+	DESC 'RFC2247: domain component object'
+	SUP top AUXILIARY MUST dc )
+
+# RFC 2377
+objectclass ( 1.3.6.1.1.3.1 NAME 'uidObject'
+	DESC 'RFC2377: uid object'
+	SUP top AUXILIARY MUST uid )
+
+# From COSINE Pilot
+attributetype ( 0.9.2342.19200300.100.1.37
+	NAME 'associatedDomain'
+	DESC 'RFC1274: domain associated with object'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+# RFC 2459 -- deprecated in favor of 'mail' (in cosine.schema)
+attributetype ( 1.2.840.113549.1.9.1
+	NAME ( 'email' 'emailAddress' 'pkcs9email' )
+	DESC 'RFC3280: legacy attribute for email addresses in DNs'
+	EQUALITY caseIgnoreIA5Match
+	SUBSTR caseIgnoreIA5SubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
+
diff --git a/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/dyngroup.schema b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/dyngroup.schema
new file mode 100644
index 0000000..70dea02
--- /dev/null
+++ b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/dyngroup.schema
@@ -0,0 +1,99 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.  
+
+# dyngroup.schema -- Dynamic Group schema
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/dyngroup.schema,v 1.6.2.2 2007/08/31 23:14:06 quanah Exp $
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2007 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+#
+# Dynamic Group schema (experimental), as defined by Netscape.  See
+# http://www.redhat.com/docs/manuals/ent-server/pdf/esadmin611.pdf
+# page 70 for details on how these groups were used.
+#
+# A description of the objectclass definition is available here:
+# http://www.redhat.com/docs/manuals/dir-server/schema/7.1/oc_dir.html#1303745
+#
+# depends upon:
+#	core.schema
+#
+# These definitions are considered experimental due to the lack of
+# a formal specification (e.g., RFC).
+#
+# NOT RECOMMENDED FOR PRODUCTION USE!  USE WITH CAUTION!
+#
+# The Netscape documentation describes this as an auxiliary objectclass
+# but their implementations have always defined it as a structural class.
+# The sloppiness here is because Netscape-derived servers don't actually
+# implement the X.500 data model, and they don't honor the distinction
+# between structural and auxiliary classes. This fact is noted here:
+# http://forum.java.sun.com/thread.jspa?threadID=5016864&messageID=9034636
+#
+# In accordance with other existing implementations, we define it as a
+# structural class.
+#
+# Our definition of memberURL also does not match theirs but again
+# their published definition and what works in practice do not agree.
+# In other words, the Netscape definitions are broken and interoperability
+# is not guaranteed.
+#
+# Also see the new DynGroup proposed spec at
+# http://tools.ietf.org/html/draft-haripriya-dynamicgroup-02
+
+objectIdentifier NetscapeRoot 2.16.840.1.113730
+
+objectIdentifier NetscapeLDAP NetscapeRoot:3
+objectIdentifier NetscapeLDAPattributeType NetscapeLDAP:1
+objectIdentifier NetscapeLDAPobjectClass NetscapeLDAP:2
+
+objectIdentifier OpenLDAPExp11	1.3.6.1.4.1.4203.666.11
+objectIdentifier DynGroupBase	OpenLDAPExp11:8
+objectIdentifier DynGroupAttr	DynGroupBase:1
+objectIdentifier DynGroupOC	DynGroupBase:2
+
+attributetype ( NetscapeLDAPattributeType:198
+	NAME 'memberURL'
+	DESC 'Identifies an URL associated with each member of a group. Any type of labeled URL can be used.'
+	SUP labeledURI )
+
+attributetype ( DynGroupAttr:1
+	NAME 'dgIdentity'
+	DESC 'Identity to use when processing the memberURL'
+	SUP distinguishedName SINGLE-VALUE )
+
+objectClass ( NetscapeLDAPobjectClass:33
+	NAME 'groupOfURLs'
+	SUP top STRUCTURAL
+	MUST cn
+	MAY ( memberURL $ businessCategory $ description $ o $ ou $
+		owner $ seeAlso ) )
+
+# The Haripriya dyngroup schema still needs a lot of work.
+# We're just adding support for the dgIdentity attribute for now...
+objectClass ( DynGroupOC:1
+	NAME 'dgIdentityAux'
+	SUP top AUXILIARY
+	MAY dgIdentity )
diff --git a/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/inetorgperson.schema b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/inetorgperson.schema
new file mode 100644
index 0000000..77e568a
--- /dev/null
+++ b/ldap/src/test/resources/org/apache/directory/shared/ldap/schema/parser/inetorgperson.schema
@@ -0,0 +1,172 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.  
+
+# inetorgperson.schema -- InetOrgPerson (RFC2798)
+# $OpenLDAP: pkg/ldap/servers/slapd/schema/inetorgperson.schema,v 1.18.2.2 2007/08/31 23:14:06 quanah Exp $
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2007 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+#
+# InetOrgPerson (RFC2798)
+#
+# Depends upon
+#   Definition of an X.500 Attribute Type and an Object Class to Hold
+#   Uniform Resource Identifiers (URIs) [RFC2079]
+#	(core.schema)
+#
+#   A Summary of the X.500(96) User Schema for use with LDAPv3 [RFC2256]
+#	(core.schema)
+#
+#   The COSINE and Internet X.500 Schema [RFC1274] (cosine.schema)
+
+# carLicense
+# This multivalued field is used to record the values of the license or
+# registration plate associated with an individual.
+attributetype ( 2.16.840.1.113730.3.1.1
+	NAME 'carLicense'
+	DESC 'RFC2798: vehicle license or registration plate'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# departmentNumber
+# Code for department to which a person belongs.  This can also be
+# strictly numeric (e.g., 1234) or alphanumeric (e.g., ABC/123).
+attributetype ( 2.16.840.1.113730.3.1.2
+	NAME 'departmentNumber'
+	DESC 'RFC2798: identifies a department within an organization'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# displayName
+# When displaying an entry, especially within a one-line summary list, it
+# is useful to be able to identify a name to be used.  Since other attri-
+# bute types such as 'cn' are multivalued, an additional attribute type is
+# needed.  Display name is defined for this purpose.
+attributetype ( 2.16.840.1.113730.3.1.241
+	NAME 'displayName'
+	DESC 'RFC2798: preferred name to be used when displaying entries'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# employeeNumber
+# Numeric or alphanumeric identifier assigned to a person, typically based
+# on order of hire or association with an organization.  Single valued.
+attributetype ( 2.16.840.1.113730.3.1.3
+	NAME 'employeeNumber'
+	DESC 'RFC2798: numerically identifies an employee within an organization'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# employeeType
+# Used to identify the employer to employee relationship.  Typical values
+# used will be "Contractor", "Employee", "Intern", "Temp", "External", and
+# "Unknown" but any value may be used.
+attributetype ( 2.16.840.1.113730.3.1.4
+	NAME 'employeeType'
+	DESC 'RFC2798: type of employment for a person'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+# jpegPhoto
+# Used to store one or more images of a person using the JPEG File
+# Interchange Format [JFIF].
+# Note that the jpegPhoto attribute type was defined for use in the
+# Internet X.500 pilots but no referencable definition for it could be
+# located.
+attributetype ( 0.9.2342.19200300.100.1.60
+	NAME 'jpegPhoto'
+	DESC 'RFC2798: a JPEG image'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )
+
+# preferredLanguage
+# Used to indicate an individual's preferred written or spoken
+# language.  This is useful for international correspondence or human-
+# computer interaction.  Values for this attribute type MUST conform to
+# the definition of the Accept-Language header field defined in
+# [RFC2068] with one exception:  the sequence "Accept-Language" ":"
+# should be omitted.  This is a single valued attribute type.
+attributetype ( 2.16.840.1.113730.3.1.39
+	NAME 'preferredLanguage'
+	DESC 'RFC2798: preferred written or spoken language for a person'
+	EQUALITY caseIgnoreMatch
+	SUBSTR caseIgnoreSubstringsMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+	SINGLE-VALUE )
+
+# userSMIMECertificate
+# A PKCS#7 [RFC2315] SignedData, where the content that is signed is
+# ignored by consumers of userSMIMECertificate values.  It is
+# recommended that values have a `contentType' of data with an absent
+# `content' field.  Values of this attribute contain a person's entire
+# certificate chain and an smimeCapabilities field [RFC2633] that at a
+# minimum describes their SMIME algorithm capabilities.  Values for
+# this attribute are to be stored and requested in binary form, as
+# 'userSMIMECertificate;binary'.  If available, this attribute is
+# preferred over the userCertificate attribute for S/MIME applications.
+## OpenLDAP note: ";binary" transfer should NOT be used as syntax is binary
+attributetype ( 2.16.840.1.113730.3.1.40
+	NAME 'userSMIMECertificate'
+	DESC 'RFC2798: PKCS#7 SignedData used to support S/MIME'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+# userPKCS12
+# PKCS #12 [PKCS12] provides a format for exchange of personal identity
+# information.  When such information is stored in a directory service,
+# the userPKCS12 attribute should be used. This attribute is to be stored
+# and requested in binary form, as 'userPKCS12;binary'.  The attribute
+# values are PFX PDUs stored as binary data.
+## OpenLDAP note: ";binary" transfer should NOT be used as syntax is binary
+attributetype ( 2.16.840.1.113730.3.1.216
+	NAME 'userPKCS12'
+	DESC 'RFC2798: personal identity information, a PKCS #12 PFX'
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+
+# inetOrgPerson
+# The inetOrgPerson represents people who are associated with an
+# organization in some way.  It is a structural class and is derived
+# from the organizationalPerson which is defined in X.521 [X521].
+objectclass	( 2.16.840.1.113730.3.2.2
+    NAME 'inetOrgPerson'
+	DESC 'RFC2798: Internet Organizational Person'
+    SUP organizationalPerson
+    STRUCTURAL
+	MAY (
+		audio $ businessCategory $ carLicense $ departmentNumber $
+		displayName $ employeeNumber $ employeeType $ givenName $
+		homePhone $ homePostalAddress $ initials $ jpegPhoto $
+		labeledURI $ mail $ manager $ mobile $ o $ pager $
+		photo $ roomNumber $ secretary $ uid $ userCertificate $
+		x500uniqueIdentifier $ preferredLanguage $
+		userSMIMECertificate $ userPKCS12 )
+	)
diff --git a/ldap/xdocs/index.xml b/ldap/xdocs/index.xml
deleted file mode 100644
index 115a224..0000000
--- a/ldap/xdocs/index.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document>
-  <properties>
-    <author email="jmachols@apache.org">Jeff Machols</author>
-    <title>Apache Directory Project: LDAP Common Code</title>
-  </properties>
-  
-  <body>
-    <section name="Overview">
-      <p>LDAP Common Code</p>
-      <p> 
-      This project contains code and utilities common to the LDAP protocol.
-      </p>
-    </section>
-    <section name="LDAP Common Packages">
-      <subsection name="Filter">
-        <p>
-          The filter package will parsese and LDAP expression into 
-          a filter expression tree as defined in <a href="http://www.ietf.org/rfc/rfc2254.txt">RFC 2254</a>
-        </p>  
-      </subsection>
-        
-      <subsection name="LDIF">
-        <p>
-          The The LDAP Data Interchange Format (LDIF) parsing 
-          package Parses an LDIF into a multimap or a JNDI 
-          Attributes instance of attributeToPropertyMapping key/value pairs with
-          potential more than one attributeToPropertyMapping value per attributeToPropertyMapping.
-          This parser populates the MultiMap or Attributes 
-          instance with all attributeToPropertyMappings within the LDIF including
-          control attributeToPropertyMappings like the 'dn' and the changeType.
-        </p>
-        <p>
-          The package contain an LDIF entry class that can be used.  Along
-          with the parsing utility, the embedding application can LDIF
-          parsing and management without becomming an expert on the RFC.
-          Addition details about LDIF can be obtained from the 
-          <a href="http://www.ietf.org/rfc/rfc2849.txt">LDIF RFC</a>
-        </p>        
-      </subsection>
-      
-      <subsection name="Message">
-      	<p>
-          The LDAP Common Messaging package provides a framework for
-          all LDAP request and response messages.  Each of the reponses
-          and requests have an implementation.
-      	</p>
-      </subsection>
-      
-      <subsection name="Name">
-        <p>
-          This package provides LDAP distinguished name creation and 
-          normalization.  This provides a common method for ensuring 
-          you are creating the entry DN correctly.  Failure to properly
-          create and normalize the DN of an entry will result in unpredicatble
-          results when operations are performed on the entry.  
-        </p>
-      </subsection>
-      
-    </section>
-  </body>
-</document>
diff --git a/ldap/xdocs/navigation.xml b/ldap/xdocs/navigation.xml
deleted file mode 100644
index 58d73d6..0000000
--- a/ldap/xdocs/navigation.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<project>
-
- <title>LDAP Shared</title>
-
- <body>
-
-    <links>
-      <item name="Directory" href="../../../index.html"/>
-      <item name="ApacheDS" href="../../apacheds/index.html"/>
-      <item name="LDAP" href="../../ldap.html"/>
-      <item name="Naming" href="../../naming/index.html"/>
-      <item name="ASN.1" href="../../asn1/index.html"/>
-      <item name="Kerberos" href="../../../subprojects/kerberos.html"/>
-      <item name="AuthX" href="../../authx/index.html"/>
-      <item name="MINA" href="../../network/index.html"/>
-      <item name="Protocols" href="../../providers.html"/>
-    </links>
-
-    <menu name="LDAP">
-      <item name="Overview" href="/index.html"/>
-    </menu>
-    
-    <menu name="Project Information">
-      <item name="Wiki" href="http://wiki.apache.org/directory"/>
-      <item name="Open Issues" href="http://issues.apache.org/jira/browse/DIRLDAP"/>
-      <item name="Source Repositories" href="http://svn.apache.org/viewcvs.cgi/directory/shared/ldap/trunk/?root=Apache-SVN"/>
-    </menu>
-
-    <menu name="ApacheCon Europe 2005"> 	 
-      <item name="ApacheCon Europe 2005" href="http://www.apachecon.com/"
-            img="http://apache.org/images/ac2005eu_135x50.gif" />
-    </menu>
- </body>
-
-</project>
diff --git a/pom.xml b/pom.xml
index 10f782e..674c9df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,34 +1,52 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements.  See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to You under the Apache License, Version 2.0
-    (the "License"); you may not use this file except in compliance with
-    the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<!-- $Rev:  $ $Date:  $ -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+  http://www.apache.org/licenses/LICENSE-2.0
+  
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>org.apache.directory.project</groupId>
     <artifactId>project</artifactId>
-    <version>8</version>
+    <version>10</version>
   </parent>
   <groupId>org.apache.directory.shared</groupId>
   <artifactId>shared-parent</artifactId>
   <name>Apache Directory Shared</name>
-  <packaging>pom</packaging>  
-  <version>0.9.8-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <version>0.9.12-SNAPSHOT</version>
+
+  <properties>
+    <projectName>ApacheDS-Shared</projectName>
+    <!--<siteId>apacheds-shared</siteId>-->
+  </properties>
   
+  <distributionManagement>
+    <site>
+      <id>apache.directory.shared</id>
+      <!--<url>${staging.siteURL}/${siteId}/${version}</url>-->
+      <url>scpexe://vm094.oxylos.org/var/www/html/projects/shared/</url>
+    </site>
+  </distributionManagement>
+
+  <issueManagement>
+    <system>JIRA</system>
+    <url>http://issues.apache.org/jira/browse/DIRSHARED</url>
+  </issueManagement>
+
   <modules>
     <module>asn1</module>
     <module>ldap</module>
@@ -36,6 +54,7 @@
     <module>ldap-constants</module>
     <module>asn1-codec</module>
     <module>convert</module>
+    <module>bouncycastle-reduced</module>
   </modules>
 
   <dependencyManagement>
@@ -69,8 +88,8 @@
         <artifactId>antlr</artifactId>
         <version>2.7.7</version>
       </dependency>
- 
-     <dependency>
+
+      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.4</version>
@@ -79,7 +98,7 @@
       <dependency>
         <groupId>org.apache.mina</groupId>
         <artifactId>mina-core</artifactId>
-        <version>1.1.2</version>
+        <version>1.1.6</version>
       </dependency>
     </dependencies>
   </dependencyManagement>
@@ -115,36 +134,65 @@
         </plugin>
       </plugins>
     </pluginManagement>
-
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-release-plugin</artifactId>
-        <configuration>
-          <tagBase>https://svn.apache.org/repos/asf/directory/shared/releases</tagBase>
-        </configuration>
-      </plugin>
-    </plugins>
   </build>
 
-
   <reporting>
     <excludeDefaults>true</excludeDefaults>
     <plugins>
+      <!--
+        <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>changelog-maven-plugin</artifactId>
+        <reportSets>
+        <reportSet>
+        <id>dual-report</id>
+        <configuration>
+        <type>range</type>
+        <range>30</range>
+        </configuration>
+        <reports>
+        <report>changelog</report>
+        <report>file-activity</report>
+        <report>dev-activity</report>
+        </reports>
+        </reportSet>
+        </reportSets>
+        </plugin>
+      -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-project-info-reports-plugin</artifactId>
-        <reportSets>
-          <reportSet>
-            <reports>
-              <report>project-team</report>
-              <report>mailing-list</report>
-              <report>issue-tracking</report>
-              <report>license</report>
-              <report>scm</report>
-            </reports>
-          </reportSet>
-        </reportSets>
+        <artifactId>maven-surefire-report-plugin</artifactId>
+        <configuration>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <configuration>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <configuration>
+          <linkXref>true</linkXref>
+          <sourceEncoding>utf-8</sourceEncoding>
+          <minimumTokens>100</minimumTokens>
+          <targetJdk>1.5</targetJdk>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>taglist-maven-plugin</artifactId>
+        <configuration>
+          <tags>
+            <tag>TODO</tag>
+            <tag>@todo</tag>
+            <tag>@deprecated</tag>
+            <tag>FIXME</tag>
+          </tags>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
@@ -153,50 +201,54 @@
           <aggregate>true</aggregate>
         </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>1.1.1</version>
+        <configuration>
+          <xmlOutput>false</xmlOutput>
+          <!--
+            <xmlOutput>true|false</xmlOutput>
+            <xmlOutputDirectory>directory location of xml findbugs report</xmlOutputDirectory>
+            <threshold>High|Normal|Low|Exp|Ignore</threshold>
+            <effort>Min|Default|Max</effort>
+            <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
+            <includeFilterFile>findbugs-include.xml</includeFilterFile>
+            <visitors>FindDeadLocalStores,UnreadFields</visitors>
+            <omitVisitors>FindDeadLocalStores,UnreadFields</omitVisitors>
+            <onlyAnalyze>org.codehaus.mojo.findbugs.*</onlyAnalyze>
+            <pluginList>/libs/fb-contrib/fb-contrib-2.8.0.jar</pluginList>
+            <debug>true|false</debug>
+            <relaxed>true|false</relaxed>
+          -->
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
     </plugins>
   </reporting>
 
-  <profiles>
-    <profile>
-      <id>release</id>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-gpg-plugin</artifactId>
-            <executions>
-              <execution>
-                <goals><goal>sign</goal></goals>
-              </execution>
-            </executions>
-          </plugin>
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/directory/shared/trunk</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/directory/shared/trunk</developerConnection>
+    <url>http://svn.apache.org/viewvc/directory/shared/trunk</url>
+  </scm>
 
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-source-plugin</artifactId>
-            <!-- TODO remove this version tag after using TLP pom 9 -->
-            <version>2.0.3</version>
-            <executions>
-              <execution>
-                <id>attach-sources</id>
-                <goals><goal>jar</goal></goals>
-              </execution>
-            </executions>
-          </plugin>
+  <repositories>
+    <repository>
+      <id>apache.directory.snapshot.repo</id>
+      <name>Snapshot repository for the Apache Directory project</name>
+      <url>http://vm094.oxylos.org/mirror-maven2/</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+    </repository>
+  </repositories>
 
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-javadoc-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>attach-javadocs</id>
-                <goals><goal>jar</goal></goals>
-              </execution>
-            </executions>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
 </project>
-
diff --git a/src/main/appended-resources/supplemental-models.xml b/src/main/appended-resources/supplemental-models.xml
index f686f2b..be2d715 100644
--- a/src/main/appended-resources/supplemental-models.xml
+++ b/src/main/appended-resources/supplemental-models.xml
@@ -1,4 +1,23 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
 <supplementalDataModels>
   <supplement>
     <project>