From 007e7a70e8c372d42cc27d72a09e7e175b1587f8 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Tue, 08 Jun 2010 09:28:19 +0000
Subject: [PATCH] Fix issue 4446: allow empty attributes to be added to entries and also add support for empty attributes to LDIFWriter. This was preventing types-only from working in searches.

---
 opendj-sdk/sdk/src/org/opends/sdk/Entry.java                                                |   50 +++++++++---
 opendj-sdk/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java                                 |   13 ++
 opendj-sdk/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryWriterTestCase.java |   96 ++++++++++++++++++++++++
 opendj-sdk/sdk/src/org/opends/sdk/AbstractMapEntry.java                                     |   26 ++---
 4 files changed, 154 insertions(+), 31 deletions(-)

diff --git a/opendj-sdk/sdk/src/org/opends/sdk/AbstractMapEntry.java b/opendj-sdk/sdk/src/org/opends/sdk/AbstractMapEntry.java
index 800a6b5..6dcfc77 100644
--- a/opendj-sdk/sdk/src/org/opends/sdk/AbstractMapEntry.java
+++ b/opendj-sdk/sdk/src/org/opends/sdk/AbstractMapEntry.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -74,22 +74,18 @@
   {
     Validator.ensureNotNull(attribute);
 
-    if (!attribute.isEmpty())
+    final AttributeDescription attributeDescription = attribute
+        .getAttributeDescription();
+    final Attribute oldAttribute = attributes.get(attributeDescription);
+    if (oldAttribute != null)
     {
-      final AttributeDescription attributeDescription = attribute
-          .getAttributeDescription();
-      final Attribute oldAttribute = attributes.get(attributeDescription);
-      if (oldAttribute != null)
-      {
-        return oldAttribute.addAll(attribute, duplicateValues);
-      }
-      else
-      {
-        attributes.put(attributeDescription, attribute);
-        return true;
-      }
+      return oldAttribute.addAll(attribute, duplicateValues);
     }
-    return false;
+    else
+    {
+      attributes.put(attributeDescription, attribute);
+      return true;
+    }
   }
 
 
