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 [4/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/ServerEntryUtils.java
URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.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/ServerEntryUtils.java (original)
+++ directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java Mon Mar 17 23:12:41 2008
@@ -18,7 +18,12 @@
*/
package org.apache.directory.server.core.entry;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
@@ -26,15 +31,23 @@
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.DirContext;
import javax.naming.directory.InvalidAttributeIdentifierException;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchResult;
+import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
import org.apache.directory.server.schema.registries.Registries;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.Modification;
+import org.apache.directory.shared.ldap.entry.ModificationOperation;
+import org.apache.directory.shared.ldap.entry.Value;
import org.apache.directory.shared.ldap.message.AttributeImpl;
import org.apache.directory.shared.ldap.message.AttributesImpl;
import org.apache.directory.shared.ldap.message.ModificationItemImpl;
import org.apache.directory.shared.ldap.name.LdapDN;
import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.util.EmptyEnumeration;
+import org.apache.directory.shared.ldap.util.StringTools;
/**
* A helper class used to manipulate Entries, Attributes and Values.
@@ -62,13 +75,23 @@
for ( AttributeType attributeType:entry.getAttributeTypes() )
{
- Attribute attribute = new AttributeImpl( attributeType.getName() );
-
ServerAttribute attr = entry.get( attributeType );
- for ( Iterator<ServerValue<?>> iter = attr.iterator(); iter.hasNext();)
+ // Deal with a special case : an entry without any ObjectClass
+ if ( attributeType.getOid() == SchemaConstants.OBJECT_CLASS_AT_OID )
+ {
+ if ( attr.size() == 0 )
+ {
+ // We don't have any objectClass, just dismiss this element
+ continue;
+ }
+ }
+
+ Attribute attribute = new AttributeImpl( attributeType.getName() );
+
+ for ( Iterator<Value<?>> iter = attr.iterator(); iter.hasNext();)
{
- ServerValue<?> value = iter.next();
+ Value<?> value = iter.next();
attribute.add( value.get() );
}
@@ -105,17 +128,35 @@
{
Object value = values.nextElement();
- if ( value instanceof String )
+ if ( serverAttribute.isHR() )
{
- serverAttribute.add( (String)value );
- }
- else if ( value instanceof byte[] )
- {
- serverAttribute.add( (byte[])value );
+ if ( value instanceof String )
+ {
+ serverAttribute.add( (String)value );
+ }
+ else if ( value instanceof byte[] )
+ {
+ serverAttribute.add( StringTools.utf8ToString( (byte[])value ) );
+ }
+ else
+ {
+ return null;
+ }
}
else
{
- return null;
+ if ( value instanceof String )
+ {
+ serverAttribute.add( StringTools.getBytesUtf8( (String)value ) );
+ }
+ else if ( value instanceof byte[] )
+ {
+ serverAttribute.add( (byte[])value );
+ }
+ else
+ {
+ return null;
+ }
}
}
@@ -151,7 +192,11 @@
{
Attribute attr = attrs.nextElement();
- AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( attr.getID() );
+ String attributeId = attr.getID();
+ String id = stripOptions( attributeId );
+ Set<String> options = getOptions( attributeId );
+ // TODO : handle options.
+ AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
ServerAttribute serverAttribute = ServerEntryUtils.toServerAttribute( attr, attributeType );
if ( serverAttribute != null )
@@ -191,9 +236,9 @@
ServerAttribute attr = entry.get( attributeType );
- for ( Iterator<ServerValue<?>> iter = attr.iterator(); iter.hasNext();)
+ for ( Iterator<Value<?>> iter = attr.iterator(); iter.hasNext();)
{
- ServerValue<?> value = iter.next();
+ Value<?> value = iter.next();
attribute.add( value );
}
@@ -213,7 +258,7 @@
{
Attribute attribute = new BasicAttribute( attr.getUpId(), false );
- for ( ServerValue<?> value:attr )
+ for ( Value<?> value:attr )
{
attribute.add( value.get() );
}
@@ -231,7 +276,7 @@
{
Attribute attribute = new AttributeImpl( attr.getUpId() );
- for ( ServerValue<?> value:attr )
+ for ( Value<?> value:attr )
{
attribute.add( value.get() );
}
@@ -249,21 +294,21 @@
* @return the resultant entry after the modification has taken place
* @throws NamingException if there are problems accessing attributes
*/
- public static ServerEntry getTargetEntry( ModificationItemImpl mod, ServerEntry entry, Registries registries ) throws NamingException
+ public static ServerEntry getTargetEntry( Modification mod, ServerEntry entry, Registries registries ) throws NamingException
{
ServerEntry targetEntry = ( ServerEntry ) entry.clone();
- int modOp = mod.getModificationOp();
- String id = mod.getAttribute().getID();
+ ModificationOperation modOp = mod.getOperation();
+ String id = mod.getAttribute().getId();
AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
switch ( modOp )
{
- case ( DirContext.REPLACE_ATTRIBUTE ):
- targetEntry.put( toServerAttribute( mod.getAttribute(), attributeType ) );
+ case REPLACE_ATTRIBUTE :
+ targetEntry.put( (ServerAttribute)mod.getAttribute() );
break;
- case ( DirContext.REMOVE_ATTRIBUTE ):
- ServerAttribute toBeRemoved = toServerAttribute( mod.getAttribute(), attributeType );
+ case REMOVE_ATTRIBUTE :
+ ServerAttribute toBeRemoved = (ServerAttribute)mod.getAttribute();
if ( toBeRemoved.size() == 0 )
{
@@ -275,7 +320,7 @@
if ( existing != null )
{
- for ( ServerValue<?> value:toBeRemoved )
+ for ( Value<?> value:toBeRemoved )
{
existing.remove( value );
}
@@ -283,20 +328,20 @@
}
break;
- case ( DirContext.ADD_ATTRIBUTE ):
+ case ADD_ATTRIBUTE :
ServerAttribute combined = new DefaultServerAttribute( id, attributeType );
- ServerAttribute toBeAdded = toServerAttribute( mod.getAttribute(), attributeType );
+ ServerAttribute toBeAdded = (ServerAttribute)mod.getAttribute();
ServerAttribute existing = entry.get( id );
if ( existing != null )
{
- for ( ServerValue<?> value:existing )
+ for ( Value<?> value:existing )
{
combined.add( value );
}
}
- for ( ServerValue<?> value:toBeAdded )
+ for ( Value<?> value:toBeAdded )
{
combined.add( value );
}
@@ -309,5 +354,326 @@
}
return targetEntry;
+ }
+
+
+ /**
+ * Creates a new attribute which contains the values representing the union
+ * of two attributes. If one attribute is null then the resultant attribute
+ * returned is a copy of the non-null attribute. If both are null then we
+ * cannot determine the attribute ID and an {@link IllegalArgumentException}
+ * is raised.
+ *
+ * @param attr0 the first attribute
+ * @param attr1 the second attribute
+ * @return a new attribute with the union of values from both attribute
+ * arguments
+ * @throws NamingException if there are problems accessing attribute values
+ */
+ public static ServerAttribute getUnion( ServerAttribute attr0, ServerAttribute attr1 ) throws NamingException
+ {
+ if ( attr0 == null && attr1 == null )
+ {
+ throw new IllegalArgumentException( "Cannot figure out attribute ID if both args are null" );
+ }
+ else if ( attr0 == null )
+ {
+ return (ServerAttribute)attr1.clone();
+ }
+ else if ( attr1 == null )
+ {
+ return (ServerAttribute)attr0.clone();
+ }
+ else if ( !attr0.getAttributeType().equals( attr1.getAttributeType() ) )
+ {
+ throw new IllegalArgumentException( "Cannot take union of attributes with different IDs!" );
+ }
+
+ ServerAttribute attr = (ServerAttribute)attr0.clone();
+
+ if ( attr0 != null )
+ {
+ for ( Value<?> value:attr1 )
+ {
+ attr.add( value );
+ }
+ }
+
+ return attr;
+ }
+
+
+ public static ModificationItemImpl toModificationItemImpl( Modification modification )
+ {
+ ModificationItemImpl modificationItem = new ModificationItemImpl(
+ modification.getOperation().getValue(),
+ toAttributeImpl( (ServerAttribute)modification.getAttribute() ) );
+
+ return modificationItem;
+
+ }
+
+
+ public static Modification toModification( ModificationItemImpl modificationImpl, AttributeType attributeType ) throws InvalidAttributeIdentifierException
+ {
+ Modification modification = new ServerModification(
+ modificationImpl.getModificationOp(),
+ ServerEntryUtils.toServerAttribute( modificationImpl.getAttribute(), attributeType ) );
+
+ return modification;
+
+ }
+
+
+ public static List<ModificationItemImpl> toModificationItemImpl( List<Modification> modifications )
+ {
+ if ( modifications != null )
+ {
+ List<ModificationItemImpl> modificationItems = new ArrayList<ModificationItemImpl>();
+
+ for ( Modification modification: modifications )
+ {
+ modificationItems.add( toModificationItemImpl( modification ) );
+ }
+
+ return modificationItems;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ public static List<Modification> toServerModification( List<ModificationItemImpl> modificationImpls, AttributeTypeRegistry atRegistry )
+ throws NamingException
+ {
+ if ( modificationImpls != null )
+ {
+ List<Modification> modifications = new ArrayList<Modification>();
+
+ for ( ModificationItemImpl modificationImpl: modificationImpls )
+ {
+ AttributeType attributeType = atRegistry.lookup( modificationImpl.getAttribute().getID() );
+ modifications.add( toModification( modificationImpl, attributeType ) );
+ }
+
+ return modifications;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ public static List<Modification> toServerModification( ModificationItem[] modifications, AttributeTypeRegistry atRegistry )
+ throws NamingException
+ {
+ if ( modifications != null )
+ {
+ List<Modification> modificationsList = new ArrayList<Modification>();
+
+ for ( ModificationItem modification: modifications )
+ {
+ String attributeId = modification.getAttribute().getID();
+ String id = stripOptions( attributeId );
+ Set<String> options = getOptions( attributeId );
+ // TODO : handle options
+ AttributeType attributeType = atRegistry.lookup( id );
+ modificationsList.add( toModification( (ModificationItemImpl)modification, attributeType ) );
+ }
+
+ return modificationsList;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ /**
+ * Utility method to extract a modification item from an array of modifications.
+ *
+ * @param mods the array of ModificationItems to extract the Attribute from.
+ * @param type the attributeType spec of the Attribute to extract
+ * @return the modification item on the attributeType specified
+ */
+ public static final Modification getModificationItem( List<Modification> mods, AttributeType type )
+ {
+ for ( Modification modification:mods )
+ {
+ ServerAttribute attribute = (ServerAttribute)modification.getAttribute();
+
+ if ( attribute.getAttributeType() == type )
+ {
+ return modification;
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Utility method to extract an attribute from a list of modifications.
+ *
+ * @param mods the list of ModificationItems to extract the Attribute from.
+ * @param type the attributeType spec of the Attribute to extract
+ * @return the extract Attribute or null if no such attribute exists
+ */
+ public static ServerAttribute getAttribute( List<Modification> mods, AttributeType type )
+ {
+ Modification mod = getModificationItem( mods, type );
+
+ if ( mod != null )
+ {
+ return (ServerAttribute)mod.getAttribute();
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Encapsulate a ServerSearchResult enumeration into a SearchResult enumeration
+ * @param result The ServerSearchResult enumeration
+ * @return A SearchResultEnumeration
+ */
+ public static NamingEnumeration<SearchResult> toSearchResultEnum( final NamingEnumeration<ServerSearchResult> result )
+ {
+ if ( result instanceof EmptyEnumeration<?> )
+ {
+ return new EmptyEnumeration<SearchResult>();
+ }
+
+ return new NamingEnumeration<SearchResult> ()
+ {
+ public void close() throws NamingException
+ {
+ result.close();
+ }
+
+
+ /**
+ * @see javax.naming.NamingEnumeration#hasMore()
+ */
+ public boolean hasMore() throws NamingException
+ {
+ return result.hasMore();
+ }
+
+
+ /**
+ * @see javax.naming.NamingEnumeration#next()
+ */
+ public SearchResult next() throws NamingException
+ {
+ ServerSearchResult rec = result.next();
+
+ SearchResult searchResult = new SearchResult(
+ rec.getDn().getUpName(),
+ rec.getObject(),
+ toAttributesImpl( rec.getServerEntry() ),
+ rec.isRelative() );
+
+ return searchResult;
+ }
+
+
+ /**
+ * @see java.util.Enumeration#hasMoreElements()
+ */
+ public boolean hasMoreElements()
+ {
+ return result.hasMoreElements();
+ }
+
+
+ /**
+ * @see java.util.Enumeration#nextElement()
+ */
+ public SearchResult nextElement()
+ {
+ try
+ {
+ ServerSearchResult rec = result.next();
+
+ SearchResult searchResult = new SearchResult(
+ rec.getDn().getUpName(),
+ rec.getObject(),
+ toAttributesImpl( rec.getServerEntry() ),
+ rec.isRelative() );
+
+ return searchResult;
+ }
+ catch ( NamingException ne )
+ {
+ NoSuchElementException nsee =
+ new NoSuchElementException( "Encountered NamingException on underlying enumeration." );
+ nsee.initCause( ne );
+ throw nsee;
+ }
+ }
+ };
+ }
+
+
+ /**
+ * Remove the options from the attributeType, and returns the ID.
+ *
+ * RFC 4512 :
+ * attributedescription = attributetype options
+ * attributetype = oid
+ * options = *( SEMI option )
+ * option = 1*keychar
+ */
+ private static String stripOptions( String attributeId )
+ {
+ int optionsPos = attributeId.indexOf( ";" );
+
+ if ( optionsPos != -1 )
+ {
+ return attributeId.substring( 0, optionsPos );
+ }
+ else
+ {
+ return attributeId;
+ }
+ }
+
+ /**
+ * Get the options from the attributeType.
+ *
+ * For instance, given :
+ * jpegphoto;binary;lang=jp
+ *
+ * your get back a set containing { "binary", "lang=jp" }
+ */
+ private static Set<String> getOptions( String attributeId )
+ {
+ int optionsPos = attributeId.indexOf( ";" );
+
+ if ( optionsPos != -1 )
+ {
+ Set<String> options = new HashSet<String>();
+
+ String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
+
+ for ( String option:res )
+ {
+ if ( !StringTools.isEmpty( option ) )
+ {
+ options.add( option );
+ }
+ }
+
+ return options;
+ }
+ else
+ {
+ return null;
+ }
}
}
Modified: directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java
URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.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/ServerModification.java (original)
+++ directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerModification.java Mon Mar 17 23:12:41 2008
@@ -19,10 +19,9 @@
*/
package org.apache.directory.server.core.entry;
-import java.io.Serializable;
-
import javax.naming.directory.DirContext;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
import org.apache.directory.shared.ldap.entry.Modification;
import org.apache.directory.shared.ldap.entry.ModificationOperation;
@@ -33,7 +32,7 @@
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
-public class ServerModification<T extends ServerAttribute> implements Modification<T>, Serializable
+public class ServerModification implements Modification
{
public static final long serialVersionUID = 1L;
@@ -41,9 +40,23 @@
private ModificationOperation operation;
/** The attribute which contains the modification */
- private T attribute;
+ private ServerAttribute attribute;
+ public ServerModification( ModificationOperation operation, ServerAttribute attribute )
+ {
+ this.operation = operation;
+ this.attribute = attribute;
+ }
+
+
+ public ServerModification( int operation, ServerAttribute attribute )
+ {
+ setOperation( operation );
+ this.attribute = attribute;
+ }
+
+
/**
* @return the operation
*/
@@ -64,12 +77,15 @@
{
case DirContext.ADD_ATTRIBUTE :
this.operation = ModificationOperation.ADD_ATTRIBUTE;
+ break;
case DirContext.REPLACE_ATTRIBUTE :
this.operation = ModificationOperation.REPLACE_ATTRIBUTE;
+ break;
case DirContext.REMOVE_ATTRIBUTE :
this.operation = ModificationOperation.REMOVE_ATTRIBUTE;
+ break;
}
}
@@ -88,7 +104,7 @@
/**
* @return the attribute containing the modifications
*/
- public T getAttribute()
+ public EntryAttribute getAttribute()
{
return attribute;
}
@@ -99,9 +115,9 @@
*
* @param attribute The modified attribute
*/
- public void setAttribute( T attribute )
+ public void setAttribute( EntryAttribute attribute )
{
- this.attribute = attribute;
+ this.attribute = (ServerAttribute)attribute;
}
@@ -118,6 +134,21 @@
return h;
}
+
+ public ServerModification clone()
+ {
+ try
+ {
+ ServerModification clone = (ServerModification)super.clone();
+
+ clone.attribute = (ServerAttribute)this.attribute.clone();
+ return clone;
+ }
+ catch ( CloneNotSupportedException cnse )
+ {
+ return null;
+ }
+ }
/**
* @see Object#toString()
Modified: directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java
URL: http://svn.apache.org/viewvc/directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.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/ServerStringValue.java (original)
+++ directory/sandbox/akarasulu/bigbang/apacheds/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerStringValue.java Mon Mar 17 23:12:41 2008
@@ -20,7 +20,8 @@
import org.apache.directory.shared.ldap.NotImplementedException;
-import org.apache.directory.shared.ldap.entry.AbstractStringValue;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.entry.client.ClientStringValue;
import org.apache.directory.shared.ldap.schema.AttributeType;
import org.apache.directory.shared.ldap.schema.MatchingRule;
import org.apache.directory.shared.ldap.schema.Normalizer;
@@ -45,7 +46,7 @@
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
* @version $Rev$, $Date$
*/
-public class ServerStringValue extends AbstractStringValue implements ServerValue<String>, Externalizable
+public class ServerStringValue extends ClientStringValue
{
/** Used for serialization */
public static final long serialVersionUID = 2L;
@@ -56,13 +57,50 @@
/** reference to the attributeType which is not serialized */
private transient AttributeType attributeType;
- /** the canonical representation of the wrapped String value */
- private String normalizedValue;
- /** cached results of the isValid() method call */
- private transient Boolean valid;
+ // -----------------------------------------------------------------------
+ // utility methods
+ // -----------------------------------------------------------------------
+ /**
+ * Utility method to get some logs if an assert fails
+ */
+ protected String logAssert( String message )
+ {
+ LOG.error( message );
+ return message;
+ }
+
+ /**
+ * Check the attributeType member. It should not be null,
+ * and it should contains a syntax.
+ */
+ protected String checkAttributeType( 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";
+ }
+ }
+
+
+ // -----------------------------------------------------------------------
+ // Constructors
+ // -----------------------------------------------------------------------
/**
* Creates a ServerStringValue without an initial wrapped value.
*
@@ -70,7 +108,8 @@
*/
public ServerStringValue( AttributeType attributeType )
{
- assert checkAttributeType( attributeType) == null : logAssert( checkAttributeType( attributeType ) );
+ super();
+ assert checkAttributeType( attributeType ) == null : logAssert( checkAttributeType( attributeType ) );
try
{
@@ -98,36 +137,42 @@
public ServerStringValue( AttributeType attributeType, String wrapped )
{
this( attributeType );
- super.set( wrapped );
+ this.wrapped = wrapped;
}
- // -----------------------------------------------------------------------
- // Value<String> Methods
- // -----------------------------------------------------------------------
-
-
/**
- * Sets the wrapped String value. Has the side effect of setting the
- * normalizedValue and the valid flags to null if the wrapped value is
- * different than what is already set. These cached values must be
- * recomputed to be correct with different values.
+ * Creates a ServerStringValue with an initial wrapped String value and
+ * a normalized value.
*
- * @see ServerValue#set(Object)
+ * @param attributeType the schema type associated with this ServerStringValue
+ * @param wrapped the value to wrap which can be null
+ * @param normalizedValue the normalized value
*/
- public final void set( String wrapped )
+ /** No protection */ ServerStringValue( AttributeType attributeType, String wrapped, String normalizedValue, boolean valid )
{
- // Why should we invalidate the normalized value if it's we're setting the
- // wrapper to it's current value?
- if ( ( wrapped != null ) && wrapped.equals( get() ) )
- {
- return;
- }
+ super( wrapped );
+ this.normalized = true;
+ this.attributeType = attributeType;
+ this.normalizedValue = normalizedValue;
+ this.valid = valid;
+ }
+
- normalizedValue = null;
- valid = null;
- super.set( wrapped );
+ // -----------------------------------------------------------------------
+ // Value<String> Methods, overloaded
+ // -----------------------------------------------------------------------
+ /**
+ * @return a copy of the current value
+ */
+ public ServerStringValue clone()
+ {
+ ServerStringValue clone = (ServerStringValue)super.clone();
+
+ return clone;
}
+
+
// -----------------------------------------------------------------------
@@ -141,17 +186,26 @@
*/
public void normalize() throws NamingException
{
+ // If the value is already normalized, get out.
+ if ( normalized )
+ {
+ return;
+ }
+
Normalizer normalizer = getNormalizer();
if ( normalizer == null )
{
- normalizedValue = get();
+ normalizedValue = wrapped;
}
else
{
- normalizedValue = ( String ) normalizer.normalize( get() );
+ normalizedValue = ( String ) normalizer.normalize( wrapped );
}
+
+ normalized = true;
}
+
/**
* Gets the normalized (canonical) representation for the wrapped string.
@@ -164,16 +218,26 @@
* @return gets the normalized value
* @throws NamingException if the value cannot be properly normalized
*/
- public String getNormalized() throws NamingException
+ public String getNormalizedValue()
{
if ( isNull() )
{
+ normalized = true;
return null;
}
- if ( normalizedValue == null )
+ if ( !normalized )
{
- normalize();
+ try
+ {
+ normalize();
+ }
+ catch ( NamingException ne )
+ {
+ String message = "Cannot normalize the value :" + ne.getMessage();
+ LOG.warn( message );
+ normalized = false;
+ }
}
return normalizedValue;
@@ -187,26 +251,36 @@
* change. Syntax checks only result on the first check, and when the wrapped
* value changes.
*
- * @see ServerValue#isValid()
+ * @see Value<T>#isValid()
*/
- public final boolean isValid() throws NamingException
+ public final boolean isValid()
{
if ( valid != null )
{
return valid;
}
- valid = attributeType.getSyntax().getSyntaxChecker().isValidSyntax( get() );
+ try
+ {
+ valid = attributeType.getSyntax().getSyntaxChecker().isValidSyntax( get() );
+ }
+ catch ( NamingException ne )
+ {
+ String message = "Cannot check the syntax : " + ne.getMessage();
+ LOG.error( message );
+ valid = false;
+ }
+
return valid;
}
/**
- * @see ServerValue#compareTo(ServerValue)
+ * @see Value<T>#compareTo(ServerValue)
* @throws IllegalStateException on failures to extract the comparator, or the
* normalizers needed to perform the required comparisons based on the schema
*/
- public int compareTo( ServerValue<String> value )
+ public int compareTo( Value<String> value )
{
if ( isNull() )
{
@@ -227,23 +301,52 @@
if ( value instanceof ServerStringValue )
{
ServerStringValue stringValue = ( ServerStringValue ) value;
+
+ // Normalizes the compared value
+ try
+ {
+ stringValue.normalize();
+ }
+ catch ( NamingException ne )
+ {
+ String message = "Cannot normalize the wrapped value " + stringValue;
+ LOG.error( message );
+ }
+
+ // Normalizes the value
+ try
+ {
+ normalize();
+ }
+ catch ( NamingException ne )
+ {
+ String message = "Cannot normalize the wrapped value " + this;
+ LOG.error( message );
+ }
+
try
{
//noinspection unchecked
- return getComparator().compare( getNormalized(), stringValue.getNormalized() );
+ return getComparator().compare( getNormalizedValue(), stringValue.getNormalizedValue() );
}
catch ( NamingException e )
{
- String msg = "Failed to compare normalized values for " + get() + " and " + value;
+ String msg = "Failed to compare normalized values for " + this + " and " + value;
LOG.error( msg, e );
throw new IllegalStateException( msg, e );
}
}
- throw new NotImplementedException( "I don't know what to do if value is not a ServerStringValue" );
+ String message = "I don't know what to do if value is not a ServerStringValue";
+ LOG.error( message );
+ throw new NotImplementedException( message );
}
+ /**
+ * Get the associated AttributeType
+ * @return The AttributeType
+ */
public AttributeType getAttributeType()
{
return attributeType;
@@ -251,7 +354,15 @@
/**
- * @see ServerValue#instanceOf(AttributeType)
+ * Check if the value is stored into an instance of the given
+ * AttributeType, or one of its ascendant.
+ *
+ * For instance, if the Value is associated with a CommonName,
+ * checking for Name will match.
+ *
+ * @param attributeType The AttributeType we are looking at
+ * @return <code>true</code> if the value is associated with the given
+ * attributeType or one of its ascendant
*/
public boolean instanceOf( AttributeType attributeType ) throws NamingException
{
@@ -267,40 +378,16 @@
// -----------------------------------------------------------------------
// Object Methods
// -----------------------------------------------------------------------
-
-
- /**
- * @see Object#hashCode()
- * @throws IllegalStateException on failures to extract the comparator, or the
- * normalizers needed to perform the required comparisons based on the schema
- */
- public int hashCode()
- {
- // return zero if the value is null so only one null value can be
- // stored in an attribute - the binary version does the same
- if ( isNull() )
- {
- return 0;
- }
-
- try
- {
- return getNormalized().hashCode();
- }
- catch ( NamingException e )
- {
- String msg = "Failed to normalize \"" + get() + "\" while trying to get hashCode()";
- LOG.error( msg, e );
- throw new IllegalStateException( msg, e );
- }
- }
-
-
/**
* Checks to see if this ServerStringValue equals the supplied object.
*
* This equals implementation overrides the StringValue implementation which
* is not schema aware.
+ *
+ * Two ServerStringValues are equal if they have the same AttributeType,
+ * they are both null, their value are equal or their normalized value
+ * are equal. If the AttributeType has a comparator, we use it to
+ * compare both values.
* @throws IllegalStateException on failures to extract the comparator, or the
* normalizers needed to perform the required comparisons based on the schema
*/
@@ -310,7 +397,7 @@
{
return true;
}
-
+
if ( ! ( obj instanceof ServerStringValue ) )
{
return false;
@@ -318,27 +405,44 @@
ServerStringValue other = ( ServerStringValue ) obj;
- if ( isNull() && other.isNull() )
+ if ( !attributeType.equals( other.attributeType ) )
{
- return true;
+ return false;
}
-
- if ( isNull() != other.isNull() )
+
+ if ( isNull() )
{
- return false;
+ return other.isNull();
}
- // now unlike regular values we have to compare the normalized values
- try
+ // Shortcut : compare the values without normalization
+ // If they are equal, we may avoid a normalization.
+ // Note : if two values are equal, then their normalized
+ // value are equal too if their attributeType are equal.
+ if ( get().equals( other.get() ) )
{
- return getNormalized().equals( other.getNormalized() );
+ return true;
}
- catch ( NamingException e )
+ else
{
- String msg = "Failed to normalize while testing for equality on String values: \"";
- msg += get() + "\"" + " and \"" + other.get() + "\"" ;
- LOG.error( msg, e );
- throw new IllegalStateException( msg, e );
+ try
+ {
+ Comparator<String> comparator = getComparator();
+
+ // Compare normalized values
+ if ( comparator == null )
+ {
+ return getNormalizedValue().equals( other.getNormalizedValue() );
+ }
+ else
+ {
+ return comparator.compare( getNormalizedValue(), other.getNormalizedValue() ) == 0;
+ }
+ }
+ catch ( NamingException ne )
+ {
+ return false;
+ }
}
}
@@ -396,6 +500,39 @@
/**
+ * Implement the hashCode method.
+ *
+ * @see Object#hashCode()
+ * @throws IllegalStateException on failures to extract the comparator, or the
+ * normalizers needed to perform the required comparisons based on the schema
+ */
+ public int hashCode()
+ {
+ // return the OID hashcode if the value is null.
+ if ( isNull() )
+ {
+ return attributeType.getOid().hashCode();
+ }
+
+ // If the normalized value is null, will default to wrapped
+ // which cannot be null at this point.
+ int h = 17;
+
+ String normalized = getNormalizedValue();
+
+ if ( normalized != null )
+ {
+ h = h*37 + normalized.hashCode();
+ }
+
+ // Add the OID hashcode
+ h = h*37 + attributeType.getOid().hashCode();
+
+ return h;
+ }
+
+
+ /**
* Gets a comparator using getMatchingRule() to resolve the matching
* that the comparator is extracted from.
*
@@ -416,22 +553,6 @@
/**
- * @return a copy of the current value
- */
- public ServerStringValue clone()
- {
- try
- {
- return (ServerStringValue)super.clone();
- }
- catch ( CloneNotSupportedException cnse )
- {
- return null;
- }
- }
-
-
- /**
* @see Externalizable#writeExternal(ObjectOutput)
*
* We will write the value and the normalized value, only
@@ -448,7 +569,16 @@
{
out.writeUTF( get() );
- if ( normalizedValue.equals( get() ) )
+ try
+ {
+ normalize();
+ }
+ catch ( NamingException ne )
+ {
+ normalizedValue = null;
+ }
+
+ if ( get().equals( normalizedValue ) )
{
// If the normalized value is equal to the UP value,
// don't save it
@@ -486,6 +616,11 @@
{
// In this case, the normalized value is equal to the UP value
normalizedValue = wrapped;
+ setNormalized( true );
+ }
+ else
+ {
+ setNormalized( false );
}
}
}