From 5c1781321a571986f9a1f4fcdf3e332076ee4c83 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 03 Feb 2016 14:50:55 +0000
Subject: [PATCH] Use AttributeDescription in Entry and Attribute

---
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java                  |    2 
 opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java               |   13 
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/UserAttr.java                        |    4 
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java                |    3 
 opendj-server-legacy/src/test/java/org/opends/server/core/TestModifyDNOperation.java                               |    4 
 opendj-server-legacy/src/main/java/org/opends/server/core/AddOperationBasis.java                                   |   19 
 opendj-server-legacy/src/test/java/org/opends/server/core/SubentryPasswordPolicyTestCase.java                      |    8 
 opendj-server-legacy/src/test/java/org/opends/server/util/TestLDIFReader.java                                      |   42 -
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java                       |    3 
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/HistoricalTest.java                        |   36 +
 opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java          |    4 
 opendj-server-legacy/src/main/java/org/opends/server/types/CollectiveVirtualAttribute.java                         |   13 
 opendj-server-legacy/src/test/java/org/opends/server/schema/TimeBasedMatchingRuleTest.java                         |    4 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/SearchResultEntryProtocolOp.java               |    6 
 opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java                                   |  141 ++----
 opendj-server-legacy/src/main/java/org/opends/server/plugins/UniqueAttributePlugin.java                            |   59 +-
 opendj-server-legacy/src/test/java/org/opends/server/core/PasswordPolicyTestCase.java                              |   22 
 opendj-server-legacy/src/main/java/org/opends/server/types/SearchFilter.java                                       |  175 +------
 opendj-server-legacy/src/test/java/org/opends/server/core/SubentryManagerTestCase.java                             |    8 
 opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/TestDnKeyFormat.java                       |    2 
 opendj-server-legacy/src/test/java/org/opends/server/types/AttributeBuilderTest.java                               |   34 
 opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java                                  |   87 ---
 opendj-server-legacy/src/main/java/org/opends/server/types/VirtualAttribute.java                                   |   37 -
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java                      |   32 +
 opendj-server-legacy/src/main/java/org/opends/server/tools/LDIFDiff.java                                           |   16 
 opendj-server-legacy/src/test/java/org/opends/server/replication/GenerationIdTest.java                             |    6 
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyReplaySingleValuedAttributeTest.java |   10 
 opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java |    6 
 opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyConflictTest.java                    |    4 
 opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java                       |    7 
 /dev/null                                                                                                          |   51 --
 opendj-server-legacy/src/test/java/org/opends/server/types/TestEntry.java                                          |  111 ++--
 opendj-server-legacy/src/main/java/org/opends/server/types/Attribute.java                                          |   45 -
 opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java                                              |  236 ++++++----
 opendj-server-legacy/src/main/java/org/opends/server/backends/task/Task.java                                       |    3 
 opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java                                     |    3 
 opendj-server-legacy/src/test/java/org/opends/server/schema/FakeEntryIndex.java                                    |    3 
 37 files changed, 504 insertions(+), 755 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java b/opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java
index 39518f5..a7b498c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/CompressedSchema.java
@@ -57,7 +57,6 @@
 import org.opends.server.core.ServerContext;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.AttributeDescriptions;
 import org.opends.server.types.Attributes;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.ObjectClass;
