All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.unboundid.ldap.sdk.ChangeLogEntry Maven / Gradle / Ivy

Go to download

The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use Java API for communicating with LDAP directory servers and performing related tasks like reading and writing LDIF, encoding and decoding data using base64 and ASN.1 BER, and performing secure communication. This package contains the Commercial Edition of the LDAP SDK, which includes all of the general-purpose functionality contained in the Standard Edition, plus additional functionality specific to UnboundID server products.

The newest version!
/*
 * Copyright 2007-2017 UnboundID Corp.
 * All Rights Reserved.
 */
/*
 * Copyright (C) 2008-2017 UnboundID Corp.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (GPLv2 only)
 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
package com.unboundid.ldap.sdk;



import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

import com.unboundid.ldif.LDIFAddChangeRecord;
import com.unboundid.ldif.LDIFChangeRecord;
import com.unboundid.ldif.LDIFDeleteChangeRecord;
import com.unboundid.ldif.LDIFException;
import com.unboundid.ldif.LDIFModifyChangeRecord;
import com.unboundid.ldif.LDIFModifyDNChangeRecord;
import com.unboundid.ldif.LDIFReader;
import com.unboundid.ldif.TrailingSpaceBehavior;
import com.unboundid.ldap.matchingrules.BooleanMatchingRule;
import com.unboundid.ldap.matchingrules.DistinguishedNameMatchingRule;
import com.unboundid.ldap.matchingrules.IntegerMatchingRule;
import com.unboundid.ldap.matchingrules.OctetStringMatchingRule;
import com.unboundid.util.Debug;
import com.unboundid.util.NotExtensible;
import com.unboundid.util.NotMutable;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;

import static com.unboundid.ldap.sdk.LDAPMessages.*;
import static com.unboundid.util.StaticUtils.*;



/**
 * This class provides a data structure for representing a changelog entry as
 * described in draft-good-ldap-changelog.  Changelog entries provide
 * information about a change (add, delete, modify, or modify DN) operation
 * that was processed in the directory server.  Changelog entries may be
 * parsed from entries, and they may be converted to LDIF change records or
 * processed as LDAP operations.
 */
