From 9c1e151ca2da620abfb0ed4864665c48f53e1efd Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 12 Dec 2011 17:33:59 +0000
Subject: [PATCH] Additional fixes for OPENDJ-381: Implement LDIF diff, patch, and search API support in the SDK

---
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java                |    8 
 /dev/null                                                                                                      |  233 --------------
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java           |   51 +-
 opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java |   20 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java   |  275 +++++++++++++++++
 opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java                    |   44 +
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java                           |  247 ++++++++++++++
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java         |   10 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java                             |    6 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java             |    2 
 opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java                            |   53 +++
 11 files changed, 646 insertions(+), 303 deletions(-)

diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
index 1176c4e..2cfc0d6 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/DN.java
@@ -374,12 +374,18 @@
   /**
    * Returns a DN which is an immediate child of this DN and having the
    * specified RDN.
+   * <p>
+   * <b>Note:</b> the child DN whose RDN is {@link RDN#maxValue()} compares
+   * greater than all other possible child DNs, and may be used to construct
+   * range queries against DN keyed sorted collections such as {@code SortedSet}
+   * and {@code SortedMap}.
    *
    * @param rdn
    *          The RDN for the child DN.
    * @return The child DN.
    * @throws NullPointerException
    *           If {@code rdn} was {@code null}.
+   * @see RDN#maxValue()
    */
   public DN child(final RDN rdn) throws NullPointerException
   {
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
index 957528f..9e52acc 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/RDN.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2009-2010 Sun Microsystems, Inc.
+ *      Portions copyright 2011 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldap;
@@ -75,6 +76,38 @@
  */
 public final class RDN implements Iterable<AVA>, Comparable<RDN>
 {
+
+  // A constant holding a special RDN having zero AVAs and which always compares
+  // greater than any other RDN other than itself.
+  private static final RDN MAX_VALUE = new RDN(new AVA[0], "");
+
+
+
+  /**
+   * Returns a constant containing a special RDN which is greater than any other
+   * RDN other than itself. This RDN may be used in order to perform range
+   * queries on DN keyed collections such as {@code SortedSet}s and
+   * {@code SortedMap}s. For example, the following code can be used to
+   * construct a range whose contents is a sub-tree of entries:
+   *
+   * <pre>
+   * SortedMap<DN, Entry> entries = ...;
+   * DN baseDN = ...;
+   *
+   * // Returns a map containing the baseDN and all of its subordinates.
+   * SortedMap<DN,Entry> subtree = entries.subMap(baseDN, baseDN.child(RDN.maxValue));
+   * </pre>
+   *
+   * @return A constant containing a special RDN which is greater than any other
+   *         RDN other than itself.
+   */
+  public static RDN maxValue()
+  {
+    return MAX_VALUE;
+  }
+
+
+
   /**
    * Parses the provided LDAP string representation of an RDN using the default
    * schema.
@@ -235,14 +268,32 @@
    */
   public int compareTo(final RDN rdn)
   {
+    // Identity.
+    if (this == rdn)
+    {
+      return 0;
+    }
+
+    // MAX_VALUE is always greater than any other RDN other than itself.
+    if (this == MAX_VALUE)
+    {
+      return 1;
+    }
+
+    if (rdn == MAX_VALUE)
+    {
+      return -1;
+    }
+
+    // Compare number of AVAs first as this is quick and easy.
     final int sz1 = avas.length;
     final int sz2 = rdn.avas.length;
-
     if (sz1 != sz2)
     {
       return sz1 - sz2 > 0 ? 1 : -1;
     }
 
+    // Fast path for common case.
     if (sz1 == 1)
     {
       return avas[0].compareTo(rdn.avas[0]);
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
index 7b8b0e7..36e2270 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
@@ -230,7 +230,7 @@
 
 
 
-  RejectedRecordListener rejectedRecordListener = RejectedRecordListener.FAIL_FAST;
+  RejectedLDIFListener rejectedRecordListener = RejectedLDIFListener.FAIL_FAST;
 
   Schema schema = Schema.getDefaultSchema().asNonStrictSchema();
 
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
index d3061ec..17d8b4d 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIF.java
@@ -28,11 +28,18 @@
 
 
 
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_DELETE;
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFY;
+import static org.forgerock.opendj.ldap.CoreMessages.REJECTED_CHANGE_FAIL_MODIFYDN;
+
 import java.io.IOException;
 import java.util.*;
 
 import org.forgerock.opendj.ldap.*;
+import org.forgerock.opendj.ldap.controls.SubtreeDeleteRequestControl;
 import org.forgerock.opendj.ldap.requests.*;
+import org.forgerock.opendj.ldap.schema.AttributeUsage;
+import org.forgerock.opendj.ldap.schema.Schema;
 
 
 
@@ -66,7 +73,7 @@
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  public static final ChangeRecordWriter copyTo(final ChangeRecordReader input,
+  public static ChangeRecordWriter copyTo(final ChangeRecordReader input,
       final ChangeRecordWriter output) throws IOException
   {
     while (input.hasNext())
@@ -90,7 +97,7 @@
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  public static final EntryWriter copyTo(final EntryReader input,
+  public static EntryWriter copyTo(final EntryReader input,
       final EntryWriter output) throws IOException
   {
     while (input.hasNext())
@@ -278,7 +285,7 @@
   public static EntryReader patch(final EntryReader input,
       final ChangeRecordReader patch) throws IOException
   {
-    return patch(input, patch, RejectedChangeListener.OVERWRITE);
+    return patch(input, patch, RejectedChangeRecordListener.OVERWRITE);
   }
 
 
@@ -305,8 +312,8 @@
    *           If an unexpected IO error occurred.
    */
   public static EntryReader patch(final EntryReader input,
-      final ChangeRecordReader patch, final RejectedChangeListener listener)
-      throws IOException
+      final ChangeRecordReader patch,
+      final RejectedChangeRecordListener listener) throws IOException
   {
     final SortedMap<DN, Entry> entries = readEntries(input);
 
@@ -353,7 +360,9 @@
               {
                 try
                 {
-                  listener.handleMissingEntry(change);
+                  listener.handleRejectedChangeRecord(change,
+                      REJECTED_CHANGE_FAIL_DELETE.get(change.getName()
+                          .toString()));
                 }
                 catch (final DecodeException e)
                 {
@@ -362,7 +371,24 @@
               }
               else
               {
-                entries.remove(change.getName());
+                try
+                {
+                  if (change.getControl(SubtreeDeleteRequestControl.DECODER,
+                      new DecodeOptions()) != null)
+                  {
+                    entries.subMap(change.getName(),
+                        change.getName().child(RDN.maxValue())).clear();
+                  }
+                  else
+                  {
+                    entries.remove(change.getName());
+                  }
+                }
+                catch (final DecodeException e)
+                {
+                  return e;
+                }
+
               }
               return null;
             }
@@ -377,7 +403,9 @@
               {
                 try
                 {
-                  listener.handleMissingEntry(change);
+                  listener.handleRejectedChangeRecord(change,
+                      REJECTED_CHANGE_FAIL_MODIFYDN.get(change.getName()
+                          .toString()));
                 }
                 catch (final DecodeException e)
                 {
@@ -404,7 +432,9 @@
                 // avoid cases where the renamed subtree overlaps.
                 final SortedMap<DN, Entry> renamedEntries = new TreeMap<DN, Entry>();
                 final Iterator<Map.Entry<DN, Entry>> i = entries
-                    .tailMap(change.getName()).entrySet().iterator();
+                    .subMap(change.getName(),
+                        change.getName().child(RDN.maxValue())).entrySet()
+                    .iterator();
                 while (i.hasNext())
                 {
                   final Map.Entry<DN, Entry> e = i.next();
@@ -466,7 +496,9 @@
               {
                 try
                 {
-                  listener.handleMissingEntry(change);
+                  listener.handleRejectedChangeRecord(change,
+                      REJECTED_CHANGE_FAIL_MODIFY.get(change.getName()
+                          .toString()));
                 }
                 catch (final DecodeException e)
                 {
@@ -551,6 +583,201 @@
 
 
 
+  /**
+   * Returns a filtered view of {@code input} containing only those entries
+   * which match the search base DN, scope, and filtered defined in
+   * {@code search}. In addition, returned entries will be filtered according to
+   * any attribute filtering criteria defined in the search request.
+   * <p>
+   * The filter and attribute descriptions will be decoded using the default
+   * schema.
+   *
+   * @param input
+   *          The entry reader containing the set of entries to be filtered.
+   * @param search
+   *          The search request defining the filtering criteria.
+   * @return A filtered view of {@code input} containing only those entries
+   *         which match the provided search request.
+   */
+  public static EntryReader search(final EntryReader input,
+      final SearchRequest search)
+  {
+    return search(input, search, Schema.getDefaultSchema());
+  }
+
+
+
+  /**
+   * Returns a filtered view of {@code input} containing only those entries
+   * which match the search base DN, scope, and filtered defined in
+   * {@code search}. In addition, returned entries will be filtered according to
+   * any attribute filtering criteria defined in the search request.
+   * <p>
+   * The filter and attribute descriptions will be decoded using the provided
+   * schema.
+   *
+   * @param input
+   *          The entry reader containing the set of entries to be filtered.
+   * @param search
+   *          The search request defining the filtering criteria.
+   * @param schema
+   *          The schema which should be used to decode the search filter and
+   *          attribute descriptions.
+   * @return A filtered view of {@code input} containing only those entries
+   *         which match the provided search request.
+   */
+  public static EntryReader search(final EntryReader input,
+      final SearchRequest search, final Schema schema)
+  {
+    final Matcher matcher = search.getFilter().matcher(schema);
+
+    return new EntryReader()
+    {
+      private Entry nextEntry = null;
+      private int entryCount = 0;
+
+
+
+      public void close() throws IOException
+      {
+        input.close();
+      }
+
+
+
+      public boolean hasNext() throws IOException
+      {
+        if (nextEntry == null)
+        {
+          final int sizeLimit = search.getSizeLimit();
+          if (sizeLimit == 0 || entryCount < sizeLimit)
+          {
+            final DN baseDN = search.getName();
+            final SearchScope scope = search.getScope();
+            while (input.hasNext())
+            {
+              final Entry entry = input.readEntry();
+              if (entry.getName().isInScopeOf(baseDN, scope)
+                  && matcher.matches(entry).toBoolean())
+              {
+                nextEntry = filterEntry(entry);
+                break;
+              }
+            }
+          }
+        }
+        return nextEntry != null;
+      }
+
+
+
+      public Entry readEntry() throws IOException, NoSuchElementException
+      {
+        if (hasNext())
+        {
+          final Entry entry = nextEntry;
+          nextEntry = null;
+          entryCount++;
+          return entry;
+        }
+        else
+        {
+          throw new NoSuchElementException();
+        }
+      }
+
+
+
+      private Entry filterEntry(final Entry entry)
+      {
+        // TODO: rename attributes; move functionality to Entries.
+        if (search.getAttributes().isEmpty())
+        {
+          if (search.isTypesOnly())
+          {
+            final Entry filteredEntry = new LinkedHashMapEntry(entry.getName());
+            for (final Attribute attribute : entry.getAllAttributes())
+            {
+              filteredEntry.addAttribute(Attributes.emptyAttribute(attribute
+                  .getAttributeDescription()));
+            }
+            return filteredEntry;
+          }
+          else
+          {
+            return entry;
+          }
+        }
+        else
+        {
+          final Entry filteredEntry = new LinkedHashMapEntry(entry.getName());
+          for (final String atd : search.getAttributes())
+          {
+            if (atd.equals("*"))
+            {
+              for (final Attribute attribute : entry.getAllAttributes())
+              {
+                if (attribute.getAttributeDescription().getAttributeType()
+                    .getUsage() == AttributeUsage.USER_APPLICATIONS)
+                {
+                  if (search.isTypesOnly())
+                  {
+                    filteredEntry.addAttribute(Attributes
+                        .emptyAttribute(attribute.getAttributeDescription()));
+                  }
+                  else
+                  {
+                    filteredEntry.addAttribute(attribute);
+                  }
+                }
+              }
+            }
+            else if (atd.equals("+"))
+            {
+              for (final Attribute attribute : entry.getAllAttributes())
+              {
+                if (attribute.getAttributeDescription().getAttributeType()
+                    .getUsage() != AttributeUsage.USER_APPLICATIONS)
+                {
+                  if (search.isTypesOnly())
+                  {
+                    filteredEntry.addAttribute(Attributes
+                        .emptyAttribute(attribute.getAttributeDescription()));
+                  }
+                  else
+                  {
+                    filteredEntry.addAttribute(attribute);
+                  }
+                }
+              }
+            }
+            else
+            {
+              final AttributeDescription ad = AttributeDescription.valueOf(atd,
+                  schema);
+              for (final Attribute attribute : entry.getAllAttributes(ad))
+              {
+                if (search.isTypesOnly())
+                {
+                  filteredEntry.addAttribute(Attributes
+                      .emptyAttribute(attribute.getAttributeDescription()));
+                }
+                else
+                {
+                  filteredEntry.addAttribute(attribute);
+                }
+              }
+            }
+          }
+          return filteredEntry;
+        }
+      }
+
+    };
+  }
+
+
+
   private static SortedMap<DN, Entry> readEntries(final EntryReader reader)
       throws IOException
   {
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
index c8498ad..1807e90 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
@@ -336,17 +336,17 @@
 
 
   /**
-   * Sets the rejected record listener which should be notified whenever a
+   * Sets the rejected record listener which should be notified whenever an LDIF
    * record is skipped, malformed, or fails schema validation.
    * <p>
-   * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used.
+   * By default the {@link RejectedLDIFListener#FAIL_FAST} listener is used.
    *
    * @param listener
    *          The rejected record listener.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
-  public LDIFChangeRecordReader setRejectedRecordListener(
-      final RejectedRecordListener listener)
+  public LDIFChangeRecordReader setRejectedLDIFListener(
+      final RejectedLDIFListener listener)
   {
     this.rejectedRecordListener = listener;
     return this;
@@ -623,7 +623,7 @@
         case WARN:
           schemaErrors.add(message);
           continue;
-        default: //Ignore
+        default: // Ignore
           // This should not happen: we should be using a non-strict schema for
           // this policy.
           throw new IllegalStateException(
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
index 5e15fb0..3772797 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
@@ -364,17 +364,17 @@
 
 
   /**
-   * Sets the rejected record listener which should be notified whenever a
+   * Sets the rejected record listener which should be notified whenever an LDIF
    * record is skipped, malformed, or fails schema validation.
    * <p>
-   * By default the {@link RejectedRecordListener#FAIL_FAST} listener is used.
+   * By default the {@link RejectedLDIFListener#FAIL_FAST} listener is used.
    *
    * @param listener
    *          The rejected record listener.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setRejectedRecordListener(
-      final RejectedRecordListener listener)
+  public LDIFEntryReader setRejectedLDIFListener(
+      final RejectedLDIFListener listener)
   {
     this.rejectedRecordListener = listener;
     return this;
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java
deleted file mode 100644
index 856230f..0000000
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeListener.java
+++ /dev/null
@@ -1,233 +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
- * trunk/opendj3/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
- * trunk/opendj3/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 2011 ForgeRock AS
- */
-
-package org.forgerock.opendj.ldif;
-
-
-
-import static org.forgerock.opendj.ldap.CoreMessages.*;
-
-import org.forgerock.opendj.ldap.DecodeException;
-import org.forgerock.opendj.ldap.Entry;
-import org.forgerock.opendj.ldap.requests.AddRequest;
-import org.forgerock.opendj.ldap.requests.DeleteRequest;
-import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
-import org.forgerock.opendj.ldap.requests.ModifyRequest;
-
-
-
-/**
- * A listener interface which is notified whenever a change record cannot be
- * applied to an entry. This may occur when an attempt is made to update a
- * non-existent entry, or add an entry which already exists.
- * <p>
- * By default the {@link #FAIL_FAST} listener is used.
- */
-public interface RejectedChangeListener
-{
-  /**
-   * A handler which terminates processing by throwing a {@code DecodeException}
-   * as soon as a change is rejected.
-   */
-  public final static RejectedChangeListener FAIL_FAST = new RejectedChangeListener()
-  {
-
-    @Override
-    public Entry handleDuplicateEntry(final AddRequest change,
-        final Entry existingEntry) throws DecodeException
-    {
-      throw DecodeException.error(REJECTED_CHANGE_FAIL_ADD_DUPE.get(change
-          .getName().toString()));
-    }
-
-
-
-    @Override
-    public Entry handleDuplicateEntry(final ModifyDNRequest change,
-        final Entry existingEntry, final Entry renamedEntry)
-        throws DecodeException
-    {
-      throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN_DUPE
-          .get(renamedEntry.getName().toString()));
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final DeleteRequest change)
-        throws DecodeException
-    {
-      throw DecodeException.error(REJECTED_CHANGE_FAIL_DELETE.get(change
-          .getName().toString()));
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final ModifyDNRequest change)
-        throws DecodeException
-    {
-      throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN.get(change
-          .getName().toString()));
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final ModifyRequest change)
-        throws DecodeException
-    {
-      throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFY.get(change
-          .getName().toString()));
-    }
-  };
-
-  /**
-   * The default handler which ignores changes applied to missing entries and
-   * tolerates duplicate entries by overwriting the existing entry with the new
-   * entry.
-   */
-  public final static RejectedChangeListener OVERWRITE = new RejectedChangeListener()
-  {
-
-    @Override
-    public Entry handleDuplicateEntry(final AddRequest change,
-        final Entry existingEntry) throws DecodeException
-    {
-      // Overwrite existing entries.
-      return change;
-    }
-
-
-
-    @Override
-    public Entry handleDuplicateEntry(final ModifyDNRequest change,
-        final Entry existingEntry, final Entry renamedEntry)
-        throws DecodeException
-    {
-      // Overwrite existing entries.
-      return renamedEntry;
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final DeleteRequest change)
-        throws DecodeException
-    {
-      // Ignore changes applied to missing entries.
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final ModifyDNRequest change)
-        throws DecodeException
-    {
-      // Ignore changes applied to missing entries.
-    }
-
-
-
-    @Override
-    public void handleMissingEntry(final ModifyRequest change)
-        throws DecodeException
-    {
-      // Ignore changes applied to missing entries.
-    }
-  };
-
-
-
-  /**
-   * Invoked when an attempt was made to add an entry which already exists.
-   *
-   * @param change
-   *          The conflicting add request.
-   * @param existingEntry
-   *          The pre-existing entry.
-   * @return The entry which should be kept.
-   * @throws DecodeException
-   *           If processing should terminate.
-   */
-  Entry handleDuplicateEntry(AddRequest change, Entry existingEntry)
-      throws DecodeException;
-
-
-
-  /**
-   * Invoked when an attempt was made to rename an entry which already exists.
-   *
-   * @param change
-   *          The conflicting add request.
-   * @param existingEntry
-   *          The pre-existing entry.
-   * @param renamedEntry
-   *          The renamed entry.
-   * @return The entry which should be kept.
-   * @throws DecodeException
-   *           If processing should terminate.
-   */
-  Entry handleDuplicateEntry(ModifyDNRequest change, Entry existingEntry,
-      Entry renamedEntry) throws DecodeException;
-
-
-
-  /**
-   * Invoked when an attempt was made to delete an entry which does not exist.
-   *
-   * @param change
-   *          The conflicting delete request.
-   * @throws DecodeException
-   *           If processing should terminate.
-   */
-  void handleMissingEntry(DeleteRequest change) throws DecodeException;
-
-
-
-  /**
-   * Invoked when an attempt was made to rename an entry which does not exist.
-   *
-   * @param change
-   *          The conflicting rename request.
-   * @throws DecodeException
-   *           If processing should terminate.
-   */
-  void handleMissingEntry(ModifyDNRequest change) throws DecodeException;
-
-
-
-  /**
-   * Invoked when an attempt was made to modify an entry which does not exist.
-   *
-   * @param change
-   *          The conflicting modify request.
-   * @throws DecodeException
-   *           If processing should terminate.
-   */
-  void handleMissingEntry(ModifyRequest change) throws DecodeException;
-
-}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java
new file mode 100644
index 0000000..62d9b2a
--- /dev/null
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java
@@ -0,0 +1,275 @@
+/*
+ * 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/opendj3/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
+ * trunk/opendj3/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 2011 ForgeRock AS
+ */
+
+package org.forgerock.opendj.ldif;
+
+
+
+import static org.forgerock.opendj.ldap.CoreMessages.*;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.Entry;
+import org.forgerock.opendj.ldap.requests.AddRequest;
+import org.forgerock.opendj.ldap.requests.DeleteRequest;
+import org.forgerock.opendj.ldap.requests.ModifyDNRequest;
+import org.forgerock.opendj.ldap.requests.ModifyRequest;
+
+
+
+/**
+ * A listener interface which is notified whenever a change record cannot be
+ * applied to an entry. This may occur when an attempt is made to update a
+ * non-existent entry, or add an entry which already exists.
+ * <p>
+ * By default the {@link #FAIL_FAST} listener is used.
+ */
+public interface RejectedChangeRecordListener
+{
+  /**
+   * A handler which terminates processing by throwing a {@code DecodeException}
+   * as soon as a change is rejected.
+   */
+  public final static RejectedChangeRecordListener FAIL_FAST = new RejectedChangeRecordListener()
+  {
+
+    public Entry handleDuplicateEntry(final AddRequest change,
+        final Entry existingEntry) throws DecodeException
+    {
+      throw DecodeException.error(REJECTED_CHANGE_FAIL_ADD_DUPE.get(change
+          .getName().toString()));
+    }
+
+
+
+    public Entry handleDuplicateEntry(final ModifyDNRequest change,
+        final Entry existingEntry, final Entry renamedEntry)
+        throws DecodeException
+    {
+      throw DecodeException.error(REJECTED_CHANGE_FAIL_MODIFYDN_DUPE
+          .get(renamedEntry.getName().toString()));
+    }
+
+
+
+    public void handleRejectedChangeRecord(final AddRequest change,
+        final LocalizableMessage reason) throws DecodeException
+    {
+      throw DecodeException.error(reason);
+    }
+
+
+
+    public void handleRejectedChangeRecord(final DeleteRequest change,
+        final LocalizableMessage reason) throws DecodeException
+    {
+      throw DecodeException.error(reason);
+    }
+
+
+
+    public void handleRejectedChangeRecord(final ModifyRequest change,
+        final LocalizableMessage reason) throws DecodeException
+    {
+      throw DecodeException.error(reason);
+    }
+
+
+
+    public void handleRejectedChangeRecord(final ModifyDNRequest change,
+        final LocalizableMessage reason) throws DecodeException
+    {
+      throw DecodeException.error(reason);
+    }
+
+  };
+
+  /**
+   * The default handler which ignores changes applied to missing entries and
+   * tolerates duplicate entries by overwriting the existing entry with the new
+   * entry.
+   */
+  public final static RejectedChangeRecordListener OVERWRITE = new RejectedChangeRecordListener()
+  {
+
+    public Entry handleDuplicateEntry(final AddRequest change,
+        final Entry existingEntry) throws DecodeException
+    {
+      // Overwrite existing entries.
+      return change;
+    }
+
+
+
+    public Entry handleDuplicateEntry(final ModifyDNRequest change,
+        final Entry existingEntry, final Entry renamedEntry)
+        throws DecodeException
+    {
+      // Overwrite existing entries.
+      return renamedEntry;
+    }
+
+
+
+    public void handleRejectedChangeRecord(AddRequest change,
+        LocalizableMessage reason) throws DecodeException
+    {
+      // Ignore.
+    }
+
+
+
+    public void handleRejectedChangeRecord(DeleteRequest change,
+        LocalizableMessage reason) throws DecodeException
+    {
+      // Ignore.
+    }
+
+
+
+    public void handleRejectedChangeRecord(ModifyRequest change,
+        LocalizableMessage reason) throws DecodeException
+    {
+      // Ignore.
+    }
+
+
+
+    public void handleRejectedChangeRecord(ModifyDNRequest change,
+        LocalizableMessage reason) throws DecodeException
+    {
+      // Ignore.
+    }
+
+  };
+
+
+
+  /**
+   * Invoked when an attempt was made to add an entry which already exists.
+   *
+   * @param change
+   *          The conflicting add request.
+   * @param existingEntry
+   *          The pre-existing entry.
+   * @return The entry which should be kept.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  Entry handleDuplicateEntry(AddRequest change, Entry existingEntry)
+      throws DecodeException;
+
+
+
+  /**
+   * Invoked when an attempt was made to rename an entry which already exists.
+   *
+   * @param change
+   *          The conflicting add request.
+   * @param existingEntry
+   *          The pre-existing entry.
+   * @param renamedEntry
+   *          The renamed entry.
+   * @return The entry which should be kept.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  Entry handleDuplicateEntry(ModifyDNRequest change, Entry existingEntry,
+      Entry renamedEntry) throws DecodeException;
+
+
+
+  /**
+   * Invoked when an attempt to add an entry was rejected. This may be because
+   * the target parent entry was not found, or controls provided with the
+   * request are not supported. This method will not be called when the entry to
+   * be added already exists, since this is handled by
+   * {@link #handleDuplicateEntry(AddRequest, Entry)}.
+   *
+   * @param change
+   *          The rejected add request.
+   * @param reason
+   *          The reason why the record was rejected.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  void handleRejectedChangeRecord(AddRequest change, LocalizableMessage reason)
+      throws DecodeException;
+
+
+
+  /**
+   * Invoked when an attempt to delete an entry was rejected. This may be
+   * because the target entry was not found, or controls provided with the
+   * request are not supported.
+   *
+   * @param change
+   *          The rejected delete request.
+   * @param reason
+   *          The reason why the record was rejected.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  void handleRejectedChangeRecord(DeleteRequest change,
+      LocalizableMessage reason) throws DecodeException;
+
+
+
+  /**
+   * Invoked when an attempt to modify an entry was rejected. This may be
+   * because the target entry was not found, or controls provided with the
+   * request are not supported.
+   *
+   * @param change
+   *          The rejected modify request.
+   * @param reason
+   *          The reason why the record was rejected.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  void handleRejectedChangeRecord(ModifyRequest change,
+      LocalizableMessage reason) throws DecodeException;
+
+
+
+  /**
+   * Invoked when an attempt to rename an entry was rejected. This may be
+   * because the target entry was not found, or controls provided with the
+   * request are not supported. This method will not be called when a renamed
+   * entry already exists, since this is handled by
+   * {@link #handleDuplicateEntry(ModifyDNRequest, Entry, Entry)}.
+   *
+   * @param change
+   *          The rejected modify DN request.
+   * @param reason
+   *          The reason why the record was rejected.
+   * @throws DecodeException
+   *           If processing should terminate.
+   */
+  void handleRejectedChangeRecord(ModifyDNRequest change,
+      LocalizableMessage reason) throws DecodeException;
+
+}
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
similarity index 77%
rename from opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java
rename to opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
index 157a4d1..0be1187 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedRecordListener.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
@@ -36,24 +36,24 @@
 
 
 /**
- * A listener interface which is notified whenever records are skipped,
+ * A listener interface which is notified whenever LDIF records are skipped,
  * malformed, or fail schema validation.
  * <p>
  * By default the {@link #FAIL_FAST} listener is used.
  */
-public interface RejectedRecordListener
+public interface RejectedLDIFListener
 {
   /**
    * The default handler which ignores skipped records but which terminates
    * processing by throwing a {@code DecodeException} as soon as a record is
    * found to be malformed or rejected due to a schema validation failure.
    */
-  public static final RejectedRecordListener FAIL_FAST = new RejectedRecordListener()
+  public static final RejectedLDIFListener FAIL_FAST = new RejectedLDIFListener()
   {
 
     @Override
     public void handleMalformedRecord(final long lineNumber,
-        final List<String> ldifRecord, final LocalizableMessage reason)
+        final List<String> lines, final LocalizableMessage reason)
         throws DecodeException
     {
       // Fail fast.
@@ -64,7 +64,7 @@
 
     @Override
     public void handleSchemaValidationFailure(final long lineNumber,
-        final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+        final List<String> lines, final List<LocalizableMessage> reasons)
         throws DecodeException
     {
       // Fail fast - just use first message.
@@ -75,7 +75,7 @@
 
     @Override
     public void handleSchemaValidationWarning(final long lineNumber,
-        final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+        final List<String> lines, final List<LocalizableMessage> reasons)
         throws DecodeException
     {
       // Ignore schema validation warnings.
@@ -85,7 +85,7 @@
 
     @Override
     public void handleSkippedRecord(final long lineNumber,
-        final List<String> ldifRecord, final LocalizableMessage reason)
+        final List<String> lines, final LocalizableMessage reason)
         throws DecodeException
     {
       // Ignore skipped records.
@@ -95,12 +95,12 @@
   /**
    * A handler which ignores all rejected record notifications.
    */
-  public static final RejectedRecordListener IGNORE_ALL = new RejectedRecordListener()
+  public static final RejectedLDIFListener IGNORE_ALL = new RejectedLDIFListener()
   {
 
     @Override
     public void handleMalformedRecord(final long lineNumber,
-        final List<String> ldifRecord, final LocalizableMessage reason)
+        final List<String> lines, final LocalizableMessage reason)
         throws DecodeException
     {
       // Ignore malformed records.
@@ -110,7 +110,7 @@
 
     @Override
     public void handleSchemaValidationFailure(final long lineNumber,
-        final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+        final List<String> lines, final List<LocalizableMessage> reasons)
         throws DecodeException
     {
       // Ignore schema validation failures.
@@ -120,7 +120,7 @@
 
     @Override
     public void handleSchemaValidationWarning(final long lineNumber,
-        final List<String> ldifRecord, final List<LocalizableMessage> reasons)
+        final List<String> lines, final List<LocalizableMessage> reasons)
         throws DecodeException
     {
       // Ignore schema validation warnings.
@@ -130,7 +130,7 @@
 
     @Override
     public void handleSkippedRecord(final long lineNumber,
-        final List<String> ldifRecord, final LocalizableMessage reason)
+        final List<String> lines, final LocalizableMessage reason)
         throws DecodeException
     {
       // Ignore skipped records.
@@ -146,14 +146,14 @@
    * @param lineNumber
    *          The line number within the source location in which the malformed
    *          record is located, if known, otherwise {@code -1}.
-   * @param ldifRecord
-   *          An LDIF representation of the malformed record.
+   * @param lines
+   *          The content of the malformed record.
    * @param reason
    *          The reason why the record is malformed.
    * @throws DecodeException
    *           If processing should terminate.
    */
-  void handleMalformedRecord(long lineNumber, List<String> ldifRecord,
+  void handleMalformedRecord(long lineNumber, List<String> lines,
       LocalizableMessage reason) throws DecodeException;
 
 
@@ -165,15 +165,14 @@
    * @param lineNumber
    *          The line number within the source location in which the rejected
    *          record is located, if known, otherwise {@code -1}.
-   * @param ldifRecord
-   *          An LDIF representation of the record which failed schema
-   *          validation.
+   * @param lines
+   *          The content of the record which failed schema validation.
    * @param reasons
    *          The reasons why the record failed schema validation.
    * @throws DecodeException
    *           If processing should terminate.
    */
-  void handleSchemaValidationFailure(long lineNumber, List<String> ldifRecord,
+  void handleSchemaValidationFailure(long lineNumber, List<String> lines,
       List<LocalizableMessage> reasons) throws DecodeException;
 
 
@@ -185,15 +184,15 @@
    * @param lineNumber
    *          The line number within the source location in which the record is
    *          located, if known, otherwise {@code -1}.
-   * @param ldifRecord
-   *          An LDIF representation of the record which contained schema
-   *          validation warnings.
+   * @param lines
+   *          The content of the record which contained schema validation
+   *          warnings.
    * @param reasons
    *          The schema validation warnings.
    * @throws DecodeException
    *           If processing should terminate.
    */
-  void handleSchemaValidationWarning(long lineNumber, List<String> ldifRecord,
+  void handleSchemaValidationWarning(long lineNumber, List<String> lines,
       List<LocalizableMessage> reasons) throws DecodeException;
 
 
@@ -205,14 +204,14 @@
    * @param lineNumber
    *          The line number within the source location in which the skipped
    *          record is located, if known, otherwise {@code -1}.
-   * @param ldifRecord
-   *          An LDIF representation of the skipped record.
+   * @param lines
+   *          The content of the record which was skipped.
    * @param reason
    *          The reason why the record was skipped.
    * @throws DecodeException
    *           If processing should terminate.
    */
-  void handleSkippedRecord(long lineNumber, List<String> ldifRecord,
+  void handleSkippedRecord(long lineNumber, List<String> lines,
       LocalizableMessage reason) throws DecodeException;
 
 }
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
index f589f31..27a5e6d 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
@@ -23,6 +23,7 @@
  *
  *
  *      Copyright 2010 Sun Microsystems, Inc.
+ *      Portions copyright 2011 ForgeRock AS.
  */
 
 package org.forgerock.opendj.ldap;
@@ -149,6 +150,7 @@
   @DataProvider(name = "createRDNEqualityData")
   public Object[][] createRDNEqualityData()
   {
+    // @formatter:off
     return new Object[][] {
         { "cn=hello world", "cn=hello world", 0 },
         { "cn=hello world", "CN=hello world", 0 },
@@ -168,10 +170,19 @@
         // { "x-test-integer-type=999", "x-test-integer-type=1000", -1 },
         // { "x-test-integer-type=-1", "x-test-integer-type=0", -1 },
         // { "x-test-integer-type=0", "x-test-integer-type=-1", 1 },
-        { "cn=aaa", "cn=aaaa", -1 }, { "cn=AAA", "cn=aaaa", -1 },
-        { "cn=aaa", "cn=AAAA", -1 }, { "cn=aaaa", "cn=aaa", 1 },
-        { "cn=AAAA", "cn=aaa", 1 }, { "cn=aaaa", "cn=AAA", 1 },
-        { "cn=aaab", "cn=aaaa", 1 }, { "cn=aaaa", "cn=aaab", -1 } };
+        { "cn=aaa", "cn=aaaa", -1 },
+        { "cn=AAA", "cn=aaaa", -1 },
+        { "cn=aaa", "cn=AAAA", -1 },
+        { "cn=aaaa", "cn=aaa", 1 },
+        { "cn=AAAA", "cn=aaa", 1 },
+        { "cn=aaaa", "cn=AAA", 1 },
+        { "cn=aaab", "cn=aaaa", 1 },
+        { "cn=aaaa", "cn=aaab", -1 },
+        { RDN.maxValue(), RDN.maxValue(), 0 },
+        { RDN.maxValue(), "cn=aaa", 1 },
+        { "cn=aaa", RDN.maxValue(), -1 },
+    };
+    // @formatter:on
   }
 
 
@@ -206,11 +217,11 @@
    *           If the test failed unexpectedly.
    */
   @Test(dataProvider = "createRDNEqualityData")
-  public void testCompareTo(final String first, final String second,
+  public void testCompareTo(final Object first, final Object second,
       final int result) throws Exception
   {
-    final RDN rdn1 = RDN.valueOf(first);
-    final RDN rdn2 = RDN.valueOf(second);
+    final RDN rdn1 = parseRDN(first);
+    final RDN rdn2 = parseRDN(second);
 
     int rc = rdn1.compareTo(rdn2);
 
@@ -230,6 +241,13 @@
 
 
 
+  private RDN parseRDN(final Object value)
+  {
+    return (value instanceof RDN) ? ((RDN) value) : RDN.valueOf(value.toString());
+  }
+
+
+
   /**
    * Test RDN construction with single AVA.
    *
@@ -362,11 +380,11 @@
    *           If the test failed unexpectedly.
    */
   @Test(dataProvider = "createRDNEqualityData")
-  public void testEquality(final String first, final String second,
+  public void testEquality(final Object first, final Object second,
       final int result) throws Exception
   {
-    final RDN rdn1 = RDN.valueOf(first);
-    final RDN rdn2 = RDN.valueOf(second);
+    final RDN rdn1 = parseRDN(first);
+    final RDN rdn2 = parseRDN(second);
 
     if (result == 0)
     {
@@ -448,11 +466,11 @@
    *           If the test failed unexpectedly.
    */
   @Test(dataProvider = "createRDNEqualityData")
-  public void testHashCode(final String first, final String second,
+  public void testHashCode(final Object first, final Object second,
       final int result) throws Exception
   {
-    final RDN rdn1 = RDN.valueOf(first);
-    final RDN rdn2 = RDN.valueOf(second);
+    final RDN rdn1 = parseRDN(first);
+    final RDN rdn2 = parseRDN(second);
 
     final int h1 = rdn1.hashCode();
     final int h2 = rdn2.hashCode();
diff --git a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
index 99a99c4..91fe962 100644
--- a/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
+++ b/opendj-sdk/opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
@@ -342,7 +342,7 @@
   @Test
   public void testRejectedRecordListenerMalformedFirstRecord() throws Exception
   {
-    RejectedRecordListener listener = mock(RejectedRecordListener.class);
+    RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
 
     // @formatter:off
     LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -351,7 +351,7 @@
         "objectClass: top",
         "objectClass: domainComponent",
         "dc: example"
-        ).setRejectedRecordListener(listener);
+        ).setRejectedLDIFListener(listener);
     // @formatter:on
 
     assertThat(reader.hasNext()).isFalse();
@@ -375,7 +375,7 @@
   public void testRejectedRecordListenerMalformedSecondRecord()
       throws Exception
   {
-    RejectedRecordListener listener = mock(RejectedRecordListener.class);
+    RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
 
     // @formatter:off
     LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -390,7 +390,7 @@
         "objectClass: top",
         "objectClass: domainComponent",
         "dc: example"
-        ).setRejectedRecordListener(listener);
+        ).setRejectedLDIFListener(listener);
     // @formatter:on
 
     reader.readChangeRecord(); // Skip good record.
@@ -414,7 +414,7 @@
   @Test
   public void testRejectedRecordListenerSkipsRecord() throws Exception
   {
-    RejectedRecordListener listener = mock(RejectedRecordListener.class);
+    RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
 
     // @formatter:off
     LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -423,7 +423,7 @@
         "objectClass: top",
         "objectClass: domainComponent",
         "dc: example"
-        ).setRejectedRecordListener(listener).setExcludeBranch(DN.valueOf("dc=com"));
+        ).setRejectedLDIFListener(listener).setExcludeBranch(DN.valueOf("dc=com"));
     // @formatter:on
 
     assertThat(reader.hasNext()).isFalse();
@@ -449,7 +449,7 @@
   public void testRejectedRecordListenerRejectsBadSchemaRecord()
       throws Exception
   {
-    RejectedRecordListener listener = mock(RejectedRecordListener.class);
+    RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
 
     // @formatter:off
     LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -459,7 +459,7 @@
         "objectClass: domainComponent",
         "dc: example",
         "xxx: unknown attribute"
-        ).setRejectedRecordListener(listener)
+        ).setRejectedLDIFListener(listener)
          .setSchemaValidationPolicy(
              SchemaValidationPolicy.ignoreAll()
              .checkAttributesAndObjectClasses(Policy.REJECT));
@@ -487,7 +487,7 @@
   public void testRejectedRecordListenerWarnsBadSchemaRecord()
       throws Exception
   {
-    RejectedRecordListener listener = mock(RejectedRecordListener.class);
+    RejectedLDIFListener listener = mock(RejectedLDIFListener.class);
 
     // @formatter:off
     LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
@@ -497,7 +497,7 @@
         "objectClass: domainComponent",
         "dc: example",
         "xxx: unknown attribute"
-        ).setRejectedRecordListener(listener)
+        ).setRejectedLDIFListener(listener)
          .setSchemaValidationPolicy(
              SchemaValidationPolicy.ignoreAll()
              .checkAttributesAndObjectClasses(Policy.WARN));

--
Gitblit v1.10.0