/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.directory.server.core.entry; | |
import javax.naming.NamingException; | |
import javax.naming.directory.InvalidAttributeValueException; | |
import org.apache.directory.shared.asn1.primitives.OID; | |
import org.apache.directory.shared.ldap.entry.EntryAttribute; | |
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; | |
import org.slf4j.LoggerFactory; | |
/** | |
* A server side entry attribute aware of schema. | |
* | |
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> | |
* @version $Rev$, $Date$ | |
*/ | |
public final class DefaultServerAttribute extends DefaultClientAttribute implements ServerAttribute | |
{ | |
/** logger for reporting errors that might not be handled properly upstream */ | |
private static final Logger LOG = LoggerFactory.getLogger( DefaultServerAttribute.class ); | |
/** The associated AttributeType */ | |
private AttributeType attributeType; | |
// ----------------------------------------------------------------------- | |
// utility methods | |
// ----------------------------------------------------------------------- | |
/** | |
* Private helper method used to set an UpId from an attributeType | |
* | |
* @param at The attributeType for which we want the upID | |
* @return the ID of the given attributeType | |
*/ | |
private String getUpId( AttributeType at ) | |
{ | |
String atUpId = at.getName(); | |
if ( atUpId == null ) | |
{ | |
atUpId = at.getOid(); | |
} | |
return atUpId; | |
} | |
/** | |
* <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> | |
* 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 | |
{ | |
// 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 ) | |
{ | |
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. | |
* | |
* @param attributeType The attributeType added on creation | |
* @param vals The added value for this attribute | |
*/ | |
public DefaultServerAttribute( AttributeType attributeType, String... vals ) | |
{ | |
this( null, attributeType, vals ); | |
} | |
/** | |
* Create a new instance of a EntryAttribute. | |
* | |
* @param upId the ID for the added attribute | |
* @param attributeType The attributeType added on creation | |
* @param vals the added values for this attribute | |
*/ | |
public DefaultServerAttribute( String upId, AttributeType attributeType, String... vals ) | |
{ | |
if ( attributeType == null ) | |
{ | |
throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); | |
} | |
setAttributeType( attributeType ); | |
add( vals ); | |
setUpId( upId, attributeType ); | |
} | |
/** | |
* Create a new instance of a EntryAttribute, with some byte[] values. | |
* | |
* @param attributeType The attributeType added on creation | |
* @param vals The value for the added attribute | |
*/ | |
public DefaultServerAttribute( AttributeType attributeType, byte[]... vals ) | |
{ | |
this( null, attributeType, vals ); | |
} | |
/** | |
* Create a new instance of a EntryAttribute, with some byte[] values. | |
* | |
* @param upId the ID for the added attribute | |
* @param attributeType the AttributeType to be added | |
* @param vals the values for the added attribute | |
*/ | |
public DefaultServerAttribute( String upId, AttributeType attributeType, byte[]... vals ) | |
{ | |
if ( attributeType == null ) | |
{ | |
throw new IllegalArgumentException( "The AttributeType parameter should not be null" ); | |
} | |
setAttributeType( attributeType ); | |
add( vals ); | |
setUpId( upId, attributeType ); | |
} | |
/** | |
* 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; | |
} | |
/** | |
* <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> | |
* 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#add(org.apache.directory.shared.ldap.entry.Value...) | |
* | |
* @return the number of added values into this attribute | |
*/ | |
public int add( Value<?>... vals ) | |
{ | |
int nbAdded = 0; | |
for ( Value<?> val:vals ) | |
{ | |
try | |
{ | |
if ( attributeType.getSyntax().isHumanReadable() ) | |
{ | |
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 | |
{ | |
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 ); | |
} | |
} | |
} | |
catch ( NamingException ne ) | |
{ | |
String message = "Error while adding value '" + val.toString() +"' : " + ne.getMessage(); | |
LOG.error( message ); | |
} | |
} | |
return nbAdded; | |
} | |
/** | |
* <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; | |
} | |
} | |
/** | |
* <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 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( byte[]... vals ) | |
{ | |
if ( !isHR ) | |
{ | |
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 | |
{ | |
// We can't add Binary values into a String serverAttribute | |
return 0; | |
} | |
} | |
/** | |
* 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> | |
* <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( Value<?>... vals ) | |
{ | |
// Iterate through all the values, and quit if we | |
// don't find one in the values. We have to separate the check | |
// depending on the isHR flag value. | |
if ( isHR ) | |
{ | |
for ( Value<?> val:vals ) | |
{ | |
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; | |
} | |
} | |
} | |
else | |
{ | |
for ( Value<?> val:vals ) | |
{ | |
if ( val instanceof ClientBinaryValue ) | |
{ | |
if ( !values.contains( val ) ) | |
{ | |
return false; | |
} | |
} | |
else | |
{ | |
// Not a Binary value | |
return false; | |
} | |
} | |
} | |
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> | |
* | |
* @param vals the values | |
* @return true if this attribute contains all the values, otherwise false | |
*/ | |
public boolean contains( String... vals ) | |
{ | |
if ( isHR ) | |
{ | |
// Iterate through all the values, and quit if we | |
// don't find one in the values | |
for ( String val:vals ) | |
{ | |
ServerStringValue value = new ServerStringValue( attributeType, val ); | |
if ( !values.contains( value ) ) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
/** | |
* <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 | |
*/ | |
public boolean contains( byte[]... vals ) | |
{ | |
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; | |
} | |
} | |
/** | |
* @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; | |
} | |
/** | |
* @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; | |
} | |
//------------------------------------------------------------------------- | |
// Overloaded Object classes | |
//------------------------------------------------------------------------- | |
/** | |
* 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#equals(Object) | |
* | |
* @return <code>true</code> if the two objects are equal | |
*/ | |
public boolean equals( Object obj ) | |
{ | |
if ( obj == this ) | |
{ | |
return true; | |
} | |
if ( ! (obj instanceof ServerAttribute ) ) | |
{ | |
return false; | |
} | |
ServerAttribute other = (ServerAttribute)obj; | |
if ( !attributeType.equals( other.getAttributeType() ) ) | |
{ | |
return false; | |
} | |
if ( values.size() != other.size() ) | |
{ | |
return false; | |
} | |
for ( Value<?> val:values ) | |
{ | |
if ( ! other.contains( val ) ) | |
{ | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* @see Object#toString() | |
* | |
* @return A String representation of this instance | |
*/ | |
public String toString() | |
{ | |
StringBuilder sb = new StringBuilder(); | |
if ( ( values != null ) && ( values.size() != 0 ) ) | |
{ | |
for ( Value<?> value:values ) | |
{ | |
sb.append( " " ).append( upId ).append( ": " ); | |
if ( value.isNull() ) | |
{ | |
sb.append( "''" ); | |
} | |
else | |
{ | |
sb.append( value ); | |
} | |
sb.append( '\n' ); | |
} | |
} | |
else | |
{ | |
sb.append( " " ).append( upId ).append( ": (null)\n" ); | |
} | |
return sb.toString(); | |
} | |
} |