@NotExtensible()
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public class ChangeLogEntry
       extends ReadOnlyEntry
{
  /**
   * The name of the attribute that contains the change number that identifies
   * the change and the order it was processed in the server.
   */
  public static final String ATTR_CHANGE_NUMBER = "changeNumber";



  /**
   * The name of the attribute that contains the DN of the entry targeted by
   * the change.
   */
  public static final String ATTR_TARGET_DN = "targetDN";



  /**
   * The name of the attribute that contains the type of change made to the
   * target entry.
   */
  public static final String ATTR_CHANGE_TYPE = "changeType";



  /**
   * The name of the attribute used to hold a list of changes.  For an add
   * operation, this will be an LDIF representation of the attributes that make
   * up the entry.  For a modify operation, this will be an LDIF representation
   * of the changes to the target entry.
   */
  public static final String ATTR_CHANGES = "changes";



  /**
   * The name of the attribute used to hold the new RDN for a modify DN
   * operation.
   */
  public static final String ATTR_NEW_RDN = "newRDN";



  /**
   * The name of the attribute used to hold the flag indicating whether the old
   * RDN value(s) should be removed from the target entry for a modify DN
   * operation.
   */
  public static final String ATTR_DELETE_OLD_RDN = "deleteOldRDN";



  /**
   * The name of the attribute used to hold the new superior DN for a modify DN
   * operation.
   */
  public static final String ATTR_NEW_SUPERIOR = "newSuperior";



  /**
   * The name of the attribute used to hold information about attributes from a
   * deleted entry, if available.
   */
  public static final String ATTR_DELETED_ENTRY_ATTRS = "deletedEntryAttrs";



  /**
   * The serial version UID for this serializable class.
   */
  private static final long serialVersionUID = -4018129098468341663L;



  // Indicates whether to delete the old RDN value(s) in a modify DN operation.
  private final boolean deleteOldRDN;

  // The change type for this changelog entry.
  private final ChangeType changeType;

  // A list of the attributes for an add, or the deleted entry attributes for a
  // delete operation.
  private final List attributes;

  // A list of the modifications for a modify operation.
  private final List modifications;

  // The change number for the changelog entry.
  private final long changeNumber;

  // The new RDN for a modify DN operation.
  private final String newRDN;

  // The new superior DN for a modify DN operation.
  private final String newSuperior;

  // The DN of the target entry.
  private final String targetDN;



  /**
   * Creates a new changelog entry from the provided entry.
   *
   * @param  entry  The entry from which to create this changelog entry.
   *
   * @throws  LDAPException  If the provided entry cannot be parsed as a
   *                         changelog entry.
   */
  public ChangeLogEntry(final Entry entry)
         throws LDAPException
  {
    super(entry);


    final Attribute changeNumberAttr = entry.getAttribute(ATTR_CHANGE_NUMBER);
    if ((changeNumberAttr == null) || (! changeNumberAttr.hasValue()))
    {
      throw new LDAPException(ResultCode.DECODING_ERROR,
                              ERR_CHANGELOG_NO_CHANGE_NUMBER.get());
    }

    try
    {
      changeNumber = Long.parseLong(changeNumberAttr.getValue());
    }
    catch (NumberFormatException nfe)
    {
      Debug.debugException(nfe);
      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_CHANGELOG_INVALID_CHANGE_NUMBER.get(changeNumberAttr.getValue()),
           nfe);
    }


    final Attribute targetDNAttr = entry.getAttribute(ATTR_TARGET_DN);
    if ((targetDNAttr == null) || (! targetDNAttr.hasValue()))
    {
      throw new LDAPException(ResultCode.DECODING_ERROR,
                              ERR_CHANGELOG_NO_TARGET_DN.get());
    }
    targetDN = targetDNAttr.getValue();


    final Attribute changeTypeAttr = entry.getAttribute(ATTR_CHANGE_TYPE);
    if ((changeTypeAttr == null) || (! changeTypeAttr.hasValue()))
    {
      throw new LDAPException(ResultCode.DECODING_ERROR,
                              ERR_CHANGELOG_NO_CHANGE_TYPE.get());
    }
    changeType = ChangeType.forName(changeTypeAttr.getValue());
    if (changeType == null)
    {
      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_CHANGELOG_INVALID_CHANGE_TYPE.get(changeTypeAttr.getValue()));
    }


    switch (changeType)
    {
      case ADD:
        attributes    = parseAddAttributeList(entry, ATTR_CHANGES, targetDN);
        modifications = null;
        newRDN        = null;
        deleteOldRDN  = false;
        newSuperior   = null;
        break;

      case DELETE:
        attributes    = parseDeletedAttributeList(entry, targetDN);
        modifications = null;
        newRDN        = null;
        deleteOldRDN  = false;
        newSuperior   = null;
        break;

      case MODIFY:
        attributes    = null;
        modifications = parseModificationList(entry, targetDN);
        newRDN        = null;
        deleteOldRDN  = false;
        newSuperior   = null;
        break;

      case MODIFY_DN:
        attributes    = null;
        modifications = parseModificationList(entry, targetDN);
        newSuperior   = getAttributeValue(ATTR_NEW_SUPERIOR);

        final Attribute newRDNAttr = getAttribute(ATTR_NEW_RDN);
        if ((newRDNAttr == null) || (! newRDNAttr.hasValue()))
        {
          throw new LDAPException(ResultCode.DECODING_ERROR,
                                  ERR_CHANGELOG_MISSING_NEW_RDN.get());
        }
        newRDN = newRDNAttr.getValue();

        final Attribute deleteOldRDNAttr = getAttribute(ATTR_DELETE_OLD_RDN);
        if ((deleteOldRDNAttr == null) || (! deleteOldRDNAttr.hasValue()))
        {
          throw new LDAPException(ResultCode.DECODING_ERROR,
                                  ERR_CHANGELOG_MISSING_DELETE_OLD_RDN.get());
        }
        final String delOldRDNStr = toLowerCase(deleteOldRDNAttr.getValue());
        if (delOldRDNStr.equals("true"))
        {
          deleteOldRDN = true;
        }
        else if (delOldRDNStr.equals("false"))
        {
          deleteOldRDN = false;
        }
        else
        {
          throw new LDAPException(ResultCode.DECODING_ERROR,
               ERR_CHANGELOG_MISSING_DELETE_OLD_RDN.get(delOldRDNStr));
        }
        break;

      default:
        // This should never happen.
        throw new LDAPException(ResultCode.DECODING_ERROR,
             ERR_CHANGELOG_INVALID_CHANGE_TYPE.get(changeTypeAttr.getValue()));
    }
  }



  /**
   * Constructs a changelog entry from information contained in the provided
   * LDIF change record.
   *
   * @param  changeNumber  The change number to use for the constructed
   *                       changelog entry.
   * @param  changeRecord  The LDIF change record with the information to
   *                       include in the generated changelog entry.
   *
   * @return  The changelog entry constructed from the provided change record.
   *
   * @throws  LDAPException  If a problem is encountered while constructing the
   *                         changelog entry.
   */
  public static ChangeLogEntry constructChangeLogEntry(final long changeNumber,
                                    final LDIFChangeRecord changeRecord)
         throws LDAPException
  {
    final Entry e =
         new Entry(ATTR_CHANGE_NUMBER + '=' + changeNumber + ",cn=changelog");
    e.addAttribute("objectClass", "top", "changeLogEntry");
    e.addAttribute(new Attribute(ATTR_CHANGE_NUMBER,
         IntegerMatchingRule.getInstance(), String.valueOf(changeNumber)));
    e.addAttribute(new Attribute(ATTR_TARGET_DN,
         DistinguishedNameMatchingRule.getInstance(), changeRecord.getDN()));
    e.addAttribute(ATTR_CHANGE_TYPE, changeRecord.getChangeType().getName());

    switch (changeRecord.getChangeType())
    {
      case ADD:
        // The changes attribute should be an LDIF-encoded representation of the
        // attributes from the entry, which is the LDIF representation of the
        // entry without the first line (which contains the DN).
        final LDIFAddChangeRecord addRecord =
             (LDIFAddChangeRecord) changeRecord;
        final Entry addEntry = new Entry(addRecord.getDN(),
             addRecord.getAttributes());
        final String[] entryLdifLines = addEntry.toLDIF(0);
        final StringBuilder entryLDIFBuffer = new StringBuilder();
        for (int i=1; i < entryLdifLines.length; i++)
        {
          entryLDIFBuffer.append(entryLdifLines[i]);
          entryLDIFBuffer.append(EOL);
        }
        e.addAttribute(new Attribute(ATTR_CHANGES,
             OctetStringMatchingRule.getInstance(),
             entryLDIFBuffer.toString()));
        break;

      case DELETE:
        // No additional information is needed.
        break;

      case MODIFY:
        // The changes attribute should be an LDIF-encoded representation of the
        // modification, with the first two lines (the DN and changetype)
        // removed.
        final String[] modLdifLines = changeRecord.toLDIF(0);
        final StringBuilder modLDIFBuffer = new StringBuilder();
        for (int i=2; i < modLdifLines.length; i++)
        {
          modLDIFBuffer.append(modLdifLines[i]);
          modLDIFBuffer.append(EOL);
        }
        e.addAttribute(new Attribute(ATTR_CHANGES,
             OctetStringMatchingRule.getInstance(), modLDIFBuffer.toString()));
        break;

      case MODIFY_DN:
        final LDIFModifyDNChangeRecord modDNRecord =
             (LDIFModifyDNChangeRecord) changeRecord;
        e.addAttribute(new Attribute(ATTR_NEW_RDN,
             DistinguishedNameMatchingRule.getInstance(),
             modDNRecord.getNewRDN()));
        e.addAttribute(new Attribute(ATTR_DELETE_OLD_RDN,
             BooleanMatchingRule.getInstance(),
             (modDNRecord.deleteOldRDN() ? "TRUE" : "FALSE")));
        if (modDNRecord.getNewSuperiorDN() != null)
        {
          e.addAttribute(new Attribute(ATTR_NEW_SUPERIOR,
               DistinguishedNameMatchingRule.getInstance(),
               modDNRecord.getNewSuperiorDN()));
        }
        break;
    }

    return new ChangeLogEntry(e);
  }



  /**
   * Parses the attribute list from the specified attribute in a changelog
   * entry.
   *
   * @param  entry     The entry containing the data to parse.
   * @param  attrName  The name of the attribute from which to parse the
   *                   attribute list.
   * @param  targetDN  The DN of the target entry.
   *
   * @return  The parsed attribute list.
   *
   * @throws  LDAPException  If an error occurs while parsing the attribute
   *                         list.
   */
  protected static List parseAddAttributeList(final Entry entry,
                                                         final String attrName,
                                                         final String targetDN)
            throws LDAPException
  {
    final Attribute changesAttr = entry.getAttribute(attrName);
    if ((changesAttr == null) || (! changesAttr.hasValue()))
    {
      throw new LDAPException(ResultCode.DECODING_ERROR,
                              ERR_CHANGELOG_MISSING_CHANGES.get());
    }

    final ArrayList ldifLines = new ArrayList();
    ldifLines.add("dn: " + targetDN);

    final StringTokenizer tokenizer =
         new StringTokenizer(changesAttr.getValue(), "\r\n");
    while (tokenizer.hasMoreTokens())
    {
      ldifLines.add(tokenizer.nextToken());
    }

    final String[] lineArray = new String[ldifLines.size()];
    ldifLines.toArray(lineArray);

    try
    {
      final Entry e = LDIFReader.decodeEntry(true, TrailingSpaceBehavior.RETAIN,
           null, lineArray);
      return Collections.unmodifiableList(
                  new ArrayList(e.getAttributes()));
    }
    catch (LDIFException le)
    {
      Debug.debugException(le);
      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_CHANGELOG_CANNOT_PARSE_ATTR_LIST.get(attrName,
                getExceptionMessage(le)),
           le);
    }
  }



  /**
   * Parses the list of deleted attributes from a changelog entry representing a
   * delete operation.  The attribute is optional, so it may not be present at
   * all, and there are two different encodings that we need to handle.  One
   * encoding is the same as is used for the add attribute list, and the second
   * is similar to the encoding used for the list of changes, except that it
   * ends with a NULL byte (0x00).
   *
   * @param  entry     The entry containing the data to parse.
   * @param  targetDN  The DN of the target entry.
   *
   * @return  The parsed deleted attribute list, or {@code null} if the
   *          changelog entry does not include a deleted attribute list.
   *
   * @throws  LDAPException  If an error occurs while parsing the deleted
   *                         attribute list.
   */
  private static List parseDeletedAttributeList(final Entry entry,
                                      final String targetDN)
          throws LDAPException
  {
    final Attribute deletedEntryAttrs =
         entry.getAttribute(ATTR_DELETED_ENTRY_ATTRS);
    if ((deletedEntryAttrs == null) || (! deletedEntryAttrs.hasValue()))
    {
      return null;
    }

    final byte[] valueBytes = deletedEntryAttrs.getValueByteArray();
    if ((valueBytes.length > 0) && (valueBytes[valueBytes.length-1] == 0x00))
    {
      final String valueStr = new String(valueBytes, 0, valueBytes.length-2);

      final ArrayList ldifLines = new ArrayList();
      ldifLines.add("dn: " + targetDN);
      ldifLines.add("changetype: modify");

      final StringTokenizer tokenizer = new StringTokenizer(valueStr, "\r\n");
      while (tokenizer.hasMoreTokens())
      {
        ldifLines.add(tokenizer.nextToken());
      }

      final String[] lineArray = new String[ldifLines.size()];
      ldifLines.toArray(lineArray);

      try
      {

        final LDIFModifyChangeRecord changeRecord =
             (LDIFModifyChangeRecord) LDIFReader.decodeChangeRecord(lineArray);
        final Modification[] mods = changeRecord.getModifications();
        final ArrayList attrs =
             new ArrayList(mods.length);
        for (final Modification m : mods)
        {
          if (! m.getModificationType().equals(ModificationType.DELETE))
          {
            throw new LDAPException(ResultCode.DECODING_ERROR,
                 ERR_CHANGELOG_INVALID_DELENTRYATTRS_MOD_TYPE.get(
                      ATTR_DELETED_ENTRY_ATTRS));
          }

          attrs.add(m.getAttribute());
        }

        return Collections.unmodifiableList(attrs);
      }
      catch (LDIFException le)
      {
        Debug.debugException(le);
        throw new LDAPException(ResultCode.DECODING_ERROR,
             ERR_CHANGELOG_INVALID_DELENTRYATTRS_MODS.get(
                  ATTR_DELETED_ENTRY_ATTRS, getExceptionMessage(le)), le);
      }
    }
    else
    {
      final ArrayList ldifLines = new ArrayList();
      ldifLines.add("dn: " + targetDN);

      final StringTokenizer tokenizer =
           new StringTokenizer(deletedEntryAttrs.getValue(), "\r\n");
      while (tokenizer.hasMoreTokens())
      {
        ldifLines.add(tokenizer.nextToken());
      }

      final String[] lineArray = new String[ldifLines.size()];
      ldifLines.toArray(lineArray);

      try
      {
        final Entry e = LDIFReader.decodeEntry(true,
             TrailingSpaceBehavior.RETAIN, null, lineArray);
        return Collections.unmodifiableList(
                    new ArrayList(e.getAttributes()));
      }
      catch (LDIFException le)
      {
        Debug.debugException(le);
        throw new LDAPException(ResultCode.DECODING_ERROR,
             ERR_CHANGELOG_CANNOT_PARSE_DELENTRYATTRS.get(
                  ATTR_DELETED_ENTRY_ATTRS, getExceptionMessage(le)), le);
      }
    }
  }



  /**
   * Parses the modification list from a changelog entry representing a modify
   * operation.
   *
   * @param  entry     The entry containing the data to parse.
   * @param  targetDN  The DN of the target entry.
   *
   * @return  The parsed modification list, or {@code null} if the changelog
   *          entry does not include any modifications.
   *
   * @throws  LDAPException  If an error occurs while parsing the modification
   *                         list.
   */
  private static List parseModificationList(final Entry entry,
                                                          final String targetDN)
          throws LDAPException
  {
    final Attribute changesAttr = entry.getAttribute(ATTR_CHANGES);
    if ((changesAttr == null) || (! changesAttr.hasValue()))
    {
      return null;
    }

    final byte[] valueBytes = changesAttr.getValueByteArray();
    if (valueBytes.length == 0)
    {
      return null;
    }


    final ArrayList ldifLines = new ArrayList();
    ldifLines.add("dn: " + targetDN);
    ldifLines.add("changetype: modify");

    // Even though it's a violation of the specification in
    // draft-good-ldap-changelog, it appears that some servers (e.g., Sun DSEE)
    // may terminate the changes value with a null character (\u0000).  If that
    // is the case, then we'll need to strip it off before trying to parse it.
    final StringTokenizer tokenizer;
    if ((valueBytes.length > 0) && (valueBytes[valueBytes.length-1] == 0x00))
    {
      final String fullValue = changesAttr.getValue();
      final String realValue = fullValue.substring(0, fullValue.length()-2);
      tokenizer = new StringTokenizer(realValue, "\r\n");
    }
    else
    {
      tokenizer = new StringTokenizer(changesAttr.getValue(), "\r\n");
    }

    while (tokenizer.hasMoreTokens())
    {
      ldifLines.add(tokenizer.nextToken());
    }

    final String[] lineArray = new String[ldifLines.size()];
    ldifLines.toArray(lineArray);

    try
    {
      final LDIFModifyChangeRecord changeRecord =
           (LDIFModifyChangeRecord) LDIFReader.decodeChangeRecord(lineArray);
      return Collections.unmodifiableList(
                  Arrays.asList(changeRecord.getModifications()));
    }
    catch (LDIFException le)
    {
      Debug.debugException(le);
      throw new LDAPException(ResultCode.DECODING_ERROR,
           ERR_CHANGELOG_CANNOT_PARSE_MOD_LIST.get(ATTR_CHANGES,
                getExceptionMessage(le)),
           le);
    }
  }



  /**
   * Retrieves the change number for this changelog entry.
   *
   * @return  The change number for this changelog entry.
   */
  public final long getChangeNumber()
  {
    return changeNumber;
  }



  /**
   * Retrieves the target DN for this changelog entry.
   *
   * @return  The target DN for this changelog entry.
   */
  public final String getTargetDN()
  {
    return targetDN;
  }



  /**
   * Retrieves the change type for this changelog entry.
   *
   * @return  The change type for this changelog entry.
   */
  public final ChangeType getChangeType()
  {
    return changeType;
  }



  /**
   * Retrieves the attribute list for an add changelog entry.
   *
   * @return  The attribute list for an add changelog entry, or {@code null} if
   *          this changelog entry does not represent an add operation.
   */
  public final List getAddAttributes()
  {
    if (changeType == ChangeType.ADD)
    {
      return attributes;
    }
    else
    {
      return null;
    }
  }



  /**
   * Retrieves the list of deleted entry attributes for a delete changelog
   * entry.  Note that this is a non-standard extension implemented by some
   * types of servers and is not defined in draft-good-ldap-changelog and may
   * not be provided by some servers.
   *
   * @return  The delete entry attribute list for a delete changelog entry, or
   *          {@code null} if this changelog entry does not represent a delete
   *          operation or no deleted entry attributes were included in the
   *          changelog entry.
   */
  public final List getDeletedEntryAttributes()
  {
    if (changeType == ChangeType.DELETE)
    {
      return attributes;
    }
    else
    {
      return null;
    }
  }



  /**
   * Retrieves the list of modifications for a modify changelog entry.  Note
   * some directory servers may also include changes for modify DN change
   * records if there were updates to operational attributes (e.g.,
   * modifiersName and modifyTimestamp).
   *
   * @return  The list of modifications for a modify (or possibly modify DN)
   *          changelog entry, or {@code null} if this changelog entry does
   *          not represent a modify operation or a modify DN operation with
   *          additional changes.
   */
  public final List getModifications()
  {
    return modifications;
  }



  /**
   * Retrieves the new RDN for a modify DN changelog entry.
   *
   * @return  The new RDN for a modify DN changelog entry, or {@code null} if
   *          this changelog entry does not represent a modify DN operation.
   */
  public final String getNewRDN()
  {
    return newRDN;
  }



  /**
   * Indicates whether the old RDN value(s) should be removed from the entry
   * targeted by this modify DN changelog entry.
   *
   * @return  {@code true} if the old RDN value(s) should be removed from the
   *          entry, or {@code false} if not or if this changelog entry does not
   *          represent a modify DN operation.
   */
  public final boolean deleteOldRDN()
  {
    return deleteOldRDN;
  }



  /**
   * Retrieves the new superior DN for a modify DN changelog entry.
   *
   * @return  The new superior DN for a modify DN changelog entry, or
   *          {@code null} if there is no new superior DN, or if this changelog
   *          entry does not represent a modify DN operation.
   */
  public final String getNewSuperior()
  {
    return newSuperior;
  }



  /**
   * Retrieves the DN of the entry after the change has been processed.  For an
   * add or modify operation, the new DN will be the same as the target DN.  For
   * a modify DN operation, the new DN will be constructed from the original DN,
   * the new RDN, and the new superior DN.  For a delete operation, it will be
   * {@code null} because the entry will no longer exist.
   *
   * @return  The DN of the entry after the change has been processed, or
   *          {@code null} if the entry no longer exists.
   */
  public final String getNewDN()
  {
    switch (changeType)
    {
      case ADD:
      case MODIFY:
        return targetDN;

      case MODIFY_DN:
        // This will be handled below.
        break;

      case DELETE:
      default:
        return null;
    }

    try
    {
      final RDN parsedNewRDN = new RDN(newRDN);

      if (newSuperior == null)
      {
        final DN parsedTargetDN = new DN(targetDN);
        final DN parentDN = parsedTargetDN.getParent();
        if (parentDN == null)
        {
          return new DN(parsedNewRDN).toString();
        }
        else
        {
          return new DN(parsedNewRDN, parentDN).toString();
        }
      }
      else
      {
        final DN parsedNewSuperior = new DN(newSuperior);
        return new DN(parsedNewRDN, parsedNewSuperior).toString();
      }
    }
    catch (final Exception e)
    {
      // This should never happen.
      Debug.debugException(e);
      return null;
    }
  }



  /**
   * Retrieves an LDIF change record that is analogous to the operation
   * represented by this changelog entry.
   *
   * @return  An LDIF change record that is analogous to the operation
   *          represented by this changelog entry.
   */
  public final LDIFChangeRecord toLDIFChangeRecord()
  {
    switch (changeType)
    {
      case ADD:
        return new LDIFAddChangeRecord(targetDN, attributes);

      case DELETE:
        return new LDIFDeleteChangeRecord(targetDN);

      case MODIFY:
        return new LDIFModifyChangeRecord(targetDN, modifications);

      case MODIFY_DN:
        return new LDIFModifyDNChangeRecord(targetDN, newRDN, deleteOldRDN,
                                            newSuperior);

      default:
        // This should never happen.
        return null;
    }
  }



  /**
   * Processes the operation represented by this changelog entry using the
   * provided LDAP connection.
   *
   * @param  connection  The connection (or connection pool) to use to process
   *                     the operation.
   *
   * @return  The result of processing the operation.
   *
   * @throws  LDAPException  If the operation could not be processed
   *                         successfully.
   */
  public final LDAPResult processChange(final LDAPInterface connection)
         throws LDAPException
  {
    switch (changeType)
    {
      case ADD:
        return connection.add(targetDN, attributes);

      case DELETE:
        return connection.delete(targetDN);

      case MODIFY:
        return connection.modify(targetDN, modifications);

      case MODIFY_DN:
        return connection.modifyDN(targetDN, newRDN, deleteOldRDN, newSuperior);

      default:
        // This should never happen.
        return null;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy