blob: 2d9d54fea9c5a877ad6a693ab76596101c0e3747 [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
*
* https://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.entry;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
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.ldif.LdapLdifException;
import org.apache.directory.api.ldap.model.ldif.LdifAttributesReader;
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.schema.AttributeType;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.util.Base64;
import org.apache.directory.api.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A default implementation of a ServerEntry which should suite most
* use cases.<br>
* <br>
* This class is final, it should not be extended.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public final class DefaultEntry implements Entry
{
/** Used for serialization */
private static final long serialVersionUID = 2L;
/** The logger for this class */
private static final Logger LOG = LoggerFactory.getLogger( DefaultEntry.class );
/** The Dn for this entry */
private Dn dn;
/** A map containing all the attributes for this entry */
private Map<String, Attribute> attributes = new HashMap<>();
/** A speedup to get the ObjectClass attribute */
private static AttributeType objectClassAttributeType;
/** The SchemaManager */
private transient SchemaManager schemaManager;
/** The computed hashcode. We don't want to compute it each time the hashcode() method is called */
private volatile int h;
/** A mutex to manage synchronization*/
private static final Object MUTEX = new Object();
//-------------------------------------------------------------------------
// Constructors
//-------------------------------------------------------------------------
/**
* Creates a new instance of DefaultEntry.
* <p>
* This entry <b>must</b> be initialized before being used !
*/
public DefaultEntry()
{
this( ( SchemaManager ) null );
}
/**
* <p>
* Creates a new instance of DefaultEntry, schema aware.
* </p>
* <p>
* No attributes will be created.
* </p>
*
* @param schemaManager The reference to the schemaManager
*/
public DefaultEntry( SchemaManager schemaManager )
{
this.schemaManager = schemaManager;
dn = Dn.EMPTY_DN;
// Initialize the ObjectClass object
if ( schemaManager != null )
{
initObjectClassAT();
}
}
/**
* Creates a new instance of DefaultEntry, with a Dn.
*
* @param dn The String Dn for this serverEntry. Can be null.
* @throws LdapInvalidDnException If the Dn is invalid
*/
public DefaultEntry( String dn ) throws LdapInvalidDnException
{
this.dn = new Dn( dn );
}
/**
* Creates a new instance of DefaultEntry, with a Dn.
*
* @param dn The Dn for this serverEntry. Can be null.
*/
public DefaultEntry( Dn dn )
{
this.dn = dn;
}
/**
* <p>
* Creates a new instance of DefaultEntry, schema aware.
* </p>
* <p>
* No attributes will be created.
* </p>
*
* @param schemaManager The reference to the schemaManager
* @param dn The String Dn for this serverEntry. Can be null.
* @throws LdapInvalidDnException If the Dn is invalid
*/
public DefaultEntry( SchemaManager schemaManager, String dn ) throws LdapInvalidDnException
{
this.schemaManager = schemaManager;
if ( Strings.isEmpty( dn ) )
{
this.dn = Dn.EMPTY_DN;
}
else
{
this.dn = new Dn( schemaManager, dn );
}
// Initialize the ObjectClass object
initObjectClassAT();
}
/**
* <p>
* Creates a new instance of DefaultEntry, schema aware.
* </p>
* <p>
* No attributes will be created.
* </p>
*
* @param schemaManager The reference to the schemaManager
* @param dn The Dn for this serverEntry. Can be null.
*/
public DefaultEntry( SchemaManager schemaManager, Dn dn )
{
this.schemaManager = schemaManager;
if ( dn == null )
{
this.dn = Dn.EMPTY_DN;
}
else
{
this.dn = normalizeDn( dn );
}
// Initialize the ObjectClass object
initObjectClassAT();
}
/**
* Creates a new instance of DefaultEntry, with a
* Dn and a list of IDs.
*
* @param dn The Dn for this serverEntry. Can be null.
* @param elements The list of elements to inject in the entry
* @throws LdapException If the elements are invalid
* @throws LdapException If the provided Dn or elements are invalid
*/
public DefaultEntry( String dn, Object... elements ) throws LdapException
{
this( null, dn, elements );
}
/**
* Creates a new instance of DefaultEntry, with a
* Dn and a list of IDs.
*
* @param dn The Dn for this serverEntry. Can be null.
* @param elements The list of attributes to create.
* @throws LdapException If the provided Dn or elements are invalid
*/
public DefaultEntry( Dn dn, Object... elements ) throws LdapException
{
this( null, dn, elements );
}
/**
* Creates a new instance of DefaultEntry, with a
* Dn and a list of IDs.
*
* @param schemaManager The SchemaManager
* @param dn The Dn for this serverEntry. Can be null.
* @param elements The list of attributes to create.
* @throws LdapException If the provided Dn or elements are invalid
*/
public DefaultEntry( SchemaManager schemaManager, String dn, Object... elements ) throws LdapException
{
this( schemaManager, new Dn( schemaManager, dn ), elements );
}
/**
* Creates a new instance of DefaultEntry, with a
* Dn and a list of IDs.
*
* @param schemaManager The reference to the schemaManager
* @param dn The Dn for this serverEntry. Can be null.
* @param elements The list of attributes to create.
* @throws LdapException If the provided Dn or Elements are invalid
*/
public DefaultEntry( SchemaManager schemaManager, Dn dn, Object... elements ) throws LdapException
{
DefaultEntry entry = ( DefaultEntry ) createEntry( schemaManager, elements );
this.dn = dn;
this.attributes = entry.attributes;
this.schemaManager = schemaManager;
if ( schemaManager != null )
{
if ( !dn.isSchemaAware() )
{
this.dn = new Dn( schemaManager, dn );
}
initObjectClassAT();
}
}
/**
* <p>
* Creates a new instance of DefaultEntry, copying
* another entry.
* </p>
* <p>
* No attributes will be created.
* </p>
*
* @param schemaManager The reference to the schemaManager
* @param entry the entry to copy
* @throws LdapException If the provided entry is invalid
*/
public DefaultEntry( SchemaManager schemaManager, Entry entry ) throws LdapException
{
this.schemaManager = schemaManager;
// Initialize the ObjectClass object
initObjectClassAT();
// We will clone the existing entry, because it may be normalized
if ( entry.getDn() != null )
{
dn = normalizeDn( entry.getDn() );
}
else
{
dn = Dn.EMPTY_DN;
}
// Init the attributes map
attributes = new HashMap<>( entry.size() );
// and copy all the attributes
for ( Attribute attribute : entry )
{
try
{
// First get the AttributeType
AttributeType attributeType = attribute.getAttributeType();
if ( attributeType == null )
{
attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );
}
// Create a new ServerAttribute.
Attribute serverAttribute = new DefaultAttribute( attributeType, attribute );
// And store it
add( serverAttribute );
}
catch ( Exception ne )
{
// Just log a warning
if ( LOG.isWarnEnabled() )
{
LOG.warn( I18n.msg( I18n.MSG_13200_CANT_STORE_ATTRIBUTE, attribute.getId() ) );
}
throw ne;
}
}
}
//-------------------------------------------------------------------------
// Helper methods
//-------------------------------------------------------------------------
private Entry createEntry( SchemaManager schemaManager, Object... elements )
throws LdapInvalidAttributeValueException, LdapLdifException
{
StringBuilder sb = new StringBuilder();
int pos = 0;
boolean valueExpected = false;
for ( Object element : elements )
{
if ( !valueExpected )
{
if ( !( element instanceof String ) )
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
I18n.ERR_13233_ATTRIBUTE_ID_MUST_BE_A_STRING, pos + 1 ) );
}
String attribute = ( String ) element;
sb.append( attribute );
if ( attribute.indexOf( ':' ) != -1 )
{
sb.append( '\n' );
}
else
{
valueExpected = true;
}
}
else
{
if ( element instanceof String )
{
sb.append( ": " ).append( ( String ) element ).append( '\n' );
}
else if ( element instanceof byte[] )
{
sb.append( ":: " );
sb.append( new String( Base64.encode( ( byte[] ) element ) ) );
sb.append( '\n' );
}
else
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
I18n.ERR_13234_ATTRIBUTE_VAL_STRING_OR_BYTE, pos + 1 ) );
}
valueExpected = false;
}
}
if ( valueExpected )
{
throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n
.err( I18n.ERR_13250_VALUE_MISSING_AT_THE_END ) );
}
try ( LdifAttributesReader reader = new LdifAttributesReader() )
{
return reader.parseEntry( schemaManager, sb.toString() );
}
catch ( IOException e )
{
throw new LdapLdifException( I18n.err( I18n.ERR_13248_CANNOT_READ_ENTRY ), e );
}
}
/**
* Get the trimmed and lower cased entry ID
*
* @param upId The ID
* @return The retrieved ID
*/
private String getId( String upId )
{
String id = Strings.trim( Strings.toLowerCaseAscii( upId ) );
// If empty, throw an error
if ( Strings.isEmpty( id ) )
{
String message = I18n.err( I18n.ERR_13216_AT_ID_NULL );
LOG.error( message );
throw new IllegalArgumentException( message );
}
return id;
}
/**
* Get the UpId if it is null.
*
* @param upId The ID
* @param attributeType The AttributeType to retrieve
* @return the retrieved ID
*/
private String getUpId( String upId, AttributeType attributeType )
{
String normUpId = Strings.trim( upId );
if ( attributeType == null )
{
if ( Strings.isEmpty( normUpId ) )
{
String message = I18n.err( I18n.ERR_13226_CANNOT_ADD_ATTRIBUTE_NO_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
return upId;
}
else if ( Strings.isEmpty( normUpId ) )
{
String id = attributeType.getName();
if ( Strings.isEmpty( id ) )
{
id = attributeType.getOid();
}
return id;
}
else
{
return upId;
}
}
/**
* This method is used to initialize the OBJECT_CLASS_AT attributeType.
*
* We want to do it only once, so it's a synchronized method. Note that
* the alternative would be to call the lookup() every time, but this won't
* be very efficient, as it will get the AT from a map, which is also
* synchronized, so here, we have a very minimal cost.
*
* We can't do it once as a static part in the body of this class, because
* the access to the registries is mandatory to get back the AttributeType.
*/
private void initObjectClassAT()
{
if ( schemaManager == null )
{
return;
}
try
{
synchronized ( MUTEX )
{
if ( objectClassAttributeType == null )
{
objectClassAttributeType = schemaManager
.lookupAttributeTypeRegistry( SchemaConstants.OBJECT_CLASS_AT );
}
}
}
catch ( LdapException ne )
{
// do nothing...
}
}
/**
* Normalizes the given Dn if it was not already normalized
*
* @param dn the Dn to be normalized
* @return The normalized Dn
*/
private Dn normalizeDn( Dn dn )
{
if ( !dn.isSchemaAware() )
{
try
{
// The dn must be normalized
return new Dn( schemaManager, dn );
}
catch ( LdapException ne )
{
if ( LOG.isWarnEnabled() )
{
LOG.warn( I18n.msg( I18n.MSG_13201_DN_CANT_BE_NORMALIZED, dn ) );
}
return dn;
}
}
else
{
return dn;
}
}
/**
* A helper method to recompute the hash code
*/
private void rehash()
{
int hTmp = 37;
h = hTmp * 17 + dn.hashCode();
}
/**
* Add a new EntryAttribute, with its upId. If the upId is null,
* default to the AttributeType name.
*
* Updates the AttributeMap.
*
* @param upId The user provided ID for the attribute to create
* @param attributeType The AttributeType to use
* @param values The values to add to this attribute
* @throws LdapInvalidAttributeValueException If one of the value is incorrect
*/
protected void createAttribute( String upId, AttributeType attributeType, byte[]... values )
throws LdapInvalidAttributeValueException
{
Attribute attribute = new DefaultAttribute( attributeType, values );
attribute.setUpId( upId, attributeType );
attributes.put( attributeType.getOid(), attribute );
}
/**
* Add a new EntryAttribute, with its upId. If the upId is null,
* default to the AttributeType name.
*
* Updates the AttributeMap.
*
* @param upId The user provided ID for the attribute to create
* @param attributeType The AttributeType to use
* @param values The values to add to this attribute
* @throws LdapInvalidAttributeValueException If one of the value is incorrect
*/
protected void createAttribute( String upId, AttributeType attributeType, String... values )
throws LdapInvalidAttributeValueException
{
Attribute attribute = new DefaultAttribute( attributeType, values );
attribute.setUpId( upId, attributeType );
attributes.put( attributeType.getOid(), attribute );
}
/**
* Add a new EntryAttribute, with its upId. If the upId is null,
* default to the AttributeType name.
*
* Updates the AttributeMap.
*
* @param upId The user provided ID for the attribute to create
* @param attributeType The AttributeType to use
* @param values The values to add to this attribute
* @throws LdapInvalidAttributeValueException If one of the value is incorrect
*/
protected void createAttribute( String upId, AttributeType attributeType, Value... values )
throws LdapInvalidAttributeValueException
{
Attribute attribute = new DefaultAttribute( attributeType, values );
attribute.setUpId( upId, attributeType );
attributes.put( attributeType.getOid(), attribute );
}
/**
* Returns the attributeType from an Attribute ID.
*
* @param upId The ID we are looking for
* @return The found attributeType
* @throws LdapException If the lookup failed
*/
protected AttributeType getAttributeType( String upId ) throws LdapException
{
if ( Strings.isEmpty( Strings.trim( upId ) ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
return schemaManager.lookupAttributeTypeRegistry( upId );
}
//-------------------------------------------------------------------------
// Entry methods
//-------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public Entry add( AttributeType attributeType, byte[]... values ) throws LdapException
{
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( ( values == null ) || ( values.length == 0 ) )
{
String message = I18n.err( I18n.ERR_13232_NO_VALUE_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
// ObjectClass with binary values are not allowed
if ( attributeType.equals( objectClassAttributeType ) )
{
String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED );
LOG.error( message );
throw new UnsupportedOperationException( message );
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
}
else
{
// We have to create a new Attribute and set the values.
// The upId, which is set to null, will be setup by the
// createAttribute method
createAttribute( null, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( AttributeType attributeType, String... values ) throws LdapException
{
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
}
else
{
// We have to create a new Attribute and set the values.
// The upId, which is set to null, will be setup by the
// createAttribute method
createAttribute( null, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( AttributeType attributeType, Value... values ) throws LdapException
{
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
}
else
{
// We have to create a new Attribute and set the values.
// The upId, which is set to null, will be setup by the
// createAttribute method
createAttribute( null, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
{
// ObjectClass with binary values are not allowed
if ( attributeType.equals( objectClassAttributeType ) )
{
String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED );
LOG.error( message );
throw new UnsupportedOperationException( message );
}
Attribute attribute = attributes.get( attributeType.getOid() );
String id = getUpId( upId, attributeType );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
attribute.setUpId( id, attributeType );
}
else
{
// We have to create a new Attribute and set the values
// and the upId
createAttribute( id, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, AttributeType attributeType, Value... values ) throws LdapException
{
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
String id = getUpId( upId, attributeType );
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
attribute.setUpId( id, attributeType );
}
else
{
createAttribute( id, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException
{
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
String id = getUpId( upId, attributeType );
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it
attribute.add( values );
attribute.setUpId( id, attributeType );
}
else
{
// We have to create a new Attribute and set the values
// and the upId
createAttribute( id, attributeType, values );
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( Attribute... attributes ) throws LdapException
{
// Loop on all the added attributes
for ( Attribute attribute : attributes )
{
AttributeType attributeType = attribute.getAttributeType();
if ( attributeType != null )
{
String oid = attributeType.getOid();
if ( this.attributes.containsKey( oid ) )
{
// We already have an attribute with the same AttributeType
// Just add the new values into it.
Attribute existingAttribute = this.attributes.get( oid );
for ( Value value : attribute )
{
existingAttribute.add( value );
}
// And update the upId
existingAttribute.setUpId( attribute.getUpId() );
}
else
{
// The attributeType does not exist, add it
this.attributes.put( oid, attribute );
}
}
else
{
// If the attribute already exist, we will add the new values.
if ( contains( attribute ) )
{
Attribute existingAttribute = get( attribute.getId() );
// Loop on all the values, and add them to the existing attribute
for ( Value value : attribute )
{
existingAttribute.add( value );
}
}
else
{
// Stores the attribute into the entry
this.attributes.put( attribute.getId(), attribute );
}
}
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, byte[]... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
// First, transform the upID to a valid ID
String id = getId( upId );
if ( schemaManager != null )
{
add( upId, schemaManager.lookupAttributeTypeRegistry( id ), values );
}
else
{
// Now, check to see if we already have such an attribute
Attribute attribute = attributes.get( id );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it. (If the values already exists, they will
// not be added, but this is done in the add() method)
attribute.add( values );
attribute.setUpId( upId );
}
else
{
// We have to create a new Attribute and set the values
// and the upId
attributes.put( id, new DefaultAttribute( upId, values ) );
}
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, String... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
// First, transform the upID to a valid ID
String id = getId( upId );
if ( schemaManager != null )
{
add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values );
}
else
{
// Now, check to see if we already have such an attribute
Attribute attribute = attributes.get( id );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it. (If the values already exists, they will
// not be added, but this is done in the add() method)
attribute.add( values );
attribute.setUpId( upId );
}
else
{
// We have to create a new Attribute and set the values
// and the upId
attributes.put( id, new DefaultAttribute( upId, values ) );
}
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public Entry add( String upId, Value... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
// First, transform the upID to a valid ID
String id = getId( upId );
if ( schemaManager != null )
{
add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values );
}
else
{
// Now, check to see if we already have such an attribute
Attribute attribute = attributes.get( id );
if ( attribute != null )
{
// This Attribute already exist, we add the values
// into it. (If the values already exists, they will
// not be added, but this is done in the add() method)
attribute.add( values );
attribute.setUpId( upId );
}
else
{
// We have to create a new Attribute and set the values
// and the upId
attributes.put( id, new DefaultAttribute( upId, values ) );
}
}
return this;
}
/**
* Clone an entry. All the element are duplicated, so a modification on
* the original object won't affect the cloned object, as a modification
* on the cloned object has no impact on the original object
*/
@Override
public Entry clone()
{
// First, clone the structure
DefaultEntry clone = ( DefaultEntry ) shallowClone();
// now clone all the attributes
clone.attributes.clear();
if ( schemaManager != null )
{
for ( Attribute attribute : attributes.values() )
{
String oid = attribute.getAttributeType().getOid();
clone.attributes.put( oid, attribute.clone() );
}
}
else
{
for ( Attribute attribute : attributes.values() )
{
clone.attributes.put( attribute.getId(), attribute.clone() );
}
}
// We are done !
return clone;
/*
// First, clone the structure
//DefaultEntry clone = ( DefaultEntry ) shallowClone();
try
{
DefaultEntry clone = ( DefaultEntry ) super.clone();
clone.attributes = new HashMap<>( attributes.size() );
// now clone all the attributes
//clone.attributes.clear();
if ( schemaManager != null )
{
for ( Attribute attribute : attributes.values() )
{
String oid = attribute.getAttributeType().getOid();
clone.attributes.put( oid, attribute.clone() );
}
}
else
{
for ( Attribute attribute : attributes.values() )
{
clone.attributes.put( attribute.getId(), attribute.clone() );
}
}
// We are done !
return clone;
}
catch ( CloneNotSupportedException cnse )
{
return this;
}
*/
}
/**
* Shallow clone an entry. We don't clone the Attributes
*/
@SuppressWarnings("unchecked")
@Override
public Entry shallowClone()
{
try
{
// First, clone the structure
DefaultEntry clone = ( DefaultEntry ) super.clone();
// An Entry has a Dn and many attributes.
// note that Dn is immutable now
clone.dn = dn;
// then clone the ClientAttribute Map.
clone.attributes = ( Map<String, Attribute> ) ( ( ( HashMap<String, Attribute> ) attributes )
.clone() );
// We are done !
return clone;
}
catch ( CloneNotSupportedException cnse )
{
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( Attribute... attributes )
{
if ( schemaManager == null )
{
for ( Attribute attribute : attributes )
{
if ( attribute == null )
{
return this.attributes.size() == 0;
}
if ( !this.attributes.containsKey( attribute.getId() ) )
{
return false;
}
}
}
else
{
for ( Attribute entryAttribute : attributes )
{
if ( entryAttribute == null )
{
return this.attributes.size() == 0;
}
AttributeType attributeType = entryAttribute.getAttributeType();
if ( ( attributeType == null ) || !this.attributes.containsKey( attributeType.getOid() ) )
{
return false;
}
}
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsAttribute( String... attributes )
{
if ( schemaManager == null )
{
for ( String attribute : attributes )
{
String id = getId( attribute );
if ( !this.attributes.containsKey( id ) )
{
return false;
}
}
return true;
}
else
{
for ( String attribute : attributes )
{
try
{
if ( !containsAttribute( schemaManager.lookupAttributeTypeRegistry( attribute ) ) )
{
return false;
}
}
catch ( LdapException ne )
{
return false;
}
}
return true;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsAttribute( AttributeType attributeType )
{
if ( attributeType == null )
{
return false;
}
return attributes.containsKey( attributeType.getOid() );
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( AttributeType attributeType, byte[]... values )
{
if ( attributeType == null )
{
return false;
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
return attribute.contains( values );
}
else
{
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( AttributeType attributeType, String... values )
{
if ( attributeType == null )
{
return false;
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
return attribute.contains( values );
}
else
{
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( AttributeType attributeType, Value... values )
{
if ( attributeType == null )
{
return false;
}
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute != null )
{
return attribute.contains( values );
}
else
{
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( String upId, byte[]... values )
{
if ( Strings.isEmpty( upId ) )
{
return false;
}
String id = getId( upId );
if ( schemaManager != null )
{
try
{
return contains( schemaManager.lookupAttributeTypeRegistry( id ), values );
}
catch ( LdapException le )
{
return false;
}
}
Attribute attribute = attributes.get( id );
if ( attribute == null )
{
return false;
}
return attribute.contains( values );
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( String upId, String... values )
{
if ( Strings.isEmpty( upId ) )
{
return false;
}
String id = getId( upId );
if ( schemaManager != null )
{
try
{
return contains( schemaManager.lookupAttributeTypeRegistry( id ), values );
}
catch ( LdapException le )
{
return false;
}
}
Attribute attribute = attributes.get( id );
if ( attribute == null )
{
return false;
}
return attribute.contains( values );
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains( String upId, Value... values )
{
if ( Strings.isEmpty( upId ) )
{
return false;
}
String id = getId( upId );
if ( schemaManager != null )
{
try
{
return contains( schemaManager.lookupAttributeTypeRegistry( id ), values );
}
catch ( LdapException le )
{
return false;
}
}
Attribute attribute = attributes.get( id );
if ( attribute == null )
{
return false;
}
return attribute.contains( values );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute get( String alias )
{
try
{
String id = getId( alias );
if ( schemaManager != null )
{
try
{
AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id );
return attributes.get( attributeType.getOid() );
}
catch ( LdapException ne )
{
String message = ne.getLocalizedMessage();
LOG.error( message );
return null;
}
}
else
{
return attributes.get( id );
}
}
catch ( IllegalArgumentException iea )
{
LOG.error( I18n.err( I18n.ERR_13217_FAILED_LOOKUP_AT, alias ) );
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public Attribute get( AttributeType attributeType )
{
if ( attributeType != null )
{
return attributes.get( attributeType.getOid() );
}
else
{
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public Collection<Attribute> getAttributes()
{
return Collections.unmodifiableMap( attributes ).values();
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, byte[]... values )
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( schemaManager == null )
{
// Get the normalized form of the ID
String id = getId( upId );
// Create a new attribute
Attribute clientAttribute = new DefaultAttribute( upId, values );
// Replace the previous one, and return it back
return attributes.put( id, clientAttribute );
}
else
{
try
{
return put( upId, getAttributeType( upId ), values );
}
catch ( LdapException ne )
{
String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() );
LOG.error( message );
throw new IllegalArgumentException( message, ne );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, String... values )
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( schemaManager == null )
{
// Get the normalized form of the ID
String id = getId( upId );
// Create a new attribute
Attribute clientAttribute = new DefaultAttribute( upId, values );
// Replace the previous one, and return it back
return attributes.put( id, clientAttribute );
}
else
{
try
{
return put( upId, getAttributeType( upId ), values );
}
catch ( LdapException ne )
{
String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() );
LOG.error( message );
throw new IllegalArgumentException( message, ne );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, Value... values )
{
if ( Strings.isEmpty( upId ) )
{
String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( schemaManager == null )
{
// Get the normalized form of the ID
String id = getId( upId );
// Create a new attribute
Attribute clientAttribute = new DefaultAttribute( upId, values );
// Replace the previous one, and return it back
return attributes.put( id, clientAttribute );
}
else
{
try
{
return put( upId, getAttributeType( upId ), values );
}
catch ( LdapException ne )
{
String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() );
LOG.error( message );
throw new IllegalArgumentException( message, ne );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public List<Attribute> put( Attribute... attributes ) throws LdapException
{
// First, get the existing attributes
List<Attribute> previous = new ArrayList<>();
if ( schemaManager == null )
{
for ( Attribute attribute : attributes )
{
String id = attribute.getId();
if ( containsAttribute( id ) )
{
// Store the attribute and remove it from the list
previous.add( get( id ) );
this.attributes.remove( id );
}
// add the new one
this.attributes.put( id, attribute );
}
}
else
{
for ( Attribute attribute : attributes )
{
if ( attribute == null )
{
String message = I18n.err( I18n.ERR_13228_AT_LIST_NULL_ELEMENTS );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( attribute.getAttributeType() == null )
{
AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );
attribute.apply( attributeType );
}
Attribute removed = this.attributes.put( attribute.getAttributeType().getOid(), attribute );
if ( removed != null )
{
previous.add( removed );
}
}
}
// return the previous attributes
return previous;
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( AttributeType attributeType, byte[]... values ) throws LdapException
{
return put( null, attributeType, values );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( AttributeType attributeType, String... values ) throws LdapException
{
return put( null, attributeType, values );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( AttributeType attributeType, Value... values ) throws LdapException
{
return put( null, attributeType, values );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, AttributeType attributeType, byte[]... values ) throws LdapException
{
if ( attributeType == null )
{
try
{
attributeType = getAttributeType( upId );
}
catch ( Exception e )
{
String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID );
LOG.error( message );
throw new IllegalArgumentException( message, e );
}
}
else
{
if ( !Strings.isEmpty( upId ) )
{
AttributeType tempAT = getAttributeType( upId );
if ( !tempAT.equals( attributeType ) )
{
String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType );
LOG.error( message );
throw new IllegalArgumentException( message );
}
}
else
{
upId = getUpId( upId, attributeType );
}
}
if ( attributeType.equals( objectClassAttributeType ) )
{
String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED );
LOG.error( message );
throw new UnsupportedOperationException( message );
}
Attribute attribute = new DefaultAttribute( upId, attributeType, values );
return attributes.put( attributeType.getOid(), attribute );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, AttributeType attributeType, String... values ) throws LdapException
{
if ( attributeType == null )
{
try
{
attributeType = getAttributeType( upId );
}
catch ( Exception e )
{
String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID );
LOG.error( message );
throw new IllegalArgumentException( message, e );
}
}
else
{
if ( !Strings.isEmpty( upId ) )
{
AttributeType tempAT = getAttributeType( upId );
if ( !tempAT.equals( attributeType ) )
{
String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType );
LOG.error( message );
throw new IllegalArgumentException( message );
}
}
else
{
upId = getUpId( upId, attributeType );
}
}
Attribute attribute = new DefaultAttribute( upId, attributeType, values );
return attributes.put( attributeType.getOid(), attribute );
}
/**
* {@inheritDoc}
*/
@Override
public Attribute put( String upId, AttributeType attributeType, Value... values ) throws LdapException
{
if ( attributeType == null )
{
try
{
attributeType = getAttributeType( upId );
}
catch ( Exception e )
{
String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID );
LOG.error( message );
throw new IllegalArgumentException( message, e );
}
}
else
{
if ( !Strings.isEmpty( upId ) )
{
AttributeType tempAT = getAttributeType( upId );
if ( !tempAT.equals( attributeType ) )
{
String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType );
LOG.error( message );
throw new IllegalArgumentException( message );
}
}
else
{
upId = getUpId( upId, attributeType );
}
}
Attribute attribute = new DefaultAttribute( upId, attributeType, values );
return attributes.put( attributeType.getOid(), attribute );
}
/**
* {@inheritDoc}
*/
@Override
public List<Attribute> remove( Attribute... attributes ) throws LdapException
{
List<Attribute> removedAttributes = new ArrayList<>();
if ( schemaManager == null )
{
for ( Attribute attribute : attributes )
{
if ( containsAttribute( attribute.getId() ) )
{
this.attributes.remove( attribute.getId() );
removedAttributes.add( attribute );
}
}
}
else
{
for ( Attribute attribute : attributes )
{
AttributeType attributeType = attribute.getAttributeType();
if ( attributeType == null )
{
String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
LOG.error( message );
throw new IllegalArgumentException( message );
}
if ( this.attributes.containsKey( attributeType.getOid() ) )
{
this.attributes.remove( attributeType.getOid() );
removedAttributes.add( attribute );
}
}
}
return removedAttributes;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove( AttributeType attributeType, byte[]... values ) throws LdapException
{
if ( attributeType == null )
{
return false;
}
try
{
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( attributeType.getOid() );
return true;
}
return nbOldValues != attribute.size();
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) );
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove( AttributeType attributeType, String... values ) throws LdapException
{
if ( attributeType == null )
{
return false;
}
try
{
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( attributeType.getOid() );
return true;
}
return nbOldValues != attribute.size();
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) );
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove( AttributeType attributeType, Value... values ) throws LdapException
{
if ( attributeType == null )
{
return false;
}
try
{
Attribute attribute = attributes.get( attributeType.getOid() );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( attributeType.getOid() );
return true;
}
return nbOldValues != attribute.size();
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) );
return false;
}
}
/**
* <p>
* Removes the attribute with the specified AttributeTypes.
* </p>
* <p>
* The removed attribute are returned by this method.
* </p>
* <p>
* If there is no attribute with the specified AttributeTypes,
* the return value is <code>null</code>.
* </p>
*
* @param attributes the AttributeTypes to be removed
*/
@Override
public void removeAttributes( AttributeType... attributes )
{
if ( ( attributes == null ) || ( attributes.length == 0 ) || ( schemaManager == null ) )
{
return;
}
for ( AttributeType attributeType : attributes )
{
if ( attributeType == null )
{
continue;
}
this.attributes.remove( attributeType.getOid() );
}
}
/**
* {@inheritDoc}
*/
@Override
public void removeAttributes( String... attributes )
{
if ( attributes.length == 0 )
{
return;
}
if ( schemaManager == null )
{
for ( String attribute : attributes )
{
Attribute attr = get( attribute );
if ( attr != null )
{
this.attributes.remove( attr.getId() );
}
else
{
if ( LOG.isWarnEnabled() )
{
LOG.warn( I18n.err( I18n.ERR_13218_AT_DOES_NOT_EXIST, attribute ) );
}
}
}
}
else
{
for ( String attribute : attributes )
{
AttributeType attributeType = null;
try
{
attributeType = schemaManager.lookupAttributeTypeRegistry( attribute );
}
catch ( LdapException ne )
{
if ( LOG.isWarnEnabled() )
{
LOG.warn( I18n.msg( I18n.MSG_13203_MISSING_ATTRIBUTE_IN_ENTRY, attribute ) );
}
continue;
}
this.attributes.remove( attributeType.getOid() );
}
}
}
/**
* <p>
* Removes the specified binary values from an attribute.
* </p>
* <p>
* If at least one value is removed, this method returns <code>true</code>.
* </p>
* <p>
* If there is no more value after having removed the values, the attribute
* will be removed too.
* </p>
* <p>
* If the attribute does not exist, nothing is done and the method returns
* <code>false</code>
* </p>
*
* @param upId The attribute ID
* @param values the values to be removed
* @return <code>true</code> if at least a value is removed, <code>false</code>
* if not all the values have been removed or if the attribute does not exist.
*/
@Override
public boolean remove( String upId, byte[]... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
if ( LOG.isInfoEnabled() )
{
LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) );
}
return false;
}
if ( schemaManager == null )
{
String id = getId( upId );
Attribute attribute = get( id );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( id );
return true;
}
return nbOldValues != attribute.size();
}
else
{
try
{
AttributeType attributeType = getAttributeType( upId );
return remove( attributeType, values );
}
catch ( LdapException ne )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) );
return false;
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) );
return false;
}
}
}
/**
* <p>
* Removes the specified String values from an attribute.
* </p>
* <p>
* If at least one value is removed, this method returns <code>true</code>.
* </p>
* <p>
* If there is no more value after having removed the values, the attribute
* will be removed too.
* </p>
* <p>
* If the attribute does not exist, nothing is done and the method returns
* <code>false</code>
* </p>
*
* @param upId The attribute ID
* @param values the attributes to be removed
* @return <code>true</code> if at least a value is removed, <code>false</code>
* if not all the values have been removed or if the attribute does not exist.
*/
@Override
public boolean remove( String upId, String... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
if ( LOG.isInfoEnabled() )
{
LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) );
}
return false;
}
if ( schemaManager == null )
{
String id = getId( upId );
Attribute attribute = get( id );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( id );
return true;
}
return nbOldValues != attribute.size();
}
else
{
try
{
AttributeType attributeType = getAttributeType( upId );
return remove( attributeType, values );
}
catch ( LdapException ne )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) );
return false;
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) );
return false;
}
}
}
/**
* <p>
* Removes the specified values from an attribute.
* </p>
* <p>
* If at least one value is removed, this method returns <code>true</code>.
* </p>
* <p>
* If there is no more value after having removed the values, the attribute
* will be removed too.
* </p>
* <p>
* If the attribute does not exist, nothing is done and the method returns
* <code>false</code>
* </p>
*
* @param upId The attribute ID
* @param values the attributes to be removed
* @return <code>true</code> if at least a value is removed, <code>false</code>
* if not all the values have been removed or if the attribute does not exist.
*/
@Override
public boolean remove( String upId, Value... values ) throws LdapException
{
if ( Strings.isEmpty( upId ) )
{
if ( LOG.isInfoEnabled() )
{
LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) );
}
return false;
}
if ( schemaManager == null )
{
String id = getId( upId );
Attribute attribute = get( id );
if ( attribute == null )
{
// Can't remove values from a not existing attribute !
return false;
}
int nbOldValues = attribute.size();
// Remove the values
attribute.remove( values );
if ( attribute.size() == 0 )
{
// No mare values, remove the attribute
attributes.remove( id );
return true;
}
return nbOldValues != attribute.size();
}
else
{
try
{
AttributeType attributeType = getAttributeType( upId );
return remove( attributeType, values );
}
catch ( LdapException ne )
{
LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) );
return false;
}
catch ( IllegalArgumentException iae )
{
LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) );
return false;
}
}
}
/**
* Get this entry's Dn.
*
* @return The entry's Dn
*/
@Override
public Dn getDn()
{
return dn;
}
/**
* {@inheritDoc}
*/
@Override
public void setDn( Dn dn )
{
this.dn = dn;
// Rehash the object
rehash();
}
/**
* {@inheritDoc}
*/
@Override
public void setDn( String dn ) throws LdapInvalidDnException
{
setDn( new Dn( dn ) );
}
/**
* Remove all the attributes for this entry. The Dn is not reset
*/
@Override
public void clear()
{
attributes.clear();
}
/**
* Returns an enumeration containing the zero or more attributes in the
* collection. The behavior of the enumeration is not specified if the
* attribute collection is changed.
*
* @return an enumeration of all contained attributes
*/
@Override
public Iterator<Attribute> iterator()
{
return attributes.values().iterator();
}
/**
* Returns the number of attributes.
*
* @return the number of attributes
*/
@Override
public int size()
{
return attributes.size();
}
/**
* This is the place where we serialize entries, and all theirs
* elements.
* <br>
* The structure used to store the entry is the following :
* <ul>
* <li>
* <b>[Dn]</b> : If it's null, stores an empty Dn
* </li>
* <li>
* <b>[attributes number]</b> : the number of attributes.
* </li>
* <li>
* <b>[attribute]*</b> : each attribute, if we have some
* </li>
* </ul>
*
* {@inheritDoc}
*/
@Override
public void writeExternal( ObjectOutput out ) throws IOException
{
// First, the Dn
if ( dn == null )
{
// Write an empty Dn
Dn.EMPTY_DN.writeExternal( out );
}
else
{
// Write the Dn
dn.writeExternal( out );
}
// Then the attributes.
// Store the attributes' nulber first
out.writeInt( attributes.size() );
// Iterate through the keys.
for ( Attribute attribute : attributes.values() )
{
// Store the attribute
attribute.writeExternal( out );
}
out.flush();
}
/**
* {@inheritDoc}
*/
@Override
public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
{
// Read the Dn
dn = new Dn( schemaManager );
dn.readExternal( in );
// Read the number of attributes
int nbAttributes = in.readInt();
// Read the attributes
for ( int i = 0; i < nbAttributes; i++ )
{
// Read each attribute
Attribute attribute = new DefaultAttribute();
attribute.readExternal( in );
if ( schemaManager != null )
{
try
{
AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() );
attribute.apply( attributeType );
attributes.put( attributeType.getOid(), attribute );
}
catch ( LdapException le )
{
String message = le.getLocalizedMessage();
LOG.error( message );
throw new IOException( message, le );
}
}
else
{
attributes.put( attribute.getId(), attribute );
}
}
}
/**
* Get the hash code of this ClientEntry. The Attributes will be sorted
* before the comparison can be done.
*
* @see java.lang.Object#hashCode()
* @return the instance's hash code
*/
@Override
public int hashCode()
{
if ( h == 0 )
{
rehash();
}
return h;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasObjectClass( String... objectClasses )
{
if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) )
{
return false;
}
for ( String objectClass : objectClasses )
{
if ( schemaManager != null )
{
if ( !contains( objectClassAttributeType, objectClass ) )
{
return false;
}
}
else
{
if ( !contains( "objectclass", objectClass ) )
{
return false;
}
}
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasObjectClass( Attribute... objectClasses )
{
if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) )
{
return false;
}
for ( Attribute objectClass : objectClasses )
{
// We have to check that we are checking the ObjectClass attributeType
if ( !objectClass.getAttributeType().equals( objectClassAttributeType ) )
{
return false;
}
Attribute attribute = attributes.get( objectClassAttributeType.getOid() );
if ( attribute == null )
{
// The entry does not have an ObjectClass attribute
return false;
}
for ( Value value : objectClass )
{
// Loop on all the values, and check if they are present
if ( !attribute.contains( value.getString() ) )
{
return false;
}
}
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSchemaAware()
{
return schemaManager != null;
}
/**
* @see Object#equals(Object)
*/
@Override
public boolean equals( Object o )
{
// Short circuit
if ( this == o )
{
return true;
}
if ( !( o instanceof Entry ) )
{
return false;
}
Entry other = ( Entry ) o;
// Both Dn must be equal
if ( dn == null )
{
if ( other.getDn() != null )
{
return false;
}
}
else
{
if ( !dn.equals( other.getDn() ) )
{
return false;
}
}
// They must have the same number of attributes
if ( size() != other.size() )
{
return false;
}
// Each attribute must be equal
for ( Attribute attribute : other )
{
if ( !attribute.equals( this.get( attribute.getId() ) ) )
{
return false;
}
}
return true;
}
/**
* @see Object#toString()
*/
@Override
public String toString()
{
return toString( "" );
}
/**
* {@inheritDoc}
*/
@Override
public String toString( String tabs )
{
StringBuilder sb = new StringBuilder();
sb.append( tabs ).append( "Entry\n" );
sb.append( tabs ).append( " dn" );
if ( dn.isSchemaAware() )
{
sb.append( "[n]" );
}
sb.append( ": " );
sb.append( dn.getName() );
sb.append( '\n' );
// First dump the ObjectClass attribute
if ( schemaManager != null )
{
// First dump the ObjectClass attribute
if ( containsAttribute( objectClassAttributeType.getOid() ) )
{
Attribute objectClass = get( objectClassAttributeType );
sb.append( objectClass.toString( tabs + " " ) );
}
}
else
{
Attribute objectClass = get( "objectclass" );
if ( objectClass != null )
{
sb.append( objectClass.toString( tabs + " " ) );
}
}
sb.append( '\n' );
if ( attributes.size() != 0 )
{
for ( Attribute attribute : attributes.values() )
{
String id = attribute.getId();
if ( schemaManager != null )
{
AttributeType attributeType = schemaManager.getAttributeType( id );
if ( attributeType == null )
{
sb.append( tabs ).append( "id: " ).append( id );
}
else if ( !attributeType.equals( objectClassAttributeType ) )
{
sb.append( attribute.toString( tabs + " " ) );
sb.append( '\n' );
}
}
else
{
if ( !id.equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT )
&& !id.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
{
sb.append( attribute.toString( tabs + " " ) );
sb.append( '\n' );
}
}
}
}
return sb.toString();
}
}