/**
   * Attempt to read a change containing a file-based attribute.
   *
   * @throws Exception If the test failed unexpectedly.
   */
  @Test(dependsOnMethods = {"testReadChangeMultiple"})
  public void testReadChangeWithFileBaseAttribute() throws Exception {
    StringBuilder buffer = new StringBuilder(TEMP_FILE_LDIF);
    buffer.append(TEMP_FILE.getCanonicalPath());
    buffer.append("\n");
    LDIFReader reader = createLDIFReader(buffer.toString());

    try {
      ChangeRecordEntry change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof AddChangeRecordEntry);
      AddChangeRecordEntry add = (AddChangeRecordEntry) change;

      DN dn = DN.decode("cn=john smith, dc=com");
      Assert.assertEquals(add.getDN(), dn);

      Attribute attr = Attributes.create("description", TEMP_FILE_STRING);
      Assert.assertTrue(add.getAttributes().contains(attr));

      // Check final state.
      Assert.assertNull(reader.readChangeRecord(false));
    } finally {
      reader.close();
    }
  }
  /**
   * Attempt to read multiple changes.
   *
   * @throws Exception If the test failed unexpectedly.
   */
  @Test(dependsOnMethods = {"testChangeRecordEmptyStream"})
  public void testReadChangeMultiple() throws Exception {
    LDIFReader reader = createLDIFReader(VALID_LDIF);

    try {
      ChangeRecordEntry change;
      AddChangeRecordEntry add;
      DeleteChangeRecordEntry delete;
      ModifyChangeRecordEntry modify;
      ModifyDNChangeRecordEntry modifyDN;
      DN dn;
      RDN rdn;
      Iterator<RawModification> i;
      Modification mod;
      Attribute attr;

      // Change record #1.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof AddChangeRecordEntry);
      add = (AddChangeRecordEntry) change;

      dn = DN.decode("cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com");
      Assert.assertEquals(add.getDN(), dn);

      List<Attribute> attrs = new ArrayList<Attribute>();
      AttributeBuilder builder = new AttributeBuilder(AT_OC, "objectclass");
      builder.add(AttributeValues.create(AT_OC, "top"));
      builder.add(AttributeValues.create(AT_OC, "person"));
      builder.add(AttributeValues.create(AT_OC, "organizationalPerson"));

      attrs.add(builder.toAttribute());
      attrs.add(Attributes.create("cn", "Fiona Jensen"));
      attrs.add(Attributes.create("sn", "Jensen"));
      attrs.add(Attributes.create("uid", "fiona"));
      attrs.add(Attributes.create("telephonenumber", "+1 408 555 1212"));
      Assert.assertTrue(add.getAttributes().containsAll(attrs));

      // Change record #2.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof DeleteChangeRecordEntry);
      delete = (DeleteChangeRecordEntry) change;

      dn = DN.decode("cn=Robert Jensen, ou=Marketing, dc=airius, dc=com");
      Assert.assertEquals(delete.getDN(), dn);

      // Change record #3.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyDNChangeRecordEntry);
      modifyDN = (ModifyDNChangeRecordEntry) change;

      dn = DN.decode("cn=Paul Jensen, ou=Product Development, dc=airius, dc=com");
      Assert.assertEquals(modifyDN.getDN(), dn);

      rdn = RDN.decode("cn=paula jensen");
      Assert.assertEquals(modifyDN.getNewRDN(), rdn);
      Assert.assertNull(modifyDN.getNewSuperiorDN());
      Assert.assertTrue(modifyDN.deleteOldRDN());

      // Change record #4.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyDNChangeRecordEntry);
      modifyDN = (ModifyDNChangeRecordEntry) change;

      dn = DN.decode("ou=PD Accountants, ou=Product Development, dc=airius, dc=com");
      Assert.assertEquals(modifyDN.getDN(), dn);

      rdn = RDN.decode("ou=Product Development Accountants");
      Assert.assertEquals(modifyDN.getNewRDN(), rdn);
      dn = DN.decode("ou=Accounting, dc=airius, dc=com");
      Assert.assertEquals(modifyDN.getNewSuperiorDN(), dn);
      Assert.assertFalse(modifyDN.deleteOldRDN());

      // Change record #5.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyChangeRecordEntry);
      modify = (ModifyChangeRecordEntry) change;

      dn = DN.decode("cn=Paula Jensen, ou=Product Development, dc=airius, dc=com");
      Assert.assertEquals(modify.getDN(), dn);

      i = modify.getModifications().iterator();

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.ADD);
      attr = Attributes.create("postaladdress", "123 Anystreet $ Sunnyvale, CA $ 94086");
      Assert.assertEquals(mod.getAttribute(), attr);

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE);
      attr = Attributes.empty(AT_DESCR);
      Assert.assertEquals(mod.getAttribute(), attr);

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.REPLACE);
      builder = new AttributeBuilder(AT_TELN, "telephonenumber");
      builder.add(AttributeValues.create(AT_TELN, "+1 408 555 1234"));
      builder.add(AttributeValues.create(AT_TELN, "+1 408 555 5678"));
      Assert.assertEquals(mod.getAttribute(), builder.toAttribute());

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE);
      attr = Attributes.create("facsimiletelephonenumber", "+1 408 555 9876");
      Assert.assertEquals(mod.getAttribute(), attr);

      Assert.assertFalse(i.hasNext());

      // Change record #6.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyChangeRecordEntry);
      modify = (ModifyChangeRecordEntry) change;

      dn = DN.decode("cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com");
      Assert.assertEquals(modify.getDN(), dn);

      i = modify.getModifications().iterator();

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.REPLACE);
      attr = Attributes.empty(DirectoryServer.getAttributeType("postaladdress"));
      Assert.assertEquals(mod.getAttribute(), attr);

      // Change record #7.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyChangeRecordEntry);
      modify = (ModifyChangeRecordEntry) change;

      Assert.assertTrue(modify.getDN().isNullDN());

      i = modify.getModifications().iterator();

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE);
      attr = Attributes.empty(AT_DESCR);
      Assert.assertEquals(mod.getAttribute(), attr);

      // Change record #8.
      change = reader.readChangeRecord(false);
      Assert.assertTrue(change instanceof ModifyChangeRecordEntry);
      modify = (ModifyChangeRecordEntry) change;

      dn = DN.decode("uid=rogasawara, ou=\u55b6\u696d\u90e8, o=airius");
      Assert.assertEquals(modify.getDN(), dn);

      i = modify.getModifications().iterator();

      Assert.assertTrue(i.hasNext());
      mod = i.next().toModification();
      Assert.assertEquals(mod.getModificationType(), ModificationType.DELETE);
      attr = Attributes.empty(AT_DESCR);
      Assert.assertEquals(mod.getAttribute(), attr);

      Assert.assertFalse(i.hasNext());

      // Check final state.

      Assert.assertNull(reader.readChangeRecord(false));

      Assert.assertEquals(reader.getEntriesIgnored(), 0);
      Assert.assertEquals(reader.getEntriesRead(), 0);
      Assert.assertEquals(reader.getEntriesRejected(), 0);
      Assert.assertEquals(reader.getLastEntryLineNumber(), 72);
    } finally {
      reader.close();
    }
  }