From eaee3f6a42c1a129f07e2364a4c32c59b9e03e19 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Tue, 09 Feb 2016 15:22:22 +0000
Subject: [PATCH] Prep work for OPENDJ-1342: align APIs for RDNs

---
 opendj-server-legacy/src/main/java/org/opends/server/admin/server/ServerManagementContext.java                        |    6 
 opendj-server-legacy/src/main/java/org/opends/server/plugins/SevenBitCleanPlugin.java                                 |   37 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java                       |   10 
 opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java                                     |   52 +
 opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java                                  |   10 
 opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java                       |   10 
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternRDN.java                         |   15 
 opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java                                                   |  398 ++++------------
 opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java                                            |   65 +-
 opendj-server-legacy/src/main/java/org/opends/server/core/PluginConfigManager.java                                    |   74 ++
 opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java       |   27 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java   |   18 
 opendj-server-legacy/src/main/java/org/opends/server/util/LDIFReader.java                                             |   25 
 opendj-server-legacy/src/main/java/org/opends/server/tasks/BackupTask.java                                            |    2 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java                         |   50 +-
 opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java                    |   29 
 opendj-server-legacy/src/main/java/org/opends/server/admin/Reference.java                                             |   12 
 opendj-server-legacy/src/test/java/org/opends/server/core/PluginConfigManagerTestCase.java                            |   20 
 opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java                                      |   53 +
 opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java                               |   53 -
 opendj-server-legacy/src/test/java/org/opends/server/types/TestRDN.java                                               |   89 ++-
 opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java                                          |    9 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java                  |  109 +--
 opendj-server-legacy/src/main/java/org/opends/server/backends/BackupBackend.java                                      |    9 
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java                         |    8 
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ExternalChangelogDomain.java                  |   11 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/nodes/BasicNode.java                           |   20 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/TableViewEntryPanel.java                       |   30 
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java                            |   11 
 opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java  |   24 
 opendj-server-legacy/src/main/java/org/opends/server/core/EntryCacheConfigManager.java                                |    4 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java                        |    4 
 opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java                                         |    4 
 opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java                                                 |    6 
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java                    |    5 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java                        |    4 
 opendj-server-legacy/src/test/java/org/opends/server/admin/server/DefaultBehaviorTest.java                            |   26 
 opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ConfigurableEnvironment.java                        |    6 
 opendj-server-legacy/src/main/java/org/opends/server/backends/TrustStoreBackend.java                                  |   34 +
 opendj-server-legacy/src/main/java/org/opends/server/extensions/SubjectAttributeToUserAttributeCertificateMapper.java |    9 
 opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java                                    |   23 
 41 files changed, 638 insertions(+), 773 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
index 397ec4a..271fb5c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2008-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
 package org.opends.guitools.controlpanel.task;
 
@@ -47,7 +47,10 @@
 import javax.swing.tree.TreePath;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.AVA;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.guitools.controlpanel.browser.BrowserController;
 import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
 import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
@@ -120,9 +123,9 @@
       }
       mustRename = !newDn.equals(oldDn);
     }
-    catch (OpenDsException ode)
+    catch (OpenDsException e)
     {
-      throw new RuntimeException("Could not parse DN: " + oldEntry.getDN(), ode);
+      throw new RuntimeException("Could not parse DN: " + oldEntry.getDN(), e);
     }
     modifications = getModifications(newEntry, oldEntry, getInfo());
     // Find password modifications
