You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2008/03/18 07:13:18 UTC
svn commit: r638228 [2/20] - in
/directory/sandbox/akarasulu/bigbang/apacheds: ./
apacheds-xbean-spring/src/site/ benchmarks/src/site/
bootstrap-extract/src/site/ bootstrap-partition/src/site/
bootstrap-plugin/src/main/java/org/apache/directory/server/...
Modified: directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java
URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java?rev=638228&r1=638227&r2=638228&view=diff
==============================================================================
--- directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java (original)
+++ directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java Mon Mar 17 23:12:41 2008
@@ -19,9 +19,12 @@
package org.apache.directory.server.core.entry;
-import org.apache.directory.shared.ldap.entry.AbstractBinaryValue;
+import org.apache.directory.shared.asn1.primitives.OID;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
-import org.apache.directory.shared.ldap.entry.AbstractStringValue;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.ClientBinaryValue;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientAttribute;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
@@ -30,13 +33,6 @@
import javax.naming.NamingException;
import javax.naming.directory.InvalidAttributeValueException;
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Iterator;
-
/**
* A server side entry attribute aware of schema.
@@ -44,7 +40,7 @@
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
-public final class DefaultServerAttribute extends AbstractServerAttribute implements Externalizable
+public final class DefaultServerAttribute extends DefaultClientAttribute implements ServerAttribute
{
/** Used for serialization */
public static final long serialVersionUID = 2L;
@@ -52,6 +48,361 @@
/** logger for reporting errors that might not be handled properly upstream */
private static final Logger LOG = LoggerFactory.getLogger( DefaultServerAttribute.class );
+ /** The associated AttributeType */
+ protected transient AttributeType attributeType;
+
+
+ // -----------------------------------------------------------------------
+ // utility methods
+ // -----------------------------------------------------------------------
+ /**
+ * Check the attributeType member. It should not be null,
+ * and it should contains a syntax.
+ */
+ protected String getErrorMessage( AttributeType attributeType )
+ {
+ try
+ {
+ if ( attributeType == null )
+ {
+ return "The AttributeType parameter should not be null";
+ }
+
+ if ( attributeType.getSyntax() == null )
+ {
+ return "There is no Syntax associated with this attributeType";
+ }
+
+ return null;
+ }
+ catch ( NamingException ne )
+ {
+ return "This AttributeType is incorrect";
+ }
+ }
+
+
+ /**
+ * Private helper method used to set an UpId from an attributeType
+ */
+ private String getUpId( AttributeType attributeType )
+ {
+ String upId = attributeType.getName();
+
+ if ( upId == null )
+ {
+ upId = attributeType.getOid();
+ }
+
+ return upId;
+ }
+
+
+ /**
+ * <p>
+ * Check if the current attribute type is of the expected attributeType
+ * </p>
+ * <p>
+ * This method won't tell if the current attribute is a descendant of
+ * the attributeType. For instance, the "CN" serverAttribute will return
+ * false if we ask if it's an instance of "Name".
+ * </p>
+ *
+ * @param attributeId The AttributeType ID to check
+ * @return True if the current attribute is of the expected attributeType
+ * @throws InvalidAttributeValueException If there is no AttributeType
+ */
+ public boolean instanceOf( String attributeId ) throws InvalidAttributeValueException
+ {
+ String trimmedId = StringTools.trim( attributeId );
+
+ if ( StringTools.isEmpty( trimmedId ) )
+ {
+ return false;
+ }
+
+ String normId = StringTools.lowerCaseAscii( trimmedId );
+
+ for ( String name:attributeType.getNames() )
+ {
+ if ( normId.equalsIgnoreCase( name ) )
+ {
+ return true;
+ }
+ }
+
+ return normId.equalsIgnoreCase( attributeType.getOid() );
+ }
+
+
+ /**
+ * <p>
+ * Overload the {@link DefaultClientAttribute#setId(String)} method.
+ * </p>
+ * <p>
+ * As the attributeType has already been set, we have to be sure that the
+ * argument is compatible with the attributeType's name.
+ * </p>
+ * <p>
+ * If the given ID is not compatible with the attributeType's possible
+ * names, the previously loaded ID will be kept.
+ * </p>
+ *
+ * @param upId The attribute ID
+ * @param attributeType The associated attributeType
+ */
+ public void setId( String id )
+ {
+ if ( !StringTools.isEmpty( StringTools.trim( id ) ) )
+ {
+ if ( attributeType.getName() == null )
+ {
+ // If the name is null, then we may have to store an OID
+ if ( OID.isOID( id ) && attributeType.getOid().equals( id ) )
+ {
+ // Everything is fine, store the upId.
+ // This should not happen...
+ super.setId( id );
+ }
+ }
+ else
+ {
+ // We have at least one name. Check that the normalized upId
+ // is one of those names. Otherwise, the upId may be an OID too.
+ // In this case, it must be equals to the attributeType OID.
+ String normId = StringTools.lowerCaseAscii( StringTools.trim( id ) );
+
+ for ( String atName:attributeType.getNames() )
+ {
+ if ( atName.equalsIgnoreCase( normId ) )
+ {
+ // Found ! We can store the upId and get out
+ super.setId( normId );
+ return;
+ }
+ }
+
+ // Last case, the UpId is an OID
+ if ( OID.isOID( normId ) && attributeType.getOid().equals( normId ) )
+ {
+ // We have an OID : stores it
+ super.setUpId( normId );
+ }
+ else
+ {
+ // The id is incorrect : this is not allowed
+ throw new IllegalArgumentException( "The ID '" + id + "'is incompatible with the AttributeType's id '" + attributeType.getName() + "'" );
+ }
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" +
+ " value when trimmed" );
+ }
+ }
+
+
+ /**
+ * <p>
+ * Overload the {@link DefaultClientAttribute#setUpId(String)} method.
+ * </p>
+ * <p>
+ * As the attributeType has already been set, we have to be sure that the
+ * argument is compatible with the attributeType's name.
+ * </p>
+ * <p>
+ * If the given ID is not compatible with the attributeType's possible
+ * names, the previously loaded ID will be kept.
+ * </p>
+ *
+ * @param upId The attribute ID
+ * @param attributeType The associated attributeType
+ */
+ public void setUpId( String upId )
+ {
+ if ( !StringTools.isEmpty( StringTools.trim( upId ) ) )
+ {
+ if ( attributeType.getName() == null )
+ {
+ // If the name is null, then we may have to store an OID
+ if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) )
+ {
+ // Everything is fine, store the upId.
+ // This should not happen...
+ super.setUpId( upId );
+
+ }
+ }
+ else
+ {
+ // We have at least one name. Check that the normalized upId
+ // is one of those names. Otherwise, the upId may be an OID too.
+ // In this case, it must be equals to the attributeType OID.
+ String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) );
+
+ for ( String id:attributeType.getNames() )
+ {
+ if ( id.equalsIgnoreCase( normUpId ) )
+ {
+ // Found ! We can store the upId and get out
+ super.setUpId( upId );
+ return;
+ }
+ }
+
+ // Last case, the UpId is an OID
+ if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) )
+ {
+ // We have an OID : stores it
+ super.setUpId( upId );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * <p>
+ * Set the user provided ID. If we have none, the upId is assigned
+ * the attributetype's name. If it does not have any name, we will
+ * use the OID.
+ * </p>
+ * <p>
+ * If we have an upId and an AttributeType, they must be compatible. :
+ * - if the upId is an OID, it must be the AttributeType's OID
+ * - otherwise, its normalized form must be equals to ones of
+ * the attributeType's names.
+ * </p>
+ * <p>
+ * In any case, the ATtributeType will be changed. The caller is responsible for
+ * the present values to be compatoble with the new AttributeType.
+ * </p>
+ *
+ * @param upId The attribute ID
+ * @param attributeType The associated attributeType
+ */
+ public void setUpId( String upId, AttributeType attributeType )
+ {
+ if ( StringTools.isEmpty( StringTools.trim( upId ) ) )
+ {
+ super.setUpId( getUpId( attributeType ) );
+ this.attributeType = attributeType;
+ }
+ else
+ {
+ String name = attributeType.getName();
+
+ if ( name == null )
+ {
+ // If the name is null, then we may have to store an OID
+ if ( OID.isOID( upId ) && attributeType.getOid().equals( upId ) )
+ {
+ // Everything is fine, store the upId.
+ super.setUpId( upId );
+ this.attributeType = attributeType;
+ }
+ else
+ {
+ // We have a difference or the upId is not a valid OID :
+ // we will use the attributeTypeOID in this case.
+ LOG.warn( "The upID ({}) is not an OID or is different from the AttributeType OID({})",
+ upId, attributeType.getOid() );
+ super.setUpId( attributeType.getOid() );
+ this.attributeType = attributeType;
+ }
+ }
+ else
+ {
+ // We have at least one name. Check that the normalized upId
+ // is one of those names. Otherwise, the upId may be an OID too.
+ // In this case, it must be equals to the attributeType OID.
+ String normUpId = StringTools.lowerCaseAscii( StringTools.trim( upId ) );
+
+ for ( String id:attributeType.getNames() )
+ {
+ if ( id.equalsIgnoreCase( normUpId ) )
+ {
+ // Found ! We can store the upId and get out
+ super.setUpId( upId );
+ this.attributeType = attributeType;
+ return;
+ }
+ }
+
+ // UpId was not found in names. It should be an OID, or if not, we
+ // will use the AttributeType name.
+ if ( OID.isOID( normUpId ) && attributeType.getOid().equals( normUpId ) )
+ {
+ // We have an OID : stores it
+ super.setUpId( upId );
+ this.attributeType = attributeType;
+ }
+ else
+ {
+ String message = "The upID (" + upId + ") is not an OID or is different from the AttributeType OID (" +
+ attributeType.getOid() + ")";
+ // Not a valid OID : use the AttributeTypes OID name instead
+ LOG.error( message );
+ throw new IllegalArgumentException( message );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * <p>
+ * Set the attribute type associated with this ServerAttribute.
+ * </p>
+ * <p>
+ * The current attributeType will be replaced. It is the responsibility of
+ * the caller to insure that the existing values are compatible with the new
+ * AttributeType
+ * </p>
+ *
+ * @param the attributeType associated with this entry attribute
+ */
+ public void setAttributeType( AttributeType attributeType )
+ {
+ if ( attributeType == null )
+ {
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
+ }
+
+ this.attributeType = attributeType;
+ setUpId( null, attributeType );
+
+ try
+ {
+ if ( attributeType.getSyntax().isHumanReadable() )
+ {
+ isHR = true;
+ }
+ else
+ {
+ isHR = false;
+ }
+ }
+ catch ( NamingException ne )
+ {
+ // If we have an exception while trying to get the Syntax for this attribute
+ // just set it as Binary
+ isHR = false;
+ }
+ }
+
+
+ /**
+ * Get the attribute type associated with this ServerAttribute.
+ *
+ * @return the attributeType associated with this entry attribute
+ */
+ public AttributeType getAttributeType()
+ {
+ return attributeType;
+ }
+
// maybe have some additional convenience constructors which take
// an initial value as a string or a byte[]
@@ -62,11 +413,10 @@
{
if ( attributeType == null )
{
- throw new IllegalArgumentException( getErrorMessage( attributeType ) );
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
- this.attributeType = attributeType;
- setUpId( null, attributeType );
+ setAttributeType( attributeType );
}
@@ -77,13 +427,13 @@
{
if ( attributeType == null )
{
- String message = getErrorMessage( attributeType );
+ String message = "The AttributeType parameter should not be null";
LOG.error( message );
throw new IllegalArgumentException( message );
}
- this.attributeType = attributeType;
- setUpId( upId, attributeType );
+ setAttributeType( attributeType );
+ setUpId( upId );
}
@@ -91,14 +441,14 @@
* Doc me more!
*
* If the value does not correspond to the same attributeType, then it's
- * wrapped value is copied into a new ServerValue which uses the specified
+ * wrapped value is copied into a new Value which uses the specified
* attributeType.
*
* @param attributeType the attribute type according to the schema
* @param vals an initial set of values for this attribute
* @throws NamingException if there are problems creating the new attribute
*/
- public DefaultServerAttribute( AttributeType attributeType, ServerValue<?>... vals ) throws NamingException
+ public DefaultServerAttribute( AttributeType attributeType, Value<?>... vals )
{
this( null, attributeType, vals );
}
@@ -108,7 +458,7 @@
* Doc me more!
*
* If the value does not correspond to the same attributeType, then it's
- * wrapped value is copied into a new ServerValue which uses the specified
+ * wrapped value is copied into a new Value which uses the specified
* attributeType.
*
* Otherwise, the value is stored, but as a reference. It's not a copy.
@@ -118,62 +468,23 @@
* @param vals an initial set of values for this attribute
* @throws NamingException if there are problems creating the new attribute
*/
- public DefaultServerAttribute( String upId, AttributeType attributeType, ServerValue<?>... vals ) throws NamingException
+ public DefaultServerAttribute( String upId, AttributeType attributeType, Value<?>... vals )
{
if ( attributeType == null )
{
- throw new IllegalArgumentException( getErrorMessage( attributeType ) );
- }
-
- this.attributeType = attributeType;
-
- // The value can be null, this is a valid value.
- if ( vals[0] == null )
- {
- if ( attributeType.getSyntax().isHumanReadable() )
- {
- add( new ServerStringValue( attributeType ) );
- }
- else
- {
- add( new ServerBinaryValue( attributeType ) );
- }
- }
- else
- {
- for ( ServerValue<?> val:vals )
- {
- if ( attributeType.equals( val.getAttributeType() ) )
- {
- add( val );
- }
- else if ( val instanceof ServerStringValue )
- {
- ServerStringValue serverString = ( ServerStringValue ) val;
- add( new ServerStringValue( attributeType, serverString.get() ) );
- }
- else if ( val instanceof ServerBinaryValue )
- {
- ServerBinaryValue serverBinary = ( ServerBinaryValue ) val;
- add( new ServerBinaryValue( attributeType, serverBinary.getCopy() ) );
- }
- else
- {
- String message = "Unknown value type: " + val.getClass().getName();
- LOG.error( message );
- throw new IllegalStateException( message );
- }
- }
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
+ setAttributeType( attributeType );
setUpId( upId, attributeType );
+ add( vals );
}
/**
* Create a new instance of a EntryAttribute, without ID but with some values.
*/
- public DefaultServerAttribute( AttributeType attributeType, String... vals ) throws NamingException
+ public DefaultServerAttribute( AttributeType attributeType, String... vals )
{
this( null, attributeType, vals );
}
@@ -182,14 +493,14 @@
/**
* Create a new instance of a EntryAttribute.
*/
- public DefaultServerAttribute( String upId, AttributeType attributeType, String... vals ) throws NamingException
+ public DefaultServerAttribute( String upId, AttributeType attributeType, String... vals )
{
if ( attributeType == null )
{
- throw new IllegalArgumentException( getErrorMessage( attributeType ) );
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
- this.attributeType = attributeType;
+ setAttributeType( attributeType );
add( vals );
setUpId( upId, attributeType );
}
@@ -198,7 +509,7 @@
/**
* Create a new instance of a EntryAttribute, with some byte[] values.
*/
- public DefaultServerAttribute( AttributeType attributeType, byte[]... vals ) throws NamingException
+ public DefaultServerAttribute( AttributeType attributeType, byte[]... vals )
{
this( null, attributeType, vals );
}
@@ -207,61 +518,72 @@
/**
* Create a new instance of a EntryAttribute, with some byte[] values.
*/
- public DefaultServerAttribute( String upId, AttributeType attributeType, byte[]... vals ) throws NamingException
+ public DefaultServerAttribute( String upId, AttributeType attributeType, byte[]... vals )
{
if ( attributeType == null )
{
- throw new IllegalArgumentException( getErrorMessage( attributeType ) );
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
- this.attributeType = attributeType;
+ setAttributeType( attributeType );
add( vals );
setUpId( upId, attributeType );
}
-
-
+
+
/**
- * Gets the attribute type associated with this ServerAttribute.
- *
- * @return the attributeType associated with this entry attribute
+ * Clone an attribute. 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
*/
- public AttributeType getType()
+ public ServerAttribute clone()
{
- return attributeType;
+ // clone the structure by cloner the inherited class
+ ServerAttribute clone = (ServerAttribute)super.clone();
+
+ // We are done !
+ return clone;
}
/**
- * Get's the user provided identifier for this entry. This is the value
- * that will be used as the identifier for the attribute within the
- * entry. If this is a commonName attribute for example and the user
- * provides "COMMONname" instead when adding the entry then this is
- * the format the user will have that entry returned by the directory
- * server. To do so we store this value as it was given and track it
- * in the attribute using this property.
- *
- * @return the user provided identifier for this attribute
+ * <p>
+ * Overload the ClientAttribte isHR method : we can't change this flag
+ * for a ServerAttribute, as the HR is already set using the AttributeType.
+ * Set the attribute to Human Readable or to Binary.
+ * </p>
+ *
+ * @param isHR <code>true</code> for a Human Readable attribute,
+ * <code>false</code> for a Binary attribute.
*/
- public String getUpId()
+ public void setHR( boolean isHR )
{
- return upId;
+ // Do nothing...
}
-
+
/**
+ * <p>
* Checks to see if this attribute is valid along with the values it contains.
- *
+ * </p>
+ * <p>
+ * An attribute is valid if :
+ * <li>All of its values are valid with respect to the attributeType's syntax checker</li>
+ * <li>If the attributeType is SINGLE-VALUE, then no more than a value should be present</li>
+ *</p>
* @return true if the attribute and it's values are valid, false otherwise
* @throws NamingException if there is a failure to check syntaxes of values
*/
public boolean isValid() throws NamingException
{
- if ( attributeType.isSingleValue() && values.size() > 1 )
+ // First check if the attribute has more than one value
+ // if the attribute is supposed to be SINGLE_VALUE
+ if ( attributeType.isSingleValue() && ( values.size() > 1 ) )
{
return false;
}
- for ( ServerValue<?> value : values )
+ for ( Value<?> value : values )
{
if ( ! value.isValid() )
{
@@ -274,158 +596,201 @@
/**
- * @see EntryAttribute#add(org.apache.directory.shared.ldap.entry.Value)
+ * @see EntryAttribute#add(org.apache.directory.shared.ldap.entry.Value...)
*/
- public boolean add( ServerValue<?> val ) throws InvalidAttributeValueException, NamingException
+ public int add( Value<?>... vals )
{
- if ( attributeType.getSyntax().isHumanReadable() )
+ int nbAdded = 0;
+
+ for ( Value<?> val:vals )
{
- if ( val == null )
+ try
{
- ServerValue<String> nullSV = new ServerStringValue( attributeType, (String)null );
-
- if ( values.contains( nullSV ) )
+ if ( attributeType.getSyntax().isHumanReadable() )
{
- return false;
+ if ( val == null )
+ {
+ Value<String> nullSV = new ServerStringValue( attributeType, (String)null );
+
+ if ( !values.contains( nullSV ) )
+ {
+ values.add( nullSV );
+ nbAdded++;
+ }
+ }
+ else if ( val instanceof ServerStringValue )
+ {
+ if ( !values.contains( val ) )
+ {
+ if ( values.add( val ) )
+ {
+ nbAdded++;
+ }
+ }
+ }
+ else if ( val instanceof ClientStringValue )
+ {
+ // If we get a Client value, convert it to a Server value first
+ Value<String> serverStringValue = new ServerStringValue( attributeType, (String)val.get() );
+
+ if ( !values.contains( serverStringValue ) )
+ {
+ if ( values.add( serverStringValue ) )
+ {
+ nbAdded++;
+ }
+ }
+ }
+ else
+ {
+ String message = "The value must be a String, as its AttributeType is H/R";
+ LOG.error( message );
+ }
}
else
{
- values.add( nullSV );
- return true;
- }
- }
-
- if ( !( val instanceof AbstractStringValue ) )
- {
- String message = "The value must be a String, as its AttributeType is H/R";
- LOG.error( message );
- throw new InvalidAttributeValueException( message );
- }
- }
- else
- {
- if ( val == null )
- {
- ServerValue<byte[]> nullSV = new ServerBinaryValue( attributeType, (byte[])null );
-
- if ( values.contains( nullSV ) )
- {
- return false;
- }
- else
- {
- values.add( nullSV );
- return true;
+ if ( val == null )
+ {
+ Value<byte[]> nullSV = new ServerBinaryValue( attributeType, (byte[])null );
+
+ if ( !values.contains( nullSV ) )
+ {
+ values.add( nullSV );
+ nbAdded++;
+ }
+ }
+ else if ( ( val instanceof ClientBinaryValue ) )
+ {
+ Value<byte[]> serverBinaryValue = new ServerBinaryValue( attributeType, (byte[])val.get() );
+
+ if ( !values.contains( serverBinaryValue ) )
+ {
+ if ( values.add( serverBinaryValue ) )
+ {
+ nbAdded++;
+ }
+ }
+ }
+ else if ( val instanceof ServerBinaryValue )
+ {
+ if ( !values.contains( val ) )
+ {
+ if ( values.add( val ) )
+ {
+ nbAdded++;
+ }
+ }
+ }
+ else
+ {
+ String message = "The value must be a byte[], as its AttributeType is not H/R";
+ LOG.error( message );
+ }
}
}
-
- if ( !( val instanceof AbstractBinaryValue ) )
+ catch ( NamingException ne )
{
- String message = "The value must be a byte[], as its AttributeType is not H/R";
+ String message = "Error while adding value '" + val.toString() +"' : " + ne.getMessage();
LOG.error( message );
- throw new InvalidAttributeValueException( message );
}
}
- if ( values.contains( val ) )
- {
- return false;
- }
-
- return values.add( val );
+ return nbAdded;
}
/**
- * @see EntryAttribute#add(org.apache.directory.shared.ldap.entry.Value...)
+ * <p>
+ * Adds some values to this attribute. If the new values are already present in
+ * the attribute values, the method has no effect.
+ * </p>
+ * <p>
+ * The new values are added at the end of list of values.
+ * </p>
+ * <p>
+ * This method returns the number of values that were added.
+ * </p>
+ * If the value's type is different from the attribute's type,
+ * the value is not added.
+ *
+ * @param val some new values to be added which may be null
+ * @return the number of added values, or 0 if none has been added
*/
- public int add( ServerValue<?>... vals ) throws InvalidAttributeValueException, NamingException
+ public int add( String... vals )
{
- int nbAdded = 0;
-
- for ( ServerValue<?> val:vals )
+ if ( isHR )
{
- if ( add( val ) )
+ int nbAdded = 0;
+
+ for ( String val:vals )
{
- nbAdded ++;
+ if ( add( new ServerStringValue( attributeType, val ) ) != 0 )
+ {
+ nbAdded++;
+ }
+ else
+ {
+ LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ }
}
- }
-
- return nbAdded;
- }
-
-
- /**
- * @see EntryAttribute#add(String)
- */
- public boolean add( String val ) throws InvalidAttributeValueException, NamingException
- {
- if ( attributeType.getSyntax().isHumanReadable() )
- {
- return add( new ServerStringValue( attributeType, val ) );
+
+ return nbAdded;
}
else
{
- String message = "The value must be a String, as its AttributeType is H/R";
- LOG.warn( message );
- return add( new ServerBinaryValue( attributeType, StringTools.getBytesUtf8( val ) ) );
+ // We can't add String values into a Binary serverAttribute
+ return 0;
}
- }
-
-
- /**
- * @see EntryAttribute#add(String...)
- */
- public int add( String... vals ) throws NamingException
- {
- int nbAdded = 0;
-
- for ( String val:vals )
- {
- if ( add( val ) )
- {
- nbAdded ++;
- }
- }
-
- return nbAdded;
}
/**
- * @see EntryAttribute#add(byte[])
+ * <p>
+ * Adds some values to this attribute. If the new values are already present in
+ * the attribute values, the method has no effect.
+ * </p>
+ * <p>
+ * The new values are added at the end of list of values.
+ * </p>
+ * <p>
+ * This method returns the number of values that were added.
+ * </p>
+ * <p>
+ * If the value's type is different from the attribute's type,
+ * the value is not added.
+ * </p>
+ * It's the responsibility of the caller to check if the stored
+ * values are consistent with the attribute's type.
+ * <p>
+ *
+ * @param val some new values to be added which may be null
+ * @return the number of added values, or 0 if none has been added
*/
- public boolean add( byte[] val ) throws InvalidAttributeValueException, NamingException
+ public int add( byte[]... vals )
{
- if ( ! attributeType.getSyntax().isHumanReadable() )
+ if ( !isHR )
{
- return add( new ServerBinaryValue( attributeType, val ) );
+ int nbAdded = 0;
+
+ for ( byte[] val:vals )
+ {
+ if ( add( new ServerBinaryValue( attributeType, val ) ) != 0 )
+ {
+ nbAdded++;
+ }
+ else
+ {
+ LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ }
+ }
+
+ return nbAdded;
}
else
{
- String message = "The value must be a String, as its AttributeType is H/R";
- LOG.error( message );
- throw new InvalidAttributeValueException( message );
- }
- }
-
-
- /**
- * @see EntryAttribute#add(byte[]...)
- */
- public int add( byte[]... vals ) throws InvalidAttributeValueException, NamingException
- {
- int nbAdded = 0;
-
- for ( byte[] val:vals )
- {
- if ( add( val ) )
- {
- nbAdded ++;
- }
+ // We can't add Binary values into a String serverAttribute
+ return 0;
}
-
- return nbAdded;
}
@@ -440,231 +805,195 @@
/**
- * @see EntryAttribute#contains(org.apache.directory.shared.ldap.entry.Value)
- */
- public boolean contains( ServerValue<?> val )
- {
- return values.contains( val );
- }
-
-
- /**
- * @see EntryAttribute#contains(org.apache.directory.shared.ldap.entry.Value...)
+ * <p>
+ * Indicates whether the specified values are some of the attribute's values.
+ * </p>
+ * <p>
+ * If the Attribute is HR, te metho will only accept String Values. Otherwise,
+ * it will only accept Binary values.
+ * </p>
+ *
+ * @param vals the values
+ * @return true if this attribute contains all the values, otherwise false
*/
- public boolean contains( ServerValue<?>... vals )
+ public boolean contains( Value<?>... vals )
{
// Iterate through all the values, and quit if we
- // don't find one in the values
- for ( ServerValue<?> val:vals )
+ // don't find one in the values. We have to separate the check
+ // depending on the isHR flag value.
+ if ( isHR )
{
- if ( !values.contains( val ) )
+ for ( Value<?> val:vals )
{
- return false;
+ if ( val instanceof ServerStringValue )
+ {
+ if ( !values.contains( val ) )
+ {
+ return false;
+ }
+ }
+ else if ( val instanceof ClientStringValue )
+ {
+ ServerStringValue serverValue = new ServerStringValue( attributeType, (String)val.get() );
+
+ if ( !values.contains( serverValue ) )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Not a String value
+ return false;
+ }
}
}
-
- return true;
- }
-
-
- /**
- * @see EntryAttribute#contains(String)
- */
- public boolean contains( String val )
- {
- try
+ else
{
- if ( !attributeType.getSyntax().isHumanReadable() )
+ for ( Value<?> val:vals )
{
- return false;
+ if ( val instanceof ClientBinaryValue )
+ {
+ if ( !values.contains( val ) )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Not a Binary value
+ return false;
+ }
}
}
- catch ( NamingException ne )
- {
- // We have had a pb while getting the syntax...
- return false;
- }
-
- ServerStringValue value = new ServerStringValue( attributeType, val );
- return values.contains( value );
+ return true;
}
/**
- * @see EntryAttribute#contains(String...)
+ * <p>
+ * Indicates whether all the specified values are attribute's values. If
+ * at least one value is not an attribute's value, this method will return
+ * <code>false</code>
+ * </p>
+ * <p>
+ * If the Attribute is not HR, this method will returns <code>false</code>
+ * </p>
+ *
+ * @param vals the values
+ * @return true if this attribute contains all the values, otherwise false
*/
public boolean contains( String... vals )
{
- // Iterate through all the values, and quit if we
- // don't find one in the values
- for ( String val:vals )
- {
- if ( !contains( val ) )
- {
- return false;
- }
- }
-
- return true;
- }
-
-
- /**
- * @see EntryAttribute#contains(byte[])
- */
- public boolean contains( byte[] val )
- {
- try
+ if ( isHR )
{
- if ( attributeType.getSyntax().isHumanReadable() )
+ // Iterate through all the values, and quit if we
+ // don't find one in the values
+ for ( String val:vals )
{
- return false;
+ ServerStringValue value = new ServerStringValue( attributeType, val );
+
+ if ( !values.contains( value ) )
+ {
+ return false;
+ }
}
+
+ return true;
}
- catch ( NamingException ne )
+ else
{
- // We have had a pb while getting the syntax...
return false;
}
-
- ServerBinaryValue sbv = new ServerBinaryValue( attributeType, val );
- return values.contains( sbv );
- }
-
-
- /**
- * @see EntryAttribute#contains(byte[]...)
- */
- public boolean contains( byte[]... vals )
- {
- // Iterate through all the values, and quit if we
- // don't find one in the values
- for ( byte[] val:vals )
- {
- if ( !contains( val ) )
- {
- return false;
- }
- }
-
- return true;
}
/**
- * Get the first value of this attribute. If there is none,
- * null is returned.
- *
- * Note : as we are storing values into a Set, one can't assume
- * the values to be ordered in any way. This method is meant to
- * be used if the attribute hold only one value.
- *
- * @return The first value for this attribute.
- */
- public ServerValue<?> get()
- {
- if ( values.isEmpty() )
- {
- return null;
- }
-
- return values.iterator().next();
- }
-
-
- /**
- * Get the String value, if and only if the value is known to be a String,
- * otherwise a InvalidAttributeValueException will be thrown
- *
- * @return The value as a String
- * @throws InvalidAttributeValueException If the value is a byte[]
- */
- public String getString() throws InvalidAttributeValueException
- {
- ServerValue<?> value = get();
-
- if ( value instanceof ServerStringValue )
- {
- return (String)value.get();
- }
- else
- {
- String message = "The value is expected to be a String";
- LOG.error( message );
- throw new InvalidAttributeValueException( message );
- }
- }
-
-
- /**
- * Get the byte[] value, if and only if the value is known to be Binary,
- * otherwise a InvalidAttributeValueException will be thrown
+ * <p>
+ * Indicates whether all the specified values are attribute's values. If
+ * at least one value is not an attribute's value, this method will return
+ * <code>false</code>
+ * </p>
+ * <p>
+ * If the Attribute is HR, this method will returns <code>false</code>
+ * </p>
*
- * @return The value as a String
- * @throws InvalidAttributeValueException If the value is a String
+ * @param vals the values
+ * @return true if this attribute contains all the values, otherwise false
*/
- public byte[] getBytes() throws InvalidAttributeValueException
+ public boolean contains( byte[]... vals )
{
- ServerValue<?> value = get();
-
- if ( value instanceof ServerBinaryValue )
+ if ( !isHR )
{
- return (byte[])value.get();
+ // Iterate through all the values, and quit if we
+ // don't find one in the values
+ for ( byte[] val:vals )
+ {
+ ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
+
+ if ( !values.contains( value ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
}
else
{
- String message = "The value is expected to be a byte[]";
- LOG.error( message );
- throw new InvalidAttributeValueException( message );
+ return false;
}
}
-
-
- /**
- * Get all the stored values.
- *
- * @return An iterator over the values stored into the attribute
- */
- public Iterator<ServerValue<?>> getAll()
- {
- return iterator();
- }
-
-
- /**
- * Get the number or values stored in the attribute
- *
- * @return the number of stored values. As 'null' can be a valid
- * value, it is counted as one result, not 0.
- */
- public int size()
- {
- return values.size();
- }
-
-
- /**
- * @see EntryAttribute#remove(org.apache.directory.shared.ldap.entry.Value)
- */
- public boolean remove( ServerValue<?> val )
- {
- return values.remove( val );
- }
-
-
+
+
/**
* @see EntryAttribute#remove(org.apache.directory.shared.ldap.entry.Value...)
*/
- public boolean remove( ServerValue<?>... vals )
+ public boolean remove( Value<?>... vals )
{
- boolean removed = false;
+ boolean removed = true;
// Loop through all the values to remove. If one of
// them is not present, the method will return false.
- for ( ServerValue<?> val:vals )
+ // As the attribute may be HR or not, we have two separated treatments
+ if ( isHR )
+ {
+ for ( Value<?> val:vals )
+ {
+ if ( val instanceof ClientStringValue )
+ {
+ ServerStringValue ssv = new ServerStringValue( attributeType, (String)val.get() );
+ removed &= values.remove( ssv );
+ }
+ else if ( val instanceof ServerStringValue )
+ {
+ removed &= values.remove( val );
+ }
+ else
+ {
+ removed = false;
+ }
+ }
+ }
+ else
{
- removed &= values.remove( val );
+ for ( Value<?> val:vals )
+ {
+ if ( val instanceof ClientBinaryValue )
+ {
+ ServerBinaryValue sbv = new ServerBinaryValue( attributeType, (byte[])val.get() );
+ removed &= values.remove( sbv );
+ }
+ else if ( val instanceof ServerBinaryValue )
+ {
+ removed &= values.remove( val );
+ }
+ else
+ {
+ removed = false;
+ }
+ }
}
return removed;
@@ -672,20 +1001,15 @@
/**
- * @see EntryAttribute#remove(byte[])
- */
- public boolean remove( byte[] val )
- {
- ServerBinaryValue sbv = new ServerBinaryValue( attributeType, val );
- return values.remove( sbv );
- }
-
-
- /**
* @see EntryAttribute#remove(byte[]...)
*/
public boolean remove( byte[]... vals )
{
+ if ( isHR )
+ {
+ return false;
+ }
+
boolean removed = true;
for ( byte[] val:vals )
@@ -699,20 +1023,15 @@
/**
- * @see EntryAttribute#remove(String)
- */
- public boolean remove( String val )
- {
- ServerStringValue ssv = new ServerStringValue( attributeType, val );
- return values.remove( ssv );
- }
-
-
- /**
* @see EntryAttribute#remove(String...)
*/
public boolean remove( String... vals )
{
+ if ( !isHR )
+ {
+ return false;
+ }
+
boolean removed = true;
for ( String val:vals )
@@ -725,149 +1044,86 @@
}
+ //-------------------------------------------------------------------------
+ // Overloaded Object classes
+ //-------------------------------------------------------------------------
/**
- * An iterator on top of the stored values.
- *
- * @return an iterator over the stored values.
- */
- public Iterator<ServerValue<?>> iterator()
- {
- return values.iterator();
- }
-
- /**
- * @see Object#toString()
+ * The hashCode is based on the id, the isHR flag and
+ * on the internal values.
+ *
+ * @see Object#hashCode()
*/
- public String toString()
+ public int hashCode()
{
- StringBuilder sb = new StringBuilder();
+ int h = super.hashCode();
- if ( ( values != null ) && ( values.size() != 0 ) )
+ if ( attributeType != null )
{
- for ( ServerValue<?> value:values )
- {
- sb.append( " " ).append( upId ).append( ": " ).append( value ).append( '\n' );
- }
- }
- else
- {
- sb.append( " " ).append( upId ).append( ": (null)\n" );
+ h = h*17 + attributeType.hashCode();
}
- return sb.toString();
+ return h;
}
-
+
/**
- * @see Externalizable#writeExternal(ObjectOutput)
- *
- * We have to store the UPid, and all the values, if any.
+ * @see Object#equals(Object)
*/
- public void writeExternal( ObjectOutput out ) throws IOException
+ public boolean equals( Object obj )
{
- // Store the attribute's HR : true means H/R, false is for binary
- try
+ if ( obj == this )
{
- out.writeBoolean( attributeType.getSyntax().isHumanReadable() );
+ return true;
}
- catch ( NamingException ne )
+
+ if ( ! (obj instanceof ServerAttribute ) )
{
- out.writeBoolean( false );
+ return false;
}
- // Store the UP id
- out.writeUTF( upId );
+ ServerAttribute other = (ServerAttribute)obj;
- // The number of values
- if ( values == null )
+ if ( !attributeType.equals( other.getAttributeType() ) )
{
- out.writeInt( -1 );
+ return false;
}
- else if ( values.size() == 0 )
+
+ if ( values.size() != other.size() )
{
- out.writeInt( 0 );
+ return false;
}
- else
+
+ for ( Value<?> val:values )
{
- out.writeInt( values.size() );
-
- for ( ServerValue<?> value:values )
+ if ( ! other.contains( val ) )
{
- out.writeObject( value );
+ return false;
}
}
- out.flush();
+ return true;
}
-
+
/**
- * @see Externalizable#readExternal(ObjectInput)
+ * @see Object#toString()
*/
- public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+ public String toString()
{
- if ( in.available() == 0 )
+ StringBuilder sb = new StringBuilder();
+
+ if ( ( values != null ) && ( values.size() != 0 ) )
{
- String message = "Cannot read an null Attribute";
- LOG.error( message );
- throw new IOException( message );
+ for ( Value<?> value:values )
+ {
+ sb.append( " " ).append( upId ).append( ": " ).append( value ).append( '\n' );
+ }
}
else
{
- // Read the HR flag
- boolean hr = in.readBoolean();
-
- // Read the UPid
- upId = in.readUTF();
-
- // Read the number of values
- int nbValues = in.readInt();
-
- switch ( nbValues )
- {
- case -1 :
- values = null;
- break;
-
- case 0 :
- values = new ArrayList<ServerValue<?>>();
- break;
-
- default :
- values = new ArrayList<ServerValue<?>>();
-
- for ( int i = 0; i < nbValues; i++ )
- {
- if ( hr )
- {
- ServerStringValue value = new ServerStringValue( attributeType );
- }
- }
-
- break;
- }
-
- if ( nbValues != 0 )
- {
-
- }
- else
- {
-
- }
-
- String wrapped = in.readUTF();
- /**
- set( wrapped );
-
- normalizedValue = in.readUTF();
-
- if ( ( normalizedValue.length() == 0 ) && ( wrapped.length() != 0 ) )
- {
- // In this case, the normalized value is equal to the UP value
- normalizedValue = wrapped;
- }
- */
+ sb.append( " " ).append( upId ).append( ": (null)\n" );
}
+
+ return sb.toString();
}
}