blob: b61533d955548299b1c992a21b70b7657db4a523 [file] [view]
---
title: 6.3 - Attribute
navPrev: 6.2-administrative-role.html
navPrevText: 6.2 - AdministrativeRole
navUp: 6-ldap-data-structures.html
navUpText: 6 - LDAP data structures
navNext: 6.4-attribute-type.html
navNextText: 6.4 - AttributeType
---
# 6.3 - Attribute
The _Attribute_ class is used to store values associated with an _AttributeType_. An _Entry_ can contain many _Attribute{s_, but only one of them is mandatory: the _ObjectClass_ _Attribute_.
An _Attribute_ can store zero, one or N values, accordingly to its associated _AttributeType_, which may allow null values, and which also can forbid muli-values.
The _Attribute_ has a internal _AttributeType_ which is usually defined using its name. This name is case insensitive, and we can also use the _AttributeType_ _OID_.
## Creating an Attribute
Creating an _Attribute_ is not complex. Again, we split the API into two categories:
* the schema agnostic _Attributes_
* the schema aware _Attributes_
### Schema agnostic Attribute
If we don't inject a _SchemaManager_ into the constructor, then the _Attribute_ will have no way to control whether its _AttributeType_ exists, nor that its _Values_ are valid.
Let's see how we can create _Attributes_. Basically, all what that needed is to provide the _AttributeType_ as a String, and some _Values_ (that are optional). Here is an example:
```Java
Attribute attribute = new DefaultAttribute( " CN " );
```
Here, we created an empty _Attribute_. Note that _cn_ does not allow empty values, but it's not enforced. Also note that the _AttributeType_ is lowercase and trimmed internally.
Let's see another example, with some values:
```Java
Attribute attribute = new DefaultAttribute( " CN ", "test", "Test", " test ", "test" );
```
Here, we create an _Attribute_ with 3 values. We can see that the values are not duplicated (the _"test"_ value is only inserted once) and that values are case sensitive (the _"test"_ and _"Test"_ values are both stored in the _Attribute_). The values aren't trimmed either, so we can have a _"test"_ and a _" test "_ values stored.
This is why having a schema aware _Attribute_ is really handy.
It's possible to store binary values into an _Attribute_ too:
```Java
byte[] bytes1 = new byte[]{0x01, 0x02};
byte[] bytes2 = new byte[]{0x03, 0x04};
byte[] bytes3 = new byte[]{0x01, 0x02};
Attribute attribute = new DefaultAttribute( " JpegPhoto ", bytes1, bytes2, bytes3 );
```
Same here: values are not duplicated.
Note that it's not allowed to store a mix of binary and String values into an _Attribute_:
```Java
byte[] bytes1 = new byte[]{0x01, 0x02};
Attribute attribute = new DefaultAttribute( " JpegPhoto ", "test", bytes1 ); // Does not compile
```
### Schema aware Attribute
We can inject a _SchemaManager_ into the _Attribute_ which will allow more control over the values stored within the _Attribute_. Let's see an example of how this works:
```Java
Attribute attribute = new DefaultAttribute( atCn );
```
Here, we created an _Attribute_ with a specific _AttributeType_ ('atCn') and no value. Let's create a new _Attribute_ with some values:
```Java
Attribute attribute = new DefaultAttribute( atCn, "test", "Test", " test " );
```
The important point here is that the values are all considered equal. The _contains_ method also uses the schema to compare its given value with the interned values. Here, with the _cn_ _AttributeType_, the value is not case sensitive, so _"TEST"_ is considered as an existing value, even if we injected _"test"_.
## Modifying an Attribute
Now that we created an _Attribute_ we would like to add or remove values from it. This is quite easy. We have a set of methods to add or remove values, and depending on whether the _Attribute_ is schema aware or not, the added values will be checked.
### Adding some value
Here is an example of a value addition into a schema agnostic _Attribute_, then the same operation into a schema aware _Attribute_:
```Java
Attribute attribute = new DefaultAttribute( " CN " );
Attribute attributeSA = new DefaultAttribute( atCn );
// Add two values
attribute.add( "test1", "" );
// add two values
attributeSA.add( "test1", "" );
```
We can see that the schema aware _Attribute_ just contains only one value after the operation, as the _cn_ attribute type does not allow empty strings.
There is one important point to understand -- whenever a schema agnostic _Attribute_ is created, it knows nothing about the type of values it will store. Once the first value is added, the _Attribute_ will be typed accordingly to the first value added. Then we can no longer add values that are not of the same type.
If the _Attribute_ is schema aware, it's quite obvious. You won't be able to add a binary value into a Human Readable _Attribute_.
The following test shows that:
```Java
Attribute attribute = new DefaultAttribute( " CN " );
Attribute attributeSA = new DefaultAttribute( atCn );
byte[] bytes = new byte[]{0x01, 0x02};
// Add two values
attribute.add( "test1" );
attribute.add( bytes );
// add two values
attributeSA.add( "test1" );
attributeSA.add( bytes );
```
### Removing some values
Removing a value from an _Attribute_ is a trivial operation. Of course, if the _Attribute_ is schema aware, we will use the _AttributeType_ comparator to check if the value is present in the _Attribute_ or not (the comparator is associated with the attribute equality _MatchingRule_.
Here is an example:
```Java
Attribute attribute = new DefaultAttribute( " CN " );
// Add three values
attribute.add( "test1", "test2", "test3" );
// Remove 2 of them
attribute.remove( "test2", "test3" );
// Try to remove the last one, using wrong casing
attribute.remove( "Test1" );
```
And the same example, on a schema aware _Attribute_. It demonstrates how convenient it is to manipulate such schema aware objects:
```Java
Attribute attribute = new DefaultAttribute( atCn );
// Add three values
attribute.add( "test 1", "test 2", "test 3" );
// Remove 2 of them
attribute.remove( "TEST 2", "test 3" );
// Try to remove the last one, using wrong casing
attribute.remove( "Test 1" );
```
## Attribute data access methods
We have a set of methods used to get some information about the _Attribute_. They are described in this chapter.
### contains()
Checks if the given values are present in the _Attribute_. We can check for more than one value, but in this case, the method returns _true_ only if **all** the values are present.
If the _Attribute_ is schema aware, then the check uses the _AttributeType_ to compare the given values with the interned values, otherwise, we do a strict comparison.
Here is an example:
```Java
Attribute attribute1 = new DefaultAttribute( atCn );
// Add three values
attribute1.add( "test 1", "test 2", "test 3" );
Attribute attribute2 = new DefaultAttribute( "cn" );
// Add three values
attribute2.add( "test 1", "test 2", "test 3" );
```
### get()
Returns the first value from the _Attribute_. The first value is the one which has been added first. Note that it returns a _Value_ instance.
### getAttributeType()
Returns the internal _AttributeType_, if the _Attribute_ is schema aware.
### getBytes()
Returns the first value as a _byte[]_, if the _Attribute_ is not human readable. The user **must** know that the _Attribute_ contains binary values, otherwise they will get an _LdapInvalidAttributeValueException_.
### getString()
Returns the first value as a _String_, if the _Attribute_ is human readable. The user **must** know that the _Attribute_ contains String values, otherwise they will get an _LdapInvalidAttributeValueException_.
### getId()
Returns the _AttributeType_ normalized ID. If the _Attribute_ is schema agnostic, it will be the trimmed and lower cased user provided ID, otherwise it will be the _AttributeType_ OID (not the name).
### getUpId()
Returns the attribute type user provided ID, if the user provided one. Typically, if the _Attribute_ is schema aware, the user might not provide an ID, and in this case, this method will return the _AttributeType_ name, or default to the OID.
### isHumanReadable()
Tells if the _Attribute_ contains String values or binary values.
## Miscellaneous methods
We also have a set of miscellaneous methods, which are not frequently used. Here they are:
### apply( AttributeType )
Inject an _AttributeType_ into the _Attribute_, making it schema aware. It will check that the associated values are valid at the same time, and normalize the values.
Here is an example of the impact of such a method on an existing attribute :
```Java
Attribute attribute = new DefaultAttribute( "CN", " A test" );
attribute.apply( atCn );
```
It shows that we can now check that a value is not literately compared, the modified attribute uses the Equality _MatchingRule_ to compare the values.
Here is another example, where we try to apply an attribute type to some attribute containing an invalid value : it generates an exception, as expected.
```Java
byte[] bytes = new byte[]{0x01, 0x02};
Attribute attribute = new DefaultAttribute( "CN", bytes );
attribute.apply( atCn );
```
### clear()
This method removes all the values from the attribute. The attribute type is not removed. Here is an example demonstrating how it works:
```Java
Attribute attribute = new DefaultAttribute( atCn, "test1", "test2" );
attribute.clear();
```
### clone()
This method creates a new instance of an existing attribute. All of the attribute values along with its attribute type are cloned and distinct from the original attribute.
### equals( Object )
Compares two _Attributes_. All of its values are compared and should be present in both attributes. If you compare a schema aware _Attribute_ with a schema agnostic _Attribute_, they won't be equal.
Here is a snippet of code demonstrating the _equals_ method:
```Java
Attribute attribute1 = new DefaultAttribute( atCn, "test 1", "test 2", "test 3" );
Attribute attribute2 = new DefaultAttribute( atCn, "Test 3", "Test 2 ", "Test 1" );
Attribute attribute3 = new DefaultAttribute( "cn", "test 1", "test 3", "test 2" );
Attribute attribute4 = new DefaultAttribute( "cn", "test 1", "test 3", "test 2" );
// Should be true
boolean equals = attribute1.equals( attribute2 );
equals = attribute3.equals( attribute4 );
// Should be false
equals = attribute1.equals( attribute3 );
equals = attribute1.equals( attribute4 );
equals = attribute2.equals( attribute4 );
// Now, inject an AttrbuteType in one attribute
attribute4.apply( atCn );
// The previously not equals attributes are now equal :
equals = attribute1.equals( attribute4 );
equals = attribute2.equals( attribute4 );
```
### isInstanceOf( AttributeType )
Tells if an _Attribute_ derives from a given _AttributeType_. It can be useful if you have a schema aware _Attribute_ and want to know if its attribute type inherits from another one. Here is an example of usage:
```Java
Attribute attribute = new DefaultAttribute( atCn, "test 1", "test 2", "test 3" );
// Should be true
boolean value = attribute.isInstanceOf( atCn );
```
### isValid( AttributeType )
Checks if the _Attribute_ contains valid data. It's useful if one wants to apply an _AttributeType_ to the _Attribute_, as the _isValid_ method will tell if it's possible to do so without throwing an exception.
Here is some code that test the different use cases:
```Java
Attribute attribute1 = new DefaultAttribute( "cn", "\uFFFDtest" );
// Should be false
boolean isValid = attribute1.isValid( atCn ) );
Attribute attribute2 = new DefaultAttribute( "cn" );
// Should be false, 'cn' requires a value
isValid = attribute2.isValid( atCn );
Attribute attribute3 = new DefaultAttribute( "cn", "test" );
// Should be true
value = attribute3.isValid( atCn );
Attribute attribute4 = new DefaultAttribute( "dc", "test", "test2" );
// Should be false, we can't put more than one value in 'dc'
value = attribute4.isValid( atDc );
```
### iterator()
A convenient way to iterate over all of the _Attribute_ values. It enables the _for ( Value<?> value : attribute )_ construct. Here is an example using the iterator:
```Java
Attribute attribute = new DefaultAttribute( atCn, "test 1", "test 2", "test 3" );
for ( Value<?> value : attribute )
{
System.out.println( "Value : " + value );
}
```
This code produces the following output:
```Text
Value : test 1
Value : test 2
Value : test 3
```
### setUpId()
Sets the user provided identifier for the attribute type. If the _Attribute_ is schema agnostic, then the normalized ID will be the given user provided ID lower cased and trimmed. If it's schema aware, it will be used instead of the _AttributeType_ ID.
### size()
Returns the number of values stored in this _Attribute_