@@ -422,14 +425,14 @@
 
   private boolean rdnTypeChanged(RDN oldRDN, RDN newRDN)
   {
-    if (newRDN.getNumValues() != oldRDN.getNumValues())
+    if (newRDN.size() != oldRDN.size())
     {
       return true;
     }
 
-    for (int i = 0; i < newRDN.getNumValues(); i++)
+    for (AVA ava : newRDN)
     {
-      if (!find(oldRDN, newRDN.getAttributeName(i)))
+      if (!find(oldRDN, ava.getAttributeType()))
       {
         return true;
       }
@@ -437,11 +440,11 @@
     return false;
   }
 
-  private boolean find(RDN rdn, String attrName)
+  private boolean find(RDN rdn, AttributeType attrType)
   {
-    for (int j = 0; j < rdn.getNumValues(); j++)
+    for (AVA ava : rdn)
     {
-      if (attrName.equalsIgnoreCase(rdn.getAttributeName(j)))
+      if (attrType.equals(ava.getAttributeType()))
       {
         return true;
       }
@@ -463,9 +466,9 @@
 
   private boolean entryContainsRdnTypes(CustomSearchResult entry, RDN rdn)
   {
-    for (int i = 0; i < rdn.getNumValues(); i++)
+    for (AVA ava : rdn)
     {
-      List<Object> values = entry.getAttributeValues(rdn.getAttributeName(i));
+      List<Object> values = entry.getAttributeValues(ava.getAttributeName());
       if (values.isEmpty())
       {
         return false;
@@ -490,7 +493,8 @@
     newAttrs.add(newEntry.getObjectClassAttribute());
     for (org.opends.server.types.Attribute attr : newAttrs)
     {
-      String attrName = attr.getNameWithOptions();
+      AttributeDescription attrDesc = attr.getAttributeDescription();
+      String attrName = attrDesc.toString();
       if (!ViewEntryPanel.isEditable(attrName, schema))
       {
         continue;
@@ -503,18 +507,15 @@
       }
       List<Object> oldValues = oldEntry.getAttributeValues(attrName);
 
-      boolean isAttributeInNewRdn = false;
       ByteString rdnValue = null;
-      RDN rdn = newEntry.getName().rdn();
-      for (int i=0; i<rdn.getNumValues() && !isAttributeInNewRdn; i++)
+      for (AVA ava : newEntry.getName().rdn())
       {
-        isAttributeInNewRdn =
-          rdn.getAttributeName(i).equalsIgnoreCase(attrName);
-        if (isAttributeInNewRdn)
+        if (ava.getAttributeType().equals(attrDesc.getAttributeType()))
         {
-          rdnValue = rdn.getAttributeValue(i);
+          rdnValue = ava.getAttributeValue();
         }
       }
+      boolean isAttributeInNewRdn = rdnValue != null;
 
       /* Check the attributes of the old DN.  If we are renaming them they
        * will be deleted.  Check that they are on the new entry but not in
@@ -532,16 +533,15 @@
       {
         oldRDN = DN.valueOf(oldEntry.getDN()).rdn();
       }
-      catch (DirectoryException de)
+      catch (DirectoryException unexpected)
       {
-        throw new RuntimeException("Unexpected error parsing DN: "+
-            oldEntry.getDN(), de);
+        throw new RuntimeException("Unexpected error parsing DN: " + oldEntry.getDN(), unexpected);
       }
-      for (int i=0; i<oldRDN.getNumValues(); i++)
+      for (AVA ava : oldRDN)
       {
-        if (oldRDN.getAttributeName(i).equalsIgnoreCase(attrName))
+        if (ava.getAttributeType().equals(attrDesc.getAttributeType()))
         {
-          ByteString value = oldRDN.getAttributeValue(i);
+          ByteString value = ava.getAttributeValue();
           if (attr.contains(value))
           {
             if (rdnValue == null || !rdnValue.equals(value))
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java
index 91e2b6a..4fb459c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/DuplicateEntryPanel.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2012-2015 ForgeRock AS
+ *      Portions Copyright 2012-2016 ForgeRock AS
  */
 
 package org.opends.guitools.controlpanel.ui;
@@ -143,7 +143,7 @@
       else
       {
         aParentDN = nodeDN.parent();
-        aRdn = nodeDN.rdn().getAttributeValue(0) + "-1";
+        aRdn = nodeDN.rdn().getFirstAVA().getAttributeValue() + "-1";
       }
     }
     catch (DirectoryException de)
@@ -406,7 +406,7 @@
         try
         {
           DN theDN = DN.valueOf(dn);
-          newValue = theDN.rdn().getAttributeValue(0).toString();
+          newValue = theDN.rdn().getFirstAVA().getAttributeValue().toString();
         }
         catch (DirectoryException de)
         {
@@ -424,7 +424,7 @@
           try
           {
             DN oldDN = DN.valueOf(entryToDuplicate.getDN());
-            oldValue = oldDN.rdn().getAttributeValue(0).toString();
+            oldValue = oldDN.rdn().getFirstAVA().getAttributeValue().toString();
           }
           catch (DirectoryException de)
           {
@@ -507,7 +507,7 @@
           try
           {
             DN dn = DN.valueOf(sr.getDN());
-            rdnAttribute = dn.rdn().getAttributeType(0).getNameOrOID();
+            rdnAttribute = dn.rdn().getFirstAVA().getAttributeType().getNameOrOID();
 
             updateDNValue();
             Boolean hasPassword = !sr.getAttributeValues(
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
index 6fbf5d0..ab5fae8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/SimplifiedViewEntryPanel.java
@@ -49,6 +49,7 @@
 import java.io.StringReader;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -79,6 +80,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.guitools.controlpanel.datamodel.BinaryValue;
@@ -93,14 +95,18 @@
 import org.opends.guitools.controlpanel.ui.nodes.DndBrowserNodes;
 import org.opends.guitools.controlpanel.util.Utilities;
 import org.opends.server.schema.SchemaConstants;
-import org.opends.server.types.*;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.OpenDsException;
+import org.opends.server.types.RDN;
+import org.opends.server.types.Schema;
 import org.opends.server.util.Base64;
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.ServerConstants;
 
-/**
- * The panel displaying a simplified view of an entry.
- */
+/** The panel displaying a simplified view of an entry. */
 public class SimplifiedViewEntryPanel extends ViewEntryPanel
 {
   private static final long serialVersionUID = 2775960608128921072L;
@@ -631,7 +637,7 @@
       basicAttrName = attrName.substring(0, index);
       subType = attrName.substring(index + 1);
     }
-    if (subType != null && subType.equalsIgnoreCase("binary"))
+    if ("binary".equalsIgnoreCase(subType))
     {
       // TODO: use message
       subType = "binary";
@@ -715,32 +721,11 @@
     Schema schema = getInfo().getServerDescriptor().getSchema();
     if (isRootEntry)
     {
-      String[] attrsNotToAdd = {"entryuuid", "hassubordinates",
-          "numsubordinates", "subschemasubentry", "entrydn",
-      "hassubordinates"};
+      List<String> attrsNotToAdd = Arrays.asList("entryuuid", "hassubordinates",
+          "numsubordinates", "subschemasubentry", "entrydn", "hassubordinates");
       for (String attr : sr.getAttributeNames())
       {
-        boolean found = false;
-        for (String addedAttr : attrNames)
-        {
-          found = addedAttr.equalsIgnoreCase(attr);
-          if (found)
-          {
-            break;
-          }
-        }
-        if (!found)
-        {
-          for (String notToAddAttr : attrsNotToAdd)
-          {
-            found = notToAddAttr.equalsIgnoreCase(attr);
-            if (found)
-            {
-              break;
-            }
-          }
-        }
-        if (!found)
+        if (!find(attrNames, attr) && !find(attrsNotToAdd, attr))
         {
           attrNames.add(attr);
         }
@@ -800,29 +785,28 @@
 
       for (String attr : attributes)
       {
-        boolean add = isEditable(attr, schema);
-
-        if (add)
+        boolean canAdd = isEditable(attr, schema);
+        if (canAdd && !find(attrNames, attr))
         {
-          boolean found = false;
-          for (String addedAttr : attrNames)
-          {
-            found = addedAttr.equalsIgnoreCase(attr);
-            if (found)
-            {
-              break;
-            }
-          }
-          if (!found)
-          {
-            attrNames.add(attr);
-          }
+          attrNames.add(attr);
         }
       }
     }
     return attrNames;
   }
 
+  private boolean find(Collection<String> attrNames, String attrNameToFind)
+  {
+    for (String attrName : attrNames)
+    {
+      if (attrName.equalsIgnoreCase(attrNameToFind))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
   private void updateAttributes(
       Collection<String> attributes,
       Set<String> newAttributes,
@@ -1416,11 +1400,7 @@
 
   private boolean hasBinaryValue(List<Object> values)
   {
-    if (!values.isEmpty())
-    {
-      return values.iterator().next() instanceof byte[];
-    }
-    return false;
+    return !values.isEmpty() && values.iterator().next() instanceof byte[];
   }
 
   private boolean mustAddBrowseButton(String attrName)
@@ -1486,13 +1466,12 @@
       if (oldDN.size() > 0)
       {
         RDN rdn = oldDN.rdn();
-        List<AttributeType> attributeTypes = new ArrayList<>();
-        List<String> attributeNames = new ArrayList<>();
-        List<ByteString> attributeValues = new ArrayList<>();
-        for (int i=0; i<rdn.getNumValues(); i++)
+        List<AVA> avas = new ArrayList<>();
+        for (AVA ava : rdn)
         {
-          String attrName = rdn.getAttributeName(i);
-          ByteString value = rdn.getAttributeValue(i);
+          AttributeType attrType = ava.getAttributeType();
+          String attrName = ava.getAttributeName();
+          ByteString value = ava.getAttributeValue();
 
           List<String> values = getDisplayedStringValues(attrName);
           if (!values.contains(value.toString()))
@@ -1502,20 +1481,16 @@
               String firstNonEmpty = getFirstNonEmpty(values);
               if (firstNonEmpty != null)
               {
-                attributeTypes.add(rdn.getAttributeType(i));
-                attributeNames.add(rdn.getAttributeName(i));
-                attributeValues.add(ByteString.valueOfUtf8(firstNonEmpty));
+                avas.add(new AVA(attrType, attrName, ByteString.valueOfUtf8(firstNonEmpty)));
               }
             }
           }
           else
           {
-            attributeTypes.add(rdn.getAttributeType(i));
-            attributeNames.add(rdn.getAttributeName(i));
-            attributeValues.add(value);
+            avas.add(new AVA(attrType, attrName, value));
           }
         }
-        if (attributeTypes.isEmpty())
+        if (avas.isEmpty())
         {
           // Check the attributes in the order that we display them and use
           // the first one.
@@ -1538,9 +1513,7 @@
                   String aName = Utilities.getAttributeNameWithoutOptions(attrName);
                   if (schema.hasAttributeType(aName))
                   {
-                    attributeTypes.add(schema.getAttributeType(aName));
-                    attributeNames.add(attrName);
-                    attributeValues.add(ByteString.valueOfUtf8((String) o));
+                    avas.add(new AVA(schema.getAttributeType(aName), aName, o));
                   }
                   break;
                 }
@@ -1549,9 +1522,9 @@
           }
         }
         DN parent = oldDN.parent();
-        if (!attributeTypes.isEmpty())
+        if (!avas.isEmpty())
         {
-          RDN newRDN = new RDN(attributeTypes, attributeNames, attributeValues);
+          RDN newRDN = new RDN(avas);
 
           DN newDN;
           if (parent == null)
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/TableViewEntryPanel.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/TableViewEntryPanel.java
index 50040a7..87a8a6f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/TableViewEntryPanel.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/TableViewEntryPanel.java
@@ -63,6 +63,7 @@
 import org.opends.guitools.controlpanel.ui.renderer.LDAPEntryTableCellRenderer;
 import org.opends.guitools.controlpanel.util.Utilities;
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.*;
@@ -284,13 +285,12 @@
       if (oldDN.size() > 0)
       {
         RDN rdn = oldDN.rdn();
-        List<AttributeType> attributeTypes = new ArrayList<>();
-        List<String> attributeNames = new ArrayList<>();
-        List<ByteString> attributeValues = new ArrayList<>();
-        for (int i=0; i<rdn.getNumValues(); i++)
+        List<AVA> avas = new ArrayList<>();
+        for (AVA ava : rdn)
         {
-          String attrName = rdn.getAttributeName(i);
-          ByteString value = rdn.getAttributeValue(i);
+          AttributeType attrType = ava.getAttributeType();
+          String attrName = ava.getAttributeName();
+          ByteString value = ava.getAttributeValue();
 
           Set<String> values = getDisplayedStringValues(attrName);
           if (!values.contains(value.toString()))
@@ -300,20 +300,16 @@
               String firstNonEmpty = getFirstNonEmpty(values);
               if (firstNonEmpty != null)
               {
-                attributeTypes.add(rdn.getAttributeType(i));
-                attributeNames.add(rdn.getAttributeName(i));
-                attributeValues.add(ByteString.valueOfUtf8(firstNonEmpty));
+                avas.add(new AVA(attrType, attrName, ByteString.valueOfUtf8(firstNonEmpty)));
               }
             }
           }
           else
           {
-            attributeTypes.add(rdn.getAttributeType(i));
-            attributeNames.add(rdn.getAttributeName(i));
-            attributeValues.add(value);
+            avas.add(new AVA(attrType, attrName, value));
           }
         }
-        if (attributeTypes.isEmpty())
+        if (avas.isEmpty())
         {
           // Check the attributes in the order that we display them and use
           // the first one.
@@ -336,9 +332,7 @@
                 String aName = Utilities.getAttributeNameWithoutOptions(attrName);
                 if (schema.hasAttributeType(aName))
                 {
-                  attributeTypes.add(schema.getAttributeType(aName));
-                  attributeNames.add(attrName);
-                  attributeValues.add(ByteString.valueOfUtf8((String) o));
+                  avas.add(new AVA(schema.getAttributeType(aName), attrName, o));
                 }
                 break;
               }
@@ -346,9 +340,9 @@
           }
         }
         DN parent = oldDN.parent();
-        if (!attributeTypes.isEmpty())
+        if (!avas.isEmpty())
         {
-          RDN newRDN = new RDN(attributeTypes, attributeNames, attributeValues);
+          RDN newRDN = new RDN(avas);
 
           DN newDN;
           if (parent == null)
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
index 9e88f04..a3d9659 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/ViewEntryPanel.java
@@ -44,6 +44,7 @@
 import javax.swing.tree.TreePath;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.ObjectClassType;
@@ -61,7 +62,6 @@
 import org.opends.server.types.Entry;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.OpenDsException;
-import org.opends.server.types.RDN;
 import org.opends.server.types.Schema;
 import org.opends.server.util.Base64;
 import org.opends.server.util.ServerConstants;
@@ -294,11 +294,10 @@
   protected void addValuesInRDN(Entry entry)
   {
     // Add the values in the RDN if they are not there
-    RDN rdn = entry.getName().rdn();
-    for (int i=0; i<rdn.getNumValues(); i++)
+    for (AVA ava : entry.getName().rdn())
     {
-      String attrName = rdn.getAttributeName(i);
-      ByteString value = rdn.getAttributeValue(i);
+      String attrName = ava.getAttributeName();
+      ByteString value = ava.getAttributeValue();
       boolean done = false;
       for (org.opends.server.types.Attribute attr : entry.getAttribute(attrName.toLowerCase()))
       {
@@ -313,7 +312,7 @@
       }
       if (!done)
       {
-        entry.addAttribute(Attributes.create(rdn.getAttributeType(i), value), newArrayList(value));
+        entry.addAttribute(Attributes.create(ava.getAttributeType(), value), newArrayList(value));
       }
     }
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/nodes/BasicNode.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/nodes/BasicNode.java
index c6d0b71..8a17ba5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/nodes/BasicNode.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/ui/nodes/BasicNode.java
@@ -22,9 +22,8 @@
  *
  *
  *      Copyright 2008-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
-
 package org.opends.guitools.controlpanel.ui.nodes;
 
 import javax.swing.Icon;
@@ -35,10 +34,7 @@
 import org.opends.server.types.LDAPURL;
 import org.opends.server.types.RDN;
 
-/**
- * The basic node used to render entries in the 'Manage Entries' tree.
- *
- */
+/** The basic node used to render entries in the 'Manage Entries' tree. */
 public class BasicNode extends DefaultMutableTreeNode {
 
   private static final long serialVersionUID = 5441658731908509872L;
@@ -203,6 +199,7 @@
    * @return <CODE>true</CODE> if the node is a leaf and <CODE>false</CODE>
    * otherwise.
    */
+  @Override
   public boolean isLeaf() {
     return isLeaf;
   }
@@ -319,10 +316,11 @@
   }
 
 
-  /**
-   * Rendering
-   */
-  /** {@inheritDoc} */
+  //
+  // Rendering
+  //
+
+  @Override
   public String toString() {
     return getDisplayName();
   }
@@ -419,7 +417,7 @@
           }
           else
           {
-            result = rdn.getAttributeValue(0).toString();
+            result = rdn.getFirstAVA().getAttributeValue().toString();
           }
         }
         else {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/Reference.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/Reference.java
index 7049e9e..bc44cf3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/admin/Reference.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/Reference.java
@@ -22,20 +22,16 @@
  *
  *
  *      Copyright 2008 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
 package org.opends.server.admin;
 
-
-
 import org.forgerock.opendj.ldap.ByteString;
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.RDN;
 import org.opends.server.util.StaticUtils;
 
-
-
 /**
  * A reference to another managed object.
  *
@@ -98,7 +94,7 @@
           + s + "\"");
     }
 
-    ByteString av = rdn.getAttributeValue(0);
+    ByteString av = rdn.getFirstAVA().getAttributeValue();
     if (av == null) {
       throw new IllegalArgumentException("Unabled to decode the DN string: \""
           + s + "\"");
@@ -217,9 +213,7 @@
     return path.toDN();
   }
 
-
-
-  /** {@inheritDoc} */
+  @Override
   public String toString() {
     return name;
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
index 50b1dfe..2762efe 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2007-2009 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
 package org.opends.server.admin.server;
 
@@ -152,9 +152,6 @@
     this.cachedManagedObject = null;
   }
 
-
-
-  /** {@inheritDoc} */
   @Override
   public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry) {
     if (optionalRelation != null) {
@@ -192,14 +189,11 @@
     return result;
   }
 
-
-
-  /** {@inheritDoc} */
   @Override
   public boolean configAddIsAcceptable(ConfigEntry configEntry,
       LocalizableMessageBuilder unacceptableReason) {
     DN dn = configEntry.getDN();
-    ByteString av = dn.rdn().getAttributeValue(0);
+    ByteString av = dn.rdn().getFirstAVA().getAttributeValue();
     String name = av.toString().trim();
 
     try {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
index d87a381..a4a7771 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
@@ -22,38 +22,35 @@
  *
  *
  *      Copyright 2007-2009 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
 package org.opends.server.admin.server;
 
-
-
 import static org.opends.messages.AdminMessages.*;
+
 import java.util.LinkedList;
 import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.Configuration;
 import org.opends.server.admin.Constraint;
 import org.opends.server.admin.DecodingException;
 import org.opends.server.admin.DefinitionDecodingException;
+import org.opends.server.admin.DefinitionDecodingException.Reason;
 import org.opends.server.admin.InstantiableRelationDefinition;
 import org.opends.server.admin.ManagedObjectDefinition;
 import org.opends.server.admin.ManagedObjectPath;
 import org.opends.server.admin.OptionalRelationDefinition;
 import org.opends.server.admin.SetRelationDefinition;
-import org.opends.server.admin.DefinitionDecodingException.Reason;
 import org.opends.server.api.ConfigDeleteListener;
 import org.opends.server.config.ConfigEntry;
-import org.forgerock.opendj.config.server.ConfigException;
-import org.forgerock.i18n.slf4j.LocalizedLogger;
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.opends.server.types.DN;
-import org.forgerock.opendj.ldap.ResultCode;
-
-
 
 /**
  * An adaptor class which converts {@link ConfigDeleteListener}
@@ -157,9 +154,7 @@
     this.cachedManagedObject = null;
   }
 
-
-
-  /** {@inheritDoc} */
+  @Override
   public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) {
     if (optionalRelation != null) {
       // Optional managed objects are located directly beneath the
@@ -197,13 +192,11 @@
     return result;
   }
 
-
-
-  /** {@inheritDoc} */
+  @Override
   public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
       LocalizableMessageBuilder unacceptableReason) {
     DN dn = configEntry.getDN();
-    ByteString av = dn.rdn().getAttributeValue(0);
+    ByteString av = dn.rdn().getFirstAVA().getAttributeValue();
     String name = av.toString().trim();
 
     try {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ServerManagementContext.java b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
index 0fd5357..109d19e 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/admin/server/ServerManagementContext.java
@@ -45,6 +45,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
 import org.opends.server.admin.AggregationPropertyDefinition;
@@ -75,7 +76,6 @@
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.DN;
 
 /**
@@ -626,7 +626,7 @@
     ArrayList<String> names = new ArrayList<>(children.size());
     for (DN child : children) {
       // Assume that RDNs are single-valued and can be trimmed.
-      ByteString av = child.rdn().getAttributeValue(0);
+      ByteString av = child.rdn().getFirstAVA().getAttributeValue();
       names.add(av.toString().trim());
     }
 
@@ -678,7 +678,7 @@
     ArrayList<String> names = new ArrayList<>(children.size());
     for (DN child : children) {
       // Assume that RDNs are single-valued and can be trimmed.
-      ByteString av = child.rdn().getAttributeValue(0);
+      ByteString av = child.rdn().getFirstAVA().getAttributeValue();
       names.add(av.toString().trim());
     }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
index 1c5902f..689dda4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -35,6 +35,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.AttributeDescription;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -916,11 +917,10 @@
   private boolean checkRDN(int right, RDN rdn, AciContainer container)
   {
     container.setRights(right);
-    final int numAVAs = rdn.getNumValues();
-    for (int i = 0; i < numAVAs; i++)
+    for (AVA ava : rdn)
     {
-      container.setCurrentAttributeType(rdn.getAttributeType(i));
-      container.setCurrentAttributeValue(rdn.getAttributeValue(i));
+      container.setCurrentAttributeType(ava.getAttributeType());
+      container.setCurrentAttributeValue(ava.getAttributeValue());
       if (!accessAllowed(container))
       {
         return false;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternRDN.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternRDN.java
index dbe698a..9a978c1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternRDN.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternRDN.java
@@ -37,6 +37,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -168,12 +169,13 @@
         return true;
       }
 
-      if (rdn.getNumValues() != 1)
+      if (rdn.size() != 1)
       {
         return false;
       }
 
-      AttributeType thatType = rdn.getAttributeType(0);
+      AVA firstAVA = rdn.getFirstAVA();
+      AttributeType thatType = firstAVA.getAttributeType();
       if (!typePatterns[0].equals("*"))
       {
         AttributeType thisType = DirectoryServer.getAttributeType(typePatterns[0]);
@@ -183,7 +185,7 @@
         }
       }
 
-      return matchValuePattern(valuePatterns.get(0), thatType, rdn.getAttributeValue(0));
+      return matchValuePattern(valuePatterns.get(0), thatType, firstAVA.getAttributeValue());
     }
 
     if (hasTypeWildcard)
@@ -191,7 +193,7 @@
       return false;
     }
 
-    if (numValues != rdn.getNumValues())
+    if (numValues != rdn.size())
     {
       return false;
     }
@@ -200,10 +202,9 @@
     TreeMap<String,ArrayList<ByteString>> patternMap = new TreeMap<>();
     TreeMap<String, ByteString> rdnMap = new TreeMap<>();
 
-    for (int i = 0; i < rdn.getNumValues(); i++)
+    for (AVA ava : rdn)
     {
-      rdnMap.put(rdn.getAttributeType(i).getNameOrOID(),
-                 rdn.getAttributeValue(i));
+      rdnMap.put(ava.getAttributeType().getNameOrOID(), ava.getAttributeValue());
     }
 
     for (int i = 0; i < numValues; i++)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/BackupBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/BackupBackend.java
index f484501..657a214 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/BackupBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/BackupBackend.java
@@ -48,6 +48,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -242,12 +243,10 @@
     LinkedHashMap<AttributeType,List<Attribute>> opAttrs = new LinkedHashMap<>(0);
     LinkedHashMap<AttributeType,List<Attribute>> userAttrs = new LinkedHashMap<>(1);
 
-    RDN rdn = backupBaseDN.rdn();
-    int numAVAs = rdn.getNumValues();
-    for (int i=0; i < numAVAs; i++)
+    for (AVA ava : backupBaseDN.rdn())
     {
-      AttributeType attrType = rdn.getAttributeType(i);
-      userAttrs.put(attrType, Attributes.createAsList(attrType, rdn.getAttributeValue(i)));
+      AttributeType attrType = ava.getAttributeType();
+      userAttrs.put(attrType, Attributes.createAsList(attrType, ava.getAttributeValue()));
     }
 
     backupBaseEntry = new Entry(backupBaseDN, objectClasses, userAttrs, opAttrs);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
index b8285ba..21f4cf3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
@@ -34,25 +34,56 @@
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.Set;
+import java.util.TreeMap;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.util.Reject;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.MonitorBackendCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.config.ConfigEntry;
-import org.opends.server.core.*;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.core.ServerContext;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.BackupDirectory;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.IndexType;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RDN;
+import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.SearchFilter;
 import org.opends.server.util.DynamicConstants;
 import org.opends.server.util.LDIFWriter;
 import org.opends.server.util.TimeThread;
@@ -669,11 +700,10 @@
     final RDN rdn = dn.rdn();
     if (rdn != null)
     {
-      // Add the RDN values
-      for (int i = 0; i < rdn.getNumValues(); i++)
+      for (AVA ava : rdn)
       {
-        final AttributeType attributeType = rdn.getAttributeType(i);
-        final ByteString value = rdn.getAttributeValue(attributeType);
+        final AttributeType attributeType = ava.getAttributeType();
+        final ByteString value = ava.getAttributeValue();
         monitorUserAttrs.put(attributeType, Attributes.createAsList(attributeType, value));
       }
     }
@@ -765,9 +795,9 @@
     final HashMap<AttributeType, List<Attribute>> attrMap = new LinkedHashMap<>(monitorAttrs.size() + 1);
 
     // Make sure to include the RDN attribute.
-    final RDN entryRDN = entryDN.rdn();
-    final AttributeType rdnType = entryRDN.getAttributeType(0);
-    final ByteString rdnValue = entryRDN.getAttributeValue(0);
+    final AVA ava = entryDN.rdn().getFirstAVA();
+    final AttributeType rdnType = ava.getAttributeType();
+    final ByteString rdnValue = ava.getAttributeValue();
 
     attrMap.put(rdnType, Attributes.createAsList(rdnType, rdnValue));
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
index 94224ac..6d0f86f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/SchemaBackend.java
@@ -63,6 +63,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.ModificationType;
@@ -96,7 +97,34 @@
 import org.opends.server.schema.NameFormSyntax;
 import org.opends.server.schema.ObjectClassSyntax;
 import org.opends.server.schema.SomeSchemaElement;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.BackupDirectory;
+import org.opends.server.types.CommonSchemaElements;
+import org.opends.server.types.DITContentRule;
+import org.opends.server.types.DITStructureRule;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ExistingFileBehavior;
+import org.opends.server.types.IndexType;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDAPSyntaxDescription;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.MatchingRuleUse;
+import org.opends.server.types.Modification;
+import org.opends.server.types.NameForm;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.Privilege;
+import org.opends.server.types.RDN;
+import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.Schema;
+import org.opends.server.types.SchemaFileElement;
+import org.opends.server.types.SearchFilter;
 import org.opends.server.util.BackupManager;
 import org.opends.server.util.DynamicConstants;
 import org.opends.server.util.LDIFException;
@@ -551,11 +579,10 @@
     RDN rdn = entryDN.rdn();
     if (rdn != null)
     {
-      int numAVAs = rdn.getNumValues();
-      for (int i = 0; i < numAVAs; i++)
+      for (AVA ava : rdn)
       {
-        AttributeType attrType = rdn.getAttributeType(i);
-        Attribute attribute = Attributes.create(attrType, rdn.getAttributeValue(i));
+        AttributeType attrType = ava.getAttributeType();
+        Attribute attribute = Attributes.create(attrType, ava.getAttributeValue());
         addAttributeToSchemaEntry(attribute, userAttrs, operationalAttrs);
       }
     }
@@ -2715,19 +2742,11 @@
     Map<AttributeType,List<Attribute>> operationalAttributes = new LinkedHashMap<>();
 
     DN  dn  = DirectoryServer.getSchemaDN();
-    RDN rdn = dn.rdn();
-    for (int i=0; i < rdn.getNumValues(); i++)
+    for (AVA ava : dn.rdn())
     {
-      AttributeType type = rdn.getAttributeType(i);
-      List<Attribute> attrList = newLinkedList(Attributes.create(type, rdn.getAttributeValue(i)));
-      if (type.isOperational())
-      {
-        operationalAttributes.put(type, attrList);
-      }
-      else
-      {
-        userAttributes.put(type, attrList);
-      }
+      AttributeType type = ava.getAttributeType();
+      Map<AttributeType, List<Attribute>> attrs = type.isOperational() ? operationalAttributes : userAttributes;
+      attrs.put(type, newLinkedList(Attributes.create(type, ava.getAttributeValue())));
     }
 
     return new Entry(dn, objectClasses,  userAttributes, operationalAttributes);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/TrustStoreBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/TrustStoreBackend.java
index b806d4a..7d5ab64 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/TrustStoreBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/TrustStoreBackend.java
@@ -63,10 +63,12 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.util.Reject;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.TrustStoreBackendCfg;
@@ -78,8 +80,24 @@
 import org.opends.server.core.ModifyOperation;
 import org.opends.server.core.SearchOperation;
 import org.opends.server.core.ServerContext;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.BackupConfig;
+import org.opends.server.types.BackupDirectory;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.FilePermission;
+import org.opends.server.types.IndexType;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.LDIFImportResult;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RDN;
+import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.SearchFilter;
 import org.opends.server.util.CertificateManager;
 import org.opends.server.util.Platform.KeyType;
 import org.opends.server.util.SetupUtils;
@@ -299,18 +317,14 @@
          DirectoryServer.getObjectClass("ds-cfg-branch", true);
     objectClasses.put(branchOC, "ds-cfg-branch");
 
-    LinkedHashMap<AttributeType,List<Attribute>> opAttrs = new LinkedHashMap<>(0);
     LinkedHashMap<AttributeType,List<Attribute>> userAttrs = new LinkedHashMap<>(1);
-
-    RDN rdn = baseDN.rdn();
-    int numAVAs = rdn.getNumValues();
-    for (int i=0; i < numAVAs; i++)
+    for (AVA ava : baseDN.rdn())
     {
-      AttributeType attrType = rdn.getAttributeType(i);
-      userAttrs.put(attrType, Attributes.createAsList(attrType, rdn.getAttributeValue(i)));
+      AttributeType attrType = ava.getAttributeType();
+      userAttrs.put(attrType, Attributes.createAsList(attrType, ava.getAttributeValue()));
     }
 
-    baseEntry = new Entry(baseDN, objectClasses, userAttrs, opAttrs);
+    baseEntry = new Entry(baseDN, objectClasses, userAttrs, null);
 
     // Register this as a change listener.
     configuration.addTrustStoreChangeListener(this);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ConfigurableEnvironment.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ConfigurableEnvironment.java
index d1ad6aa..fbc89b8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ConfigurableEnvironment.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/ConfigurableEnvironment.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2010-2015 ForgeRock AS.
+ *      Portions Copyright 2010-2016 ForgeRock AS.
  */
 package org.opends.server.backends.jeb;
 
@@ -58,11 +58,11 @@
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.MemoryQuota;
 import org.opends.server.types.DN;
+import org.opends.server.util.Platform;
 
 import com.sleepycat.je.Durability;
 import com.sleepycat.je.EnvironmentConfig;
 import com.sleepycat.je.dbi.MemoryBudget;
-import org.opends.server.util.Platform;
 
 /** This class maps JE properties to configuration attributes. */
 public class ConfigurableEnvironment
@@ -425,7 +425,7 @@
 
     EnvironmentConfig envConfig = defaultConfig();
     setDurability(envConfig, cfg.isDBTxnNoSync(), cfg.isDBTxnWriteNoSync());
-    setJEProperties(cfg, envConfig, cfg.dn().rdn().getAttributeValue(0));
+    setJEProperties(cfg, envConfig, cfg.dn().rdn().getFirstAVA().getAttributeValue());
     setDBLoggingLevel(envConfig, cfg.getDBLoggingLevel(), cfg.dn(), cfg.isDBLoggingFileHandlerOn());
 
     // See if there are any native JE properties specified in the config
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/EntryCacheConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/EntryCacheConfigManager.java
index f8890f5..c84f99f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/EntryCacheConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/EntryCacheConfigManager.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2013-2015 ForgeRock AS.
+ *      Portions Copyright 2013-2016 ForgeRock AS.
  */
 package org.opends.server.core;
 
@@ -498,7 +498,7 @@
     // Install and register the monitor for this cache.
     EntryCacheMonitorProvider monitor =
         new EntryCacheMonitorProvider(configuration.dn().
-        rdn().getAttributeValue(0).toString(), entryCache);
+        rdn().getFirstAVA().getAttributeValue().toString(), entryCache);
     try {
       monitor.initializeMonitorProvider((EntryCacheMonitorProviderCfg)
         rootConfiguration.getMonitorProvider(
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/PluginConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/PluginConfigManager.java
index fee8b94..d9b1879 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/PluginConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/PluginConfigManager.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS
+ *      Portions Copyright 2011-2016 ForgeRock AS
  */
 package org.opends.server.core;
 
@@ -30,7 +30,13 @@
 import static org.opends.messages.PluginMessages.*;
 import static org.opends.server.util.StaticUtils.*;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -56,8 +62,64 @@
 import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
 import org.opends.server.api.plugin.PluginResult;
 import org.opends.server.api.plugin.PluginType;
-import org.opends.server.types.*;
-import org.opends.server.types.operation.*;
+import org.opends.server.types.CanceledOperationException;
+import org.opends.server.types.DN;
+import org.opends.server.types.DisconnectReason;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.IntermediateResponse;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Operation;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchResultReference;
+import org.opends.server.types.operation.PluginOperation;
+import org.opends.server.types.operation.PostOperationAbandonOperation;
+import org.opends.server.types.operation.PostOperationAddOperation;
+import org.opends.server.types.operation.PostOperationBindOperation;
+import org.opends.server.types.operation.PostOperationCompareOperation;
+import org.opends.server.types.operation.PostOperationDeleteOperation;
+import org.opends.server.types.operation.PostOperationExtendedOperation;
+import org.opends.server.types.operation.PostOperationModifyDNOperation;
+import org.opends.server.types.operation.PostOperationModifyOperation;
+import org.opends.server.types.operation.PostOperationSearchOperation;
+import org.opends.server.types.operation.PostOperationUnbindOperation;
+import org.opends.server.types.operation.PostResponseAddOperation;
+import org.opends.server.types.operation.PostResponseBindOperation;
+import org.opends.server.types.operation.PostResponseCompareOperation;
+import org.opends.server.types.operation.PostResponseDeleteOperation;
+import org.opends.server.types.operation.PostResponseExtendedOperation;
+import org.opends.server.types.operation.PostResponseModifyDNOperation;
+import org.opends.server.types.operation.PostResponseModifyOperation;
+import org.opends.server.types.operation.PostResponseSearchOperation;
+import org.opends.server.types.operation.PostSynchronizationAddOperation;
+import org.opends.server.types.operation.PostSynchronizationDeleteOperation;
+import org.opends.server.types.operation.PostSynchronizationModifyDNOperation;
+import org.opends.server.types.operation.PostSynchronizationModifyOperation;
+import org.opends.server.types.operation.PreOperationAddOperation;
+import org.opends.server.types.operation.PreOperationBindOperation;
+import org.opends.server.types.operation.PreOperationCompareOperation;
+import org.opends.server.types.operation.PreOperationDeleteOperation;
+import org.opends.server.types.operation.PreOperationExtendedOperation;
+import org.opends.server.types.operation.PreOperationModifyDNOperation;
+import org.opends.server.types.operation.PreOperationModifyOperation;
+import org.opends.server.types.operation.PreOperationOperation;
+import org.opends.server.types.operation.PreOperationSearchOperation;
+import org.opends.server.types.operation.PreParseAbandonOperation;
+import org.opends.server.types.operation.PreParseAddOperation;
+import org.opends.server.types.operation.PreParseBindOperation;
+import org.opends.server.types.operation.PreParseCompareOperation;
+import org.opends.server.types.operation.PreParseDeleteOperation;
+import org.opends.server.types.operation.PreParseExtendedOperation;
+import org.opends.server.types.operation.PreParseModifyDNOperation;
+import org.opends.server.types.operation.PreParseModifyOperation;
+import org.opends.server.types.operation.PreParseOperation;
+import org.opends.server.types.operation.PreParseSearchOperation;
+import org.opends.server.types.operation.PreParseUnbindOperation;
+import org.opends.server.types.operation.SearchEntrySearchOperation;
+import org.opends.server.types.operation.SearchReferenceSearchOperation;
+import org.opends.server.types.operation.SubordinateModifyDNOperation;
 
 /**
  * This class defines a utility that will be used to manage the configuration
@@ -1010,7 +1072,7 @@
       for (DirectoryServerPlugin p : pluginArray)
       {
         DN dn = p.getPluginEntryDN();
-        String lowerName = toLowerCase(dn.rdn().getAttributeValue(0).toString());
+        String lowerName = toLowerCase(dn.rdn().getFirstAVA().getAttributeValue().toString());
         if (initialPluginNames.contains(lowerName))
         {
           initialPlugins.put(lowerName, p);
@@ -1029,7 +1091,7 @@
       // Get the name of the provided plugin from its RDN value and put it in
       // the correct category.
       DN dn = plugin.getPluginEntryDN();
-      String lowerName = toLowerCase(dn.rdn().getAttributeValue(0).toString());
+      String lowerName = toLowerCase(dn.rdn().getFirstAVA().getAttributeValue().toString());
       if (initialPluginNames.contains(lowerName))
       {
         initialPlugins.put(lowerName, plugin);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
index e651a33..3d7a6be 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/crypto/CryptoManagerSync.java
@@ -285,9 +285,7 @@
   {
     RDN srcRDN = searchEntry.getName().rdn();
 
-    // Only process the entry if it has the expected form of RDN.
-    if (!srcRDN.isMultiValued() &&
-         srcRDN.getAttributeType(0).equals(attrAlias))
+    if (canProcessEntry(srcRDN))
     {
       DN dstDN = trustStoreRootDN.child(srcRDN);
 
@@ -350,6 +348,12 @@
     }
   }
 
+  /** Only process the entry if it has the expected form of RDN. */
+  private boolean canProcessEntry(RDN rdn)
+  {
+    return !rdn.isMultiValued() && rdn.getFirstAVA().getAttributeType().equals(attrAlias);
+  }
+
 
   /**
    * Modify an entry in the local trust store if it differs from an entry in
@@ -461,10 +465,7 @@
   private void handleInstanceKeyAddOperation(Entry entry)
   {
     RDN srcRDN = entry.getName().rdn();
-
-    // Only process the entry if it has the expected form of RDN.
-    if (!srcRDN.isMultiValued() &&
-         srcRDN.getAttributeType(0).equals(attrAlias))
+    if (canProcessEntry(srcRDN))
     {
       DN dstDN = trustStoreRootDN.child(srcRDN);
 
@@ -486,12 +487,10 @@
 
     RDN srcRDN = op.getEntryToDelete().getName().rdn();
 
-    // Only process the entry if it has the expected form of RDN.
     // FIXME: Technically it is possible to perform a subtree in
     // this case however such subtree delete would essentially be
     // removing configuration branches which should not happen.
-    if (!srcRDN.isMultiValued() &&
-         srcRDN.getAttributeType(0).equals(attrAlias))
+    if (canProcessEntry(srcRDN))
     {
       DN destDN = trustStoreRootDN.child(srcRDN);
       deleteEntry(destDN);
@@ -539,9 +538,7 @@
   {
     RDN srcRDN = newEntry.getName().rdn();
 
-    // Only process the entry if it has the expected form of RDN.
-    if (!srcRDN.isMultiValued() &&
-         srcRDN.getAttributeType(0).equals(attrAlias))
+    if (canProcessEntry(srcRDN))
     {
       DN dstDN = trustStoreRootDN.child(srcRDN);
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java
index 33a3a39..15122d6 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java
@@ -29,15 +29,24 @@
 import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.admin.std.server.GoverningStructureRuleVirtualAttributeCfg;
 import org.opends.server.api.VirtualAttributeProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.SearchOperation;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.AcceptRejectWarn;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.DITStructureRule;
+import org.opends.server.types.Entry;
+import org.opends.server.types.NameForm;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RDN;
+import org.opends.server.types.VirtualAttributeRule;
 
 import static org.opends.messages.ExtensionMessages.*;
 
@@ -170,10 +179,9 @@
       }
 
       // Make sure that all attributes in the RDN are allowed.
-      int numAVAs = rdn.getNumValues();
-      for (int i = 0; i < numAVAs; i++)
+      for (AVA ava : rdn)
       {
-        AttributeType t = rdn.getAttributeType(i);
+        AttributeType t = ava.getAttributeType();
         if (!nameForm.isRequiredOrOptional(t)
             && structuralPolicy == AcceptRejectWarn.REJECT)
         {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SubjectAttributeToUserAttributeCertificateMapper.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SubjectAttributeToUserAttributeCertificateMapper.java
index 555e90e..9eb848b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SubjectAttributeToUserAttributeCertificateMapper.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SubjectAttributeToUserAttributeCertificateMapper.java
@@ -48,6 +48,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -65,7 +66,6 @@
 import org.opends.server.types.Entry;
 import org.opends.server.types.IndexType;
 import org.opends.server.types.InitializationException;
-import org.opends.server.types.RDN;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 
@@ -208,10 +208,9 @@
     LinkedList<SearchFilter> filterComps = new LinkedList<>();
     for (int i=0; i < peerDN.size(); i++)
     {
-      RDN rdn = peerDN.getRDN(i);
-      for (int j=0; j < rdn.getNumValues(); j++)
+      for (AVA ava : peerDN.getRDN(i))
       {
-        String lowerName = toLowerCase(rdn.getAttributeName(j));
+        String lowerName = toLowerCase(ava.getAttributeName());
 
         // Try to normalize lowerName
         lowerName = normalizeAttributeName(lowerName);
@@ -219,7 +218,7 @@
         AttributeType attrType = theAttributeMap.get(lowerName);
         if (attrType != null)
         {
-          filterComps.add(SearchFilter.createEqualityFilter(attrType, rdn.getAttributeValue(j)));
+          filterComps.add(SearchFilter.createEqualityFilter(attrType, ava.getAttributeValue()));
         }
       }
     }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
index 90b3a1a..77e2862 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/loggers/CommonAudit.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2015 ForgeRock AS.
+ *      Copyright 2015-2016 ForgeRock AS.
  */
 package org.opends.server.loggers;
 
@@ -748,7 +748,7 @@
 
     String getName()
     {
-      return config.dn().getRDN(0).getAttributeValue(0).toString();
+      return config.dn().getRDN(0).getFirstAVA().getAttributeValue().toString();
     }
 
     String getCommonAuditTopic() throws ConfigException
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/plugins/SevenBitCleanPlugin.java b/opendj-server-legacy/src/main/java/org/opends/server/plugins/SevenBitCleanPlugin.java
index e426837..cf04a93 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/plugins/SevenBitCleanPlugin.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/plugins/SevenBitCleanPlugin.java
@@ -32,24 +32,33 @@
 import java.util.Set;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
+import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.meta.PluginCfgDefn;
-import org.opends.server.admin.std.server.SevenBitCleanPluginCfg;
 import org.opends.server.admin.std.server.PluginCfg;
+import org.opends.server.admin.std.server.SevenBitCleanPluginCfg;
 import org.opends.server.api.plugin.DirectoryServerPlugin;
 import org.opends.server.api.plugin.PluginResult;
 import org.opends.server.api.plugin.PluginType;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
-import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.core.DirectoryServer;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
-import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.ByteString;
-import org.forgerock.opendj.ldap.ByteSequence;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.LDIFImportConfig;
+import org.opends.server.types.RDN;
+import org.opends.server.types.RawAttribute;
+import org.opends.server.types.RawModification;
 import org.opends.server.types.operation.PreParseAddOperation;
-import org.opends.server.types.operation.PreParseModifyOperation;
 import org.opends.server.types.operation.PreParseModifyDNOperation;
+import org.opends.server.types.operation.PreParseModifyOperation;
 
 /**
  * This class implements a Directory Server plugin that can be used to ensure
@@ -339,20 +348,18 @@
             ERR_PLUGIN_7BIT_CANNOT_DECODE_NEW_RDN.get(de.getMessageObject()));
       }
 
-      int numValues = newRDN.getNumValues();
-      for (int i=0; i < numValues; i++)
+      for (AVA ava : newRDN)
       {
-        if (! config.getAttributeType().contains(newRDN.getAttributeType(i)))
+        if (!config.getAttributeType().contains(ava.getAttributeType()))
         {
           continue;
         }
 
-        if (!is7BitClean(newRDN.getAttributeValue(i)))
+        if (!is7BitClean(ava.getAttributeValue()))
         {
           return PluginResult.PreParse.stopProcessing(
               ResultCode.CONSTRAINT_VIOLATION,
-              ERR_PLUGIN_7BIT_MODIFYDN_ATTR_NOT_CLEAN.get(
-                  newRDN.getAttributeName(i)));
+              ERR_PLUGIN_7BIT_MODIFYDN_ATTR_NOT_CLEAN.get(ava.getAttributeName()));
         }
       }
     }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java b/opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java
index 825b916..acd07bc 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java
@@ -39,6 +39,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
@@ -65,7 +66,6 @@
 import org.opends.server.types.Entry;
 import org.opends.server.types.IndexType;
 import org.opends.server.types.Modification;
-import org.opends.server.types.RDN;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.operation.PluginOperation;
@@ -253,9 +253,8 @@
     {
       Attribute a = m.getAttribute();
       AttributeType t = a.getAttributeDescription().getAttributeType();
-      if (! config.getType().contains(t))
+      if (!isModifyingUniqueAttribute(t, config))
       {
-        // This modification isn't for a unique attribute.
         continue;
       }
 
@@ -368,17 +367,15 @@
     }
 
     List<ByteString> recordedValues = new LinkedList<>();
-    RDN newRDN = modifyDNOperation.getNewRDN();
-    for (int i=0; i < newRDN.getNumValues(); i++)
+    for (AVA ava : modifyDNOperation.getNewRDN())
     {
-      AttributeType t = newRDN.getAttributeType(i);
-      if (! config.getType().contains(t))
+      AttributeType t = ava.getAttributeType();
+      if (!isModifyingUniqueAttribute(t, config))
       {
-        // We aren't interested in this attribute type.
         continue;
       }
 
-      ByteString v = newRDN.getAttributeValue(i);
+      ByteString v = ava.getAttributeValue();
       DN entryDN = modifyDNOperation.getEntryDN();
       PreOperation stop =
           checkUniqueness(entryDN, t, v, baseDNs, recordedValues, config);
@@ -391,9 +388,11 @@
     return PluginResult.PreOperation.continueOperationProcessing();
   }
 
+  private boolean isModifyingUniqueAttribute(AttributeType t, UniqueAttributePluginCfg config)
+  {
+    return config.getType().contains(t);
+  }
 
-
-  /** {@inheritDoc} */
   @Override
   public final void doPostSynchronization(
                          PostSynchronizationAddOperation addOperation)
@@ -442,9 +441,8 @@
     {
       Attribute a = m.getAttribute();
       AttributeType t = a.getAttributeDescription().getAttributeType();
-      if (! config.getType().contains(t))
+      if (!isModifyingUniqueAttribute(t, config))
       {
-        // This modification isn't for a unique attribute.
         continue;
       }
 
@@ -499,19 +497,14 @@
 
     DN entryDN = modifyDNOperation.getEntryDN();
     DN updatedEntryDN = modifyDNOperation.getUpdatedEntry().getName();
-    RDN newRDN = modifyDNOperation.getNewRDN();
-    for (int i=0; i < newRDN.getNumValues(); i++)
+    for (AVA ava : modifyDNOperation.getNewRDN())
     {
-      AttributeType t = newRDN.getAttributeType(i);
-      if (! config.getType().contains(t))
+      AttributeType t = ava.getAttributeType();
+      if (isModifyingUniqueAttribute(t, config))
       {
-        // We aren't interested in this attribute type.
-        continue;
+        ByteString v = ava.getAttributeValue();
+        sendAlertForUnresolvedConflict(modifyDNOperation, entryDN, updatedEntryDN, t, v, baseDNs, config);
       }
-
-      ByteString v = newRDN.getAttributeValue(i);
-      sendAlertForUnresolvedConflict(modifyDNOperation, entryDN,
-          updatedEntryDN, t, v, baseDNs, config);
     }
   }
 
@@ -830,9 +823,8 @@
     {
       Attribute a = m.getAttribute();
       AttributeType t = a.getAttributeDescription().getAttributeType();
-      if (! config.getType().contains(t))
+      if (!isModifyingUniqueAttribute(t, config))
       {
-        // This modification isn't for a unique attribute.
         continue;
       }
 
@@ -884,16 +876,13 @@
       return PostOperation.continueOperationProcessing();
     }
 
-    RDN newRDN = modifyDNOperation.getNewRDN();
-    for (int i=0; i < newRDN.getNumValues(); i++)
+    for (AVA ava : modifyDNOperation.getNewRDN())
     {
-      AttributeType t = newRDN.getAttributeType(i);
-      if (! config.getType().contains(t))
+      AttributeType t = ava.getAttributeType();
+      if (isModifyingUniqueAttribute(t, config))
       {
-        // We aren't interested in this attribute type.
-        continue;
+        uniqueAttrValue2Dn.remove(ava.getAttributeValue());
       }
-      uniqueAttrValue2Dn.remove(newRDN.getAttributeValue(i));
     }
     return PostOperation.continueOperationProcessing();
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
index ed36968..8eed7f0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPConnectionHandler.java
@@ -21,7 +21,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2013-2015 ForgeRock AS
+ *      Copyright 2013-2016 ForgeRock AS
  */
 package org.opends.server.protocols.http;
 
@@ -431,7 +431,7 @@
 
     if (friendlyName == null)
     {
-      friendlyName = config.dn().rdn().getAttributeValue(0).toString();
+      friendlyName = config.dn().rdn().getFirstAVA().getAttributeValue().toString();
     }
 
     int listenPort = config.getListenPort();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index 032a100..848179b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -22,7 +22,7 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS
+ *      Portions Copyright 2011-2016 ForgeRock AS
  */
 package org.opends.server.protocols.ldap;
 
@@ -648,7 +648,7 @@
   {
     if (friendlyName == null)
     {
-      friendlyName = config.dn().rdn().getAttributeValue(0).toString();
+      friendlyName = config.dn().rdn().getFirstAVA().getAttributeValue().toString();
     }
 
     // Open the selector.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ExternalChangelogDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ExternalChangelogDomain.java
index c3a248e..4d31b81 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ExternalChangelogDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/ExternalChangelogDomain.java
@@ -22,26 +22,23 @@
  *
  *
  *      Copyright 2006-2010 Sun Microsystems, Inc.
- *      Portions Copyright 2011-2015 ForgeRock AS
+ *      Portions Copyright 2011-2016 ForgeRock AS
  */
 package org.opends.server.replication.plugin;
 
 import java.util.List;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.server.ConfigurationAddListener;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.server.ConfigurationDeleteListener;
 import org.opends.server.admin.std.server.ExternalChangelogDomainCfg;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.RDN;
 
-/**
- * This class specifies the external changelog feature for a replication
- * domain.
- */
+/** This class specifies the external changelog feature for a replication domain. */
 public class ExternalChangelogDomain
   implements ConfigurationAddListener<ExternalChangelogDomainCfg>,
              ConfigurationDeleteListener<ExternalChangelogDomainCfg>,
@@ -117,7 +114,7 @@
       if (domain==null)
       {
         RDN rdn = configuration.dn().parent().rdn();
-        DN rdns = DN.decode(rdn.getAttributeValue(0));
+        DN rdns = DN.decode(rdn.getFirstAVA().getAttributeValue());
         domain = MultimasterReplication.findDomain(rdns, null);
       }
       return null;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index f8aa4e6..837ea8d 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -71,6 +71,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ModificationType;
@@ -1130,9 +1131,9 @@
     RDN newRdn = modifyDNOperation.getNewRDN();
 
     // Go through each attribute of the old RDN
-    for (int i=0 ; i<rdn.getNumValues() ; i++)
+    for (AVA ava : rdn)
     {
-      AttributeType attributeType = rdn.getAttributeType(i);
+      AttributeType attributeType = ava.getAttributeType();
       // Is it present in the fractional attributes established list ?
       boolean foundAttribute =
           fractionalConcernedAttributes.contains(attributeType);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tasks/BackupTask.java b/opendj-server-legacy/src/main/java/org/opends/server/tasks/BackupTask.java
index b9fce8a..68371e1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tasks/BackupTask.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tasks/BackupTask.java
@@ -346,7 +346,7 @@
           if (! backupDir.getConfigEntryDN().equals(cfg.dn()))
           {
             logger.error(ERR_BACKUPDB_CANNOT_BACKUP_IN_DIRECTORY, b.getBackendID(), backupLocation.getPath(),
-                backupDir.getConfigEntryDN().rdn().getAttributeValue(0));
+                backupDir.getConfigEntryDN().rdn().getFirstAVA().getAttributeValue());
             return false ;
           }
         }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
index f5a5a26..5956742 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
@@ -46,6 +46,7 @@
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.AttributeDescription;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteSequenceReader;
 import org.forgerock.opendj.ldap.ByteString;
@@ -1890,10 +1891,9 @@
         }
 
           // Make sure that all attributes in the RDN are allowed.
-          int numAVAs = rdn.getNumValues();
-          for (int i = 0; i < numAVAs; i++)
+          for (AVA ava : rdn)
           {
-            AttributeType t = rdn.getAttributeType(i);
+            AttributeType t = ava.getAttributeType();
             if (! nameForm.isRequiredOrOptional(t))
             {
               LocalizableMessage message =
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java b/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
index 5563917..90e720f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/RDN.java
@@ -26,22 +26,26 @@
  */
 package org.opends.server.types;
 
-import org.forgerock.opendj.ldap.schema.AttributeType;
-
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import org.forgerock.i18n.LocalizableMessage;
-import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 import org.forgerock.util.Reject;
 import org.opends.server.core.DirectoryServer;
@@ -60,19 +64,10 @@
      mayExtend=false,
      mayInvoke=true)
 public final class RDN
-       implements Comparable<RDN>
+       implements Comparable<RDN>, Iterable<AVA>
 {
-  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
-  /** The set of attribute types for the elements in this RDN. */
-  private AttributeType[] attributeTypes;
-
-  /** The set of values for the elements in this RDN. */
-  private ByteString[] attributeValues;
-
-  /** The set of user-provided names for the attributes in this RDN. */
-  private String[] attributeNames;
-
+  /** The collection of AVAs for the elements in this RDN. */
+  private final List<AVA> avas;
   /** Representation of the normalized form of this RDN. */
   private ByteString normalizedRDN;
 
@@ -85,13 +80,11 @@
    * @param  attributeValue  The value for this RDN.  It must not be
    *                         {@code null}.
    */
-  @SuppressWarnings("unchecked")
   public RDN(AttributeType attributeType, ByteString attributeValue)
   {
     Reject.ifNull(attributeType, attributeValue);
-    attributeTypes  = new AttributeType[] { attributeType };
-    attributeNames  = new String[] { attributeType.getNameOrOID() };
-    attributeValues = new ByteString[] { attributeValue };
+    avas = new ArrayList<>(1);
+    avas.add(new AVA(attributeType, attributeValue));
   }
 
 
@@ -106,13 +99,11 @@
    * @param  attributeValue  The value for this RDN.  It must not be
    *                         {@code null}.
    */
-  @SuppressWarnings("unchecked")
   public RDN(AttributeType attributeType, String attributeName, ByteString attributeValue)
   {
     Reject.ifNull(attributeType, attributeName, attributeValue);
-    attributeTypes  = new AttributeType[] { attributeType };
-    attributeNames  = new String[] { attributeName };
-    attributeValues = new ByteString[] { attributeValue };
+    avas = new ArrayList<>(1);
+    avas.add(new AVA(attributeType, attributeName, attributeValue));
   }
 
 
@@ -131,7 +122,6 @@
    *                          have the same number of elements as the
    *                          {@code attributeTypes} argument.
    */
-  @SuppressWarnings("unchecked")
   public RDN(List<AttributeType> attributeTypes,
              List<String> attributeNames,
              List<ByteString> attributeValues)
@@ -143,13 +133,11 @@
     Reject.ifFalse(attributeValues.size() == attributeTypes.size(),
             "attributeValues must have the same number of elements than attributeTypes");
 
-    this.attributeTypes  = new AttributeType[attributeTypes.size()];
-    this.attributeNames  = new String[attributeNames.size()];
-    this.attributeValues = new ByteString[attributeValues.size()];
-
-    attributeTypes.toArray(this.attributeTypes);
-    attributeNames.toArray(this.attributeNames);
-    attributeValues.toArray(this.attributeValues);
+    avas = new ArrayList<>(attributeTypes.size());
+    for (int i = 0; i < attributeTypes.size(); i++)
+    {
+      avas.add(new AVA(attributeTypes.get(i), attributeNames.get(i), attributeValues.get(i)));
+    }
   }
 
 
@@ -168,7 +156,6 @@
    *                          have the same number of elements as the
    *                          {@code attributeTypes} argument.
    */
-  @SuppressWarnings("unchecked")
   public RDN(AttributeType[] attributeTypes, String[] attributeNames, ByteString[] attributeValues)
   {
     Reject.ifNull(attributeTypes, attributeNames, attributeValues);
@@ -178,9 +165,24 @@
     Reject.ifFalse(attributeValues.length == attributeTypes.length,
         "attributeValues must have the same number of elements than attributeTypes");
 
-    this.attributeTypes = attributeTypes;
-    this.attributeNames = attributeNames;
-    this.attributeValues = attributeValues;
+    avas = new ArrayList<>(attributeTypes.length);
+    for (int i = 0; i < attributeTypes.length; i++)
+    {
+      avas.add(new AVA(attributeTypes[i], attributeNames[i], attributeValues[i]));
+    }
+  }
+
+  /**
+   * Creates a new RDN with the provided collection of {@link AVA}.
+   *
+   * @param avas
+   *          The collection of AVA that will define the new RDN
+   */
+  public RDN(Collection<AVA> avas)
+  {
+    Reject.ifNull(avas, "avas must not be null");
+    Reject.ifTrue(avas.isEmpty(), "avas must not be empty");
+    this.avas = new ArrayList<>(avas);
   }
 
 
@@ -200,22 +202,16 @@
     return new RDN(attributeType, attributeValue);
   }
 
-
-
   /**
-   * Retrieves the number of attribute-value pairs contained in this
-   * RDN.
+   * Retrieves the number of attribute-value pairs contained in this RDN.
    *
-   * @return  The number of attribute-value pairs contained in this
-   *          RDN.
+   * @return The number of attribute-value pairs contained in this RDN.
    */
-  public int getNumValues()
+  public int size()
   {
-    return attributeTypes.length;
+    return avas.size();
   }
 
-
-
   /**
    * Indicates whether this RDN includes the specified attribute type.
    *
@@ -227,14 +223,13 @@
    */
   public boolean hasAttributeType(AttributeType attributeType)
   {
-    for (AttributeType t : attributeTypes)
+    for (AVA ava : avas)
     {
-      if (t.equals(attributeType))
+      if (ava.getAttributeType().equals(attributeType))
       {
         return true;
       }
     }
-
     return false;
   }
 
@@ -252,60 +247,16 @@
    */
   public boolean hasAttributeType(String lowerName)
   {
-    for (AttributeType t : attributeTypes)
+    for (AVA ava : avas)
     {
-      if (t.hasNameOrOID(lowerName))
+      if (ava.getAttributeType().hasNameOrOID(lowerName))
       {
         return true;
       }
     }
-
-    for (String s : attributeNames)
-    {
-      if (s.equalsIgnoreCase(lowerName))
-      {
-        return true;
-      }
-    }
-
     return false;
   }
 
-
-
-  /**
-   * Retrieves the attribute type at the specified position in the set
-   * of attribute types for this RDN.
-   *
-   * @param  pos  The position of the attribute type to retrieve.
-   *
-   * @return  The attribute type at the specified position in the set
-   *          of attribute types for this RDN.
-   */
-  public AttributeType getAttributeType(int pos)
-  {
-    return attributeTypes[pos];
-  }
-
-
-
-  /**
-   * Retrieves the name for the attribute type at the specified
-   * position in the set of attribute types for this RDN.
-   *
-   * @param  pos  The position of the attribute type for which to
-   *              retrieve the name.
-   *
-   * @return  The name for the attribute type at the specified
-   *          position in the set of attribute types for this RDN.
-   */
-  public String getAttributeName(int pos)
-  {
-    return attributeNames[pos];
-  }
-
-
-
   /**
    * Retrieves the attribute value that is associated with the
    * specified attribute type.
@@ -319,36 +270,16 @@
    */
   public ByteString getAttributeValue(AttributeType attributeType)
   {
-    for (int i=0; i < attributeTypes.length; i++)
+    for (AVA ava : avas)
     {
-      if (attributeTypes[i].equals(attributeType))
+      if (ava.getAttributeType().equals(attributeType))
       {
-        return attributeValues[i];
+        return ava.getAttributeValue();
       }
     }
-
     return null;
   }
 
-
-
-  /**
-   * Retrieves the value for the attribute type at the specified
-   * position in the set of attribute types for this RDN.
-   *
-   * @param  pos  The position of the attribute type for which to
-   *              retrieve the value.
-   *
-   * @return  The value for the attribute type at the specified
-   *          position in the set of attribute types for this RDN.
-   */
-  public ByteString getAttributeValue(int pos)
-  {
-    return attributeValues[pos];
-  }
-
-
-
   /**
    * Indicates whether this RDN is multivalued.
    *
@@ -357,7 +288,7 @@
    */
   public boolean isMultiValued()
   {
-    return attributeTypes.length > 1;
+    return avas.size() > 1;
   }
 
 
@@ -375,15 +306,13 @@
    */
   public boolean hasValue(AttributeType type, ByteString value)
   {
-    for (int i=0; i < attributeTypes.length; i++)
+    for (AVA ava : avas)
     {
-      if (attributeTypes[i].equals(type) &&
-          attributeValues[i].equals(value))
+      if (ava.getAttributeType().equals(type) && ava.getAttributeValue().equals(value))
       {
         return true;
       }
     }
-
     return false;
   }
 
@@ -403,146 +332,17 @@
    */
   boolean addValue(AttributeType type, String name, ByteString value)
   {
-    int numValues = attributeTypes.length;
-    for (int i=0; i < numValues; i++)
+    for (AVA ava : avas)
     {
-      if (attributeTypes[i].equals(type) &&
-          attributeValues[i].equals(value))
+      if (ava.getAttributeType().equals(type) && ava.getAttributeValue().equals(value))
       {
         return false;
       }
     }
-    numValues++;
-    AttributeType[] newTypes = new AttributeType[numValues];
-    System.arraycopy(attributeTypes, 0, newTypes, 0, attributeTypes.length);
-    newTypes[attributeTypes.length] = type;
-    attributeTypes = newTypes;
-
-    String[] newNames = new String[numValues];
-    System.arraycopy(attributeNames, 0, newNames, 0, attributeNames.length);
-    newNames[attributeNames.length] = name;
-    attributeNames = newNames;
-
-    ByteString[] newValues = new ByteString[numValues];
-    System.arraycopy(attributeValues, 0, newValues, 0, attributeValues.length);
-    newValues[attributeValues.length] = value;
-    attributeValues = newValues;
-
+    avas.add(new AVA(type, name, value));
     return true;
   }
 
-
-
-  /**
-   * Retrieves a version of the provided value in a form that is
-   * properly escaped for use in a DN or RDN.
-   *
-   * @param  valueBS  The value to be represented in a DN-safe form.
-   *
-   * @return  A version of the provided value in a form that is
-   *          properly escaped for use in a DN or RDN.
-   */
-  private static String getDNValue(ByteString valueBS) {
-    final String value = valueBS.toString();
-    if (value == null || value.length() == 0) {
-      return "";
-    }
-
-    // Only copy the string value if required.
-    boolean needsEscaping = false;
-    int length = value.length();
-
-    needsEscaping: {
-      char c = value.charAt(0);
-      if (c == ' ' || c == '#') {
-        needsEscaping = true;
-        break needsEscaping;
-      }
-
-      if (value.charAt(length - 1) == ' ') {
-        needsEscaping = true;
-        break needsEscaping;
-      }
-
-      for (int i = 0; i < length; i++) {
-        c = value.charAt(i);
-        if (c < ' ') {
-          needsEscaping = true;
-          break needsEscaping;
-        } else {
-          switch (c) {
-          case ',':
-          case '+':
-          case '"':
-          case '\\':
-          case '<':
-          case '>':
-          case ';':
-            needsEscaping = true;
-            break needsEscaping;
-          }
-        }
-      }
-    }
-
-    if (!needsEscaping) {
-      return value;
-    }
-
-    // We need to copy and escape the string (allow for at least one
-    // escaped character).
-    StringBuilder buffer = new StringBuilder(length + 3);
-
-    // If the lead character is a space or a # it must be escaped.
-    int start = 0;
-    char c = value.charAt(0);
-    if (c == ' ' || c == '#') {
-      buffer.append('\\');
-      buffer.append(c);
-      if (length == 1) {
-        return buffer.toString();
-      }
-      start = 1;
-    }
-
-    // Escape remaining characters as necessary.
-    for (int i = start; i < length; i++) {
-      c = value.charAt(i);
-      if (c < ' ') {
-        for (byte b : getBytes(String.valueOf(c))) {
-          buffer.append('\\');
-          buffer.append(byteToLowerHex(b));
-        }
-      } else {
-        switch (value.charAt(i)) {
-        case ',':
-        case '+':
-        case '"':
-        case '\\':
-        case '<':
-        case '>':
-        case ';':
-          buffer.append('\\');
-          buffer.append(c);
-          break;
-        default:
-          buffer.append(c);
-          break;
-        }
-      }
-    }
-
-    // If the last character is a space it must be escaped.
-    if (value.charAt(length - 1) == ' ') {
-      length = buffer.length();
-      buffer.insert(length - 1, '\\');
-    }
-
-    return buffer.toString();
-  }
-
-
-
   /**
    * Decodes the provided string as an RDN.
    *
@@ -845,17 +645,7 @@
    */
   public RDN duplicate()
   {
-    int numValues = attributeTypes.length;
-    AttributeType[] newTypes = new AttributeType[numValues];
-    System.arraycopy(attributeTypes, 0, newTypes, 0, numValues);
-
-    String[] newNames = new String[numValues];
-    System.arraycopy(attributeNames, 0, newNames, 0, numValues);
-
-    ByteString[] newValues = new ByteString[numValues];
-    System.arraycopy(attributeValues, 0, newValues, 0, numValues);
-
-    return new RDN(newTypes, newNames, newValues);
+    return new RDN(avas);
   }
 
 
@@ -900,10 +690,10 @@
   }
 
   /** Returns normalized value for attribute at provided position. */
-  private ByteString getEqualityNormalizedValue(int position)
+  private ByteString getEqualityNormalizedValue(AVA ava)
   {
-    final MatchingRule matchingRule = attributeTypes[position].getEqualityMatchingRule();
-    ByteString attributeValue = attributeValues[position];
+    final MatchingRule matchingRule = ava.getAttributeType().getEqualityMatchingRule();
+    ByteString attributeValue = ava.getAttributeValue();
     if (matchingRule != null)
     {
       try
@@ -913,7 +703,7 @@
       catch (final DecodeException de)
       {
         // Unable to normalize, use default
-        attributeValue = attributeValues[position];
+        attributeValue = ava.getAttributeValue();
       }
     }
     return attributeValue;
@@ -929,17 +719,15 @@
   @Override
   public String toString()
   {
-        StringBuilder buffer = new StringBuilder();
-        buffer.append(attributeNames[0]);
-        buffer.append("=");
-        buffer.append(getDNValue(attributeValues[0]));
-        for (int i = 1; i < attributeTypes.length; i++) {
-            buffer.append("+");
-            buffer.append(attributeNames[i]);
-            buffer.append("=");
-            buffer.append(getDNValue(attributeValues[i]));
-        }
-        return buffer.toString();
+    StringBuilder buffer = new StringBuilder();
+    Iterator<AVA> it = avas.iterator();
+    buffer.append(it.next());
+    while (it.hasNext())
+    {
+      buffer.append("+");
+      buffer.append(it.next());
+    }
+    return buffer.toString();
   }
 
   /**
@@ -966,18 +754,18 @@
   String toNormalizedUrlSafeString()
   {
     final StringBuilder buffer = new StringBuilder();
-    if (attributeNames.length == 1)
+    if (avas.size() == 1)
     {
-      normalizeAVAToUrlSafeString(0, buffer);
+      normalizeAVAToUrlSafeString(getFirstAVA(), buffer);
     }
     else
     {
       // Normalization sorts RDNs alphabetically
       SortedSet<String> avaStrings = new TreeSet<>();
-      for (int i=0; i < attributeNames.length; i++)
+      for (AVA ava : avas)
       {
         StringBuilder builder = new StringBuilder();
-        normalizeAVAToUrlSafeString(i, builder);
+        normalizeAVAToUrlSafeString(ava, builder);
         avaStrings.add(builder.toString());
       }
 
@@ -1025,18 +813,18 @@
   {
     final int startPos = builder.length();
 
-    if (attributeNames.length == 1)
+    if (avas.size() == 1)
     {
-      normalizeAVAToByteString(0, builder);
+      normalizeAVAToByteString(getFirstAVA(), builder);
     }
     else
     {
       // Normalization sorts RDNs
       SortedSet<ByteString> avaStrings = new TreeSet<>();
-      for (int i = 0; i < attributeNames.length; i++)
+      for (AVA ava : avas)
       {
         ByteStringBuilder b = new ByteStringBuilder();
-        normalizeAVAToByteString(i, b);
+        normalizeAVAToByteString(ava, b);
         avaStrings.add(b.toByteString());
       }
 
@@ -1067,11 +855,11 @@
    *           Builder to add the representation to.
    * @return the builder
    */
-  private ByteStringBuilder normalizeAVAToByteString(int position, final ByteStringBuilder builder)
+  private ByteStringBuilder normalizeAVAToByteString(AVA ava, final ByteStringBuilder builder)
   {
-    builder.appendUtf8(attributeTypes[position].getNormalizedNameOrOID());
+    builder.appendUtf8(ava.getAttributeType().getNormalizedNameOrOID());
     builder.appendUtf8("=");
-    final ByteString value = getEqualityNormalizedValue(position);
+    final ByteString value = getEqualityNormalizedValue(ava);
     if (value.length() > 0)
     {
       builder.appendBytes(escapeBytes(value));
@@ -1132,18 +920,19 @@
    * @param  builder  The buffer to which to append the information.
    * @return the builder
    */
-  private StringBuilder normalizeAVAToUrlSafeString(int position, StringBuilder builder)
+  private StringBuilder normalizeAVAToUrlSafeString(AVA ava, StringBuilder builder)
   {
-      builder.append(attributeTypes[position].getNormalizedNameOrOID());
+    AttributeType attrType = ava.getAttributeType();
+    builder.append(attrType.getNormalizedNameOrOID());
       builder.append('=');
 
-      ByteString value = getEqualityNormalizedValue(position);
+    ByteString value = getEqualityNormalizedValue(ava);
       if (value.length() == 0)
       {
         return builder;
       }
-      final boolean hasAttributeName = !attributeTypes[position].getNames().isEmpty();
-      final boolean isHumanReadable = attributeTypes[position].getSyntax().isHumanReadable();
+    final boolean hasAttributeName = !attrType.getNames().isEmpty();
+    final boolean isHumanReadable = attrType.getSyntax().isHumanReadable();
       if (!hasAttributeName || !isHumanReadable)
       {
         builder.append(value.toPercentHexString());
@@ -1195,4 +984,19 @@
     return toNormalizedByteString().compareTo(rdn.toNormalizedByteString());
   }
 
+  /**
+   * Returns the first AVA of this {@link RDN}.
+   *
+   * @return the first AVA of this {@link RDN}.
+   */
+  public AVA getFirstAVA()
+  {
+    return avas.get(0);
+  }
+
+  @Override
+  public Iterator<AVA> iterator()
+  {
+    return avas.iterator();
+  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java b/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
index cee176b..379672d 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java
@@ -42,6 +42,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
@@ -3433,15 +3434,13 @@
       int count = entryDN.size();
       for (int rdnIndex = 0; rdnIndex < count; rdnIndex++)
       {
-        RDN rdn = entryDN.getRDN(rdnIndex);
-        int numAVAs = rdn.getNumValues();
-        for (int i=0; i < numAVAs; i++)
+        for (AVA ava : entryDN.getRDN(rdnIndex))
         {
           try
           {
-            if (attributeType == null || attributeType.equals(rdn.getAttributeType(i)))
+            if (attributeType == null || attributeType.equals(ava.getAttributeType()))
             {
-              ByteString v = rdn.getAttributeValue(i);
+              ByteString v = ava.getAttributeValue();
               ByteString nv = matchingRule.normalizeAttributeValue(v);
               ConditionResult r = assertion.matches(nv);
               switch (r)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/LDIFReader.java b/opendj-server-legacy/src/main/java/org/opends/server/util/LDIFReader.java
index d1c2f61..99f71b2 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/LDIFReader.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/LDIFReader.java
@@ -47,6 +47,7 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
@@ -1680,29 +1681,19 @@
           Map<AttributeType,List<Attribute>>userAttributes,
           Map<AttributeType,List<Attribute>> operationalAttributes)
   {
-    RDN rdn = entryDN.rdn();
-    int numAVAs = rdn.getNumValues();
-    for (int i=0; i < numAVAs; i++)
+    for (AVA ava : entryDN.rdn())
     {
-      AttributeType  t = rdn.getAttributeType(i);
-      ByteString v = rdn.getAttributeValue(i);
-      String         n = rdn.getAttributeName(i);
-      if (t.isOperational())
-      {
-        addRDNAttributesIfNecessary(operationalAttributes, t, v, n);
-      }
-      else
-      {
-        addRDNAttributesIfNecessary(userAttributes, t, v, n);
-      }
+      AttributeType t = ava.getAttributeType();
+      addRDNAttributesIfNecessary(t.isOperational() ? operationalAttributes : userAttributes, ava);
     }
   }
 
 
-  private void addRDNAttributesIfNecessary(
-      Map<AttributeType, List<Attribute>> attributes, AttributeType t,
-      ByteString v, String n)
+  private void addRDNAttributesIfNecessary(Map<AttributeType, List<Attribute>> attributes, AVA ava)
   {
+    AttributeType t = ava.getAttributeType();
+    String n = ava.getAttributeName();
+    ByteString v = ava.getAttributeValue();
     final List<Attribute> attrList = attributes.get(t);
     if (attrList == null)
     {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
index cbf6f19..0c0cdeb 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/StaticUtils.java
@@ -29,7 +29,15 @@
 import static org.opends.messages.UtilityMessages.*;
 import static org.opends.server.util.ServerConstants.*;
 
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
@@ -40,7 +48,18 @@
 import java.nio.channels.SocketChannel;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.TimeZone;
 
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
@@ -49,15 +68,22 @@
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.LocalizableMessageDescriptor;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.util.Reject;
 import org.opends.messages.ToolMessages;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ServerContext;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.IdentifiedException;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.types.RDN;
 
 import com.forgerock.opendj.cli.Argument;
 import com.forgerock.opendj.cli.ArgumentException;
@@ -2314,10 +2340,9 @@
 
     // Get the information about the RDN attributes.
     RDN rdn = dn.rdn();
-    int numAVAs = rdn.getNumValues();
 
     // If there is only one RDN attribute, then see which objectclass we should use.
-    ObjectClass structuralClass = DirectoryServer.getObjectClass(getObjectClassName(rdn, numAVAs));
+    ObjectClass structuralClass = DirectoryServer.getObjectClass(getObjectClassName(rdn));
 
     // Get the top and untypedObject classes to include in the entry.
     LinkedHashMap<ObjectClass,String> objectClasses = new LinkedHashMap<>(3);
@@ -2332,11 +2357,9 @@
     LinkedHashMap<AttributeType,List<Attribute>> operationalAttributes = new LinkedHashMap<>();
 
     boolean extensibleObjectAdded = false;
-    for (int i=0; i < numAVAs; i++)
+    for (AVA ava : rdn)
     {
-      AttributeType attrType = rdn.getAttributeType(i);
-      ByteString attrValue = rdn.getAttributeValue(i);
-      String attrName = rdn.getAttributeName(i);
+      AttributeType attrType = ava.getAttributeType();
 
       // First, see if this type is allowed by the untypedObject class.  If not,
       // then we'll need to include the extensibleObject class.
@@ -2355,14 +2378,7 @@
 
 
       // Create the attribute and add it to the appropriate map.
-      if (attrType.isOperational())
-      {
-        addAttributeValue(operationalAttributes, attrType, attrName, attrValue);
-      }
-      else
-      {
-        addAttributeValue(userAttributes, attrType, attrName, attrValue);
-      }
+      addAttributeValue(attrType.isOperational() ? operationalAttributes : userAttributes, ava);
     }
 
 
@@ -2370,11 +2386,11 @@
     return new Entry(dn, objectClasses, userAttributes, operationalAttributes);
   }
 
-  private static String getObjectClassName(RDN rdn, int numAVAs)
+  private static String getObjectClassName(RDN rdn)
   {
-    if (numAVAs == 1)
+    if (rdn.size() == 1)
     {
-      final AttributeType attrType = rdn.getAttributeType(0);
+      final AttributeType attrType = rdn.getFirstAVA().getAttributeType();
       if (attrType.hasName(ATTR_C))
       {
         return OC_COUNTRY;
@@ -2395,9 +2411,10 @@
     return OC_UNTYPED_OBJECT_LC;
   }
 
-  private static void addAttributeValue(LinkedHashMap<AttributeType, List<Attribute>> attrs,
-      AttributeType attrType, String attrName, ByteString attrValue)
+  private static void addAttributeValue(LinkedHashMap<AttributeType, List<Attribute>> attrs, AVA ava)
   {
+    AttributeType attrType = ava.getAttributeType();
+    ByteString attrValue = ava.getAttributeValue();
     List<Attribute> attrList = attrs.get(attrType);
     if (attrList != null && !attrList.isEmpty())
     {
@@ -2407,7 +2424,7 @@
     }
     else
     {
-      AttributeBuilder builder = new AttributeBuilder(attrType, attrName);
+      AttributeBuilder builder = new AttributeBuilder(attrType, ava.getAttributeName());
       builder.add(attrValue);
       attrs.put(attrType, builder.toAttributeList());
     }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
index 58301f7..4bb8d53 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendAddOperation.java
@@ -34,6 +34,7 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -68,7 +69,6 @@
 import org.opends.server.types.LockManager.DNLock;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.Privilege;
-import org.opends.server.types.RDN;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.operation.PostOperationAddOperation;
 import org.opends.server.types.operation.PostResponseAddOperation;
@@ -586,30 +586,21 @@
    */
   private void addRDNAttributesIfNecessary() throws DirectoryException
   {
-    RDN rdn = entryDN.rdn();
-    int numAVAs = rdn.getNumValues();
-    for (int i=0; i < numAVAs; i++)
+    for (AVA ava : entryDN.rdn())
     {
-      AttributeType  t = rdn.getAttributeType(i);
-      ByteString     v = rdn.getAttributeValue(i);
-      String         n = rdn.getAttributeName(i);
-      if (t.isOperational())
-      {
-        addRDNAttributesIfNecessary(operationalAttributes, t, v, n);
-      }
-      else
-      {
-        addRDNAttributesIfNecessary(userAttributes, t, v, n);
-      }
+      AttributeType t = ava.getAttributeType();
+      addRDNAttributesIfNecessary(t.isOperational() ? operationalAttributes : userAttributes, ava);
     }
   }
 
 
 
-  private void addRDNAttributesIfNecessary(
-      Map<AttributeType, List<Attribute>> attributes, AttributeType t,
-      ByteString v, String n) throws DirectoryException
+  private void addRDNAttributesIfNecessary(Map<AttributeType, List<Attribute>> attributes, AVA ava)
+      throws DirectoryException
   {
+    AttributeType  t = ava.getAttributeType();
+    String         n = ava.getAttributeName();
+    ByteString     v = ava.getAttributeValue();
     final List<Attribute> attrList = attributes.get(t);
     if (attrList == null)
     {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
index baabf0f..63b9c84 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyDNOperation.java
@@ -34,6 +34,7 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
@@ -630,14 +631,12 @@
     // If we should delete the old RDN values from the entry, then do so.
     if (deleteOldRDN())
     {
-      RDN currentRDN = entryDN.rdn();
-      int numValues  = currentRDN.getNumValues();
-      for (int i=0; i < numValues; i++)
+      for (AVA ava : entryDN.rdn())
       {
         Attribute a = Attributes.create(
-            currentRDN.getAttributeType(i),
-            currentRDN.getAttributeName(i),
-            currentRDN.getAttributeValue(i));
+            ava.getAttributeType(),
+            ava.getAttributeName(),
+            ava.getAttributeValue());
 
         // If the associated attribute type is marked NO-USER-MODIFICATION, then
         // refuse the update.
@@ -661,13 +660,12 @@
 
 
     // Add the new RDN values to the entry.
-    int newRDNValues = newRDN.getNumValues();
-    for (int i=0; i < newRDNValues; i++)
+    for (AVA ava : newRDN)
     {
       Attribute a = Attributes.create(
-          newRDN.getAttributeType(i),
-          newRDN.getAttributeName(i),
-          newRDN.getAttributeValue(i));
+          ava.getAttributeType(),
+          ava.getAttributeName(),
+          ava.getAttributeValue());
 
       List<ByteString> duplicateValues = new LinkedList<>();
       newEntry.addAttribute(a, duplicateValues);
@@ -704,9 +702,9 @@
             ERR_MODDN_VIOLATES_SCHEMA.get(entryDN, invalidReason));
       }
 
-      for (int i=0; i < newRDNValues; i++)
+      for (AVA ava : newRDN)
       {
-        AttributeType at = newRDN.getAttributeType(i);
+        AttributeType at = ava.getAttributeType();
         if (at.isObsolete())
         {
           throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION,
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/admin/server/DefaultBehaviorTest.java b/opendj-server-legacy/src/test/java/org/opends/server/admin/server/DefaultBehaviorTest.java
index cd14c36..e490b9d 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/admin/server/DefaultBehaviorTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/admin/server/DefaultBehaviorTest.java
@@ -32,6 +32,8 @@
 import javax.naming.ldap.LdapName;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
+import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.admin.AdminTestCase;
 import org.opends.server.admin.TestCfg;
@@ -39,9 +41,7 @@
 import org.opends.server.admin.TestParentCfg;
 import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
 import org.opends.server.admin.std.server.RootCfg;
-import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.core.DirectoryServer;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.testng.Assert;
 import org.testng.annotations.AfterClass;
@@ -71,9 +71,7 @@
       // No implementation required.
     }
 
-
-
-    /** {@inheritDoc} */
+    @Override
     public ConfigChangeResult applyConfigurationAdd(TestChildCfg configuration) {
       return new ConfigChangeResult();
     }
@@ -90,19 +88,16 @@
      */
     public TestChildCfg getChild(String expectedName) {
       Assert.assertNotNull(child);
-      Assert.assertEquals(child.dn().rdn().getAttributeValue(0).toString(), expectedName);
+      Assert.assertEquals(child.dn().rdn().getFirstAVA().getAttributeValue().toString(), expectedName);
       return child;
     }
 
-
-
-    /** {@inheritDoc} */
+    @Override
     public boolean isConfigurationAddAcceptable(TestChildCfg configuration,
         List<LocalizableMessage> unacceptableReasons) {
       child = configuration;
       return true;
     }
-
   }
 
 
@@ -125,9 +120,7 @@
       // No implementation required.
     }
 
-
-
-    /** {@inheritDoc} */
+    @Override
     public ConfigChangeResult applyConfigurationChange(TestChildCfg configuration) {
       return new ConfigChangeResult();
     }
@@ -144,19 +137,16 @@
      */
     public TestChildCfg getChild(String expectedName) {
       Assert.assertNotNull(child);
-      Assert.assertEquals(child.dn().rdn().getAttributeValue(0).toString(), expectedName);
+      Assert.assertEquals(child.dn().rdn().getFirstAVA().getAttributeValue().toString(), expectedName);
       return child;
     }
 
-
-
-    /** {@inheritDoc} */
+    @Override
     public boolean isConfigurationChangeAcceptable(TestChildCfg configuration,
         List<LocalizableMessage> unacceptableReasons) {
       child = configuration;
       return true;
     }
-
   }
 
   /** Test child 1 LDIF. */
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/PluginConfigManagerTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/core/PluginConfigManagerTestCase.java
index 78eaf0a..a0dd41f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/PluginConfigManagerTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/PluginConfigManagerTestCase.java
@@ -22,31 +22,25 @@
  *
  *
  *      Copyright 2006-2008 Sun Microsystems, Inc.
- *      Portions Copyright 2014-2015 ForgeRock AS
+ *      Portions Copyright 2014-2016 ForgeRock AS
  */
 package org.opends.server.core;
 
-
-
 import java.util.ArrayList;
 
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.api.plugin.DirectoryServerPlugin;
 import org.opends.server.api.plugin.PluginType;
 import org.opends.server.types.DN;
 
-import static org.testng.Assert.*;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 import static org.opends.server.util.ServerConstants.*;
+import static org.testng.Assert.*;
 
-
-
-/**
- * A set of test cases for the plugin config manager.
- */
+/** A set of test cases for the plugin config manager. */
 public class PluginConfigManagerTestCase
        extends CoreTestCase
 {
@@ -639,7 +633,7 @@
       expectedOrder.append(expectedNameOrder[i]);
 
       DN dn = pluginArray[i].getPluginEntryDN();
-      String name = dn.rdn().getAttributeValue(0).toString().toLowerCase();
+      String name = dn.rdn().getFirstAVA().getAttributeValue().toString().toLowerCase();
       actualOrder.append(name);
 
       if (! name.equals(expectedNameOrder[i]))
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java b/opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java
index f275655..c3577c1 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java
@@ -38,6 +38,7 @@
 import javax.naming.directory.InitialDirContext;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -321,12 +322,11 @@
     final Entry newEntry = DirectoryServer.getEntry(dn(entryDN));
     assertNotNull(newEntry);
 
-    final RDN rdn = newEntry.getName().rdn();
-    for (int i = 0; i < rdn.getNumValues(); i++)
+    for (AVA ava : newEntry.getName().rdn())
     {
-      AttributeType attribute = rdn.getAttributeType(i);
-      assertEquals(newEntry.hasValue(attribute, b("user.0")), user0Exists);
-      assertEquals(newEntry.hasValue(attribute, b("user.test0")), userTest0Exists);
+      AttributeType attrType = ava.getAttributeType();
+      assertEquals(newEntry.hasValue(attrType, b("user.0")), user0Exists);
+      assertEquals(newEntry.hasValue(attrType, b("user.test0")), userTest0Exists);
     }
   }
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/types/TestRDN.java b/opendj-server-legacy/src/test/java/org/opends/server/types/TestRDN.java
index 218af4f..1e0ea76 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/types/TestRDN.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/types/TestRDN.java
@@ -31,7 +31,9 @@
 import static org.testng.Assert.*;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 
+import org.forgerock.opendj.ldap.AVA;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
@@ -92,10 +94,11 @@
   public void testConstructor() throws Exception {
     RDN rdn = new RDN(AT_DC, AV_DC_ORG);
 
-    assertEquals(rdn.getNumValues(), 1);
-    assertEquals(rdn.getAttributeType(0), AT_DC);
-    assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
-    assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
+    assertEquals(rdn.size(), 1);
+    AVA ava = rdn.getFirstAVA();
+    assertEquals(ava.getAttributeType(), AT_DC);
+    assertEquals(ava.getAttributeName(), AT_DC.getNameOrOID());
+    assertEquals(ava.getAttributeValue(), AV_DC_ORG);
   }
 
 
@@ -110,10 +113,11 @@
   public void testConstructorWithName() throws Exception {
     RDN rdn = new RDN(AT_DC, "domainComponent", AV_DC_ORG);
 
-    assertEquals(rdn.getNumValues(), 1);
-    assertEquals(rdn.getAttributeType(0), AT_DC);
-    assertEquals(rdn.getAttributeName(0), "domainComponent");
-    assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
+    assertEquals(rdn.size(), 1);
+    AVA ava = rdn.getFirstAVA();
+    assertEquals(ava.getAttributeType(), AT_DC);
+    assertEquals(ava.getAttributeName(), "domainComponent");
+    assertEquals(ava.getAttributeValue(), AV_DC_ORG);
   }
 
 
@@ -133,15 +137,19 @@
 
     RDN rdn = new RDN(attrTypes, attrNames, attrValues);
 
-    assertEquals(rdn.getNumValues(), 2);
+    assertEquals(rdn.size(), 2);
 
-    assertEquals(rdn.getAttributeType(0), AT_DC);
-    assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
-    assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
+    Iterator<AVA> it = rdn.iterator();
+    AVA ava1 = it.next();
+    AVA ava2 = it.next();
 
-    assertEquals(rdn.getAttributeType(1), AT_CN);
-    assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
-    assertEquals(rdn.getAttributeValue(1), AV_CN);
+    assertEquals(ava1.getAttributeType(), AT_DC);
+    assertEquals(ava1.getAttributeName(), AT_DC.getNameOrOID());
+    assertEquals(ava1.getAttributeValue(), AV_DC_ORG);
+
+    assertEquals(ava2.getAttributeType(), AT_CN);
+    assertEquals(ava2.getAttributeName(), AT_CN.getNameOrOID());
+    assertEquals(ava2.getAttributeValue(), AV_CN);
   }
 
 
@@ -168,15 +176,19 @@
 
     RDN rdn = new RDN(typeList, nameList, valueList);
 
-    assertEquals(rdn.getNumValues(), 2);
+    assertEquals(rdn.size(), 2);
 
-    assertEquals(rdn.getAttributeType(0), AT_DC);
-    assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
-    assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
+    Iterator<AVA> it = rdn.iterator();
+    AVA ava1 = it.next();
+    AVA ava2 = it.next();
 
-    assertEquals(rdn.getAttributeType(1), AT_CN);
-    assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
-    assertEquals(rdn.getAttributeValue(1), AV_CN);
+    assertEquals(ava1.getAttributeType(), AT_DC);
+    assertEquals(ava1.getAttributeName(), AT_DC.getNameOrOID());
+    assertEquals(ava1.getAttributeValue(), AV_DC_ORG);
+
+    assertEquals(ava2.getAttributeType(), AT_CN);
+    assertEquals(ava2.getAttributeName(), AT_CN.getNameOrOID());
+    assertEquals(ava2.getAttributeValue(), AV_CN);
   }
 
 
@@ -292,8 +304,6 @@
     fail("Expected exception for value \"" + rawRDN + "\"");
   }
 
-
-
   /**
    * Test getAttributeName.
    *
@@ -309,10 +319,13 @@
 
     RDN rdn = new RDN(attrTypes, attrNames, attrValues);
 
-    assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
-    assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
-  }
+    Iterator<AVA> it = rdn.iterator();
+    AVA ava1 = it.next();
+    AVA ava2 = it.next();
 
+    assertEquals(ava1.getAttributeName(), AT_DC.getNameOrOID());
+    assertEquals(ava2.getAttributeName(), AT_CN.getNameOrOID());
+ }
 
   @SuppressWarnings("javadoc")
   @Test(expectedExceptions = IllegalArgumentException.class)
@@ -334,9 +347,9 @@
     ByteString[]     attrValues = { AV_DC_ORG, AV_CN };
 
     RDN rdn = new RDN(attrTypes, attrNames, attrValues);
-
-    assertEquals(rdn.getAttributeType(0), AT_DC);
-    assertEquals(rdn.getAttributeType(1), AT_CN);
+    Iterator<AVA> it = rdn.iterator();
+    assertEquals(it.next().getAttributeType(), AT_DC);
+    assertEquals(it.next().getAttributeType(), AT_CN);
   }
 
   /**
@@ -353,9 +366,9 @@
     ByteString[]     attrValues = { AV_DC_ORG, AV_CN };
 
     RDN rdn = new RDN(attrTypes, attrNames, attrValues);
-
-    assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
-    assertEquals(rdn.getAttributeValue(1), AV_CN);
+    Iterator<AVA> it = rdn.iterator();
+    assertEquals(it.next().getAttributeValue(), AV_DC_ORG);
+    assertEquals(it.next().getAttributeValue(), AV_CN);
   }
 
   /**
@@ -375,18 +388,18 @@
 
 
   /**
-   * Test getNumValues.
+   * Test {@link RDN#size()}.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
    */
   @Test
-  public void testGetNumValues() throws Exception {
+  public void testSize() throws Exception {
     RDN rdn = new RDN(AT_DC, AV_DC_ORG);
-    assertEquals(rdn.getNumValues(), 1);
+    assertEquals(rdn.size(), 1);
 
     rdn.addValue(AT_CN, AT_CN.getNameOrOID(), AV_CN);
-    assertEquals(rdn.getNumValues(), 2);
+    assertEquals(rdn.size(), 2);
   }
 
 
@@ -419,7 +432,7 @@
   @Test
   public void testIsMultiValued() throws Exception {
     RDN rdn = new RDN(AT_DC, AV_DC_ORG);
-    assertEquals(rdn.getNumValues(), 1);
+    assertEquals(rdn.size(), 1);
     assertFalse(rdn.isMultiValued());
 
     rdn.addValue(AT_CN, AT_CN.getNameOrOID(), AV_CN);

--
Gitblit v1.10.0