blob: bb677213e6aa4d41213c736b1e6f2d189de99e28 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.api.ldap.model.ldif;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.model.entry.Attribute;
import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.DefaultModification;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.StringValue;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.message.Control;
import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.api.ldap.model.name.Rdn;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.util.Base64;
import org.apache.directory.api.util.Strings;
/**
* A entry to be populated by an ldif parser.
*
* We will have different kind of entries :
* <ul>
* <li>added entries</li>
* <li>deleted entries</li>
* <li>modified entries</li>
* <li>Rdn modified entries</li>
* <li>Dn modified entries</li>
* </ul>
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class LdifEntry implements Cloneable, Externalizable
{
/** Used in toArray() */
public static final Modification[] EMPTY_MODS = new Modification[0];
/** the change type */
private ChangeType changeType;
/** the modification item list */
private List<Modification> modificationList;
/** The map containing all the modifications */
private Map<String, Modification> modifications;
/** The new superior */
private String newSuperior;
/** The new rdn */
private String newRdn;
/** The delete old rdn flag */
private boolean deleteOldRdn;
/** the entry */
private Entry entry;
/** the DN */
private Dn entryDn;
/** The controls */
private Map<String, LdifControl> controls;
/** The lengthBeforeParsing of the entry at the time of parsing. This includes
* the lengthBeforeParsing of the comments present in entry at the time of parsing
* so this lengthBeforeParsing may not always match with the lengthBeforeParsing of the entry
* data present in memory.
*/
private int lengthBeforeParsing = 0;
/** the position of the entry in the file or given input string*/
private long offset = 0;
/**
* Creates a new LdifEntry object.
*/
public LdifEntry()
{
// Default LDIF content
changeType = ChangeType.None;
modificationList = new LinkedList<Modification>();
modifications = new HashMap<String, Modification>();
entry = new DefaultEntry( ( Dn ) null );
entryDn = null;
controls = null;
}
/**
* Creates a new schema aware LdifEntry object.
*/
public LdifEntry( SchemaManager schemaManager )
{
// Default LDIF content
changeType = ChangeType.None;
modificationList = new LinkedList<Modification>();
modifications = new HashMap<String, Modification>();
entry = new DefaultEntry( schemaManager, ( Dn ) null );
entryDn = null;
controls = null;
}
/**
* Creates a new LdifEntry object, storing an Entry
*/
public LdifEntry( Entry entry )
{
// Default LDIF content
changeType = ChangeType.None;
modificationList = new LinkedList<Modification>();
modifications = new HashMap<String, Modification>();
this.entry = entry;
entryDn = entry.getDn();
controls = null;
}
/**
* Creates a LdifEntry using a list of strings representing the Ldif element
*
* @param dn The LdifEntry DN
* @param avas The Ldif to convert to an LdifEntry
* @throws LdapInvalidAttributeValueException If either the AttributeType or the associated value
* is incorrect
* @throws LdapLdifException If we get any other exception
*/
public LdifEntry( Dn dn, Object... avas ) throws LdapInvalidAttributeValueException, LdapLdifException
{
// First, convert the arguments to a full LDIF
StringBuilder sb = new StringBuilder();
int pos = 0;
boolean valueExpected = false;
String dnStr = null;
if ( dn == null )
{
dnStr = "";
}
else
{
dnStr = dn.getName();
}
if ( LdifUtils.isLDIFSafe( dnStr ) )
{
sb.append( "dn: " ).append( dnStr ).append( '\n' );
}
else
{
sb.append( "dn:: " ).append( Base64.encode( Strings.getBytesUtf8( dnStr ) ) ).append( '\n' );
}
for ( Object ava : avas )
{
if ( !valueExpected )
{
if ( !( ava instanceof String ) )
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
I18n.ERR_12085, ( pos + 1 ) ) );
}
String attribute = ( String ) ava;
sb.append( attribute );
if ( attribute.indexOf( ':' ) != -1 )
{
sb.append( '\n' );
}
else
{
valueExpected = true;
}
}
else
{
if ( ava instanceof String )
{
sb.append( ": " ).append( ( String ) ava ).append( '\n' );
}
else if ( ava instanceof byte[] )
{
sb.append( ":: " );
sb.append( new String( Base64.encode( ( byte[] ) ava ) ) );
sb.append( '\n' );
}
else
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
I18n.ERR_12086, ( pos + 1 ) ) );
}
valueExpected = false;
}
}
if ( valueExpected )
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n
.err( I18n.ERR_12087 ) );
}
// Now, parse the Ldif and convert it to a LdifEntry
LdifReader reader = new LdifReader();
List<LdifEntry> ldifEntries = reader.parseLdif( sb.toString() );
try
{
reader.close();
}
catch ( IOException e )
{
e.printStackTrace();
}
if ( ( ldifEntries != null ) && ( ldifEntries.size() == 1 ) )
{
LdifEntry ldifEntry = ldifEntries.get( 0 );
changeType = ldifEntry.getChangeType();
controls = ldifEntry.getControls();
entryDn = ldifEntry.getDn();
switch ( ldifEntry.getChangeType() )
{
case Add:
// Fallback
case None:
entry = ldifEntry.getEntry();
break;
case Delete:
break;
case ModDn:
case ModRdn:
newRdn = ldifEntry.getNewRdn();
newSuperior = ldifEntry.getNewSuperior();
deleteOldRdn = ldifEntry.isDeleteOldRdn();
break;
case Modify:
modificationList = ldifEntry.getModifications();
modifications = new HashMap<String, Modification>();
for ( Modification modification : modificationList )
{
modifications.put( modification.getAttribute().getId(), modification );
}
break;
default:
throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
}
}
}
/**
* Creates a LdifEntry using a list of strings representing the Ldif element
*
* @param dn The LdifEntry DN
* @param avas The Ldif attributes and values to convert to an LdifEntry
* @throws LdapInvalidDnException If the Dn is invalid
* @throws LdapInvalidAttributeValueException If either the AttributeType or the associated value
* is incorrect
* @throws LdapLdifException If we get any other exception
*/
public LdifEntry( String dn, Object... strings )
throws LdapInvalidAttributeValueException, LdapLdifException, LdapInvalidDnException
{
this( new Dn( dn ), strings );
}
/**
* Set the Distinguished Name
*
* @param dn The Distinguished Name
*/
public void setDn( Dn dn )
{
entryDn = dn;
entry.setDn( dn );
}
/**
* Set the Distinguished Name
*
* @param dn The Distinguished Name
* @throws LdapInvalidDnException If the Dn is invalid
*/
public void setDn( String dn ) throws LdapInvalidDnException
{
entryDn = new Dn( dn );
entry.setDn( entryDn );
}
/**
* Set the modification type
*
* @param changeType The change type
*
*/
public void setChangeType( ChangeType changeType )
{
this.changeType = changeType;
}
/**
* Set the change type
*
* @param changeType The change type
*/
public void setChangeType( String changeType )
{
if ( "add".equals( changeType ) )
{
this.changeType = ChangeType.Add;
}
else if ( "modify".equals( changeType ) )
{
this.changeType = ChangeType.Modify;
}
else if ( "moddn".equals( changeType ) )
{
this.changeType = ChangeType.ModDn;
}
else if ( "modrdn".equals( changeType ) )
{
this.changeType = ChangeType.ModRdn;
}
else if ( "delete".equals( changeType ) )
{
this.changeType = ChangeType.Delete;
}
}
/**
* Add a modification item (used by modify operations)
*
* @param modification The modification to be added
*/
public void addModification( Modification modification )
{
if ( changeType == ChangeType.Modify )
{
modificationList.add( modification );
modifications.put( modification.getAttribute().getId(), modification );
}
}
/**
* Add a modification item (used by modify operations)
*
* @param modOp The operation. One of :
* <ul>
* <li>ModificationOperation.ADD_ATTRIBUTE</li>
* <li>ModificationOperation.REMOVE_ATTRIBUTE</li>
* <li>ModificationOperation.REPLACE_ATTRIBUTE</li>
* </ul>
*
* @param attr The attribute to be added
*/
public void addModification( ModificationOperation modOp, Attribute attr )
{
if ( changeType == ChangeType.Modify )
{
Modification item = new DefaultModification( modOp, attr );
modificationList.add( item );
modifications.put( attr.getId(), item );
}
}
/**
* Add a modification with no value
*
* @param modOp The modification operation value. One of :
* <ul>
* <li>ModificationOperation.ADD_ATTRIBUTE</li>
* <li>ModificationOperation.REMOVE_ATTRIBUTE</li>
* <li>ModificationOperation.REPLACE_ATTRIBUTE</li>
* </ul>
*
* @param id The attribute's ID
*/
public void addModification( ModificationOperation modOp, String id )
{
if ( changeType == ChangeType.Modify )
{
Attribute attr = new DefaultAttribute( id );
Modification item = new DefaultModification( modOp, attr );
modificationList.add( item );
modifications.put( id, item );
}
}
/**
* Add a modification
*
* @param modOp The modification operation value. One of :
* <ul>
* <li>ModificationOperation.ADD_ATTRIBUTE</li>
* <li>ModificationOperation.REMOVE_ATTRIBUTE</li>
* <li>ModificationOperation.REPLACE_ATTRIBUTE</li>
* </ul>
*
* @param id The attribute's ID
* @param value The attribute's value
*/
public void addModification( ModificationOperation modOp, String id, Object value )
{
if ( changeType == ChangeType.Modify )
{
Attribute attr;
if ( value == null )
{
value = new StringValue( ( String ) null );
attr = new DefaultAttribute( id, ( Value<?> ) value );
}
else
{
attr = ( Attribute ) value;
}
Modification item = new DefaultModification( modOp, attr );
modificationList.add( item );
modifications.put( id, item );
}
}
/**
* Add an attribute to the entry
*
* @param attr The attribute to be added
* @throws org.apache.directory.api.ldap.model.exception.LdapException if something went wrong
*/
public void addAttribute( Attribute attr ) throws LdapException
{
entry.put( attr );
}
/**
* Add an attribute to the entry
*
* @param id The attribute ID
*
* @param values The attribute values
* @throws LdapException if something went wrong
*/
public void addAttribute( String id, Object... values ) throws LdapException
{
Attribute attribute = entry.get( id );
Boolean isHR = null;
if ( attribute != null )
{
isHR = attribute.isHumanReadable();
}
if ( values != null )
{
for ( Object value : values )
{
if ( value instanceof String )
{
if ( isHR != null )
{
if ( isHR )
{
entry.add( id, ( String ) value );
}
else
{
entry.add( id, Strings.getBytesUtf8( ( String ) value ) );
}
}
else
{
entry.add( id, ( String ) value );
}
}
else
{
if ( isHR != null )
{
if ( isHR )
{
entry.add( id, Strings.utf8ToString( ( byte[] ) value ) );
}
else
{
entry.add( id, ( byte[] ) value );
}
}
else
{
entry.add( id, ( byte[] ) value );
}
}
}
}
else
{
entry.add( id, ( Value<?> ) null );
}
}
/**
* Remove a list of Attributes from the LdifEntry
*
* @param ids The Attributes to remove
* @return The list of removed EntryAttributes
*/
public void removeAttribute( String... ids )
{
if ( entry.containsAttribute( ids ) )
{
entry.removeAttributes( ids );
}
}
/**
* Add an attribute value to an existing attribute
*
* @param id The attribute ID
*
* @param value The attribute value
* @throws org.apache.directory.api.ldap.model.exception.LdapException if something went wrong
*/
public void putAttribute( String id, Object value ) throws LdapException
{
if ( value instanceof String )
{
entry.add( id, ( String ) value );
}
else
{
entry.add( id, ( byte[] ) value );
}
}
/**
* Get the change type
*
* @return The change type. One of :
* <ul>
* <li>ADD</li>
* <li>MODIFY</li>
* <li>MODDN</li>
* <li>MODRDN</li>
* <li>DELETE</li>
* <li>NONE</li>
* </ul>
*/
public ChangeType getChangeType()
{
return changeType;
}
/**
* @return The list of modification items
*/
public List<Modification> getModifications()
{
return modificationList;
}
/**
* Gets the modification items as an array.
*
* @return modification items as an array.
*/
public Modification[] getModificationArray()
{
return modificationList.toArray( EMPTY_MODS );
}
/**
* @return The entry Distinguished name
*/
public Dn getDn()
{
return entryDn;
}
/**
* @return The number of entry modifications
*/
public int size()
{
return modificationList.size();
}
/**
* Returns a attribute given it's id
*
* @param attributeId The attribute Id
* @return The attribute if it exists
*/
public Attribute get( String attributeId )
{
if ( "dn".equalsIgnoreCase( attributeId ) )
{
return new DefaultAttribute( "dn", entry.getDn().getName() );
}
return entry.get( attributeId );
}
/**
* Get the entry's entry
*
* @return the stored Entry
*/
public Entry getEntry()
{
if ( isEntry() )
{
return entry;
}
else
{
return null;
}
}
/**
* @return True, if the old Rdn should be deleted.
*/
public boolean isDeleteOldRdn()
{
return deleteOldRdn;
}
/**
* Set the flage deleteOldRdn
*
* @param deleteOldRdn True if the old Rdn should be deleted
*/
public void setDeleteOldRdn( boolean deleteOldRdn )
{
this.deleteOldRdn = deleteOldRdn;
}
/**
* @return The new Rdn
*/
public String getNewRdn()
{
return newRdn;
}
/**
* Set the new Rdn
*
* @param newRdn The new Rdn
*/
public void setNewRdn( String newRdn )
{
this.newRdn = newRdn;
}
/**
* @return The new superior
*/
public String getNewSuperior()
{
return newSuperior;
}
/**
* Set the new superior
*
* @param newSuperior The new Superior
*/
public void setNewSuperior( String newSuperior )
{
this.newSuperior = newSuperior;
}
/**
* @return True if this is a content ldif
*/
public boolean isLdifContent()
{
return changeType == ChangeType.None;
}
/**
* @return True if there is this is a change ldif
*/
public boolean isLdifChange()
{
return changeType != ChangeType.None;
}
/**
* @return True if the entry is an ADD entry
*/
public boolean isChangeAdd()
{
return changeType == ChangeType.Add;
}
/**
* @return True if the entry is a DELETE entry
*/
public boolean isChangeDelete()
{
return changeType == ChangeType.Delete;
}
/**
* @return True if the entry is a MODDN entry
*/
public boolean isChangeModDn()
{
return changeType == ChangeType.ModDn;
}
/**
* @return True if the entry is a MODRDN entry
*/
public boolean isChangeModRdn()
{
return changeType == ChangeType.ModRdn;
}
/**
* @return True if the entry is a MODIFY entry
*/
public boolean isChangeModify()
{
return changeType == ChangeType.Modify;
}
/**
* Tells if the current entry is a added one
*
* @return <code>true</code> if the entry is added
*/
public boolean isEntry()
{
return ( changeType == ChangeType.None ) || ( changeType == ChangeType.Add );
}
/**
* @return true if the entry has some controls
*/
public boolean hasControls()
{
return controls != null;
}
/**
* @return The set of controls for this entry
*/
public Map<String, LdifControl> getControls()
{
return controls;
}
/**
* @param oid The control's OID
* @return The associated control, if any
*/
public LdifControl getControl( String oid )
{
if ( controls != null )
{
return controls.get( oid );
}
return null;
}
/**
* Add a control to the entry
*
* @param controls The added controls
*/
public void addControl( Control... controls )
{
if ( controls == null )
{
throw new IllegalArgumentException( "The added control must not be null" );
}
for ( Control control : controls )
{
if ( changeType == ChangeType.None )
{
changeType = ChangeType.Add;
}
if ( this.controls == null )
{
this.controls = new ConcurrentHashMap<String, LdifControl>();
}
if ( control instanceof LdifControl )
{
this.controls.put( control.getOid(), ( LdifControl ) control );
}
else
{
LdifControl ldifControl = new LdifControl( control.getOid() );
ldifControl.setCritical( control.isCritical() );
this.controls.put( control.getOid(), new LdifControl( control.getOid() ) );
}
}
}
/**
* Clone method
* @return a clone of the current instance
* @exception CloneNotSupportedException If there is some problem while cloning the instance
*/
public LdifEntry clone() throws CloneNotSupportedException
{
LdifEntry clone = ( LdifEntry ) super.clone();
if ( modificationList != null )
{
for ( Modification modif : modificationList )
{
Modification modifClone = new DefaultModification( modif.getOperation(),
modif.getAttribute().clone() );
clone.modificationList.add( modifClone );
}
}
if ( modifications != null )
{
for ( Map.Entry<String, Modification> entry : modifications.entrySet() )
{
Modification modif = entry.getValue();
Modification modifClone = new DefaultModification( modif.getOperation(),
modif.getAttribute().clone() );
clone.modifications.put( entry.getKey(), modifClone );
}
}
if ( entry != null )
{
clone.entry = entry.clone();
}
return clone;
}
/**
* Returns the lengthBeforeParsing of the entry at the time of parsing. This includes
* the lengthBeforeParsing of the comments present in entry at the time of parsing
* so this lengthBeforeParsing may not always match with the lengthBeforeParsing of the entry
* data present in memory.
*/
public int getLengthBeforeParsing()
{
return lengthBeforeParsing;
}
/**
* @param lengthBeforeParsing the lengthBeforeParsing to set
*/
/**No qualifier*/
void setLengthBeforeParsing( int length )
{
this.lengthBeforeParsing = length;
}
/**
* @return the offset
*/
public long getOffset()
{
return offset;
}
/**
* @param offset the offset to set
*/
/**No qualifier*/
void setOffset( long offset )
{
this.offset = offset;
}
/**
* @return a String representing the Entry, as a LDIF
*/
public String toString()
{
try
{
return LdifUtils.convertToLdif( this );
}
catch ( LdapException ne )
{
return "";
}
}
/**
* @see Object#hashCode()
*
* @return the instance's hash code
*/
public int hashCode()
{
int result = 37;
if ( entry != null && entry.getDn() != null )
{
result = result * 17 + entry.getDn().hashCode();
}
if ( changeType != null )
{
result = result * 17 + changeType.hashCode();
// Check each different cases
switch ( changeType )
{
case None:
// Fall through
case Add:
// Checks the attributes
if ( entry != null )
{
result = result * 17 + entry.hashCode();
}
break;
case Delete:
// Nothing to compute
break;
case Modify:
if ( modificationList != null )
{
result = result * 17 + modificationList.hashCode();
for ( Modification modification : modificationList )
{
result = result * 17 + modification.hashCode();
}
}
break;
case ModDn:
case ModRdn:
result = result * 17;
if ( deleteOldRdn )
{
result++;
}
else
{
result--;
}
if ( newRdn != null )
{
result = result * 17 + newRdn.hashCode();
}
if ( newSuperior != null )
{
result = result * 17 + newSuperior.hashCode();
}
break;
default:
// do nothing
break;
}
}
if ( controls != null )
{
for ( String control : controls.keySet() )
{
result = result * 17 + control.hashCode();
}
}
return result;
}
/**
* {@inheritDoc}
*/
public boolean equals( Object o )
{
// Basic equals checks
if ( this == o )
{
return true;
}
if ( o == null )
{
return false;
}
if ( !( o instanceof LdifEntry ) )
{
return false;
}
LdifEntry otherEntry = ( LdifEntry ) o;
// Check the Dn
Dn thisDn = entryDn;
Dn dnEntry = otherEntry.getDn();
if ( !thisDn.equals( dnEntry ) )
{
return false;
}
// Check the changeType
if ( changeType != otherEntry.changeType )
{
return false;
}
// Check each different cases
switch ( changeType )
{
case None:
// Fall through
case Add:
// Checks the attributes
if ( entry.size() != otherEntry.entry.size() )
{
return false;
}
if ( !entry.equals( otherEntry.entry ) )
{
return false;
}
break;
case Delete:
// Nothing to do, if the DNs are equals
break;
case Modify:
// Check the modificationItems list
// First, deal with special cases
if ( modificationList == null )
{
if ( otherEntry.modificationList != null )
{
return false;
}
else
{
break;
}
}
if ( otherEntry.modificationList == null )
{
return false;
}
if ( modificationList.size() != otherEntry.modificationList.size() )
{
return false;
}
// Now, compares the contents
int i = 0;
for ( Modification modification : modificationList )
{
if ( !modification.equals( otherEntry.modificationList.get( i ) ) )
{
return false;
}
i++;
}
break;
case ModDn:
case ModRdn:
// Check the deleteOldRdn flag
if ( deleteOldRdn != otherEntry.deleteOldRdn )
{
return false;
}
// Check the newRdn value
try
{
Rdn thisNewRdn = new Rdn( newRdn );
Rdn entryNewRdn = new Rdn( otherEntry.newRdn );
if ( !thisNewRdn.equals( entryNewRdn ) )
{
return false;
}
}
catch ( LdapInvalidDnException ine )
{
return false;
}
// Check the newSuperior value
try
{
Dn thisNewSuperior = new Dn( newSuperior );
Dn entryNewSuperior = new Dn( otherEntry.newSuperior );
if ( !thisNewSuperior.equals( entryNewSuperior ) )
{
return false;
}
}
catch ( LdapInvalidDnException ine )
{
return false;
}
break;
default:
// do nothing
break;
}
if ( controls != null )
{
Map<String, LdifControl> otherControls = otherEntry.controls;
if ( otherControls == null )
{
return false;
}
if ( controls.size() != otherControls.size() )
{
return false;
}
for ( Map.Entry<String, LdifControl> entry : controls.entrySet() )
{
String controlOid = entry.getKey();
if ( !otherControls.containsKey( controlOid ) )
{
return false;
}
Control thisControl = entry.getValue();
Control otherControl = otherControls.get( controlOid );
if ( thisControl == null )
{
if ( otherControl != null )
{
return false;
}
}
else
{
if ( !thisControl.equals( otherControl ) )
{
return false;
}
}
}
return true;
}
else
{
return otherEntry.controls == null;
}
}
/**
* @see Externalizable#readExternal(ObjectInput)
*
* @param in The stream from which the LdifEntry is read
* @throws IOException If the stream can't be read
* @throws ClassNotFoundException If the LdifEntry can't be created
*/
public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
{
// Read the changeType
int type = in.readInt();
changeType = ChangeType.getChangeType( type );
// Read the modification
switch ( changeType )
{
case Add:
case None:
// Read the entry
entry.readExternal( in );
entryDn = entry.getDn();
break;
case Delete:
// Read the Dn
entryDn = new Dn();
entryDn.readExternal( in );
break;
case ModDn:
// Fallback
case ModRdn:
// Read the Dn
entryDn = new Dn();
entryDn.readExternal( in );
deleteOldRdn = in.readBoolean();
if ( in.readBoolean() )
{
newRdn = in.readUTF();
}
if ( in.readBoolean() )
{
newSuperior = in.readUTF();
}
break;
case Modify:
// Read the Dn
entryDn = new Dn();
entryDn.readExternal( in );
// Read the modifications
int nbModifs = in.readInt();
for ( int i = 0; i < nbModifs; i++ )
{
Modification modification = new DefaultModification();
modification.readExternal( in );
addModification( modification );
}
break;
default:
throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
}
int nbControls = in.readInt();
// We have at least a control
if ( nbControls > 0 )
{
controls = new ConcurrentHashMap<String, LdifControl>( nbControls );
for ( int i = 0; i < nbControls; i++ )
{
LdifControl control = new LdifControl();
control.readExternal( in );
controls.put( control.getOid(), control );
}
}
}
/**
* @see Externalizable#readExternal(ObjectInput)
* @param out The stream in which the ChangeLogEvent will be serialized.
* @throws IOException If the serialization fail
*/
public void writeExternal( ObjectOutput out ) throws IOException
{
// Write the changeType
out.writeInt( changeType.getChangeType() );
// Write the data
switch ( changeType )
{
case Add:
case None:
entry.writeExternal( out );
break;
// Fallback
case Delete:
// we write the Dn
entryDn.writeExternal( out );
break;
case ModDn:
// Fallback
case ModRdn:
// Write the Dn
entryDn.writeExternal( out );
out.writeBoolean( deleteOldRdn );
if ( newRdn == null )
{
out.writeBoolean( false );
}
else
{
out.writeBoolean( true );
out.writeUTF( newRdn );
}
if ( newSuperior != null )
{
out.writeBoolean( true );
out.writeUTF( newSuperior );
}
else
{
out.writeBoolean( false );
}
break;
case Modify:
// Write the Dn
entryDn.writeExternal( out );
// Write the modifications
out.writeInt( modificationList.size() );
for ( Modification modification : modificationList )
{
modification.writeExternal( out );
}
break;
default:
throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
}
// The controls
if ( controls != null )
{
// Write the control
out.writeInt( controls.size() );
for ( LdifControl control : controls.values() )
{
control.writeExternal( out );
}
}
else
{
// No control, write -1
out.writeInt( -1 );
}
// and flush the result
out.flush();
}
}