From 72650d4cc41c64136d064967d7fec3726d850fee Mon Sep 17 00:00:00 2001
From: Ludovic Poitou <ludovic.poitou@forgerock.com>
Date: Thu, 14 Oct 2010 11:52:28 +0000
Subject: [PATCH] Multiple enhancements and bug fixes to the SDK (update from OpenDS by matthew_swift):

---
 sdk/src/org/opends/sdk/Entries.java |  182 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 173 insertions(+), 9 deletions(-)

diff --git a/sdk/src/org/opends/sdk/Entries.java b/sdk/src/org/opends/sdk/Entries.java
index 14fbaae..55a17da 100644
--- a/sdk/src/org/opends/sdk/Entries.java
+++ b/sdk/src/org/opends/sdk/Entries.java
@@ -30,14 +30,21 @@
 
 
 import java.util.Collection;
+import java.util.Iterator;
+
+import org.opends.sdk.requests.ModifyRequest;
+import org.opends.sdk.requests.Requests;
 
 import com.sun.opends.sdk.util.Function;
 import com.sun.opends.sdk.util.Iterables;
+import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
  * This class contains methods for creating and manipulating entries.
+ *
+ * @see Entry
  */
 public final class Entries
 {
@@ -58,6 +65,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean addAttribute(final Attribute attribute)
         throws UnsupportedOperationException, NullPointerException
     {
@@ -69,6 +77,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean addAttribute(final Attribute attribute,
         final Collection<ByteString> duplicateValues)
         throws UnsupportedOperationException, NullPointerException
@@ -81,6 +90,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Entry addAttribute(final String attributeDescription,
         final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
@@ -90,6 +100,7 @@
 
 
 
+    @Override
     public Entry clearAttributes() throws UnsupportedOperationException
     {
       throw new UnsupportedOperationException();
@@ -97,6 +108,7 @@
 
 
 
+    @Override
     public boolean containsAttribute(final Attribute attribute,
         final Collection<ByteString> missingValues) throws NullPointerException
     {
@@ -105,6 +117,7 @@
 
 
 
+    @Override
     public boolean containsAttribute(final String attributeDescription,
         final Object... values) throws LocalizedIllegalArgumentException,
         NullPointerException
@@ -125,19 +138,21 @@
 
 
 
+    @Override
     public Iterable<Attribute> getAllAttributes()
     {
-      return Iterables.unmodifiable(Iterables.transform(entry
-          .getAllAttributes(), UNMODIFIABLE_ATTRIBUTE_FUNCTION));
+      return Iterables.unmodifiable(Iterables.transform(
+          entry.getAllAttributes(), UNMODIFIABLE_ATTRIBUTE_FUNCTION));
     }
 
 
 
+    @Override
     public Iterable<Attribute> getAllAttributes(
         final AttributeDescription attributeDescription)
     {
-      return Iterables.unmodifiable(Iterables.transform(entry
-          .getAllAttributes(attributeDescription),
+      return Iterables.unmodifiable(Iterables.transform(
+          entry.getAllAttributes(attributeDescription),
           UNMODIFIABLE_ATTRIBUTE_FUNCTION));
     }
 
@@ -146,17 +161,19 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Iterable<Attribute> getAllAttributes(
         final String attributeDescription)
         throws LocalizedIllegalArgumentException, NullPointerException
     {
-      return Iterables.unmodifiable(Iterables.transform(entry
-          .getAllAttributes(attributeDescription),
+      return Iterables.unmodifiable(Iterables.transform(
+          entry.getAllAttributes(attributeDescription),
           UNMODIFIABLE_ATTRIBUTE_FUNCTION));
     }
 
 
 
+    @Override
     public Attribute getAttribute(
         final AttributeDescription attributeDescription)
     {
@@ -176,6 +193,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Attribute getAttribute(final String attributeDescription)
         throws LocalizedIllegalArgumentException, NullPointerException
     {
@@ -192,6 +210,7 @@
 
 
 
+    @Override
     public int getAttributeCount()
     {
       return entry.getAttributeCount();
@@ -202,6 +221,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public DN getName()
     {
       return entry.getName();
@@ -223,6 +243,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean removeAttribute(final Attribute attribute,
         final Collection<ByteString> missingValues)
         throws UnsupportedOperationException, NullPointerException
@@ -232,6 +253,7 @@
 
 
 
+    @Override
     public boolean removeAttribute(
         final AttributeDescription attributeDescription)
         throws UnsupportedOperationException, NullPointerException
@@ -244,6 +266,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Entry removeAttribute(final String attributeDescription,
         final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
@@ -256,6 +279,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean replaceAttribute(final Attribute attribute)
         throws UnsupportedOperationException, NullPointerException
     {
@@ -267,6 +291,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Entry replaceAttribute(final String attributeDescription,
         final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
@@ -276,6 +301,7 @@
 
 
 
+    @Override
     public Entry setName(final DN dn) throws UnsupportedOperationException,
         NullPointerException
     {
@@ -287,6 +313,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Entry setName(final String dn)
         throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
@@ -309,10 +336,11 @@
 
 
 
-  private static final Function<Attribute, Attribute, Void>
-    UNMODIFIABLE_ATTRIBUTE_FUNCTION = new Function<Attribute, Attribute, Void>()
+  private static final Function<Attribute, Attribute, Void> UNMODIFIABLE_ATTRIBUTE_FUNCTION =
+    new Function<Attribute, Attribute, Void>()
   {
 
+    @Override
     public Attribute apply(final Attribute value, final Void p)
     {
       return Attributes.unmodifiableAttribute(value);
@@ -323,8 +351,144 @@
 
 
   /**
+   * Creates a new modify request containing a list of modifications which can
+   * be used to transform {@code fromEntry} into entry {@code toEntry}.
+   * <p>
+   * The modify request is reversible: it will contain only modifications of
+   * type {@link ModificationType#ADD ADD} and {@link ModificationType#DELETE
+   * DELETE}.
+   * <p>
+   * Finally, the modify request will use the distinguished name taken from
+   * {@code fromEntry}. Moreover, this method will not check to see if both
+   * {@code fromEntry} and {@code toEntry} have the same distinguished name.
+   * <p>
+   * This method is equivalent to:
+   *
+   * <pre>
+   * ModifyRequest request = Requests.newModifyRequest(fromEntry, toEntry);
+   * </pre>
+   *
+   * @param fromEntry
+   *          The source entry.
+   * @param toEntry
+   *          The destination entry.
+   * @return A modify request containing a list of modifications which can be
+   *         used to transform {@code fromEntry} into entry {@code toEntry}.
+   * @throws NullPointerException
+   *           If {@code fromEntry} or {@code toEntry} were {@code null}.
+   * @see Requests#newModifyRequest(Entry, Entry)
+   */
+  public static final ModifyRequest diffEntries(final Entry fromEntry,
+      final Entry toEntry) throws NullPointerException
+  {
+    Validator.ensureNotNull(fromEntry, toEntry);
+
+    final ModifyRequest request = Requests
+        .newModifyRequest(fromEntry.getName());
+
+    TreeMapEntry tfrom;
+    if (fromEntry instanceof TreeMapEntry)
+    {
+      tfrom = (TreeMapEntry) fromEntry;
+    }
+    else
+    {
+      tfrom = new TreeMapEntry(fromEntry);
+    }
+
+    TreeMapEntry tto;
+    if (toEntry instanceof TreeMapEntry)
+    {
+      tto = (TreeMapEntry) toEntry;
+    }
+    else
+    {
+      tto = new TreeMapEntry(toEntry);
+    }
+
+    final Iterator<Attribute> ifrom = tfrom.getAllAttributes().iterator();
+    final Iterator<Attribute> ito = tto.getAllAttributes().iterator();
+
+    Attribute afrom = ifrom.hasNext() ? ifrom.next() : null;
+    Attribute ato = ito.hasNext() ? ito.next() : null;
+
+    while (afrom != null && ato != null)
+    {
+      final AttributeDescription adfrom = afrom.getAttributeDescription();
+      final AttributeDescription adto = ato.getAttributeDescription();
+
+      final int cmp = adfrom.compareTo(adto);
+      if (cmp == 0)
+      {
+        // Attribute is in both entries. Compute the set of values to be added
+        // and removed. We won't replace the attribute because this is not
+        // reversible.
+        final Attribute addedValues = new LinkedAttribute(ato);
+        addedValues.removeAll(afrom);
+        if (!addedValues.isEmpty())
+        {
+          request.addModification(new Modification(ModificationType.ADD,
+              addedValues));
+        }
+
+        final Attribute deletedValues = new LinkedAttribute(afrom);
+        deletedValues.removeAll(ato);
+        if (!deletedValues.isEmpty())
+        {
+          request.addModification(new Modification(ModificationType.DELETE,
+              deletedValues));
+        }
+
+        afrom = ifrom.hasNext() ? ifrom.next() : null;
+        ato = ito.hasNext() ? ito.next() : null;
+      }
+      else if (cmp < 0)
+      {
+        // afrom in source, but not destination.
+        request
+            .addModification(new Modification(ModificationType.DELETE, afrom));
+        afrom = ifrom.hasNext() ? ifrom.next() : null;
+      }
+      else
+      {
+        // ato in destination, but not in source.
+        request.addModification(new Modification(ModificationType.ADD, ato));
+        ato = ito.hasNext() ? ito.next() : null;
+      }
+    }
+
+    // Additional attributes in source entry: these must be deleted.
+    if (afrom != null)
+    {
+      request.addModification(new Modification(ModificationType.DELETE, afrom));
+    }
+
+    while (ifrom.hasNext())
+    {
+      final Attribute a = ifrom.next();
+      request.addModification(new Modification(ModificationType.DELETE, a));
+    }
+
+    // Additional attributes in destination entry: these must be added.
+    if (ato != null)
+    {
+      request.addModification(new Modification(ModificationType.ADD, ato));
+    }
+
+    while (ito.hasNext())
+    {
+      final Attribute a = ito.next();
+      request.addModification(new Modification(ModificationType.ADD, a));
+    }
+
+    return request;
+  }
+
+
+
+  /**
    * Returns a read-only view of {@code entry} and its attributes. Query
-   * operations on the returned entry and its attributes"read-through" to the
+   * operations on the returned entry and its attributes "read-through" to the
    * underlying entry or attribute, and attempts to modify the returned entry
    * and its attributes either directly or indirectly via an iterator result in
    * an {@code UnsupportedOperationException}.

--
Gitblit v1.10.0