blob: 2009ac8e79b9a9210fc7e7a29b5163dc5f502a9c [file] [log] [blame]
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
Notice: 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.
# 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:
:::Java
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_