You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2008/08/15 01:12:13 UTC
svn commit: r686082 [1/7] - in /directory:
apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/
apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/
apacheds/branches/bigbang/c...
Author: elecharny
Date: Thu Aug 14 16:12:09 2008
New Revision: 686082
URL: http://svn.apache.org/viewvc?rev=686082&view=rev
Log:
o Replaced some of the ServerUtils methods by direct calls to the equivalent methods in the Server Entry/Attribute/Modification classes
o Completely reviewed the serialization of entries/attributes/values/Modifications/LdifEnties
o Added tests for all those serialization
o Used Externalizable,instead of Serializable
o Added some missing Javadoc
o Fixed some failing tests in ModifyDN class
o Fixed the wrong LDIF in referrals tests
o Removed a lot of references on Attribute(s) and JNDI objects
o Removed the password wrom the LdapPrincipal serialized form
Added:
directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/authn/LdapPrincipalTest.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientModification.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientModificationTest.java
Modified:
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerEntry.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerAttribute.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerBinaryValue.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntry.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntrySerializer.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java
directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerAttributeTest.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/DefaultServerEntryTest.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerBinaryValueTest.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerEntrySerializerTest.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerModificationTest.java
directory/apacheds/branches/bigbang/core-entry/src/test/java/org/apache/directory/server/core/entry/ServerStringValueTest.java
directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/IntegrationUtils.java
directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/AbstractState.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authz/AuthorizationServiceAsNonAdminIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ListIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ModifyContextIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ObjStateFactoryIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ReferralIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/operational/OperationalAttributeServiceIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SchemaPersistenceIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SchemaServiceIT.java
directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/schema/SubschemaSubentryIT.java
directory/apacheds/branches/bigbang/core-jndi/src/main/java/org/apache/directory/server/core/jndi/ServerDirContext.java
directory/apacheds/branches/bigbang/core-unit/src/main/java/org/apache/directory/server/core/unit/AbstractTestCase.java
directory/apacheds/branches/bigbang/core-unit/src/main/java/org/apache/directory/server/core/unit/IntegrationUtils.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultCoreSession.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/authn/LdapPrincipal.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogEvent.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/ChangeLogInterceptor.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/DefaultChangeLog.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/changelog/MemoryChangeLogStore.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/collective/CollectiveAttributesSchemaChecker.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/ModifyOperationContext.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/PartitionFrame.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java
directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/sp/StoredProcExecutionManager.java
directory/apacheds/branches/bigbang/core/src/test/java/org/apache/directory/server/core/changelog/MemoryChangeLogStoreTest.java
directory/apacheds/branches/bigbang/protocol-shared/src/main/java/org/apache/directory/server/protocol/shared/store/LdifFileLoader.java
directory/apacheds/branches/bigbang/protocol-shared/src/main/java/org/apache/directory/server/protocol/shared/store/LdifLoadFilter.java
directory/apacheds/branches/bigbang/server-integ/src/main/java/org/apache/directory/server/integ/state/AbstractState.java
directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/bind/BindIT.java
directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/bind/SimpleBindIT.java
directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/ModifyRdnIT.java
directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/search/ReferralSearchIT.java
directory/apacheds/branches/bigbang/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java
directory/apacheds/branches/bigbang/server-jndi/src/main/java/org/apache/directory/server/configuration/ApacheDS.java
directory/apacheds/branches/bigbang/server-jndi/src/test/java/org/apache/directory/server/configuration/ApacheDSTest.java
directory/apacheds/branches/bigbang/server-tools/src/main/java/org/apache/directory/server/tools/ImportCommand.java
directory/apacheds/branches/bigbang/server-unit/src/main/java/org/apache/directory/server/unit/AbstractServerTest.java
directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/AttributeTypeHolder.java
directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/ObjectClassHolder.java
directory/shared/branches/bigbang/convert/src/main/java/org/apache/directory/shared/converter/schema/SchemaElementImpl.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Entry.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/EntryAttribute.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/Modification.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/ModificationOperation.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValue.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/ClientStringValue.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttribute.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntry.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifEntry.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifReader.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/LdapDN.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/name/Rdn.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/AttributeUtils.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/DNUtils.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/Position.java
directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/util/PropertiesUtils.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientBinaryValueTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/ClientStringValueTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientAttributeTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/entry/client/DefaultClientEntryTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifReaderTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/ldif/LdifUtilsTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/name/AttributeTypeAndValueTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/name/RdnTest.java
directory/shared/branches/bigbang/ldap/src/test/java/org/apache/directory/shared/ldap/util/AttributeUtilsTest.java
Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ClonedServerEntry.java Thu Aug 14 16:12:09 2008
@@ -20,6 +20,9 @@
package org.apache.directory.server.core.entry;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -27,8 +30,10 @@
import javax.naming.NamingException;
+import org.apache.directory.shared.ldap.entry.Entry;
import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.DefaultClientEntry;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
@@ -75,7 +80,7 @@
/**
* @return the cloned Entry
*/
- public ServerEntry getClonedEntry()
+ public Entry getClonedEntry()
{
return clonedEntry;
}
@@ -399,6 +404,44 @@
}
+ public Entry toClientEntry() throws NamingException
+ {
+ // Copy the DN
+ Entry clientEntry = new DefaultClientEntry( clonedEntry.getDn() );
+
+ // Convert each attribute
+ for ( EntryAttribute clonedEntry:this )
+ {
+ EntryAttribute clientAttribute = ((ServerAttribute)clonedEntry).toClientAttribute();
+ clientEntry.add( clientAttribute );
+ }
+
+ return clientEntry;
+ }
+
+
+ /**
+ * @see java.io.Externalizable#readExternal(ObjectInput)
+ *
+ * We can't use this method for a ServerEntry
+ */
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+ {
+ throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
+ }
+
+
+ /**
+ * @see java.io.Externalizable#writeExternal(ObjectOutput)
+ *
+ * We can't use this method for a ServerEntry
+ */
+ public void writeExternal( ObjectOutput out ) throws IOException
+ {
+ throw new IllegalStateException( "Cannot use standard serialization for a ServerEntry" );
+ }
+
+
public ServerEntry clone()
{
return ( ServerEntry ) clonedEntry.clone();
@@ -676,9 +719,36 @@
return 0;
}
+
public ServerEntry clone()
{
return new EmptyEntry( dn );
}
+
+
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
+ {
+ }
+
+
+ public void writeExternal( ObjectOutput out ) throws IOException
+ {
+ }
+
+
+ public Entry toClientEntry() throws NamingException
+ {
+ // Copy the DN
+ Entry clientEntry = new DefaultClientEntry( dn );
+
+ // Convert each attribute
+ for ( EntryAttribute serverAttribute:this )
+ {
+ EntryAttribute clientAttribute = ((ServerAttribute)serverAttribute).toClientAttribute();
+ clientEntry.add( clientAttribute );
+ }
+
+ return clientEntry;
+ }
}
}
Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java?rev=686082&r1=686081&r2=686082&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/DefaultServerAttribute.java Thu Aug 14 16:12:09 2008
@@ -19,6 +19,10 @@
package org.apache.directory.server.core.entry;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.naming.NamingException;
import javax.naming.directory.InvalidAttributeValueException;
@@ -42,6 +46,8 @@
*/
public final class DefaultServerAttribute extends DefaultClientAttribute implements ServerAttribute
{
+ public static final long serialVersionUID = 1L;
+
/** logger for reporting errors that might not be handled properly upstream */
private static final Logger LOG = LoggerFactory.getLogger( DefaultServerAttribute.class );
@@ -49,9 +55,9 @@
private AttributeType attributeType;
- // -----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
// utility methods
- // -----------------------------------------------------------------------
+ //-----------------------------------------------------------------------
/**
* Private helper method used to set an UpId from an attributeType
*
@@ -71,381 +77,157 @@
}
+ //-------------------------------------------------------------------------
+ // Constructors
+ //-------------------------------------------------------------------------
/**
- * <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>
+ *
+ * Creates a new instance of DefaultServerAttribute, by copying
+ * another attribute, which can be a ClientAttribute. If the other
+ * attribute is a ServerAttribute, it will be copied.
*
- * @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
+ * @param attributeType The attribute's type
+ * @param attribute The attribute to be copied
*/
- public boolean instanceOf( String attributeId ) throws InvalidAttributeValueException
+ public DefaultServerAttribute( AttributeType attributeType, EntryAttribute attribute )
{
- String trimmedId = StringTools.trim( attributeId );
-
- if ( StringTools.isEmpty( trimmedId ) )
- {
- return false;
- }
-
- String normId = StringTools.lowerCaseAscii( trimmedId );
-
- for ( String name:attributeType.getNamesRef() )
+ // Copy the common values. isHR is only available on a ServerAttribute
+ this.attributeType = attributeType;
+ this.id = attribute.getId();
+ this.upId = attribute.getUpId();
+
+ if ( attribute instanceof ServerAttribute )
{
- if ( normId.equalsIgnoreCase( name ) )
+ isHR = attribute.isHR();
+
+ // Copy all the values
+ for ( Value<?> value:attribute )
{
- return true;
+ add( value.clone() );
}
}
-
- 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 id The attribute ID
- */
- public void setId( String id )
- {
- if ( !StringTools.isEmpty( StringTools.trim( id ) ) )
+ else
{
- if ( attributeType.getName() == null )
+
+ try
{
- // 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 );
- }
+ isHR = attributeType.getSyntax().isHumanReadable();
}
- else
+ catch ( NamingException ne )
{
- // 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.getNamesRef() )
+ // Do nothing : the syntax should always exist ...
+ }
+
+
+ // Copy all the values
+ for ( Value<?> clientValue:attribute )
+ {
+ Value<?> serverValue = null;
+
+ // We have to convert the value first
+ if ( clientValue instanceof ClientStringValue )
{
- if ( atName.equalsIgnoreCase( normId ) )
+ if ( isHR )
{
- // Found ! We can store the upId and get out
- super.setId( normId );
- return;
+ serverValue = new ServerStringValue( attributeType, (String)clientValue.get() );
+ }
+ else
+ {
+ // We have to convert the value to a binary value first
+ serverValue = new ServerBinaryValue( attributeType,
+ StringTools.getBytesUtf8( (String)clientValue.get() ) );
}
}
-
- // 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
+ else if ( clientValue instanceof ClientBinaryValue )
{
- // The id is incorrect : this is not allowed
- throw new IllegalArgumentException( "The ID '" + id + "'is incompatible with the AttributeType's id '" +
- attributeType.getName() + "'" );
+ if ( isHR )
+ {
+ // We have to convert the value to a String value first
+ serverValue = new ServerStringValue( attributeType,
+ StringTools.utf8ToString( (byte[])clientValue.get() ) );
+ }
+ else
+ {
+ serverValue = new ServerBinaryValue( attributeType, (byte[])clientValue.get() );
+ }
}
+
+ add( serverValue );
}
}
- else
- {
- throw new IllegalArgumentException( "An ID cannnot be null, empty, or resolved to an emtpy" +
- " value when trimmed" );
- }
}
+ // maybe have some additional convenience constructors which take
+ // an initial value as a string or a byte[]
/**
- * <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
+ * Create a new instance of a EntryAttribute, without ID nor value.
+ *
+ * @param attributeType the attributeType for the empty attribute added into the entry
*/
- public void setUpId( String upId )
+ public DefaultServerAttribute( AttributeType attributeType )
{
- if ( !StringTools.isEmpty( StringTools.trim( upId ) ) )
+ if ( attributeType == null )
{
- 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 atId:attributeType.getNamesRef() )
- {
- if ( atId.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 );
- }
- }
+ throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
+
+ setAttributeType( attributeType );
}
-
-
+
+
/**
- * <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
+ * Create a new instance of a EntryAttribute, without value.
+ *
+ * @param upId the ID for the added attributeType
+ * @param attributeType the added AttributeType
*/
- public void setUpId( String upId, AttributeType attributeType )
+ public DefaultServerAttribute( String upId, AttributeType attributeType )
{
- if ( StringTools.isEmpty( StringTools.trim( upId ) ) )
+ if ( attributeType == null )
{
- super.setUpId( getUpId( attributeType ) );
- this.attributeType = attributeType;
+ String message = "The AttributeType parameter should not be null";
+ LOG.error( message );
+ throw new IllegalArgumentException( message );
}
- 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 atId:attributeType.getNamesRef() )
- {
- if ( atId.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 attributeType 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[]
- /**
- * Create a new instance of a EntryAttribute, without ID nor value.
- *
- * @param attributeType the attributeType for the empty attribute added into the entry
- */
- public DefaultServerAttribute( AttributeType attributeType )
- {
- if ( attributeType == null )
- {
- throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
- }
-
- setAttributeType( attributeType );
- }
-
-
- /**
- * Create a new instance of a EntryAttribute, without value.
- *
- * @param upId the ID for the added attributeType
- * @param attributeType the added AttributeType
- */
- public DefaultServerAttribute( String upId, AttributeType attributeType )
- {
- if ( attributeType == null )
- {
- String message = "The AttributeType parameter should not be null";
- LOG.error( message );
- throw new IllegalArgumentException( message );
- }
-
- setAttributeType( attributeType );
- setUpId( upId );
- }
-
-
- /**
- * Doc me more!
- *
- * If the value does not correspond to the same attributeType, then it's
- * 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
- */
- public DefaultServerAttribute( AttributeType attributeType, Value<?>... vals )
- {
- this( null, attributeType, vals );
- }
-
-
- /**
- * Doc me more!
- *
- * If the value does not correspond to the same attributeType, then it's
- * 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.
- *
- * @param upId the ID of the added attribute
- * @param attributeType the attribute type according to the schema
- * @param vals an initial set of values for this attribute
- */
- public DefaultServerAttribute( String upId, AttributeType attributeType, Value<?>... vals )
- {
- if ( attributeType == null )
+
+ setAttributeType( attributeType );
+ setUpId( upId );
+ }
+
+
+ /**
+ * Doc me more!
+ *
+ * If the value does not correspond to the same attributeType, then it's
+ * 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
+ */
+ public DefaultServerAttribute( AttributeType attributeType, Value<?>... vals )
+ {
+ this( null, attributeType, vals );
+ }
+
+
+ /**
+ * Doc me more!
+ *
+ * If the value does not correspond to the same attributeType, then it's
+ * 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.
+ *
+ * @param upId the ID of the added attribute
+ * @param attributeType the attribute type according to the schema
+ * @param vals an initial set of values for this attribute
+ */
+ public DefaultServerAttribute( String upId, AttributeType attributeType, Value<?>... vals )
+ {
+ if ( attributeType == null )
{
throw new IllegalArgumentException( "The AttributeType parameter should not be null" );
}
@@ -520,70 +302,115 @@
}
- /**
- * 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
- *
- * @return a clone of the current attribute
- */
- public ServerAttribute clone()
- {
- // clone the structure by cloner the inherited class
- ServerAttribute clone = (ServerAttribute)super.clone();
-
- // We are done !
- return clone;
- }
-
-
+ //-------------------------------------------------------------------------
+ // API
+ //-------------------------------------------------------------------------
/**
* <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.
+ * Adds some values to this attribute. If the new values are already present in
+ * the attribute values, the method has no effect.
* </p>
- *
- * @param isHR <code>true</code> for a Human Readable attribute,
- * <code>false</code> for a Binary attribute.
- */
- public void setHR( boolean isHR )
- {
- // Do nothing...
- }
-
-
- /**
* <p>
- * Checks to see if this attribute is valid along with the values it contains.
+ * The new values are added at the end of list of values.
* </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
+ * 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 vals 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 isValid() throws NamingException
+ public int add( byte[]... vals )
{
- // 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 ( Value<?> value : values )
+ if ( !isHR )
{
- if ( ! value.isValid() )
+ int nbAdded = 0;
+
+ for ( byte[] val:vals )
{
- return false;
+ Value<?> value = new ServerBinaryValue( attributeType, val );
+
+ try
+ {
+ value.normalize();
+ }
+ catch( NamingException ne )
+ {
+ // The value can't be normalized : we don't add it.
+ LOG.error( "The value '" + val + "' can't be normalized, it hasn't been added" );
+ return 0;
+ }
+
+ if ( add( value ) != 0 )
+ {
+ nbAdded++;
+ }
+ else
+ {
+ LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ }
}
+
+ return nbAdded;
}
+ else
+ {
+ // We can't add Binary values into a String serverAttribute
+ return 0;
+ }
+ }
- return true;
- }
+
+ /**
+ * <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 vals 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( String... vals )
+ {
+ if ( isHR )
+ {
+ int nbAdded = 0;
+
+ for ( String val:vals )
+ {
+ if ( add( new ServerStringValue( attributeType, val ) ) != 0 )
+ {
+ nbAdded++;
+ }
+ else
+ {
+ LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ }
+ }
+
+ return nbAdded;
+ }
+ else
+ {
+ // We can't add String values into a Binary serverAttribute
+ return 0;
+ }
+ }
/**
@@ -693,111 +520,101 @@
/**
+ * Remove all the values from this attribute type, including a
+ * null value.
+ */
+ public void clear()
+ {
+ values.clear();
+ }
+
+
+ /**
* <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.
+ * 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>
- * This method returns the number of values that were added.
+ * If the Attribute is HR, this method will returns <code>false</code>
* </p>
- * If the value's type is different from the attribute's type,
- * the value is not added.
*
- * @param vals some new values to be added which may be null
- * @return the number of added values, or 0 if none has been added
+ * @param vals the values
+ * @return true if this attribute contains all the values, otherwise false
*/
- public int add( String... vals )
+ public boolean contains( byte[]... vals )
{
- if ( isHR )
+ if ( !isHR )
{
- int nbAdded = 0;
-
- for ( String val:vals )
+ // Iterate through all the values, and quit if we
+ // don't find one in the values
+ for ( byte[] val:vals )
{
- if ( add( new ServerStringValue( attributeType, val ) ) != 0 )
+ ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
+
+ try
{
- nbAdded++;
+ value.normalize();
}
- else
+ catch ( NamingException ne )
{
- LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ return false;
+ }
+
+ if ( !values.contains( value ) )
+ {
+ return false;
}
}
- return nbAdded;
+ return true;
}
else
{
- // We can't add String values into a Binary serverAttribute
- return 0;
+ return false;
}
- }
+ }
/**
* <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.
+ * 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 value's type is different from the attribute's type,
- * the value is not added.
+ * If the Attribute is not HR, this method will returns <code>false</code>
* </p>
- * It's the responsibility of the caller to check if the stored
- * values are consistent with the attribute's type.
- * <p>
*
- * @param vals some new values to be added which may be null
- * @return the number of added values, or 0 if none has been added
+ * @param vals the values
+ * @return true if this attribute contains all the values, otherwise false
*/
- public int add( byte[]... vals )
+ public boolean contains( String... vals )
{
- if ( !isHR )
+ if ( isHR )
{
- int nbAdded = 0;
-
- for ( byte[] val:vals )
+ // Iterate through all the values, and quit if we
+ // don't find one in the values
+ for ( String val:vals )
{
- if ( add( new ServerBinaryValue( attributeType, val ) ) != 0 )
- {
- nbAdded++;
- }
- else
+ ServerStringValue value = new ServerStringValue( attributeType, val );
+
+ if ( !values.contains( value ) )
{
- LOG.error( "The value '" + val + "' is incorrect, it hasn't been added" );
+ return false;
}
}
- return nbAdded;
+ return true;
}
else
{
- // We can't add Binary values into a String serverAttribute
- return 0;
+ return false;
}
- }
+ }
/**
- * Remove all the values from this attribute type, including a
- * null value.
- */
- public void clear()
- {
- values.clear();
- }
-
-
- /**
* <p>
* Indicates whether the specified values are some of the attribute's values.
* </p>
@@ -840,230 +657,667 @@
return false;
}
}
- }
- else
- {
- for ( Value<?> val:vals )
+ }
+ else
+ {
+ for ( Value<?> val:vals )
+ {
+ if ( val instanceof ClientBinaryValue )
+ {
+ if ( !values.contains( val ) )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Not a Binary value
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Get the attribute type associated with this ServerAttribute.
+ *
+ * @return the attributeType associated with this entry attribute
+ */
+ public AttributeType getAttributeType()
+ {
+ return attributeType;
+ }
+
+
+ /**
+ * <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.getNamesRef() )
+ {
+ if ( normId.equalsIgnoreCase( name ) )
+ {
+ return true;
+ }
+ }
+
+ return normId.equalsIgnoreCase( attributeType.getOid() );
+ }
+
+
+ /**
+ * <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
+ {
+ // 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 ( Value<?> value : values )
+ {
+ if ( ! value.isValid() )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * @see EntryAttribute#remove(byte[]...)
+ *
+ * @return <code>true</code> if all the values shave been removed from this attribute
+ */
+ public boolean remove( byte[]... vals )
+ {
+ if ( isHR )
+ {
+ return false;
+ }
+
+ boolean removed = true;
+
+ for ( byte[] val:vals )
+ {
+ ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
+ removed &= values.remove( value );
+ }
+
+ return removed;
+ }
+
+
+ /**
+ * @see EntryAttribute#remove(String...)
+ *
+ * @return <code>true</code> if all the values shave been removed from this attribute
+ */
+ public boolean remove( String... vals )
+ {
+ if ( !isHR )
+ {
+ return false;
+ }
+
+ boolean removed = true;
+
+ for ( String val:vals )
+ {
+ ServerStringValue value = new ServerStringValue( attributeType, val );
+ removed &= values.remove( value );
+ }
+
+ return removed;
+ }
+
+
+ /**
+ * @see EntryAttribute#remove(org.apache.directory.shared.ldap.entry.Value...)
+ *
+ * @return <code>true</code> if all the values shave been removed from this attribute
+ */
+ public boolean remove( Value<?>... vals )
+ {
+ boolean removed = true;
+
+ // Loop through all the values to remove. If one of
+ // them is not present, the method will return false.
+ // 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
+ {
+ 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;
+ }
+
+
+
+ /**
+ * <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 attributeType 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;
+ }
+ }
+
+
+ /**
+ * <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 void setHR( boolean isHR )
+ {
+ // Do nothing...
+ }
+
+
+ /**
+ * <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 id The attribute ID
+ */
+ 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.getNamesRef() )
+ {
+ 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
+ */
+ 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 atId:attributeType.getNamesRef() )
+ {
+ if ( atId.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
{
- if ( val instanceof ClientBinaryValue )
+ // 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 atId:attributeType.getNamesRef() )
{
- if ( !values.contains( val ) )
+ if ( atId.equalsIgnoreCase( normUpId ) )
{
- return false;
+ // 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
{
- // Not a Binary value
- return false;
+ 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 );
}
}
}
-
- return true;
}
/**
- * <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>
+ * Convert the ServerAttribute to a ClientAttribute
*
- * @param vals the values
- * @return true if this attribute contains all the values, otherwise false
+ * @return An instance of ClientAttribute
*/
- public boolean contains( String... vals )
+ public EntryAttribute toClientAttribute()
{
- if ( isHR )
+ // Create the new EntryAttribute
+ EntryAttribute clientAttribute = new DefaultClientAttribute( upId );
+
+ // Copy the values
+ for ( Value<?> value:this )
{
- // Iterate through all the values, and quit if we
- // don't find one in the values
- for ( String val:vals )
+ Value<?> clientValue = null;
+
+ if ( value instanceof ServerStringValue )
{
- ServerStringValue value = new ServerStringValue( attributeType, val );
-
- if ( !values.contains( value ) )
- {
- return false;
- }
+ clientValue = new ClientStringValue( (String)value.get() );
+ }
+ else
+ {
+ clientValue = new ClientBinaryValue( (byte[])value.get() );
}
- return true;
- }
- else
- {
- return false;
+ clientAttribute.add( clientValue );
}
+
+ return clientAttribute;
}
-
+
+
+ //-------------------------------------------------------------------------
+ // Serialization methods
+ //-------------------------------------------------------------------------
/**
- * <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>
- *
- * @param vals the values
- * @return true if this attribute contains all the values, otherwise false
+ * @see java.io.Externalizable#writeExternal(ObjectOutput)
+ *
+ * We can't use this method for a ServerAttribute, as we have to feed the value
+ * with an AttributeType object
*/
- public boolean contains( byte[]... vals )
+ public void writeExternal( ObjectOutput out ) throws IOException
{
- if ( !isHR )
- {
- // 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
- {
- return false;
- }
+ throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
}
/**
- * @see EntryAttribute#remove(org.apache.directory.shared.ldap.entry.Value...)
+ * @see Externalizable#writeExternal(ObjectOutput)
+ * <p>
+ *
+ * This is the place where we serialize attributes, and all theirs
+ * elements.
+ *
+ * The inner structure is the same as the client attribute, but we can't call
+ * it as we won't be able to serialize the serverValues
*
- * @return <code>true</code> if all the values shave been removed from this attribute
*/
- public boolean remove( Value<?>... vals )
+ public void serialize( ObjectOutput out ) throws IOException
{
- boolean removed = true;
+ // Write the UPId (the id will be deduced from the upID)
+ out.writeUTF( upId );
- // Loop through all the values to remove. If one of
- // them is not present, the method will return false.
- // As the attribute may be HR or not, we have two separated treatments
- if ( isHR )
+ // Write the HR flag, if not null
+ if ( isHR != null )
{
- 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;
- }
- }
+ out.writeBoolean( true );
+ out.writeBoolean( isHR );
}
else
{
- for ( Value<?> val:vals )
+ out.writeBoolean( false );
+ }
+
+ // Write the number of values
+ out.writeInt( size() );
+
+ if ( size() > 0 )
+ {
+ // Write each value
+ for ( Value<?> value:values )
{
- if ( val instanceof ClientBinaryValue )
- {
- ServerBinaryValue sbv = new ServerBinaryValue( attributeType, (byte[])val.get() );
- removed &= values.remove( sbv );
- }
- else if ( val instanceof ServerBinaryValue )
+ // Write the value, using the correct method
+ if ( value instanceof ServerStringValue )
{
- removed &= values.remove( val );
+ ((ServerStringValue)value).serialize( out );
}
else
{
- removed = false;
+ ((ServerBinaryValue)value).serialize( out );
}
}
}
- return removed;
+ out.flush();
}
-
+
/**
- * @see EntryAttribute#remove(byte[]...)
+ * @see java.io.Externalizable#readExternal(ObjectInput)
*
- * @return <code>true</code> if all the values shave been removed from this attribute
+ * We can't use this method for a ServerAttribute, as we have to feed the value
+ * with an AttributeType object
*/
- public boolean remove( byte[]... vals )
+ public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
{
- if ( isHR )
- {
- return false;
- }
-
- boolean removed = true;
-
- for ( byte[] val:vals )
- {
- ServerBinaryValue value = new ServerBinaryValue( attributeType, val );
- removed &= values.remove( value );
- }
-
- return removed;
+ throw new IllegalStateException( "Cannot use standard serialization for a ServerAttribute" );
}
-
-
+
+
/**
- * @see EntryAttribute#remove(String...)
- *
- * @return <code>true</code> if all the values shave been removed from this attribute
+ * @see Externalizable#readExternal(ObjectInput)
*/
- public boolean remove( String... vals )
+ public void deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
{
- if ( !isHR )
- {
- return false;
- }
+ // Read the ID and the UPId
+ upId = in.readUTF();
- boolean removed = true;
+ // Compute the id
+ setUpId( upId );
- for ( String val:vals )
+ // Read the HR flag, if not null
+ if ( in.readBoolean() )
{
- ServerStringValue value = new ServerStringValue( attributeType, val );
- removed &= values.remove( value );
+ isHR = in.readBoolean();
}
-
- return removed;
- }
+ // Read the number of values
+ int nbValues = in.readInt();
+ if ( nbValues > 0 )
+ {
+ for ( int i = 0; i < nbValues; i++ )
+ {
+ Value<?> value = null;
+
+ if ( isHR )
+ {
+ value = new ServerStringValue( attributeType );
+ ((ServerStringValue)value).deserialize( in );
+ }
+ else
+ {
+ value = new ServerBinaryValue( attributeType );
+ ((ServerBinaryValue)value).deserialize( in );
+ }
+
+ try
+ {
+ value.normalize();
+ }
+ catch ( NamingException ne )
+ {
+ // Do nothing...
+ }
+
+ values.add( value );
+ }
+ }
+ }
+
+
//-------------------------------------------------------------------------
- // Overloaded Object classes
+ // Overloaded Object class methods
//-------------------------------------------------------------------------
/**
- * The hashCode is based on the id, the isHR flag and
- * on the internal values.
- *
- * @see Object#hashCode()
+ * 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
*
- * @return the instance's hash code
+ * @return a clone of the current attribute
*/
- public int hashCode()
+ public ServerAttribute clone()
{
- int h = super.hashCode();
-
- if ( attributeType != null )
- {
- h = h*17 + attributeType.hashCode();
- }
+ // clone the structure by cloner the inherited class
+ ServerAttribute clone = (ServerAttribute)super.clone();
- return h;
+ // We are done !
+ return clone;
}
@@ -1109,6 +1363,27 @@
/**
+ * The hashCode is based on the id, the isHR flag and
+ * on the internal values.
+ *
+ * @see Object#hashCode()
+ *
+ * @return the instance's hash code
+ */
+ public int hashCode()
+ {
+ int h = super.hashCode();
+
+ if ( attributeType != null )
+ {
+ h = h*17 + attributeType.hashCode();
+ }
+
+ return h;
+ }
+
+
+ /**
* @see Object#toString()
*
* @return A String representation of this instance