diff --git a/opendj-sdk/sdk/src/org/opends/sdk/Entry.java b/opendj-sdk/sdk/src/org/opends/sdk/Entry.java
index 0b588e4..e237739 100644
--- a/opendj-sdk/sdk/src/org/opends/sdk/Entry.java
+++ b/opendj-sdk/sdk/src/org/opends/sdk/Entry.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -62,11 +62,19 @@
 {
 
   /**
-   * Adds all of the attribute values contained in {@code attribute} to this
-   * entry, merging with any existing attribute values (optional operation). If
-   * {@code attribute} is empty then this entry is left unchanged.
+   * Ensures that this entry contains the provided attribute and values
+   * (optional operation). This method has the following semantics:
+   * <ul>
+   * <li>If this entry does not already contain an attribute with the same
+   * attribute description, then this entry will be modified such that it
+   * contains {@code attribute}, even if it is empty.
+   * <li>If this entry already contains an attribute with the same attribute
+   * description, then the attribute values contained in {@code attribute} will
+   * be merged with the existing attribute values.
+   * </ul>
    * <p>
-   * <b>NOTE:</b> This method implements LDAP Modify add semantics.
+   * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
+   * LDAP Modify add semantics.
    *
    * @param attribute
    *          The attribute values to be added to this entry, merging with any
@@ -84,11 +92,19 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code attribute} to this
-   * entry, merging with any existing attribute values (optional operation). If
-   * {@code attribute} is empty then this entry is left unchanged.
+   * Ensures that this entry contains the provided attribute and values
+   * (optional operation). This method has the following semantics:
+   * <ul>
+   * <li>If this entry does not already contain an attribute with the same
+   * attribute description, then this entry will be modified such that it
+   * contains {@code attribute}, even if it is empty.
+   * <li>If this entry already contains an attribute with the same attribute
+   * description, then the attribute values contained in {@code attribute} will
+   * be merged with the existing attribute values.
+   * </ul>
    * <p>
-   * <b>NOTE:</b> This method implements LDAP Modify add semantics.
+   * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
+   * LDAP Modify add semantics.
    *
    * @param attribute
    *          The attribute values to be added to this entry, merging with any
@@ -110,9 +126,16 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code values} to this entry,
-   * merging with any existing attribute values (optional operation). If {@code
-   * values} is {@code null} or empty then this entry is left unchanged.
+   * Ensures that this entry contains the provided attribute and values
+   * (optional operation). This method has the following semantics:
+   * <ul>
+   * <li>If this entry does not already contain an attribute with the same
+   * attribute description, then this entry will be modified such that it
+   * contains {@code attribute}, even if it is empty.
+   * <li>If this entry already contains an attribute with the same attribute
+   * description, then the attribute values contained in {@code attribute} will
+   * be merged with the existing attribute values.
+   * </ul>
    * <p>
    * The attribute description will be decoded using the schema associated with
    * this entry (usually the default schema).
@@ -120,7 +143,8 @@
    * Any attribute values which are not instances of {@code ByteString} will be
    * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
-   * <b>NOTE:</b> This method implements LDAP Modify add semantics.
+   * <b>NOTE:</b> When {@code attribute} is non-empty, this method implements
+   * LDAP Modify add semantics.
    *
    * @param attributeDescription
    *          The name of the attribute whose values are to be added.
diff --git a/opendj-sdk/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java b/opendj-sdk/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
index 6914a81..273b378 100644
--- a/opendj-sdk/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
+++ b/opendj-sdk/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.ldif;
@@ -341,9 +341,16 @@
 
       final String attributeDescription = attribute
           .getAttributeDescriptionAsString();
-      for (final ByteString value : attribute)
+      if (attribute.isEmpty())
       {
-        writeKeyAndValue(attributeDescription, value);
+        writeKeyAndValue(attributeDescription, ByteString.empty());
+      }
+      else
+      {
+        for (final ByteString value : attribute)
+        {
+          writeKeyAndValue(attributeDescription, value);
+        }
       }
     }
 
diff --git a/opendj-sdk/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryWriterTestCase.java b/opendj-sdk/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryWriterTestCase.java
new file mode 100644
index 0000000..bba7e3c
--- /dev/null
+++ b/opendj-sdk/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryWriterTestCase.java
@@ -0,0 +1,96 @@
+/*
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  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 2009-2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.ldif;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.sdk.Entry;
+import org.opends.sdk.LinkedHashMapEntry;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class tests the LDIFEntryWriter functionality.
+ */
+public final class LDIFEntryWriterTestCase extends LDIFTestCase
+{
+
+  /**
+   * Tests writeEntry method of LDIFEntryWriter class.See
+   * https://opends.dev.java.net/issues/show_bug.cgi?id=4545 for more details.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test()
+  public void testWriteEntry() throws Exception
+  {
+    final Entry entry = new LinkedHashMapEntry(
+        "cn=John Doe,ou=people,dc=example,dc=com");
+    entry.addAttribute("objectClass", "top", "person", "inetOrgPerson");
+    entry.addAttribute("cn", "John Doe");
+    entry.addAttribute("sn", "Doe");
+    entry.addAttribute("givenName", "John");
+    entry.addAttribute("description", "one two", "three four", "five six");
+    entry.addAttribute("typeOnly");
+    entry.addAttribute("localized;lang-fr", "\u00e7edilla");
+
+    final List<String> actual = new ArrayList<String>();
+    final LDIFEntryWriter writer = new LDIFEntryWriter(actual);
+    writer.writeEntry(entry);
+    writer.close();
+
+    final String[] expected = new String[] {
+        "dn: cn=John Doe,ou=people,dc=example,dc=com",
+        "objectClass: top",
+        "objectClass: person",
+        "objectClass: inetOrgPerson",
+        "cn: John Doe",
+        "sn: Doe",
+        "givenName: John",
+        "description: one two",
+        "description: three four",
+        "description: five six",
+        "typeOnly: ",
+        "localized;lang-fr:: w6dlZGlsbGE=",
+        "",
+        };
+
+    Assert.assertEquals(actual.size(), expected.length);
+    for (int i = 0; i < expected.length; i++)
+    {
+      Assert.assertEquals(actual.get(i), expected[i], "LDIF output was "
+          + actual);
+    }
+  }
+}

--
Gitblit v1.10.0