@@ -319,7 +318,7 @@
       final Attribute attribute) throws DirectoryException
   {
     // Re-use or allocate a new ID.
-    int id = getAttributeId(AttributeDescriptions.create(attribute));
+    int id = getAttributeId(attribute.getAttributeDescription());
 
     // Encode the attribute.
     final byte[] idBytes = encodeId(id);
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 3e552d6..21eac1b 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
@@ -34,10 +34,12 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.admin.std.server.DseeCompatAccessControlHandlerCfg;
 import org.opends.server.api.AccessControlHandler;
 import org.opends.server.api.ClientConnection;
@@ -53,9 +55,26 @@
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.protocols.ldap.LDAPControl;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
-import org.opends.server.workflowelement.localbackend.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.AuthenticationInfo;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Operation;
+import org.opends.server.types.Privilege;
+import org.opends.server.types.RDN;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchResultReference;
+import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendCompareOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation;
+import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
 
 import static org.opends.messages.AccessControlMessages.*;
 import static org.opends.server.authorization.dseecompat.Aci.*;
@@ -718,7 +737,7 @@
           && resourceEntry.hasAttribute(modAttrType))
       {
         container.setCurrentAttributeType(modAttrType);
-        for (Attribute a : resourceEntry.getAttribute(modAttrType, modAttr.getOptions()))
+        for (Attribute a : resourceEntry.getAttribute(modAttr.getAttributeDescription()))
         {
           for (ByteString v : a)
           {
@@ -758,7 +777,7 @@
             break;
           case INCREMENT:
             Entry modifiedEntry = operation.getModifiedEntry();
-            for (Attribute attr : modifiedEntry.getAttribute(modAttrType, modAttr.getOptions()))
+            for (Attribute attr : modifiedEntry.getAttribute(modAttr.getAttributeDescription()))
             {
               for (ByteString val : attr)
               {
@@ -1301,8 +1320,7 @@
         logger.debug(INFO_ACI_ADD_FAILED_PRIVILEGE, entry.getName(), clientDN);
         return false;
       }
-      List<Attribute> attributeList =
-          entry.getOperationalAttribute(aciType, null);
+      List<Attribute> attributeList = entry.getOperationalAttribute(AttributeDescription.create(aciType));
       for (Attribute attribute : attributeList)
       {
         for (ByteString value : attribute)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/UserAttr.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/UserAttr.java
index 9316bd2..9a66e2d 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/UserAttr.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/UserAttr.java
@@ -209,9 +209,9 @@
         if (!result.isEmpty()) {
             ByteString val= ByteString.valueOfUtf8(attrVal);
             SearchResultEntry resultEntry = result.getFirst();
-            if(resultEntry.hasValue(attrType, null, val)) {
+            if(resultEntry.hasValue(attrType, val)) {
                 Entry e=evalCtx.getResourceEntry();
-                if(e.hasValue(attrType, null, val))
+                if(e.hasValue(attrType, val))
                 {
                     matched=EnumEvalResult.TRUE;
                 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/task/Task.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/task/Task.java
index 6f51d7d..e4b9a5a 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/task/Task.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/task/Task.java
@@ -42,6 +42,7 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageDescriptor.Arg2;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -832,7 +833,7 @@
       logMessages.add(messageString);
 
       final AttributeType type = DirectoryServer.getAttributeType(ATTR_TASK_LOG_MESSAGES);
-      final Attribute attr = taskEntry.getExactAttribute(type, Collections.<String> emptySet());
+      final Attribute attr = taskEntry.getExactAttribute(AttributeDescription.create(type));
       final AttributeBuilder builder = attr != null ? new AttributeBuilder(attr) : new AttributeBuilder(type);
       builder.add(messageString);
       taskEntry.putAttribute(type, builder.toAttributeList());
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/AddOperationBasis.java b/opendj-server-legacy/src/main/java/org/opends/server/core/AddOperationBasis.java
index 2b5a20d..89ebb3a 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/AddOperationBasis.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/AddOperationBasis.java
@@ -34,11 +34,24 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.protocols.ldap.LDAPAttribute;
 import org.opends.server.protocols.ldap.LDAPResultCode;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.AbstractOperation;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.CancelResult;
+import org.opends.server.types.CanceledOperationException;
+import org.opends.server.types.Control;
+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.ObjectClass;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
+import org.opends.server.types.RawAttribute;
 import org.opends.server.types.operation.PostResponseAddOperation;
 import org.opends.server.types.operation.PreParseAddOperation;
 import org.opends.server.workflowelement.localbackend.LocalBackendAddOperation;
@@ -356,7 +369,7 @@
               boolean attributeSeen = false;
               for (int i = 0; i < attrs.size(); i++) {
                 Attribute ea = attrs.get(i);
-                if (ea.optionsEqual(attr.getOptions()))
+                if (ea.getAttributeDescription().equals(attr.getAttributeDescription()))
                 {
                   AttributeBuilder builder = new AttributeBuilder(ea);
                   builder.addAll(attr);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
index a90f64a..27c9658 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -734,7 +734,7 @@
       if(e.hasAttribute(type))
       {
         ByteString value = ByteString.valueOfUtf8(oldEntryDN.toString());
-        if (e.hasValue(type, null, value))
+        if (e.hasValue(type, value))
         {
           mods.add(new Modification(ModificationType.DELETE, Attributes
               .create(type, value)));
@@ -1071,10 +1071,7 @@
         break;
       }
 
-      AttributeType attrType      = mod.getAttribute().getAttributeType();
-      Set<String> attrOptions     = mod.getAttribute().getOptions();
-      Attribute modifiedAttribute = entry.getExactAttribute(attrType,
-                                                            attrOptions);
+      Attribute modifiedAttribute = entry.getExactAttribute(mod.getAttribute().getAttributeDescription());
       if (modifiedAttribute != null)
       {
         PluginResult.PreOperation result =
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 82341c5..3f22cda 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
@@ -26,7 +26,13 @@
  */
 package org.opends.server.plugins;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.forgerock.i18n.LocalizableMessage;
@@ -36,6 +42,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+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.PluginCfg;
@@ -52,9 +59,25 @@
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.schema.SchemaConstants;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
-import org.opends.server.types.operation.*;
+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.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;
+import org.opends.server.types.operation.PostOperationAddOperation;
+import org.opends.server.types.operation.PostOperationModifyDNOperation;
+import org.opends.server.types.operation.PostOperationModifyOperation;
+import org.opends.server.types.operation.PostSynchronizationAddOperation;
+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.PreOperationModifyDNOperation;
+import org.opends.server.types.operation.PreOperationModifyOperation;
 
 import static org.opends.messages.PluginMessages.*;
 import static org.opends.server.protocols.internal.InternalClientConnection.*;
@@ -148,7 +171,7 @@
     {
       for (DN baseDN : cfgBaseDNs)
       {
-        Backend b = DirectoryServer.getBackend(baseDN);
+        Backend<?> b = DirectoryServer.getBackend(baseDN);
         if (b != null && ! b.isIndexed(t, IndexType.EQUALITY))
         {
           throw new ConfigException(ERR_PLUGIN_UNIQUEATTR_ATTR_UNINDEXED.get(
@@ -253,13 +276,9 @@
 
         case INCREMENT:
           // We could calculate the new value, but we'll just take it from the updated entry.
-          for (Attribute updatedAttr : modifyOperation.getModifiedEntry().getAttribute(t, a.getOptions()))
+          Attribute updatedAttr = modifyOperation.getModifiedEntry().getExactAttribute(a.getAttributeDescription());
+          if (updatedAttr != null)
           {
-            if (! updatedAttr.optionsEqual(a.getOptions()))
-            {
-              continue;
-            }
-
             for (ByteString v : updatedAttr)
             {
               PreOperation stop = checkUniqueness(entryDN, t, v, baseDNs, recordedValues, config);
@@ -442,13 +461,9 @@
 
         case INCREMENT:
           // We could calculate the new value, but we'll just take it from the updated entry.
-          for (Attribute updatedAttr : modifyOperation.getModifiedEntry().getAttribute(t, a.getOptions()))
+          Attribute updatedAttr = modifyOperation.getModifiedEntry().getExactAttribute(a.getAttributeDescription());
+          if (updatedAttr != null)
           {
-            if (! updatedAttr.optionsEqual(a.getOptions()))
-            {
-              continue;
-            }
-
             for (ByteString v : updatedAttr)
             {
               sendAlertForUnresolvedConflict(modifyOperation, entryDN,
@@ -703,7 +718,7 @@
     {
       for (DN baseDN : cfgBaseDNs)
       {
-        Backend b = DirectoryServer.getBackend(baseDN);
+        Backend<?> b = DirectoryServer.getBackend(baseDN);
         if (b != null && ! b.isIndexed(t, IndexType.EQUALITY))
         {
           unacceptableReasons.add(ERR_PLUGIN_UNIQUEATTR_ATTR_UNINDEXED.get(
@@ -833,13 +848,9 @@
 
         case INCREMENT:
           // We could calculate the new value, but we'll just take it from the updated entry.
-          for (Attribute updatedAttr : modifyOperation.getModifiedEntry().getAttribute(t, a.getOptions()))
+          Attribute updatedAttr = modifyOperation.getModifiedEntry().getExactAttribute(a.getAttributeDescription());
+          if (updatedAttr != null)
           {
-            if (!updatedAttr.optionsEqual(a.getOptions()))
-            {
-              continue;
-            }
-
             for (ByteString v : updatedAttr)
             {
               uniqueAttrValue2Dn.remove(v);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/SearchResultEntryProtocolOp.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/SearchResultEntryProtocolOp.java
index 8cd4b10..c478028 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/SearchResultEntryProtocolOp.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/SearchResultEntryProtocolOp.java
@@ -40,6 +40,7 @@
 import java.util.Map;
 
 import org.forgerock.opendj.io.ASN1Writer;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.core.DirectoryServer;
@@ -551,7 +552,8 @@
     for (LDAPAttribute a : getAttributes())
     {
       Attribute     attr     = a.toAttribute();
-      AttributeType attrType = attr.getAttributeType();
+      AttributeDescription attrDesc = attr.getAttributeDescription();
+      AttributeType attrType = attrDesc.getAttributeType();
 
       if (attrType.isObjectClass())
       {
@@ -593,7 +595,7 @@
           boolean attributeSeen = false;
           for (int i = 0; i < attrs.size(); i++) {
             Attribute ea = attrs.get(i);
-            if (ea.optionsEqual(attr.getOptions()))
+            if (ea.getAttributeDescription().equals(attrDesc))
             {
               AttributeBuilder builder = new AttributeBuilder(ea);
               builder.addAll(attr);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
index 283cce4..08cce09 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalMultiple.java
@@ -472,8 +472,7 @@
          * MOD to make sure the delete is going to succeed
          */
         if (!deleteIt
-            || (!modifiedEntry.hasValue(modAttr.getAttributeType(), modAttr
-                .getOptions(), val) && ! addedInCurrentOp))
+            || (!modifiedEntry.hasValue(modAttr.getAttributeDescription(), val) && ! addedInCurrentOp))
         {
           // this value was already deleted before and therefore
           // this should not be replayed.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
index 39863de..5cc4904 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/AttrHistoricalSingle.java
@@ -170,7 +170,7 @@
             modsIterator.remove();
           }
           else if (newValue != null &&
-              !modifiedEntry.hasValue(type, modAttr.getOptions(), newValue))
+              !modifiedEntry.hasValue(modAttr.getAttributeDescription(), newValue))
           {
             conflict = true;
             modsIterator.remove();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
index 7e7a894..980a537 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/EntryHistorical.java
@@ -46,7 +46,6 @@
 import org.opends.server.replication.protocol.OperationContext;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.AttributeDescriptions;
 import org.opends.server.types.Attributes;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
@@ -316,7 +315,7 @@
 
     // Read from this entryHistorical,
     // Create one empty if none was existing in this entryHistorical.
-    AttributeDescription attrDesc = AttributeDescriptions.create(modAttr);
+    AttributeDescription attrDesc = modAttr.getAttributeDescription();
     AttrHistorical attrHist = attributesHistorical.get(attrDesc);
     if (attrHist == null)
     {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/LDIFDiff.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/LDIFDiff.java
index f1893f3..ad91c3c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/LDIFDiff.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/LDIFDiff.java
@@ -41,14 +41,15 @@
 import java.util.TreeMap;
 
 import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ModificationType;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler;
 import org.opends.server.extensions.ConfigFileHandler;
 import org.opends.server.loggers.JDKLogging;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeBuilder;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.ldap.ByteString;
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
@@ -56,7 +57,6 @@
 import org.opends.server.types.LDIFExportConfig;
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.Modification;
-import org.forgerock.opendj.ldap.ModificationType;
 import org.opends.server.types.NullOutputStream;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.util.LDIFReader;
@@ -69,16 +69,14 @@
 import com.forgerock.opendj.cli.CommonArguments;
 import com.forgerock.opendj.cli.StringArgument;
 
+import static com.forgerock.opendj.cli.ArgumentConstants.*;
+import static com.forgerock.opendj.cli.Utils.*;
+
 import static org.opends.messages.ToolMessages.*;
 import static org.opends.server.protocols.ldap.LDAPResultCode.*;
-
-import static com.forgerock.opendj.cli.ArgumentConstants.*;
-
 import static org.opends.server.util.CollectionUtils.*;
 import static org.opends.server.util.ServerConstants.*;
 
-import static com.forgerock.opendj.cli.Utils.*;
-
 /**
  * This class provides a program that may be used to determine the differences
  * between two LDIF files, generating the output in LDIF change format.  There
@@ -841,7 +839,7 @@
           while (attrIterator.hasNext())
           {
             Attribute a = attrIterator.next();
-            if (a.optionsEqual(sourceAttr.getOptions()))
+            if (a.getAttributeDescription().equals(sourceAttr.getAttributeDescription()))
             {
               targetAttr = a;
               attrIterator.remove();
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java b/opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java
index 4024e8f..b747966 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/AbstractAttribute.java
@@ -30,11 +30,10 @@
 
 import java.util.Collection;
 import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
 
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.schema.MatchingRule;
 
 /** An abstract base class for implementing new types of {@link Attribute}. */
@@ -84,9 +83,7 @@
     }
 
     Attribute a = (Attribute) o;
-    return getAttributeType().equals(a.getAttributeType())
-        && valuesEqual(a)
-        && optionsEqual(a.getOptions());
+    return getAttributeDescription().equals(a.getAttributeDescription()) && valuesEqual(a);
   }
 
   private boolean valuesEqual(Attribute a)
@@ -119,6 +116,12 @@
     return getAttributeType().getNameOrOID();
   }
 
+  @Override
+  public AttributeType getAttributeType()
+  {
+    return getAttributeDescription().getAttributeType();
+  }
+
   /**
    * {@inheritDoc}
    * <p>
@@ -145,57 +148,6 @@
     return buffer.toString();
   }
 
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation returns {@code true} if the provided
-   * collection of options is {@code null} or empty. If the
-   * collection is non-empty and this attribute does not have any
-   * options then it returns {@code false}. Otherwise, {@code true} is
-   * returned if all the provided options are present.
-   */
-  @Override
-  public boolean hasAllOptions(Collection<String> options)
-  {
-    // FIXME use AttributeDescription instead
-    return containsAllOptions(getOptions(), options);
-  }
-
-  private static boolean containsAllOptions(Collection<String> options1, Collection<String> options2)
-  {
-    if (options1 == options2)
-    {
-      return true;
-    }
-    else if (isEmpty(options2))
-    {
-      return true;
-    }
-    else if (isEmpty(options1))
-    {
-      return false;
-    }
-    // normalize all options before calling containsAll()
-    Set<String> set1 = toLowercaseSet(options1);
-    Set<String> set2 = toLowercaseSet(options2);
-    return set1.size() >= set2.size() && set1.containsAll(set2);
-  }
-
-  private static boolean isEmpty(Collection<String> col)
-  {
-    return col == null || col.isEmpty();
-  }
-
-  private static SortedSet<String> toLowercaseSet(Collection<String> strings)
-  {
-    final SortedSet<String> results = new TreeSet<>();
-    for (String s : strings)
-    {
-      results.add(toLowerCase(s));
-    }
-    return results;
-  }
-
   @Override
   public int hashCode()
   {
@@ -276,29 +228,6 @@
     return !isVirtual();
   }
 
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation returns !{@link #hasOptions()} if the
-   * provided set of options is <code>null</code>. Otherwise it
-   * checks that the size of the provided set of options is equal to
-   * the size of this attribute's options, return <code>false</code>
-   * if the sizes differ. If the sizes are the same then each option
-   * in the provided set is checked using
-   * {@link #hasOption(String)} and <code>true</code> is
-   * returned if all the provided options are present.
-   */
-  @Override
-  public boolean optionsEqual(Set<String> options)
-  {
-    if (options != null)
-    {
-      return getOptions().size() == options.size()
-          && hasAllOptions(options);
-    }
-    return !hasOptions();
-  }
-
   @Override
   public final String toString()
   {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Attribute.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Attribute.java
index 00b9d2a..08e04ec 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Attribute.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Attribute.java
@@ -26,15 +26,15 @@
  */
 package org.opends.server.types;
 
-import org.forgerock.opendj.ldap.schema.AttributeType;
-
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 
 /**
  * This class defines a data structure for storing and interacting
@@ -124,6 +124,13 @@
   AttributeType getAttributeType();
 
   /**
+   * Retrieves the attribute description for this attribute.
+   *
+   * @return The attribute description for this attribute.
+   */
+  AttributeDescription getAttributeDescription();
+
+  /**
    * Retrieves the user-provided name for this attribute.
    *
    * @return The user-provided name for this attribute.
@@ -140,11 +147,11 @@
   String getNameWithOptions();
 
   /**
-   * Retrieves the unmodifiable set of attribute options for this
-   * attribute. The returned set of options are not normalized.
+   * Retrieves the unmodifiable set of attribute options for this attribute. The returned set of
+   * options are not normalized.
    *
-   * @return The unmodifiable set of attribute options for this
-   *         attribute.
+   * @return The unmodifiable set of attribute options for this attribute.
+   * @Deprecated use {@link #getAttributeDescription()}
    */
   Set<String> getOptions();
 
@@ -162,18 +169,8 @@
   ConditionResult greaterThanOrEqualTo(ByteString assertionValue);
 
   /**
-   * Indicates whether this attribute has all of the options in the provided collection.
-   *
-   * @param options
-   *          The collection of options for which to make the determination (may be {@code null}).
-   * @return {@code true} if this attribute has all of the specified options,
-   *         or {@code false} if it does not have at least one of them.
-   */
-  boolean hasAllOptions(Collection<String> options);
-
-  /**
-   * Retrieves the hash code for this attribute. It will be calculated
-   * as the sum of the hash code for the attribute type and all values.
+   * Retrieves the hash code for this attribute. It will be calculated as the sum of the hash code
+   * for the attribute type and all values.
    *
    * @return The hash code for this attribute.
    */
@@ -266,18 +263,6 @@
       List<ByteString> subAny, ByteString subFinal);
 
   /**
-   * Indicates whether this attribute has exactly the specified set of
-   * options.
-   *
-   * @param options
-   *          The set of options for which to make the determination
-   *          (may be {@code null}).
-   * @return {@code true} if this attribute has exactly the
-   *         specified set of options.
-   */
-  boolean optionsEqual(Set<String> options);
-
-  /**
    * Returns the number of attribute values in this attribute.
    *
    * @return The number of attribute values in this attribute.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java b/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java
index 65b87d7..71a9ce9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeBuilder.java
@@ -31,6 +31,7 @@
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -41,6 +42,7 @@
 
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.Assertion;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.DecodeException;
@@ -119,8 +121,8 @@
   {
     private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-    /** The attribute type for this attribute. */
-    private final AttributeType attributeType;
+    /** The attribute description for this attribute. */
+    private final AttributeDescription attributeDescription;
 
     /** The name of this attribute as provided by the end user. */
     private final String name;
@@ -143,9 +145,9 @@
      * @param values
      *          The attribute values.
      */
-    private RealAttribute(AttributeType attributeType, String name, Set<AttributeValue> values)
+    private RealAttribute(AttributeDescription attributeDescription, String name, Set<AttributeValue> values)
     {
-      this.attributeType = attributeType;
+      this.attributeDescription = attributeDescription;
       this.name = name;
       this.values = values;
     }
@@ -154,7 +156,7 @@
     @Override
     public final ConditionResult approximatelyEqualTo(ByteString assertionValue)
     {
-      MatchingRule matchingRule = attributeType.getApproximateMatchingRule();
+      MatchingRule matchingRule = getAttributeType().getApproximateMatchingRule();
       if (matchingRule == null)
       {
         return ConditionResult.UNDEFINED;
@@ -196,7 +198,7 @@
     @Override
     public final boolean contains(ByteString value)
     {
-      return values.contains(createAttributeValue(attributeType, value));
+      return values.contains(createAttributeValue(getAttributeType(), value));
     }
 
     @Override
@@ -222,12 +224,38 @@
     }
 
     @Override
-    public final AttributeType getAttributeType()
+    public AttributeDescription getAttributeDescription()
     {
-      return attributeType;
+      return attributeDescription;
     }
 
+    @Override
+    public Set<String> getOptions()
+    {
+      return Collections.unmodifiableSet(toSet(attributeDescription.getOptions()));
+    }
 
+    @Override
+    public boolean hasOption(String option)
+    {
+      return attributeDescription.hasOption(option);
+    }
+
+    private Set<String> toSet(Iterable<String> options)
+    {
+      Set<String> results = new HashSet<>();
+      for (String option : options)
+      {
+        results.add(option);
+      }
+      return results;
+    }
+
+    @Override
+    public boolean hasOptions()
+    {
+      return attributeDescription.hasOptions();
+    }
 
     @Override
     public final String getName()
@@ -235,12 +263,10 @@
       return name;
     }
 
-
-
     @Override
     public final ConditionResult greaterThanOrEqualTo(ByteString assertionValue)
     {
-      MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
+      MatchingRule matchingRule = getAttributeType().getOrderingMatchingRule();
       if (matchingRule == null)
       {
         return ConditionResult.UNDEFINED;
@@ -297,7 +323,7 @@
     @Override
     public final ConditionResult lessThanOrEqualTo(ByteString assertionValue)
     {
-      MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
+      MatchingRule matchingRule = getAttributeType().getOrderingMatchingRule();
       if (matchingRule == null)
       {
         return ConditionResult.UNDEFINED;
@@ -342,7 +368,7 @@
     @Override
     public final ConditionResult matchesSubstring(ByteString subInitial, List<ByteString> subAny, ByteString subFinal)
     {
-      MatchingRule matchingRule = attributeType.getSubstringMatchingRule();
+      MatchingRule matchingRule = getAttributeType().getSubstringMatchingRule();
       if (matchingRule == null)
       {
         return ConditionResult.UNDEFINED;
@@ -421,15 +447,6 @@
   private static final class RealAttributeManyOptions
     extends RealAttribute
   {
-
-    /** The normalized options. */
-    private final SortedSet<String> normalizedOptions;
-
-    /** The options. */
-    private final Set<String> options;
-
-
-
     /**
      * Creates a new real attribute that has multiple options.
      *
@@ -448,28 +465,7 @@
         AttributeType attributeType, String name, Set<AttributeValue> values, Set<String> options,
         SortedSet<String> normalizedOptions)
     {
-      super(attributeType, name, values);
-      this.options = options;
-      this.normalizedOptions = normalizedOptions;
-    }
-
-    @Override
-    public Set<String> getOptions()
-    {
-      return options;
-    }
-
-    @Override
-    public boolean hasOption(String option)
-    {
-      String s = toLowerCase(option);
-      return normalizedOptions.contains(s);
-    }
-
-    @Override
-    public boolean hasOptions()
-    {
-      return true;
+      super(AttributeDescription.create(attributeType, options), name, values);
     }
   }
 
@@ -492,7 +488,7 @@
      */
     private RealAttributeNoOptions(AttributeType attributeType, String name, Set<AttributeValue> values)
     {
-      super(attributeType, name, values);
+      super(AttributeDescription.create(attributeType), name, values);
     }
 
     @Override
@@ -506,30 +502,6 @@
     {
       return Collections.emptySet();
     }
-
-    @Override
-    public boolean hasAllOptions(Collection<String> options)
-    {
-      return options == null || options.isEmpty();
-    }
-
-    @Override
-    public boolean hasOption(String option)
-    {
-      return false;
-    }
-
-    @Override
-    public boolean hasOptions()
-    {
-      return false;
-    }
-
-    @Override
-    public boolean optionsEqual(Set<String> options)
-    {
-      return options == null || options.isEmpty();
-    }
   }
 
 
@@ -540,14 +512,6 @@
   private static final class RealAttributeSingleOption
     extends RealAttribute
   {
-    /** The normalized single option. */
-    private final String normalizedOption;
-
-    /** A singleton set containing the single option. */
-    private final Set<String> option;
-
-
-
     /**
      * Creates a new real attribute that has a single option.
      *
@@ -566,28 +530,7 @@
         Set<AttributeValue> values,
         String option)
     {
-      super(attributeType, name, values);
-      this.option = Collections.singleton(option);
-      this.normalizedOption = toLowerCase(option);
-    }
-
-    @Override
-    public Set<String> getOptions()
-    {
-      return option;
-    }
-
-    @Override
-    public boolean hasOption(String option)
-    {
-      String s = toLowerCase(option);
-      return normalizedOption.equals(s);
-    }
-
-    @Override
-    public boolean hasOptions()
-    {
-      return true;
+      super(AttributeDescription.create(attributeType, option), name, values);
     }
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeDescriptions.java b/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeDescriptions.java
deleted file mode 100644
index 0cfed30..0000000
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/AttributeDescriptions.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at legal-notices/CDDLv1_0.txt.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *      Copyright 2015-2016 ForgeRock AS
- */
-package org.opends.server.types;
-
-import org.forgerock.opendj.ldap.AttributeDescription;
-
-/** Temporary class until we move fully to {@link AttributeDescription}. */
-public class AttributeDescriptions
-{
-  private AttributeDescriptions()
-  {
-    // private for utility class
-  }
-
-  /**
-   * Creates an attribute description with the attribute type and options of the provided
-   * {@link Attribute}.
-   *
-   * @param attr
-   *          The attribute.
-   * @return The attribute description.
-   * @throws NullPointerException
-   *           If {@code attributeType} or {@code options} was {@code null}.
-   */
-  public static AttributeDescription create(Attribute attr)
-  {
-    return AttributeDescription.create(attr.getAttributeType(), attr.getOptions());
-  }
-}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/CollectiveVirtualAttribute.java b/opendj-server-legacy/src/main/java/org/opends/server/types/CollectiveVirtualAttribute.java
index 8dd4986..ccdac85 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/CollectiveVirtualAttribute.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/CollectiveVirtualAttribute.java
@@ -27,14 +27,14 @@
 
 package org.opends.server.types;
 
-import org.forgerock.opendj.ldap.schema.AttributeType;
-
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 
 /**
  * This class defines a collective virtual attribute, which is a
@@ -68,20 +68,23 @@
     return attribute.contains(value);
   }
 
-  /** {@inheritDoc} */
   @Override
   public ConditionResult matchesEqualityAssertion(ByteString assertionValue)
   {
     return attribute.matchesEqualityAssertion(assertionValue);
   }
 
-  /** {@inheritDoc} */
+  @Override
+  public AttributeDescription getAttributeDescription()
+  {
+    return attribute.getAttributeDescription();
+  }
+
   @Override
   public AttributeType getAttributeType() {
     return attribute.getAttributeType();
   }
 
-  /** {@inheritDoc} */
   @Override
   public Set<String> getOptions() {
     return attribute.getOptions();
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 d375368..0725f2b 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
@@ -28,12 +28,24 @@
 
 import java.io.BufferedWriter;
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteSequenceReader;
 import org.forgerock.opendj.ldap.ByteString;
@@ -393,7 +405,7 @@
    */
   public boolean hasAttribute(AttributeType attributeType)
   {
-    return hasAttribute(attributeType, null, true);
+    return hasAttribute(AttributeDescription.create(attributeType), true);
   }
 
 
@@ -412,7 +424,7 @@
   public boolean hasAttribute(AttributeType attributeType,
                               boolean includeSubordinates)
   {
-    return hasAttribute(attributeType, null, includeSubordinates);
+    return hasAttribute(AttributeDescription.create(attributeType), includeSubordinates);
   }
 
 
@@ -423,50 +435,42 @@
    * attribute of the specified attribute will also be used in the
    * determination.
    *
-   * @param attributeType
-   *          The attribute type for which to make the determination.
-   * @param options
-   *          The set of options to use in the determination.
+   * @param attributeDescription
+   *          The attribute description for which to make the determination.
    * @return <CODE>true</CODE> if this entry contains the specified
    *         attribute, or <CODE>false</CODE> if not.
    */
-  public boolean hasAttribute(AttributeType attributeType, Set<String> options)
+  public boolean hasAttribute(AttributeDescription attributeDescription)
   {
-    return hasAttribute(attributeType, options, true);
+    return hasAttribute(attributeDescription, true);
   }
 
-
-
   /**
-   * Indicates whether this entry contains the specified attribute
-   * with all of the options in the provided set.
+   * Indicates whether this entry contains the specified attribute with all of the options in the
+   * provided set.
    *
-   * @param attributeType
-   *          The attribute type for which to make the determination.
-   * @param options
-   *          The set of options to use in the determination.
+   * @param attributeDescription
+   *          The attribute description for which to make the determination.
    * @param includeSubordinates
-   *          Whether to include any subordinate attributes of the
-   *          attribute type being retrieved.
-   * @return <CODE>true</CODE> if this entry contains the specified
-   *         attribute, or <CODE>false</CODE> if not.
+   *          Whether to include any subordinate attributes of the attribute type being retrieved.
+   * @return <CODE>true</CODE> if this entry contains the specified attribute, or <CODE>false</CODE>
+   *         if not.
    */
-  public boolean hasAttribute(
-      AttributeType attributeType,
-      Set<String> options,
-      boolean includeSubordinates)
+  public boolean hasAttribute(AttributeDescription attributeDescription, boolean includeSubordinates)
   {
+    AttributeType attributeType = attributeDescription.getAttributeType();
+
     // Handle object class.
     if (attributeType.isObjectClass())
     {
-      return !objectClasses.isEmpty() && (options == null || options.isEmpty());
+      return !objectClasses.isEmpty() && !attributeDescription.hasOptions();
     }
 
     if (!includeSubordinates)
     {
       // It's possible that there could be an attribute without any
       // values, which we should treat as not having the requested attribute.
-      Attribute attribute = getExactAttribute(attributeType, options);
+      Attribute attribute = getExactAttribute(attributeDescription);
       return attribute != null && !attribute.isEmpty();
     }
 
@@ -478,7 +482,7 @@
       {
         // It's possible that there could be an attribute without any
         // values, which we should treat as not having the requested attribute.
-        if (!attribute.isEmpty() && attribute.hasAllOptions(options))
+        if (!attribute.isEmpty() && attribute.getAttributeDescription().isSubTypeOf(attributeDescription))
         {
           return true;
         }
@@ -495,7 +499,7 @@
         {
           // It's possible that there could be an attribute without any values,
           // which we should treat as not having the requested attribute.
-          if (!attribute.isEmpty() && attribute.hasAllOptions(options))
+          if (!attribute.isEmpty() && attribute.getAttributeDescription().isSubTypeOf(attributeDescription))
           {
             return true;
           }
@@ -712,9 +716,28 @@
    *          attribute type is not present in this entry with the
    *          provided set of options.
    */
-  public List<Attribute> getAttribute(AttributeType attributeType,
-                                      Set<String> options)
+  @Deprecated
+  public List<Attribute> getAttribute(AttributeType attributeType, Set<String> options)
   {
+    return getAttribute(AttributeDescription.create(attributeType, options));
+  }
+
+  /**
+   * Retrieves the requested attribute element(s) for the specified
+   * attribute description.  The list returned may include multiple elements
+   * if the same attribute exists in the entry multiple times with
+   * different sets of options. It may also include any subordinate
+   * attributes of the attribute being retrieved.
+   *
+   * @param  attributeDescription The attribute description to retrieve.
+   * @return  The requested attribute element(s) for the specified
+   *          attribute type, or an empty list if the specified
+   *          attribute type is not present in this entry with the
+   *          provided set of options.
+   */
+  public List<Attribute> getAttribute(AttributeDescription attributeDescription)
+  {
+    AttributeType attributeType = attributeDescription.getAttributeType();
     List<Attribute> attributes = new LinkedList<>();
     if (!attributeType.isObjectClass())
     {
@@ -737,7 +760,7 @@
         {
           if (attributeType.isObjectClass()
               && !objectClasses.isEmpty()
-              && (options == null || options.isEmpty()))
+              && !attributeDescription.hasOptions())
           {
             attributes.add(getObjectClassAttribute());
             return attributes;
@@ -748,7 +771,7 @@
       attributes.addAll(attrs);
     }
 
-    onlyKeepAttributesWithAllOptions(attributes, options);
+    onlyKeepAttributesWithAllOptions(attributes, attributeDescription);
 
     return attributes;
   }
@@ -845,9 +868,10 @@
    *          the attributes Map where to find the attributes
    * @return the filtered List of attributes
    */
-  private List<Attribute> getAttribute(AttributeType attributeType,
-      Set<String> options, Map<AttributeType, List<Attribute>> attrs)
+  private List<Attribute> getAttribute(AttributeDescription attributeDescription,
+      Map<AttributeType, List<Attribute>> attrs)
   {
+    AttributeType attributeType = attributeDescription.getAttributeType();
     List<Attribute> attributes = new LinkedList<>();
     addAllIfNotNull(attributes, attrs.get(attributeType));
 
@@ -856,7 +880,7 @@
       addAllIfNotNull(attributes, attrs.get(at));
     }
 
-    onlyKeepAttributesWithAllOptions(attributes, options);
+    onlyKeepAttributesWithAllOptions(attributes, attributeDescription);
     return attributes;
   }
 
@@ -865,17 +889,16 @@
    *
    * @param attributes
    *          the attributes to filter.
-   * @param options
-   *          the options to look for
+   * @param attributeDescription
+   *          contains the options to look for
    */
-  private void onlyKeepAttributesWithAllOptions(List<Attribute> attributes,
-      Set<String> options)
+  private void onlyKeepAttributesWithAllOptions(List<Attribute> attributes, AttributeDescription attributeDescription)
   {
     Iterator<Attribute> iterator = attributes.iterator();
     while (iterator.hasNext())
     {
       Attribute a = iterator.next();
-      if (!a.hasAllOptions(options))
+      if (!a.getAttributeDescription().isSubTypeOf(attributeDescription))
       {
         iterator.remove();
       }
@@ -941,19 +964,15 @@
    * elements if the same attribute exists in the entry multiple times
    * with different sets of options.
    *
-   * @param  attributeType  The attribute type to retrieve.
-   * @param  options        The set of attribute options to include in
-   *                        matching elements.
+   * @param  attributeDescription  The attribute description to retrieve.
    *
    * @return  The requested attribute element(s) for the specified
    *          attribute type, or an empty list if there is no such
    *          operational attribute with the specified set of options.
    */
-  public List<Attribute> getOperationalAttribute(
-                              AttributeType attributeType,
-                              Set<String> options)
+  public List<Attribute> getOperationalAttribute(AttributeDescription attributeDescription)
   {
-    return getAttribute(attributeType, options, operationalAttributes);
+    return getAttribute(attributeDescription, operationalAttributes);
   }
 
 
@@ -1058,12 +1077,9 @@
    *           parsed as an integer of if the existing attribute
    *           values could not be parsed as integers.
    */
-  public void incrementAttribute(
-      Attribute attribute) throws DirectoryException
+  public void incrementAttribute(Attribute attribute) throws DirectoryException
   {
-    // Get the attribute that is to be incremented.
-    AttributeType attributeType = attribute.getAttributeType();
-    Attribute a = getExactAttribute(attributeType, attribute.getOptions());
+    Attribute a = getExactAttribute(attribute.getAttributeDescription());
     if (a == null)
     {
       LocalizableMessage message = ERR_ENTRY_INCREMENT_NO_SUCH_ATTRIBUTE.get(
@@ -1186,7 +1202,9 @@
   {
     attachment = null;
 
-    if (attribute.getAttributeType().isObjectClass())
+    AttributeDescription attrDesc = attribute.getAttributeDescription();
+    AttributeType attrType = attrDesc.getAttributeType();
+    if (attrType.isObjectClass())
     {
       if (attribute.isEmpty())
       {
@@ -1196,8 +1214,7 @@
 
       boolean allSuccessful = true;
 
-      MatchingRule rule =
-          attribute.getAttributeType().getEqualityMatchingRule();
+      MatchingRule rule = attrType.getEqualityMatchingRule();
       for (ByteString v : attribute)
       {
         String ocName = toLowerName(rule, v);
@@ -1223,8 +1240,7 @@
       return allSuccessful;
     }
 
-    AttributeType attributeType = attribute.getAttributeType();
-    List<Attribute> attributes = getAttributes(attributeType);
+    List<Attribute> attributes = getAttributes(attrType);
     if (attributes == null)
     {
       // There are no attributes with the same attribute type.
@@ -1236,11 +1252,10 @@
     }
 
     // There are already attributes with the same attribute type.
-    Set<String> options = attribute.getOptions();
     for (int i = 0; i < attributes.size(); i++)
     {
       Attribute a = attributes.get(i);
-      if (a.optionsEqual(options))
+      if (a.getAttributeDescription().equals(attrDesc))
       {
         if (attribute.isEmpty())
         {
@@ -1273,7 +1288,7 @@
         // If the attribute list is now empty remove it.
         if (attributes.isEmpty())
         {
-          removeAttributes(attributeType);
+          removeAttributes(attrType);
         }
 
         return true;
@@ -1297,23 +1312,37 @@
     }
   }
 
+  /**
+   * Indicates whether this entry contains the specified attribute value.
+   *
+   * @param attributeDescription
+   *          The attribute description for the attribute.
+   * @param value
+   *          The value for the attribute.
+   * @return {@code true} if this entry contains the specified attribute value, {@code false}
+   *         otherwise.
+   */
+  public boolean hasValue(AttributeDescription attributeDescription, ByteString value)
+  {
+    Attribute attr = getExactAttribute(attributeDescription);
+    return attr != null && attr.contains(value);
+  }
 
   /**
-   * Indicates whether this entry contains the specified attribute
-   * value.
+   * Indicates whether this entry contains the specified attribute value.
    *
-   * @param  attributeType  The attribute type for the attribute.
-   * @param  options        The set of options for the attribute.
-   * @param  value          The value for the attribute.
-   *
-   * @return  <CODE>true</CODE> if this entry contains the specified
-   *          attribute value, or <CODE>false</CODE> if it does not.
+   * @param attributeType
+   *          The attribute type for the attribute.
+   * @param value
+   *          The value for the attribute.
+   * @return {@code true} if this entry contains the specified attribute value, {@code false}
+   *         otherwise.
    */
-  public boolean hasValue(AttributeType attributeType, Set<String> options, ByteString value)
+  public boolean hasValue(AttributeType attributeType, ByteString value)
   {
     for (Attribute a : getAttribute(attributeType))
     {
-      if (a.optionsEqual(options) && a.contains(value))
+      if (!a.hasOptions() && a.contains(value))
       {
         return true;
       }
@@ -2430,7 +2459,7 @@
           for (int i = 0; i < targetList.size(); i++)
           {
             Attribute otherAttribute = targetList.get(i);
-            if (otherAttribute.optionsEqual(a.getOptions()))
+            if (otherAttribute.getAttributeDescription().equals(a.getAttributeDescription()))
             {
               targetList.set(i, Attributes.merge(a, otherAttribute));
               found = true;
@@ -2939,9 +2968,7 @@
           {
             if (inheritFromEntry != null)
             {
-              collectiveAttr = inheritFromEntry.getExactAttribute(
-                      collectiveAttr.getAttributeType(),
-                      collectiveAttr.getOptions());
+              collectiveAttr = inheritFromEntry.getExactAttribute(collectiveAttr.getAttributeDescription());
               if (collectiveAttr == null || collectiveAttr.isEmpty())
               {
                 continue;
@@ -4233,24 +4260,21 @@
    * does not contain an attribute with the specified attribute type
    * and options.
    *
-   * @param attributeType
-   *          The attribute type to retrieve.
-   * @param options
-   *          The set of attribute options.
+   * @param attributeDescription
+   *          The attribute description to retrieve.
    * @return The requested attribute element for the specified
    *         attribute type and options, or <code>null</code> if the
    *         specified attribute type is not present in this entry
    *         with the provided set of options.
    */
-  public Attribute getExactAttribute(AttributeType attributeType,
-      Set<String> options)
+  public Attribute getExactAttribute(AttributeDescription attributeDescription)
   {
-    List<Attribute> attributes = getAttributes(attributeType);
+    List<Attribute> attributes = getAttributes(attributeDescription.getAttributeType());
     if (attributes != null)
     {
       for (Attribute attribute : attributes)
       {
-        if (attribute.optionsEqual(options))
+        if (attribute.getAttributeDescription().equals(attributeDescription))
         {
           return attribute;
         }
@@ -4280,9 +4304,9 @@
   {
     attachment = null;
 
-    AttributeType attributeType = attribute.getAttributeType();
-
-    if (attribute.getAttributeType().isObjectClass())
+    AttributeDescription attrDesc = attribute.getAttributeDescription();
+    AttributeType attrType = attrDesc.getAttributeType();
+    if (attrType.isObjectClass())
     {
       // We will not do any validation of the object classes - this is
       // left to the caller.
@@ -4291,16 +4315,14 @@
         objectClasses.clear();
       }
 
-      MatchingRule rule =
-          attribute.getAttributeType().getEqualityMatchingRule();
+      MatchingRule rule = attrType.getEqualityMatchingRule();
       for (ByteString v : attribute)
       {
         String name = v.toString();
         String lowerName = toLowerName(rule, v);
 
         // Create a default object class if necessary.
-        ObjectClass oc =
-          DirectoryServer.getObjectClass(lowerName, true);
+        ObjectClass oc = DirectoryServer.getObjectClass(lowerName, true);
 
         if (replace)
         {
@@ -4322,7 +4344,7 @@
       return;
     }
 
-    List<Attribute> attributes = getAttributes(attributeType);
+    List<Attribute> attributes = getAttributes(attrType);
     if (attributes == null)
     {
       // Do nothing if we are deleting a non-existing attribute.
@@ -4332,16 +4354,15 @@
       }
 
       // We are adding the first attribute with this attribute type.
-      putAttributes(attributeType, newArrayList(attribute));
+      putAttributes(attrType, newArrayList(attribute));
       return;
     }
 
     // There are already attributes with the same attribute type.
-    Set<String> options = attribute.getOptions();
     for (int i = 0; i < attributes.size(); i++)
     {
       Attribute a = attributes.get(i);
-      if (a.optionsEqual(options))
+      if (a.getAttributeDescription().equals(attrDesc))
       {
         if (replace)
         {
@@ -4355,7 +4376,7 @@
 
             if (attributes.isEmpty())
             {
-              removeAttributes(attributeType);
+              removeAttributes(attrType);
             }
           }
         }
@@ -4634,6 +4655,15 @@
       AttributeType attrType, String attrName, Set<String> options,
       boolean omitValues, boolean omitReal, boolean omitVirtual)
   {
+    AttributeDescription attrDesc = AttributeDescription.create(attrType, options);
+    mergeAttributeLists(sourceList, destMap, attrDesc, attrName, omitValues, omitReal, omitVirtual);
+  }
+
+  private void mergeAttributeLists(List<Attribute> sourceList,
+      Map<AttributeType, List<Attribute>> destMap,
+      AttributeDescription attrDesc, String attrName,
+      boolean omitValues, boolean omitReal, boolean omitVirtual)
+  {
     if (sourceList == null)
     {
       return;
@@ -4644,7 +4674,7 @@
       if (attribute.isEmpty()
           || (omitReal && attribute.isReal())
           || (omitVirtual && attribute.isVirtual())
-          || !attribute.hasAllOptions(options))
+          || !attribute.getAttributeDescription().isSubTypeOf(attrDesc))
       {
         continue;
       }
@@ -4653,10 +4683,11 @@
         // If a non-default attribute name was provided or if the
         // attribute has options then we will need to rebuild the
         // attribute so that it contains the user-requested names and options.
-        AttributeType subAttrType = attribute.getAttributeType();
+        AttributeDescription subAttrDesc = attribute.getAttributeDescription();
+        AttributeType subAttrType = subAttrDesc.getAttributeType();
 
         if ((attrName != null && !attrName.equals(attribute.getName()))
-            || (options != null && !options.isEmpty()))
+            || attrDesc.hasOptions())
         {
           AttributeBuilder builder = new AttributeBuilder();
 
@@ -4664,7 +4695,7 @@
           // the same type as the requested type. This might not be the case for
           // sub-types e.g. requesting "name" and getting back "cn" - we don't
           // want to rename "name" to "cn".
-          if (attrName == null || !subAttrType.equals(attrType))
+          if (attrName == null || !subAttrType.equals(attrDesc.getAttributeType()))
           {
             builder.setAttributeType(subAttrType, attribute.getName());
           }
@@ -4673,10 +4704,7 @@
             builder.setAttributeType(subAttrType, attrName);
           }
 
-          if (options != null)
-          {
-            builder.setOptions(options);
-          }
+          builder.setOptions(attrDesc.getOptions());
 
           // Now add in remaining options from original attribute
           // (this will not overwrite options already present).
@@ -4721,7 +4749,7 @@
           for (int i = 0; i < attrList.size(); i++)
           {
             Attribute otherAttribute = attrList.get(i);
-            if (otherAttribute.optionsEqual(attribute.getOptions()))
+            if (otherAttribute.getAttributeDescription().equals(subAttrDesc))
             {
               // Assume that wildcards appear first in an attribute
               // list with more specific attribute names afterwards:
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 b91970b..cee176b 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
@@ -43,6 +43,7 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.Assertion;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.forgerock.opendj.ldap.ConditionResult;
@@ -67,6 +68,8 @@
 
   private static SearchFilter objectClassPresent;
 
+  /** The attribute description for this filter. */
+  private final AttributeDescription attributeDescription;
   /** The attribute type for this filter. */
   private final AttributeType attributeType;
 
@@ -91,9 +94,6 @@
   /** The not filter component for this search filter. */
   private final SearchFilter notComponent;
 
-  /** The set of options for the attribute type in this filter. */
-  private final Set<String> attributeOptions;
-
   /** The matching rule ID for this search filter. */
   private final String matchingRuleID;
 
@@ -151,8 +151,10 @@
     this.filterType        = filterType;
     this.filterComponents  = new LinkedHashSet<>(filterComponents);
     this.notComponent      = notComponent;
+    this.attributeDescription = attributeType != null
+        ? AttributeDescription.create(attributeType, attributeOptions)
+        : null;
     this.attributeType     = attributeType;
-    this.attributeOptions  = attributeOptions;
     this.assertionValue    = assertionValue;
     this.subInitialElement = subInitialElement;
     this.subAnyElements    = subAnyElements;
@@ -2638,7 +2640,7 @@
     }
 
     // See if the entry has an attribute with the requested type.
-    List<Attribute> attrs = entry.getAttribute(attributeType, attributeOptions);
+    List<Attribute> attrs = entry.getAttribute(attributeDescription);
     if (attrs.isEmpty())
     {
       if (logger.isTraceEnabled())
@@ -2742,7 +2744,7 @@
     }
 
     // See if the entry has an attribute with the requested type.
-    List<Attribute> attrs = entry.getAttribute(attributeType, attributeOptions);
+    List<Attribute> attrs = entry.getAttribute(attributeDescription);
     if (attrs.isEmpty())
     {
       if (logger.isTraceEnabled())
@@ -2843,7 +2845,7 @@
     }
 
     // See if the entry has an attribute with the requested type.
-    List<Attribute> attrs = entry.getAttribute(attributeType, attributeOptions);
+    List<Attribute> attrs = entry.getAttribute(attributeDescription);
     if (attrs.isEmpty())
     {
       if (logger.isTraceEnabled())
@@ -2941,7 +2943,7 @@
     }
 
     // See if the entry has an attribute with the requested type.
-    List<Attribute> attrs = entry.getAttribute(attributeType, attributeOptions);
+    List<Attribute> attrs = entry.getAttribute(attributeDescription);
     if (attrs.isEmpty())
     {
       if (logger.isTraceEnabled())
@@ -3032,8 +3034,7 @@
 
     // See if the entry has an attribute with the requested type.
     // If so, then it's a match.  If not, then it's not a match.
-    ConditionResult result = ConditionResult.valueOf(
-        entry.hasAttribute(attributeType, attributeOptions));
+    ConditionResult result = ConditionResult.valueOf(entry.hasAttribute(attributeDescription));
     if (logger.isTraceEnabled())
     {
       logger.trace(
@@ -3085,7 +3086,7 @@
     }
 
     // See if the entry has an attribute with the requested type.
-    List<Attribute> attrs = entry.getAttribute(attributeType, attributeOptions);
+    List<Attribute> attrs = entry.getAttribute(attributeDescription);
     if (attrs.isEmpty())
     {
       if (logger.isTraceEnabled())
@@ -3387,7 +3388,7 @@
     }
     else
     {
-      for (Attribute a : entry.getAttribute(attributeType, attributeOptions))
+      for (Attribute a : entry.getAttribute(attributeDescription))
       {
         for (ByteString v : a)
         {
@@ -3522,21 +3523,18 @@
         return andOrEqual(f);
       case NOT:
         return notComponent.equals(f.notComponent);
-      case EQUALITY:
-        return typeAndOptionsAndAssertionEqual(f);
       case SUBSTRING:
         return substringEqual(f);
-      case GREATER_OR_EQUAL:
-        return typeAndOptionsAndAssertionEqual(f);
-      case LESS_OR_EQUAL:
-        return typeAndOptionsAndAssertionEqual(f);
       case PRESENT:
-        return attributeType.equals(f.attributeType) &&
-                optionsEqual(attributeOptions, f.attributeOptions);
-      case APPROXIMATE_MATCH:
-        return typeAndOptionsAndAssertionEqual(f);
+        return attributeDescription.equals(f.attributeDescription);
       case EXTENSIBLE_MATCH:
         return extensibleEqual(f);
+      case EQUALITY:
+      case APPROXIMATE_MATCH:
+      case GREATER_OR_EQUAL:
+      case LESS_OR_EQUAL:
+        return attributeDescription.equals(f.attributeDescription)
+            && assertionValue.equals(f.assertionValue);
       default:
         return false;
     }
@@ -3559,18 +3557,9 @@
     return true;
   }
 
-
-  private boolean typeAndOptionsAndAssertionEqual(SearchFilter f)
-  {
-    return attributeType.equals(f.attributeType)
-        && optionsEqual(attributeOptions, f.attributeOptions)
-        && assertionValue.equals(f.assertionValue);
-  }
-
-
   private boolean substringEqual(SearchFilter other)
   {
-    if (! attributeType.equals(other.attributeType))
+    if (!attributeDescription.equals(other.attributeDescription))
     {
       return false;
     }
@@ -3580,10 +3569,6 @@
     {
       return false;
     }
-    if (! optionsEqual(attributeOptions, other.attributeOptions))
-    {
-      return false;
-    }
 
     boolean initialCheck = subInitialElement == null ?
         other.subInitialElement == null : subInitialElement.equals(other.subInitialElement);
@@ -3625,17 +3610,9 @@
         return false;
       }
     }
-    else
+    else if (!attributeDescription.equals(f.attributeDescription))
     {
-      if (! attributeType.equals(f.attributeType))
-      {
-        return false;
-      }
-
-      if (! optionsEqual(attributeOptions, f.attributeOptions))
-      {
-        return false;
-      }
+      return false;
     }
 
     if (dnAttributes != f.dnAttributes)
@@ -3699,56 +3676,6 @@
     return true;
   }
 
-
-  /**
-   * Indicates whether the two provided sets of attribute options
-   * should be considered equal.
-   *
-   * @param  options1  The first set of attribute options for which to
-   *                   make the determination.
-   * @param  options2  The second set of attribute options for which
-   *                   to make the determination.
-   *
-   * @return  {@code true} if the sets of attribute options are equal,
-   *          or {@code false} if not.
-   */
-  private static boolean optionsEqual(Set<String> options1,
-                                      Set<String> options2)
-  {
-    if (options1 == null || options1.isEmpty())
-    {
-      return options2 == null || options2.isEmpty();
-    }
-    else if (options2 == null || options2.isEmpty())
-    {
-      return false;
-    }
-    else
-    {
-      if (options1.size() != options2.size())
-      {
-        return false;
-      }
-
-      HashSet<String> lowerOptions = new HashSet<>(options1.size());
-      for (String option : options1)
-      {
-        lowerOptions.add(toLowerCase(option));
-      }
-
-      for (String option : options2)
-      {
-        if (! lowerOptions.remove(toLowerCase(option)))
-        {
-          return false;
-        }
-      }
-
-      return lowerOptions.isEmpty();
-    }
-  }
-
-
   /**
    * Retrieves the hash code for this search filter.
    *
@@ -3896,17 +3823,11 @@
         buffer.append(")");
         break;
       case EQUALITY:
-        buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
-        buffer.append("=");
-        valueToFilterString(buffer, assertionValue);
-        buffer.append(")");
+        appendEquation(buffer, "=");
         break;
       case SUBSTRING:
         buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
+        buffer.append(attributeDescription);
         buffer.append("=");
 
         if (subInitialElement != null)
@@ -3933,42 +3854,25 @@
         buffer.append(")");
         break;
       case GREATER_OR_EQUAL:
-        buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
-        buffer.append(">=");
-        valueToFilterString(buffer, assertionValue);
-        buffer.append(")");
+        appendEquation(buffer, ">=");
         break;
       case LESS_OR_EQUAL:
-        buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
-        buffer.append("<=");
-        valueToFilterString(buffer, assertionValue);
-        buffer.append(")");
+        appendEquation(buffer, "<=");
         break;
       case PRESENT:
         buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
+        buffer.append(attributeDescription);
         buffer.append("=*)");
         break;
       case APPROXIMATE_MATCH:
-        buffer.append("(");
-        buffer.append(attributeType.getNameOrOID());
-        appendOptions(buffer);
-        buffer.append("~=");
-        valueToFilterString(buffer, assertionValue);
-        buffer.append(")");
+        appendEquation(buffer, "~=");
         break;
       case EXTENSIBLE_MATCH:
         buffer.append("(");
 
-        if (attributeType != null)
+        if (attributeDescription != null)
         {
-          buffer.append(attributeType.getNameOrOID());
-          appendOptions(buffer);
+          buffer.append(attributeDescription);
         }
 
         if (dnAttributes)
@@ -3989,21 +3893,16 @@
     }
   }
 
-
-  private void appendOptions(StringBuilder buffer)
+  private void appendEquation(StringBuilder buffer, String operator)
   {
-    if (attributeOptions != null && !attributeOptions.isEmpty())
-    {
-      for (String option : attributeOptions)
-      {
-        buffer.append(";");
-        buffer.append(option);
-      }
-    }
+    buffer.append("(");
+    buffer.append(attributeDescription);
+    buffer.append(operator);
+    valueToFilterString(buffer, assertionValue);
+    buffer.append(")");
   }
 
 
-
   /**
    * Appends a properly-cleaned version of the provided value to the
    * given buffer so that it can be safely used in string
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/VirtualAttribute.java b/opendj-server-legacy/src/main/java/org/opends/server/types/VirtualAttribute.java
index 900a388..45602c4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/VirtualAttribute.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/VirtualAttribute.java
@@ -26,17 +26,16 @@
  */
 package org.opends.server.types;
 
-import org.forgerock.opendj.ldap.schema.AttributeType;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
-import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.util.Utils;
 import org.opends.server.api.VirtualAttributeProvider;
 
@@ -53,10 +52,8 @@
 public final class VirtualAttribute
   extends AbstractAttribute
 {
-  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
-
-  /** The attribute type. */
-  private final AttributeType attributeType;
+  /** The attribute description. */
+  private final AttributeDescription attributeDescription;
   /** The entry with which this virtual attribute is associated. */
   private final Entry entry;
   /** The virtual attribute provider for this virtual attribute. */
@@ -80,7 +77,7 @@
   public VirtualAttribute(AttributeType attributeType, Entry entry,
       VirtualAttributeRule rule)
   {
-    this.attributeType = attributeType;
+    this.attributeDescription = AttributeDescription.create(attributeType);
     this.entry = entry;
     this.rule = rule;
     this.provider = rule.getProvider();
@@ -111,18 +108,18 @@
   }
 
   @Override
-  public AttributeType getAttributeType()
-  {
-    return attributeType;
-  }
-
-  @Override
   public String getNameWithOptions()
   {
     return getName();
   }
 
   @Override
+  public AttributeDescription getAttributeDescription()
+  {
+    return attributeDescription;
+  }
+
+  @Override
   public Set<String> getOptions()
   {
     return Collections.emptySet();
@@ -149,12 +146,6 @@
   }
 
   @Override
-  public boolean hasAllOptions(Collection<String> options)
-  {
-    return options == null || options.isEmpty();
-  }
-
-  @Override
   public boolean hasOption(String option)
   {
     return false;
@@ -198,12 +189,6 @@
   }
 
   @Override
-  public boolean optionsEqual(Set<String> options)
-  {
-    return options == null || options.isEmpty();
-  }
-
-  @Override
   public int size()
   {
     if (provider.isMultiValued())
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
index c9d41c1..df4ac33 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -1325,7 +1325,7 @@
         RDN rdn = modifiedEntry.getName().rdn();
         if (rdn != null
             && rdn.hasAttributeType(t)
-            && !modifiedEntry.hasValue(t, attr.getOptions(), rdn.getAttributeValue(t)))
+            && !modifiedEntry.hasValue(attr.getAttributeDescription(), rdn.getAttributeValue(t)))
         {
           throw newDirectoryException(currentEntry,
               ResultCode.NOT_ALLOWED_ON_RDN,
@@ -1380,7 +1380,7 @@
     RDN rdn = modifiedEntry.getName().rdn();
     if (rdn != null
         && rdn.hasAttributeType(t)
-        && !modifiedEntry.hasValue(t, attr.getOptions(), rdn.getAttributeValue(t)))
+        && !modifiedEntry.hasValue(attr.getAttributeDescription(), rdn.getAttributeValue(t)))
     {
       throw newDirectoryException(modifiedEntry, ResultCode.NOT_ALLOWED_ON_RDN,
           ERR_MODIFY_DELETE_RDN_ATTR.get(entryDN, attr.getName()));
@@ -1436,7 +1436,7 @@
     }
 
     // Get the attribute that is to be incremented.
-    Attribute a = modifiedEntry.getExactAttribute(t, attr.getOptions());
+    Attribute a = modifiedEntry.getExactAttribute(attr.getAttributeDescription());
     if (a == null)
     {
       throw newDirectoryException(modifiedEntry,
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
index 8e93f0e..28c4cbe 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
@@ -50,6 +50,7 @@
 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.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -83,7 +84,6 @@
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.BackupConfig;
 import org.opends.server.types.BackupDirectory;
 import org.opends.server.types.DN;
@@ -688,7 +688,7 @@
     ModifyOperation modifyOp = mock(ModifyOperation.class);
     when(modifyOp.getModifications()).thenReturn(mods);
     backend.replaceEntry(oldEntry, newEntry, modifyOp);
-    assertTrue(backend.getEntry(oldEntry.getName()).hasValue(modifyAttribute, null, modifyValue));
+    assertTrue(backend.getEntry(oldEntry.getName()).hasValue(modifyAttribute, modifyValue));
 
     final List<Entry> returnedEntries = new ArrayList<>();
     backend.search(createSearchOperation(
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/TestDnKeyFormat.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/TestDnKeyFormat.java
index 4e93d13..5421f93 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/TestDnKeyFormat.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/TestDnKeyFormat.java
@@ -400,7 +400,7 @@
             boolean found = false;
 
             for (Attribute attrAfter : listAfter) {
-              if (attrAfter.optionsEqual(attrBefore.getOptions())) {
+              if (attrAfter.getAttributeDescription().equals(attrBefore.getAttributeDescription())) {
                 // Found the corresponding attribute
                 assertEquals(attrBefore, attrAfter);
                 found = true;
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/PasswordPolicyTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/core/PasswordPolicyTestCase.java
index 3d73ac6..2b93c02 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/PasswordPolicyTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/PasswordPolicyTestCase.java
@@ -26,17 +26,13 @@
  */
 package org.opends.server.core;
 
-
-
 import java.util.List;
 import java.util.Set;
 
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.admin.server.AdminTestCaseUtils;
 import org.opends.server.admin.std.meta.PasswordPolicyCfgDefn;
@@ -45,15 +41,19 @@
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.schema.UserPasswordSyntax;
 import org.opends.server.tools.LDAPModify;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+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.InitializationException;
 import org.opends.server.util.TimeThread;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.testng.Assert.*;
 
-
-
 /**
  * A set of generic test cases for the Directory Server password policy class.
  */
@@ -4315,7 +4315,7 @@
     assertNotNull(entry);
     AttributeType pwdHistory = DirectoryServer.getAttributeType("pwdhistory");
     assertNotNull(pwdHistory);
-    Attribute historyAttr = entry.getExactAttribute(pwdHistory, null);
+    Attribute historyAttr = entry.getExactAttribute(AttributeDescription.create(pwdHistory));
     assertNotNull(historyAttr);
     assertThat(historyAttr).hasSize(3);
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryManagerTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryManagerTestCase.java
index fdb5f57..76cacd5 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryManagerTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryManagerTestCase.java
@@ -35,6 +35,7 @@
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -44,7 +45,6 @@
 import org.opends.server.tools.LDAPDelete;
 import org.opends.server.tools.LDAPModify;
 import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
@@ -335,7 +335,7 @@
     assertTrue(entry.hasAttribute(attrType));
     for (String value : values)
     {
-      assertTrue(entry.hasValue(attrType, null, ByteString.valueOfUtf8(value)));
+      assertTrue(entry.hasValue(attrType, ByteString.valueOfUtf8(value)));
     }
   }
 
@@ -346,7 +346,7 @@
     assertTrue(entry.hasAttribute(attrType));
     for (String value : values)
     {
-      assertFalse(entry.hasValue(attrType, null, ByteString.valueOfUtf8(value)));
+      assertFalse(entry.hasValue(attrType, ByteString.valueOfUtf8(value)));
     }
   }
 
@@ -368,7 +368,7 @@
     assertEquals(searchOperation.getEntriesSent(), 1);
     AttributeType attrType = DirectoryServer.getAttributeType("collectiveattributesubentries");
     Entry e = searchOperation.getSearchEntries().getFirst();
-    assertTrue(e.hasValue(attrType, null, ByteString.valueOfObject(collectiveSubentry.getName())));
+    assertTrue(e.hasValue(attrType, ByteString.valueOfObject(collectiveSubentry.getName())));
   }
 
   @Test
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryPasswordPolicyTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryPasswordPolicyTestCase.java
index 1560503..6a56be8 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryPasswordPolicyTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/SubentryPasswordPolicyTestCase.java
@@ -31,10 +31,10 @@
 
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.api.AuthenticationPolicy;
 import org.opends.server.api.PasswordValidator;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.util.StaticUtils;
@@ -420,7 +420,7 @@
     // Make sure that default policy is in effect
     // for the user entry.
     assertTrue(testEntry.hasAttribute(attrType));
-    assertTrue(testEntry.hasValue(attrType, null,
+    assertTrue(testEntry.hasValue(attrType,
             ByteString.valueOfUtf8(defaultPolicy.getDN().toString())));
 
     // Add new subentry policy with the
@@ -443,7 +443,7 @@
     assertNotNull(testEntry);
 
     assertTrue(testEntry.hasAttribute(attrType));
-    assertTrue(testEntry.hasValue(attrType, null, ByteString.valueOfUtf8("cn=Temp Policy," + SUFFIX)));
+    assertTrue(testEntry.hasValue(attrType, ByteString.valueOfUtf8("cn=Temp Policy," + SUFFIX)));
 
     // Remove subentry policy and make sure
     // default policy is in effect again.
@@ -454,7 +454,7 @@
     assertNotNull(testEntry);
 
     assertTrue(testEntry.hasAttribute(attrType));
-    assertTrue(testEntry.hasValue(attrType, null,
+    assertTrue(testEntry.hasValue(attrType,
             ByteString.valueOfUtf8(defaultPolicy.getDN().toString())));
   }
 }
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 c27376c..f275655 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
@@ -325,8 +325,8 @@
     for (int i = 0; i < rdn.getNumValues(); i++)
     {
       AttributeType attribute = rdn.getAttributeType(i);
-      assertEquals(newEntry.hasValue(attribute, null, b("user.0")), user0Exists);
-      assertEquals(newEntry.hasValue(attribute, null, b("user.test0")), userTest0Exists);
+      assertEquals(newEntry.hasValue(attribute, b("user.0")), user0Exists);
+      assertEquals(newEntry.hasValue(attribute, b("user.test0")), userTest0Exists);
     }
   }
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
index cf9084e..de49b39 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
@@ -44,7 +44,12 @@
 import org.opends.server.api.Group;
 import org.opends.server.api.plugin.PluginType;
 import org.opends.server.controls.SubtreeDeleteControl;
-import org.opends.server.core.*;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.GroupManager;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
@@ -68,9 +73,7 @@
 import static org.opends.server.util.CollectionUtils.*;
 import static org.testng.Assert.*;
 
-/**
- * Unit test to test Referential Integrity plugin.
- */
+/** Unit test to test Referential Integrity plugin. */
 @SuppressWarnings("javadoc")
 public class ReferentialIntegrityPluginTestCase extends PluginTestCase  {
 
@@ -1123,7 +1126,7 @@
     for (SearchResultEntry entry : operation.getSearchEntries()) {
       for(String dn : dns) {
         ByteString value = ByteString.valueOfUtf8(dn);
-        assertEquals(entry.hasValue(type, null, value), expected);
+        assertEquals(entry.hasValue(type, value), expected);
       }
     }
   }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/GenerationIdTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/GenerationIdTest.java
index 16ae47d..f863754 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/GenerationIdTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/GenerationIdTest.java
@@ -35,7 +35,6 @@
 import java.io.File;
 import java.net.SocketTimeoutException;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.UUID;
@@ -45,7 +44,9 @@
 import org.assertj.core.api.SoftAssertions;
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.backends.MemoryBackend;
 import org.opends.server.core.DirectoryServer;
@@ -66,7 +67,6 @@
 import org.opends.server.replication.service.ReplicationBroker;
 import org.opends.server.tasks.LdifFileWriter;
 import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.types.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.Entry;
@@ -481,7 +481,7 @@
       debugInfo("Entry found <" + baseDN + ">");
 
       AttributeType synchronizationGenIDType = DirectoryServer.getAttributeType(REPLICATION_GENERATION_ID);
-      Attribute attr = resultEntry.getExactAttribute(synchronizationGenIDType, new HashSet<String>());
+      Attribute attr = resultEntry.getExactAttribute(AttributeDescription.create(synchronizationGenIDType));
       return Long.valueOf(attr.iterator().next().toString());
     }
     return -1;
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/HistoricalTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/HistoricalTest.java
index cfed051..2df2405 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/HistoricalTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/HistoricalTest.java
@@ -26,12 +26,12 @@
  */
 package org.opends.server.replication.plugin;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.Callable;
 
 import org.assertj.core.api.Assertions;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
@@ -44,7 +44,13 @@
 import org.opends.server.replication.protocol.ModifyMsg;
 import org.opends.server.replication.service.ReplicationBroker;
 import org.opends.server.tools.LDAPModify;
-import org.opends.server.types.*;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Operation;
 import org.opends.server.util.TestTimer;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -234,7 +240,9 @@
     final DN dn2 = DN.valueOf("cn=test2," + TEST_ROOT_DN_STRING);
     final DN baseDN = DN.valueOf(TEST_ROOT_DN_STRING);
     final AttributeType attrType = DirectoryServer.getAttributeType("displayname");
+    final AttributeDescription attrDesc = AttributeDescription.create(attrType);
     final AttributeType entryuuidType = DirectoryServer.getAttributeType("entryuuid");
+    final AttributeDescription entryuuidDesc = AttributeDescription.create(entryuuidType);
 
     /*
      * Open a session to the replicationServer using the broker API.
@@ -244,7 +252,7 @@
       openReplicationSession(baseDN, 2, 100, replServerPort, 1000);
 
 
-    // Clear the backend and create top entrye
+    // Clear the backend and create top entry
     TestCaseUtils.initializeTestBackend(true);
 
     // Add the first test entry.
@@ -259,7 +267,7 @@
        );
 
     // Read the entry back to get its UUID.
-    String entryuuid = getEntryValue(dn1, entryuuidType);
+    String entryuuid = getEntryValue(dn1, entryuuidDesc);
 
     // Add the second test entry.
     TestCaseUtils.addEntry(
@@ -274,7 +282,7 @@
        );
 
     // Read the entry back to get its UUID.
-    String entryuuid2 = getEntryValue(dn2, entryuuidType);
+    String entryuuid2 = getEntryValue(dn2, entryuuidDesc);
 
     long now = System.currentTimeMillis();
     final int serverId1 = 3;
@@ -287,7 +295,7 @@
 
     // Replay an add of a value A at time t1 on a first server.
     publishModify(broker, t1, dn1, entryuuid, attrType, "A");
-    waitUntilEntryValueEquals(dn1, attrType, "A");
+    waitUntilEntryValueEquals(dn1, attrDesc, "A");
 
     // Replay an add of a value B at time t2 on a second server.
     publishModify(broker, t2, dn1, entryuuid, attrType, "B");
@@ -299,22 +307,22 @@
     t2 = new CSN(now+4,  0,  serverId2);
 
     publishModify(broker, t2, dn2, entryuuid2, attrType, "B");
-    waitUntilEntryValueEquals(dn2, attrType, "B");
+    waitUntilEntryValueEquals(dn2, attrDesc, "B");
 
     // Replay an add of a value A at time t1 on a first server.
     publishModify(broker, t1, dn2, entryuuid2, attrType, "A");
 
     // See how the conflicts were resolved.
     // The two values should be the first value added.
-    waitUntilEntryValueEquals(dn1, attrType, "A");
-    waitUntilEntryValueEquals(dn2, attrType, "A");
+    waitUntilEntryValueEquals(dn1, attrDesc, "A");
+    waitUntilEntryValueEquals(dn2, attrDesc, "A");
 
     TestCaseUtils.deleteEntry(dn1);
     TestCaseUtils.deleteEntry(dn2);
   }
 
-  private void waitUntilEntryValueEquals(final DN entryDN, final AttributeType attrType, final String expectedValue)
-      throws Exception
+  private void waitUntilEntryValueEquals(final DN entryDN, final AttributeDescription attrDesc,
+      final String expectedValue) throws Exception
   {
     final TestTimer timer = new TestTimer.Builder()
       .maxSleep(2, SECONDS)
@@ -325,16 +333,16 @@
       @Override
       public Void call() throws Exception
       {
-        assertEquals(getEntryValue(entryDN, attrType), expectedValue);
+        assertEquals(getEntryValue(entryDN, attrDesc), expectedValue);
         return null;
       }
     });
   }
 
-  private String getEntryValue(final DN dn, final AttributeType attrType) throws Exception
+  private String getEntryValue(final DN dn, AttributeDescription attrDesc) throws DirectoryException
   {
     Entry entry = DirectoryServer.getEntry(dn);
-    Attribute attr = entry.getExactAttribute(attrType, Collections.<String> emptySet());
+    Attribute attr = entry.getExactAttribute(attrDesc);
     Assertions.assertThat(attr).hasSize(1);
     return attr.iterator().next().toString();
   }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyConflictTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyConflictTest.java
index 203cd8b..8284086 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyConflictTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyConflictTest.java
@@ -26,13 +26,13 @@
  */
 package org.opends.server.replication.plugin;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -1204,7 +1204,7 @@
 
   private void assertContainsOnlyValues(Entry entry, String attrName, String... expectedValues)
   {
-    Attribute attr = entry.getExactAttribute(getAttributeType(attrName), Collections.<String> emptySet());
+    Attribute attr = entry.getExactAttribute(AttributeDescription.create(getAttributeType(attrName)));
     assertThat(attr).hasSize(expectedValues.length);
     for (String value : expectedValues)
     {
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyReplaySingleValuedAttributeTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyReplaySingleValuedAttributeTest.java
index 90d2237..da7b55d 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyReplaySingleValuedAttributeTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/plugin/ModifyReplaySingleValuedAttributeTest.java
@@ -31,13 +31,11 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ModificationType;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.replication.ReplicationTestCase;
 import org.opends.server.replication.common.CSN;
@@ -376,9 +374,7 @@
     entryHistorical.replayOperation(op, entry);
     entry.applyModification(new Modification(REPLACE, entryHistorical.encodeAndPurge()));
 
-    AttributeType attrType = expectedDsSyncHist.getAttributeType();
-    Attribute actual = entry.getExactAttribute(attrType, Collections.<String> emptySet());
-
+    Attribute actual = entry.getExactAttribute(expectedDsSyncHist.getAttributeDescription());
     Assert.assertEquals(actual, expectedDsSyncHist, "wrong final value for ds-sync-hist attribute");
   }
 
@@ -414,9 +410,7 @@
       entry.applyModification(new Modification(REPLACE, entryHistorical.encodeAndPurge()));
     }
 
-    AttributeType attrType = expectedDsSyncHist.getAttributeType();
-    Attribute actual = entry.getExactAttribute(attrType, Collections.<String> emptySet());
-
+    Attribute actual = entry.getExactAttribute(expectedDsSyncHist.getAttributeDescription());
     Assert.assertEquals(actual, expectedDsSyncHist, "wrong final value for ds-sync-hist attribute");
   }
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/schema/FakeEntryIndex.java b/opendj-server-legacy/src/test/java/org/opends/server/schema/FakeEntryIndex.java
index 9f9c649..4d39a00 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/schema/FakeEntryIndex.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/schema/FakeEntryIndex.java
@@ -38,6 +38,7 @@
 import java.util.TreeSet;
 
 import org.forgerock.opendj.ldap.Assertion;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.DecodeException;
 import org.forgerock.opendj.ldap.schema.AttributeType;
@@ -80,7 +81,7 @@
 
   void add(Entry entry) throws DecodeException
   {
-    Attribute attribute = entry.getExactAttribute(attrType, Collections.<String>emptySet());
+    Attribute attribute = entry.getExactAttribute(AttributeDescription.create(attrType));
     for (ByteString key : index(attribute))
     {
       Set<Entry> entries = index.get(key);
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/schema/TimeBasedMatchingRuleTest.java b/opendj-server-legacy/src/test/java/org/opends/server/schema/TimeBasedMatchingRuleTest.java
index 2bac0c5..7d496f2 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/schema/TimeBasedMatchingRuleTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/schema/TimeBasedMatchingRuleTest.java
@@ -30,13 +30,13 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.GregorianCalendar;
 import java.util.List;
 import java.util.Set;
 import java.util.TimeZone;
 
 import org.forgerock.opendj.ldap.Assertion;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.DecodeException;
@@ -143,7 +143,7 @@
     Collection<DN> results = new ArrayList<>();
     for (Entry entry : makeEntries())
     {
-      Attribute attribute = entry.getExactAttribute(attrType, Collections.<String> emptySet());
+      Attribute attribute = entry.getExactAttribute(AttributeDescription.create(attrType));
       if (attribute != null)
       {
         ByteString attrValue = rule.normalizeAttributeValue(attribute.iterator().next());
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/types/AttributeBuilderTest.java b/opendj-server-legacy/src/test/java/org/opends/server/types/AttributeBuilderTest.java
index ce7e2b0..119e26e 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/types/AttributeBuilderTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/types/AttributeBuilderTest.java
@@ -31,6 +31,7 @@
 import static org.testng.Assert.*;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -38,6 +39,7 @@
 import java.util.NoSuchElementException;
 import java.util.Set;
 
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
@@ -1419,24 +1421,25 @@
    *          The expected attribute values.
    */
   @Test(dataProvider = "createAttributes", dependsOnMethods = "testAttributeNotNull")
-  public void testAttributeHasAllOptions(int testCase, Attribute a,
+  public void testAttributeDescriptionIsSubTypeOf(int testCase, Attribute a,
       AttributeType type, String name, String[] options, String[] values)
       throws Exception
   {
-    Assert.assertTrue(a.hasAllOptions(null));
-    Assert.assertTrue(a.hasAllOptions(Collections.<String> emptySet()));
-    Assert.assertTrue(a.hasAllOptions(Arrays.asList(options)));
+    AttributeDescription attrDesc = a.getAttributeDescription();
+    Assert.assertTrue(attrDesc.isSubTypeOf(AttributeDescription.create(type)));
+    Assert.assertTrue(attrDesc.isSubTypeOf(AttributeDescription.create(type, options)));
 
     if (options.length > 1)
     {
-      Assert.assertTrue(a.hasAllOptions(Arrays.asList(options).subList(1, options.length)));
+      List<String> options2 = Arrays.asList(options).subList(1, options.length);
+      Assert.assertTrue(attrDesc.isSubTypeOf(AttributeDescription.create(type, options2)));
     }
 
     List<String> tmp = newArrayList(options);
     tmp.add("xxxx");
-    Assert.assertFalse(a.hasAllOptions(tmp));
+    Assert.assertFalse(attrDesc.isSubTypeOf(AttributeDescription.create(type, tmp)));
 
-    Assert.assertFalse(a.hasAllOptions(newHashSet("xxxx")));
+    Assert.assertFalse(attrDesc.isSubTypeOf(AttributeDescription.create(type, "xxxx")));
 
     tmp.clear();
     for (String option : options)
@@ -1444,11 +1447,9 @@
       // Assumes internal normalization to lower-case.
       tmp.add(option.toUpperCase());
     }
-    Assert.assertTrue(a.hasAllOptions(tmp));
+    Assert.assertTrue(attrDesc.isSubTypeOf(AttributeDescription.create(type, tmp)));
   }
 
-
-
   /**
    * Tests {@link Attribute#hashCode()}.
    *
@@ -1758,21 +1759,22 @@
    *          The expected attribute values.
    */
   @Test(dataProvider = "createAttributes", dependsOnMethods = "testAttributeNotNull")
-  public void testAttributeOptionsEquals(int testCase, Attribute a,
+  public void testAttributeDescriptionEquals(int testCase, Attribute a,
       AttributeType type, String name, String[] options, String[] values)
       throws Exception
   {
-    // Check optionsEquals.
-    Assert.assertTrue(a.optionsEqual(newHashSet(options)));
+    // Check attributeDescription.equals()
+    AttributeDescription attrDesc = a.getAttributeDescription();
+    Assert.assertTrue(attrDesc.equals(AttributeDescription.create(type, options)));
 
     if (options.length > 1)
     {
-      Assert.assertFalse(a.optionsEqual(Collections.singleton(options[0])));
+      Assert.assertFalse(attrDesc.equals(AttributeDescription.create(type, options[0])));
     }
 
     Set<String> stmp = newHashSet(options);
     stmp.add("xxxx");
-    Assert.assertFalse(a.optionsEqual(stmp));
+    Assert.assertFalse(attrDesc.equals(AttributeDescription.create(type, stmp)));
 
     stmp.clear();
     for (String option : options)
@@ -1780,7 +1782,7 @@
       // Assumes internal normalization to lower-case.
       stmp.add(option.toUpperCase());
     }
-    Assert.assertTrue(a.optionsEqual(stmp));
+    Assert.assertTrue(attrDesc.equals(AttributeDescription.create(type, stmp)));
   }
 
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/types/TestEntry.java b/opendj-server-legacy/src/test/java/org/opends/server/types/TestEntry.java
index 6eeb9a0..e459219 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/types/TestEntry.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/types/TestEntry.java
@@ -39,6 +39,7 @@
 import org.assertj.core.api.Assertions;
 import org.forgerock.i18n.LocalizableMessageBuilder;
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.TestCaseUtils;
@@ -302,45 +303,45 @@
     assertTrue(e.hasAttribute(mnType));
 
     LinkedHashSet<String> options = null;
-    assertTrue(e.hasAttribute(ocType, options));
-    assertTrue(e.hasAttribute(cnType, options));
-    assertTrue(e.hasAttribute(nameType, options));
-    assertFalse(e.hasAttribute(nameType, options, false));
-    assertFalse(e.hasAttribute(uidType, options));
-    assertTrue(e.hasAttribute(mnType, options));
+    assertTrue(e.hasAttribute(AttributeDescription.create(ocType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(cnType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(nameType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), false));
+    assertFalse(e.hasAttribute(AttributeDescription.create(uidType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(mnType, options), true));
 
     options = new LinkedHashSet<>();
-    assertTrue(e.hasAttribute(ocType, options));
-    assertTrue(e.hasAttribute(cnType, options));
-    assertTrue(e.hasAttribute(nameType, options));
-    assertFalse(e.hasAttribute(nameType, options, false));
-    assertFalse(e.hasAttribute(uidType, options));
-    assertTrue(e.hasAttribute(mnType, options));
+    assertTrue(e.hasAttribute(AttributeDescription.create(ocType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(cnType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(nameType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), false));
+    assertFalse(e.hasAttribute(AttributeDescription.create(uidType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(mnType, options), true));
 
     options.add("lang-en-US");
-    assertFalse(e.hasAttribute(ocType, options));
-    assertTrue(e.hasAttribute(cnType, options));
-    assertTrue(e.hasAttribute(nameType, options));
-    assertFalse(e.hasAttribute(nameType, options, false));
-    assertFalse(e.hasAttribute(uidType, options));
-    assertFalse(e.hasAttribute(mnType, options));
+    assertFalse(e.hasAttribute(AttributeDescription.create(ocType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(cnType, options), true));
+    assertTrue(e.hasAttribute(AttributeDescription.create(nameType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), false));
+    assertFalse(e.hasAttribute(AttributeDescription.create(uidType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(mnType, options), true));
 
     options.add("lang-en-GB");
-    assertFalse(e.hasAttribute(ocType, options));
-    assertFalse(e.hasAttribute(cnType, options));
-    assertFalse(e.hasAttribute(nameType, options));
-    assertFalse(e.hasAttribute(nameType, options, false));
-    assertFalse(e.hasAttribute(uidType, options));
-    assertFalse(e.hasAttribute(mnType, options));
+    assertFalse(e.hasAttribute(AttributeDescription.create(ocType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(cnType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), false));
+    assertFalse(e.hasAttribute(AttributeDescription.create(uidType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(mnType, options), true));
 
     options.clear();
     options.add("lang-en-GB");
-    assertFalse(e.hasAttribute(ocType, options));
-    assertFalse(e.hasAttribute(cnType, options));
-    assertFalse(e.hasAttribute(nameType, options));
-    assertFalse(e.hasAttribute(nameType, options, false));
-    assertFalse(e.hasAttribute(uidType, options));
-    assertFalse(e.hasAttribute(mnType, options));
+    assertFalse(e.hasAttribute(AttributeDescription.create(ocType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(cnType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(nameType, options), false));
+    assertFalse(e.hasAttribute(AttributeDescription.create(uidType, options), true));
+    assertFalse(e.hasAttribute(AttributeDescription.create(mnType, options), true));
   }
 
 
@@ -618,39 +619,39 @@
     assertThat(e.getOperationalAttribute(mnType)).hasSize(1);
 
     LinkedHashSet<String> options = null;
-    assertThat(e.getOperationalAttribute(ocType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(cnType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(nameType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(uidType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(mnType, options)).hasSize(1);
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(ocType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(cnType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(nameType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(uidType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(mnType, options))).hasSize(1);
 
     options = new LinkedHashSet<>();
-    assertThat(e.getOperationalAttribute(ocType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(cnType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(nameType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(uidType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(mnType, options)).hasSize(1);
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(ocType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(cnType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(nameType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(uidType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(mnType, options))).hasSize(1);
 
     options.add("lang-en-US");
-    assertThat(e.getOperationalAttribute(ocType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(cnType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(nameType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(uidType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(mnType, options)).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(ocType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(cnType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(nameType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(uidType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(mnType, options))).isEmpty();
 
     options.add("lang-en-GB");
-    assertThat(e.getOperationalAttribute(ocType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(cnType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(nameType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(uidType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(mnType, options)).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(ocType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(cnType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(nameType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(uidType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(mnType, options))).isEmpty();
 
     options.clear();
     options.add("lang-en-GB");
-    assertThat(e.getOperationalAttribute(ocType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(cnType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(nameType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(uidType, options)).isEmpty();
-    assertThat(e.getOperationalAttribute(mnType, options)).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(ocType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(cnType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(nameType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(uidType, options))).isEmpty();
+    assertThat(e.getOperationalAttribute(AttributeDescription.create(mnType, options))).isEmpty();
   }
 }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/util/TestLDIFReader.java b/opendj-server-legacy/src/test/java/org/opends/server/util/TestLDIFReader.java
index 3aa45c7..80fbc64 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/util/TestLDIFReader.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/util/TestLDIFReader.java
@@ -321,18 +321,15 @@
         + "objectClass: top\n" + "objectClass: person\n" + "cn: john\n"
         + "sn: smith\n";
 
-    LDIFReader reader = createLDIFReader(ldifString);
-
-    try {
+    try (LDIFReader reader = createLDIFReader(ldifString)) {
       Entry entry = reader.readEntry();
       Assert.assertNotNull(entry);
 
-      Assert.assertEquals(entry.getName(), DN
-          .valueOf("cn=john, dc=foo, dc=com"));
+      Assert.assertEquals(entry.getName(), DN.valueOf("cn=john, dc=foo, dc=com"));
       Assert.assertTrue(entry.hasObjectClass(OC_TOP));
       Assert.assertTrue(entry.hasObjectClass(OC_PERSON));
-      Assert.assertTrue(entry.hasValue(AT_CN, null, ByteString.valueOfUtf8("john")));
-      Assert.assertTrue(entry.hasValue(AT_SN, null, ByteString.valueOfUtf8("smith")));
+      Assert.assertTrue(entry.hasValue(AT_CN, ByteString.valueOfUtf8("john")));
+      Assert.assertTrue(entry.hasValue(AT_SN, ByteString.valueOfUtf8("smith")));
 
       Assert.assertNull(reader.readEntry());
 
@@ -340,8 +337,6 @@
       Assert.assertEquals(reader.getEntriesRead(), 1);
       Assert.assertEquals(reader.getEntriesRejected(), 0);
       Assert.assertEquals(reader.getLastEntryLineNumber(), 1);
-    } finally {
-      reader.close();
     }
   }
 
@@ -358,14 +353,10 @@
         + "sn: smith\n" + "description: once upon a time\n"
         + "  in the west\n";
 
-    LDIFReader reader = createLDIFReader(ldifString);
-
-    try {
+    try (LDIFReader reader = createLDIFReader(ldifString)) {
       Entry entry = reader.readEntry();
       Assert.assertNotNull(entry);
-      Assert.assertTrue(entry.hasValue(AT_DESCR, null, ByteString.valueOfUtf8("once upon a time in the west")));
-    } finally {
-      reader.close();
+      Assert.assertTrue(entry.hasValue(AT_DESCR, ByteString.valueOfUtf8("once upon a time in the west")));
     }
   }
 
@@ -382,14 +373,10 @@
         + "sn: smith\n"
         + "description:: b25jZSB1cG9uIGEgdGltZSBpbiB0aGUgd2VzdA==\n";
 
-    LDIFReader reader = createLDIFReader(ldifString);
-
-    try {
+    try (LDIFReader reader = createLDIFReader(ldifString)) {
       Entry entry = reader.readEntry();
       Assert.assertNotNull(entry);
-      Assert.assertTrue(entry.hasValue(AT_DESCR, null, ByteString.valueOfUtf8("once upon a time in the west")));
-    } finally {
-      reader.close();
+      Assert.assertTrue(entry.hasValue(AT_DESCR, ByteString.valueOfUtf8("once upon a time in the west")));
     }
   }
 
@@ -407,20 +394,17 @@
         + "objectClass: top\n" + "objectClass: person\n" + "cn: anne\n"
         + "sn: other\n" + "\n";
 
-    LDIFReader reader = createLDIFReader(ldifString);
-
-    try {
+    try (LDIFReader reader = createLDIFReader(ldifString)) {
       reader.readEntry();
       Entry entry = reader.readEntry();
 
       Assert.assertNotNull(entry);
 
-      Assert.assertEquals(entry.getName(), DN
-          .valueOf("cn=anne, dc=foo, dc=com"));
+      Assert.assertEquals(entry.getName(), DN.valueOf("cn=anne, dc=foo, dc=com"));
       Assert.assertTrue(entry.hasObjectClass(OC_TOP));
       Assert.assertTrue(entry.hasObjectClass(OC_PERSON));
-      Assert.assertTrue(entry.hasValue(AT_CN, null, ByteString.valueOfUtf8("anne")));
-      Assert.assertTrue(entry.hasValue(AT_SN, null, ByteString.valueOfUtf8("other")));
+      Assert.assertTrue(entry.hasValue(AT_CN, ByteString.valueOfUtf8("anne")));
+      Assert.assertTrue(entry.hasValue(AT_SN, ByteString.valueOfUtf8("other")));
 
       Assert.assertNull(reader.readEntry());
 
@@ -428,8 +412,6 @@
       Assert.assertEquals(reader.getEntriesRead(), 2);
       Assert.assertEquals(reader.getEntriesRejected(), 0);
       Assert.assertEquals(reader.getLastEntryLineNumber(), 7);
-    } finally {
-      reader.close();
     }
   }
 

--
Gitblit v1.10.0