directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1186334 [3/4] - in /directory/documentation/ldap-api-manuals/trunk: ./ src/ src/docbkx-stylesheet/ src/docbkx-stylesheet/fo/ src/docbkx-stylesheet/html/ src/ldap-api-user-guide-confluence/ src/ldap-api-user-guide-confluence/chapter-2/ src/...
Date Wed, 19 Oct 2011 16:58:09 GMT
Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-02-Attribute.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-02-Attribute.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-02-Attribute.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-02-Attribute.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,471 @@
+h2. Attribute
+
+The *Attribute* class is used to store values associated to *[AttributeType (...)]*. An *[DIRAPI: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 the associated *[AttributeType (...)]*, which may allow null values, and which also can forbid muli-values.
+
+The *Attribute* has a interned *[AttributeType (...)]* which is usually defined using its name. This name is case insensitive, and we can also use the *[AttributeType (...)]* *[DIRAPI:OID]*.
+
+h3. Creating an Attribute
+
+Creating an *Attribute* is not really a complex operation. Again, we split the API into two categories:
+* the schema agnostic *Attributes*
+* the schema aware *Attributes*
+
+h4. Schema agnostic Attribute
+
+If we don't inject a *[SchemaManager (...)]* in the constructor, then the *Attribute* will have no way to control that the *[AttributeType (...)]* exists, nor that the *[DIRAPI:Value]s* are valid.
+
+Let's see how we can create *Attributes*. Basically, all what you need is to provide the *[AttributeType (...)]* as a String, and some *[DIRAPI:Value]s* (it's optional). Here is an example:
+
+{code:java}
+    @Test
+    public void testCreateEmptyAttribute()
+    {
+        Attribute attribute = new DefaultAttribute( " CN " );
+        
+        assertNotNull( attribute );
+        assertEquals( "cn", attribute.getId() );
+        assertEquals( " CN ", attribute.getUpId() );
+        assertNotSame( "CommonName", attribute.getId() );
+    }
+{code}
+
+Here, we created an empty *Attribute*. Note that *cn* does not allow empty values, but it's not controlled. Also note that the *[AttributeType (...)]* is lower cased and trimmed internally.
+
+Let's see another example, with some values:
+
+{code:java}
+    @Test
+    public void testCreateAttribute()
+    {
+        Attribute attribute = new DefaultAttribute( " CN ", "test", "Test", " test ", "test" );
+        
+        assertNotNull( attribute );
+        assertEquals( "cn", attribute.getId() );
+        assertEquals( " CN ", attribute.getUpId() );
+        assertEquals( 3, attribute.size() );
+        assertTrue( attribute.contains( "test", "Test", " test " ) );
+    }
+{code}
+
+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:
+
+{code:java}
+    @Test
+    public void testCreateBinaryAttribute()
+    {
+        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 );
+        
+        assertNotNull( attribute );
+        assertEquals( "jpegphoto", attribute.getId() );
+        assertEquals( " JpegPhoto ", attribute.getUpId() );
+        assertEquals( 2, attribute.size() );
+        assertTrue( attribute.contains( bytes1, bytes2, bytes3 ) );
+    }
+{code}
+
+Same here : values are not duplicated.
+
+Note that it's not allowed to store a mix of binary and String values in an *Attribute*:
+
+{code:java}
+    @Test
+    public void testCreateMixedAttribute()
+    {
+        byte[] bytes1 = new byte[]{0x01, 0x02};
+
+        Attribute attribute = new DefaultAttribute( " JpegPhoto ", "test", bytes1 ); // Does not compile
+        
+        assertNotNull( attribute );
+        assertEquals( "jpegphoto", attribute.getId() );
+        assertEquals( " JpegPhoto ", attribute.getUpId() );
+        assertEquals( 3, attribute.size() );
+        assertTrue( attribute.contains( bytes1, "test" ) ); // Does not compile
+    }
+{code}
+
+h4. Schema aware Attribute
+
+We can inject a *[SchemaManager (...)]* into the *Attribute* which will allow more control on the values stored into the *Attribute*. Let's see with some example how it works:
+
+{code:java}
+    @Test
+    public void testCreateEmptySchemaAwareAttribute() throws Exception
+    {
+        Attribute attribute = new DefaultAttribute( atCn );
+        
+        assertNotNull( attribute );
+        assertEquals( "2.5.4.3", attribute.getId() );
+        assertEquals( "cn", attribute.getUpId() );
+        assertTrue( attribute.isInstanceOf( atCn ) );
+        assertEquals( 0, attribute.size() );
+    }
+{code}
+
+Here, we created an *Attribute* with a specific *[AttributeType (...)]* and no value. Let's create a new *Attribute* with some values:
+
+{code:java}
+    @Test
+    public void testCreateSchemaAwareAttribute() throws Exception
+    {
+        Attribute attribute = new DefaultAttribute( atCn, "test", "Test", "  test  " );
+        
+        assertNotNull( attribute );
+        assertEquals( "2.5.4.3", attribute.getId() );
+        assertEquals( "cn", attribute.getUpId() );
+        assertTrue( attribute.isInstanceOf( atCn ) );
+        assertEquals( 1, attribute.size() );
+        assertTrue( attribute.contains( "TEST" ) );
+    }
+{code}
+
+The important point here is that the values are all considered equals. The _contains_ method also use the schema to compare the 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"_.
+
+h3. 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 the fact the *Attribute* is schema aware or not, the added values will be checked. 
+
+h5. Adding some value
+
+Here is an example of some value addition into a schema agnostic *Attribute*, then the same operation into a schema aware *Attribute*:
+
+{code:java}
+    @Test
+    public void testAddValue() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( " CN " );
+        Attribute attributeSA = new DefaultAttribute( atCn );
+        
+        // Add two values
+        attribute.add( "test1", "" );
+        
+        assertEquals( 2, attribute.size() );
+        
+        // add two values
+        attributeSA.add( "test1", "" );
+
+        assertEquals( 1, attributeSA.size() );
+    }
+{code}
+
+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 : when 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't anymore add values if it has not 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:
+
+{code:java}
+    @Test
+    public void testAddMixedValue() throws LdapInvalidAttributeValueException
+    {
+        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 );
+        
+        assertEquals( 1, attribute.size() );
+        assertTrue( attribute.contains( "test1" ) );
+        assertFalse( attribute.contains( bytes ) );
+
+        // add two values
+        attributeSA.add( "test1" );
+        attributeSA.add( bytes );
+
+        assertEquals( 1, attributeSA.size() );
+        assertTrue( attributeSA.contains( "test1" ) );
+        assertFalse( attributeSA.contains( bytes ) );
+    }
+{code}
+
+h5. 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 (e)]*).
+
+Here is an example:
+{code:java}
+    @Test
+    public void testRemoveValue() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( " CN " );
+        
+        // Add three values
+        attribute.add( "test1", "test2", "test3" );
+        assertEquals( 3, attribute.size() );
+        
+        // Remove 2 of them
+        attribute.remove( "test2", "test3" );
+        assertEquals( 1, attribute.size() );
+        assertTrue( attribute.contains( "test1" ) );
+        assertFalse( attribute.contains( "test2" ) );
+        assertFalse( attribute.contains( "test3" ) );
+        
+        // Try to remove the last one, using wrong casing
+        attribute.remove( "Test1" );
+        assertEquals( 1, attribute.size() );
+        assertTrue( attribute.contains( "test1" ) );
+    }
+{code}
+
+And the same example, on a schema aware *Attribute*. It demonstrates how convenient it is to manipulate such schema aware objects:
+{code:java}
+    @Test
+    public void testRemoveSchemaAwareValue() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( atCn );
+        
+        // Add three values
+        attribute.add( "test 1", "test 2", "test 3" );
+        assertEquals( 3, attribute.size() );
+        
+        // Remove 2 of them
+        attribute.remove( "TEST 2", "test   3" );
+        assertEquals( 1, attribute.size() );
+        assertTrue( attribute.contains( "tESt 1" ) );
+        assertFalse( attribute.contains( "test   2" ) );
+        assertFalse( attribute.contains( "TEST 3" ) );
+        
+        // Try to remove the last one, using wrong casing
+        attribute.remove( "Test 1" );
+        assertEquals( 0, attribute.size() );
+    }
+{code}
+
+h3. Attribute data access methods
+
+We have a set of methods used to get some information about the *Attribute*. They are described in this chapter.
+
+h5. 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:
+{code:java}
+    @Test
+    public void testContains() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute1 = new DefaultAttribute( atCn );
+        
+        // Add three values
+        attribute1.add( "test 1", "test 2", "test 3" );
+        
+        assertTrue( attribute1.contains( "tESt 1", "test 2  " ) );
+        assertTrue( attribute1.contains( "  test   2" ) );
+        assertTrue( attribute1.contains( "TEST 3" ) );
+        assertFalse( attribute1.contains( "test 1", "Test 4" ) );
+
+        Attribute attribute2 = new DefaultAttribute( "cn" );
+        
+        // Add three values
+        attribute2.add( "test 1", "test 2", "test 3" );
+        
+        assertTrue( attribute2.contains( "test 1" ) );
+        assertTrue( attribute2.contains( "test 2" ) );
+        assertTrue( attribute2.contains( "test 3" ) );
+
+        assertFalse( attribute2.contains( "Test 1" ) );
+        assertFalse( attribute2.contains( " test   2" ) );
+        assertFalse( attribute2.contains( "test 4" ) );
+    }
+{code}
+
+h5. get()
+
+Returns the first value from the *Attribute*. The first value is the one which has been added first. Note that it returns a *[DIRAPI:Value]* instance.
+
+h5. getAttributeType()
+
+Returns the internal *[AttributeType (...)]*, if the *Attribute* is schema aware.
+
+h5. 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 he will get an _LdapInvalidAttributeValueException_.
+
+h5. 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 he will get an _LdapInvalidAttributeValueException_.
+
+h5. 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).
+
+h5. 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.
+
+h5. isHumanReadable()
+
+Tells if the *Attribute* contains String values or binary values. 
+
+h3. Miscellaneous methods
+
+We also have a set of miscellaneous methods, which are not frequently used. Here they are:
+
+h5. 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 :
+
+{code:java}
+    @Test
+    public void testApplyAttributeType() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( "CN", "  A    test" );
+        
+        attribute.apply( atCn );
+        
+        assertTrue( attribute.contains( "a         test" ) );
+        assertEquals( "2.5.4.3", attribute.getId() );
+    }
+{code}
+
+It shows that we can now check that a value is not literately compared, the modified attribute uses the Equality *[MatchingRule (e)]* 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.
+{code:java}
+    @Test( expected=LdapInvalidAttributeValueException.class )
+    public void testApplyAttributeTypeWrongValue() throws LdapInvalidAttributeValueException
+    {
+        byte[] bytes = new byte[]{0x01, 0x02};
+        Attribute attribute = new DefaultAttribute( "CN", bytes );
+        
+        attribute.apply( atCn );
+    }
+{code}
+
+
+h5. clear()
+This method removes all the values from the attribute. The attribute type is not removed. Here is an example demonstrating how it works:
+
+{code:java}
+    @Test
+    public void testClear() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( atCn, "test1", "test2" );
+        
+        assertEquals( 2, attribute.size() );
+        
+        attribute.clear();
+        assertEquals( 0, attribute.size() );
+    }
+{code}
+
+h5. clone()
+This method create a new instance of an existing attribute. All the values and the attribute type are cloned too and distinct from the original attribute.
+
+h5. equals( Object )
+Compares two *Attributes*. All the 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:
+
+{code:java}
+    @Test
+    public void testEquals() throws LdapInvalidAttributeValueException
+    {
+        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" );
+        
+        assertEquals( attribute1, attribute2 );
+        assertEquals( attribute3, attribute4 );
+        assertNotSame( attribute1, attribute3 );
+        assertNotSame( attribute1, attribute4 );
+        assertNotSame( attribute2, attribute4 );
+        
+        attribute4.apply( atCn );
+        assertEquals( attribute1, attribute4 );
+        assertEquals( attribute2, attribute4 );
+        assertNotSame( attribute3, attribute4 );
+    }
+{code}
+
+h5. isInstanceOf( AttributeType )
+
+Tells if an *Attribute* derives from a given *[AttributeType (...)]*. It can be useful if you have some schema aware *Attribute* and if you want to know if its attribute type inherit from an other one. Here is an example of usage:
+
+{code:java}
+    @Test
+    public void testIsInstanceOf() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( atCn, "test 1", "test 2", "test 3" );
+        
+        assertTrue( attribute.isInstanceOf( atCn ) );
+        assertTrue( attribute.isInstanceOf( atName ) );
+        assertFalse( attribute.isInstanceOf( atSn ) );
+    }
+{code}
+
+h5. 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:
+
+{code:java}
+    @Test
+    public void testIsValid() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute1 = new DefaultAttribute( "cn", "\uFFFDtest" );
+        
+        assertFalse( attribute1.isValid( atCn ) );
+        
+        Attribute attribute2 = new DefaultAttribute( "cn" );
+
+        assertFalse( attribute2.isValid( atCn ) );
+        
+        Attribute attribute3 = new DefaultAttribute( "cn", "test" );
+
+        assertTrue( attribute3.isValid( atCn ) );
+        
+        Attribute attribute4 = new DefaultAttribute( "dc", "test", "test2" );
+
+        assertFalse( attribute4.isValid( atDc ) );
+    }
+{code}
+
+h5. iterator()
+
+A convenient way to iterate on all the *Attribute* values. It makes it possible to use a _for ( Value<?> value : attribute )_ construct. Here is an example using the iterator:
+
+{code:java}
+    @Test
+    public void testIIterator() throws LdapInvalidAttributeValueException
+    {
+        Attribute attribute = new DefaultAttribute( atCn, "test 1", "test 2", "test 3" );
+        
+        for ( Value<?> value : attribute )
+        {
+            System.out.println( "Value : " + value );
+        }
+    }
+{code}
+
+This code produces the following output:
+
+{code:java}
+Value : test 1
+Value : test 2
+Value : test 3
+{code}
+
+h5. 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.
+
+h5. size()
+Returns the number of values stored in this *Attribute*

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-03-Dn.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-03-Dn.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-03-Dn.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-03-Dn.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,513 @@
+h2. Dn
+
+A *Dn* (*D{*}istinguished *N{*}ame) represent a path in the *DiT*. Like *URL* names, it has to be read from right to left. For instance, the *{_}directory.apache.org{_}* name has the most generic part on the right (*org*), then a more specific part in the middle (*apache*) and the most specific part on the left (*directory*). *Dn{*}s work the exact same way, except that we use a comma (',') to separate the parts :
+*{_}dc=directory,ou=apache,ou=org{_}*
+
+Each part of a *Dn* is a *[DIRAPI:Rdn]* (*R{*}elative *D{*}Istinguished *N{*}ame, because it's relative to its parent's *Dn*). In the previous example (*{_}dc=directory,ou=apache,ou=org{_}*), the leftmost part is the *[DIRAPI:Rdn]* (*{_}dc=directory{_}*), the right most part is itself a *Dn* (*{_}ou=apache,ou=org{_}*)
+
+In other words, we can describe a hierarchy using *Dn{*}s, a bit like *Unix* paths describe the content of a file system.
+
+{tip:title=Info}
+The Dn class is immutable.
+{tip}
+
+h3. Schema awareness
+
+*Dn* are composed of *[DIRAPI:Rdn]{*}s, themselves composed of *[DIRAPI:Ava]{*}s (see the respective chapter about those elements). Base line, an *[DIRAPI:Ava]* is a *[AttributeType (...)]* and a *[DIRAPI:Value]*. *LDAP* defines a set of *[AttributeType (...)]{*}s which can be accepted by a Server, and as *Dn* are composed of *[DIRAPI:Ava]{*}s, they are constrained to accept only valid *[AttributeType (...)]{*}s.
+
+That mean we may want to make the *Dn* schema aware, in order to check that the given *[AttributeType (...)]* are valid.
+
+This can be done by passing a *[SchemaManager (...)]* to the *Dn* when creating one.
+
+Note that you may not have access to the *[SchemaManager (...)]* associated with the *LDAP* server you are working with (either because it can't provide one, or because you have no idea about what kind of *[AttributeType (...)]{*}s the server provides). This is only an issue if you don't know what kind of *Dn{*}s are acceptable by the server, otherwise you can construct schema agnostic *Dn{*}s and send them to the server, it will do the check anyway.
+
+The only big issue when you work with schema agnostic *Dn* is that comparing two *Dn{*}s may be complicated.
+
+h3. Constructing a DN
+
+There are many ways to construct a *Dn*. We can pass a string representation of a *Dn* and get back a *Dn* instance, or concatenate a *[DIRAPI:Rdn]* to an existing *Dn*, or concatenate a list of *[DIRAPI:Rdn]{*}s.
+
+Let's create some *Dn* now :
+
+h5. Creating an Empty Dn
+
+Here are four ways you can use to create an empty *Dn*, the last one being schema aware :
+
+{code:java}    @Test
+    public void testCreateDn()
+    {
+        // Create an empty DN
+        Dn dn = new Dn();
+        
+        // Same thing, using a constant
+        Dn emptyDn = Dn.EMPTY_DN;
+
+        // The RootDSE
+        Dn rootDSE = Dn.ROOT_DSE;
+        
+        // A Schema Aware empty Dn
+        Dn dnSchema = new Dn( schemaManager );
+        
+        assertEquals( dn, emptyDn );
+        assertEquals( dn, rootDSE );
+        assertEquals( emptyDn, rootDSE );
+        assertEquals( dn, dnSchema );
+    }
+{code}
+
+h5. Creating a schema agnostic Dn
+
+There are basically three ways to create a *Dn*. The first one is to pass a String representing the *Dn* :
+
+{code:java}   
+    ...
+    // Create a DN 
+    Dn dn1 = new Dn( "dc=example, dc=com" );
+    ...
+{code}
+
+Note that you can also pass more than one string, constructing your *Dn* using variable for instance, like in :
+
+{code:java}   
+    @Test
+    public void testCreateDn4() throws LdapInvalidDnException
+    {
+        // Create a DN 
+        Dn dn1 = new Dn( "dc=test, dc=example, dc=com" );
+
+        String name = "test";
+        
+        // Same thing, using a list of Strings
+        Dn dn2 = new Dn( "dc", name, "dc=example, dc=com" );
+
+        assertEquals( dn1, dn2 );
+    }
+{code}
+
+If one of the String does not contain an '=' sign, then it means the parser will consider that the next String is the value. This can be very convenient in some cases.
+
+(what happens is that the constructor first concatenates all the String in one single String, and parse it to produce a *Dn*)
+
+The second way is to pass a list of *[DIRAPI:Rdn]s* :
+
+{code:java}   
+    @Test
+    public void testCreateDn() throws LdapInvalidDnException
+    {
+        Dn dn1 = new Dn( "dc=example, dc=com" );
+
+        Rdn example = new Rdn( "dc=example" );
+        Rdn com = new Rdn( "dc=com" );
+ 
+        // Create a DN 
+        Dn dn2 = new Dn( example, com );
+
+        assertEquals( dn1, dn );
+    }
+{code}
+
+Note that the order in which the *[DIRAPI:Rdn]s* are passed is the same as the order you'll find them in the resulting *Dn*
+
+The third way is to concatenate a *[DIRAPI:Rdn]* with an existig *Dn* :
+
+{code:java}   
+    @Test
+    public void testCreateDn() throws LdapInvalidDnException
+    {
+        Dn dn1 = new Dn( "dc=test, dc=example, dc=com" );
+
+        Rdn test = new Rdn( "dc=test" );
+        Rdn baseDn = new Dn( "dc=example, dc=com" );
+ 
+        // Create a DN 
+        Dn dn2 = new Dn( example, baseDn );
+
+        assertEquals( dn1, dn );
+    }
+{code}
+
+h4. Schema aware DN construction
+
+This is just a note that all the described constructor can take an extra parameter : a reference to a *[SchemaManager (...)]* instance, to construct Schema Aware *Dn*. Here are some combined examples :
+
+{code:java}   
+    @Test
+    public void testCreateDnSchemaAware() throws Exception
+    {
+        SchemaManager schemaManager = new DefaultSchemaManager();
+        
+        // Create some schema aware DN 
+        Dn dn1 = new Dn( schemaManager, "sn=john doe, dc=example, dc=org" );
+        Dn dn2 = new Dn( new Rdn( "sn=John Doe" ), new Dn( schemaManager, "dc=example, dc=org" ) );
+        Dn dn3 = new Dn( schemaManager, "2.5.4.4 = John   Doe  ", "dc", "example", "dc=org" );
+        Dn dn4 = new Dn( schemaManager, "SN=JOHN   DOE, dc=example, dc=org" );
+        
+        assertEquals( dn1, dn2 );
+        assertEquals( dn1, dn3 );
+        assertEquals( dn1, dn4 );
+        assertEquals( dn2, dn3 );
+        assertEquals( dn2, dn4 );
+        assertEquals( dn3, dn4 );
+    }
+{code}
+
+
+h3. Basic manipulations on a DN
+
+There are a few methods that can be used on a *Dn* to get a part of it or to extend it.
+
+Let's describe each of these methods.
+
+h5. add( String ) and add( Rdn )
+
+These two methods are used to construct a new *Dn* from an existing one, by adding a *[DIRAPI:Rdn]* to it. It's important to remember that the *Dn* class is immutable, and that those two methods return a _*new{*}_ *Dn*, the original one being unmodified.
+
+{code:java}
+    @Test
+    public void testAddString() throws Exception
+    {
+        Dn dn = new Dn( "ou=apache, dc=org" );
+        
+        Dn dn2 = dn.add( "dc=directory" );
+        
+        assertEquals( "ou=apache, dc=org", dn.getName() );
+        assertEquals( "dc=directory,ou=apache, dc=org", dn2.getName() );
+        
+        Dn dn3 = dn.add( new Rdn( "dc=mina" ) );
+
+        assertEquals( "ou=apache, dc=org", dn.getName() );
+        assertEquals( "dc=mina,ou=apache, dc=org", dn3.getName() );
+    }
+{code}
+
+h5. add( Dn )
+
+Does pretty much the same that the _add( Rdn )_ method, but taking a *Dn* as an argument. It's used to concatenate two *Dn* together. Again, it creates a new *Dn.
+
+h5. applySchemaManager( SchemaManager )
+
+Make the *Dn* schema aware. It will also normalize the *Dn*, transforming the *[AttributeType (...)]*s to *[DIRAPI:Oid]*s and normalize the *[DIRAPI:Value]*s. here is an example :
+{code:java}
+    @Test
+    public void testApplySchemaManager() throws Exception
+    {
+        Dn dn = new Dn( "OU=Apache, OU=org" );
+        
+        assertEquals( "OU=Apache, OU=org", dn.getName() );
+        assertEquals( "ou=Apache,ou=org", dn.getNormName() );
+
+        dn.applySchemaManager( schemaManager );
+
+        assertEquals( "OU=Apache, OU=org", dn.getName() );
+        assertEquals( "2.5.4.11=apache,2.5.4.11=org", dn.getNormName() );
+    }
+{code}
+
+h5. getParent(), getRdn()
+
+The first method returns the right part of a *Dn*, ie the *Dn* minus its *[DIRAPI:Rdn]*. The second method returns the *[DIRAPI:Rdn]*.
+
+Note that if the *Dn* is either empty, null or contains only one *[DIRAPI:Rdn]*, those methods always returns a valid *Dn* or *[DIRAPI:Rdn]*. The returned element just be empty.
+
+This example demonstrates how those methods work :
+
+{code:java}
+    @Test
+    public void testGetRdn() throws Exception
+    {
+        Dn dn = new Dn( "dc=directory,dc=Apache,dc=org" );
+        
+        assertEquals( "dc=Apache,dc=org", dn.getParent().getName() );
+        assertEquals( "dc=directory", dn.getRdn().getName() );
+        
+        Dn singleDn = new Dn( "dc=org" );
+        
+        assertEquals( "", singleDn.getParent().getName() );
+        assertEquals( "dc=org", singleDn.getRdn().getName() );
+        
+        Dn emptyDn = Dn.EMPTY_DN;
+        
+        assertEquals( "", emptyDn.getParent().getName() );
+        assertEquals( "", emptyDn.getRdn().getName() );
+    }
+{code}
+
+h5. getRdn( int )
+
+This is a method that might be useful in some specific cases. It allows you to get a *[DIRAPI:Rdn]* in a *Dn*, specifying a position. 
+
+Note that the *Dn* is containing an list of 0-indexed, left to right *[DIRAPI:Rdn]*s.
+
+Here is an example :
+
+{code:java}
+    @Test
+    public void testGetRdnAtPos() throws Exception
+    {
+        Dn dn = new Dn( "dc=directory,dc=Apache,dc=org" );
+        
+        assertEquals( "dc=directory", dn.getRdn(0).getName() );
+        assertEquals( "dc=Apache", dn.getRdn(1).getName() );
+        assertEquals( "dc=org", dn.getRdn(2).getName() );
+    }
+{code}
+
+h5. getRdns()
+
+Gets an 0-indexed, left to right, list of *[DIRAPI:Rdn]*s from a *Dn*.
+
+{code:java}
+    @Test
+    public void testGetRdns() throws Exception
+    {
+        Dn dn = new Dn( "dc=directory,dc=Apache,dc=org" );
+        
+        assertEquals( "dc=directory", dn.getRdns().get( 0 ).getName() );
+        assertEquals( "dc=Apache", dn.getRdns().get( 1 ).getName() );
+        assertEquals( "dc=org", dn.getRdns().get( 2 ).getName() );
+    }
+{code}
+
+h5. iterator()
+
+A convenient way to iterate through *[DIRAPI:Rdn]{*}s is to use the _iterator()_ method. It walks through each *[DIRAPI:Rdn]*, from left to right. 
+
+{warning}
+Contrarely to the getRdn( int ) method, an iterator get through the Rdn from right to left.
+{warning}
+
+Here is an example using this method :
+
+{code:java}
+    @Test
+    public void testIterator() throws Exception
+    {
+        Dn dn = new Dn( "dc=directory,dc=Apache,dc=org" );
+        
+        String[] expected = new String[]{ "dc=org", "dc=Apache", "dc=directory" };
+        int pos = 0;
+        
+        for ( Rdn rdn : dn )
+        {
+            assertEquals( expected[pos++], rdn.getName() );
+        }
+    }
+{code}
+
+
+h3. Comparing DNs
+
+One very important operation done on *Dn* which leads to many problems from the user side is the comparison of *Dn*s. The issue is that when comparing *Dn*s, we process each *[DIRAPI:Rdn]* one by one, and for that we compare each *[DIRAPI:Ava]*. But a user provided *[DIRAPI:Ava]s* *[DIRAPI:Value]* may be different from another one when looking at them as Strings, and be equals when normalized using the *[AttributeType (...)]*'s *[MatchingRule (e)]*.
+
+In other words, unless the *Dn* is normalized, one has to do the normalizing himself on the client side. This is *very* inconvenient, and this is the reason we made the API Schema aware.
+
+When a *Dn* is Schema aware, comparing it with another *Dn* is just a breeze. The following example demonstrates this :
+
+{code:java}
+    @Test
+    public void testEquals() throws Exception
+    {
+        Dn dn1 = new Dn( "dc=directory project,dc=Apache,dc=org" );
+        Dn dn2 = new Dn( "DC=Directory project,dc=Apache,dc=org" );
+        Dn dn3 = new Dn( " DC = directory project,dc=Apache,dc=org" );
+        
+        // Just because the value isn't normalized, the first test fails
+        assertFalse( dn1.equals( dn2 ) );
+        
+        // Now, the AttributeType has spaces and is upper cased, but as the values are the same
+        // it's ok
+        assertTrue( dn1.equals( dn3 ) );
+        
+        // Let's check with Schema Aware Dns now
+        dn1.applySchemaManager( schemaManager );
+        dn2.applySchemaManager( schemaManager );
+        dn3.applySchemaManager( schemaManager );
+        
+        assertTrue( dn1.equals( dn2 ) );
+        assertTrue( dn1.equals( dn3 ) );
+        
+        // One last check
+        Dn dn4 = new Dn( schemaManager, " 0.9.2342.19200300.100.1.25 = Directory   PROJECT  , DomainComponent =  apache, Dc = ORG    " );
+        
+        assertTrue( dn1.equals( dn4 ) );
+    }
+{code}
+
+The last check is quite impressive... :)
+h3. Miscellaneous methods
+
+The API offers a few other methods. Some of them are useful to discover the relation between two *Dn{*}s, some other provide an information about the *Dn* itself :
+
+h5. isSchemaAware()
+
+Tells if the current *Dn* has some knowledge about a *[SchemaManager (...)]*. This is the case if it was created with a *[SchemaManager (...)]*. Here is some code that demonstrates the usage of this method :
+
+{code:java}
+    @Test
+    public void testIsSchemaAware() throws Exception
+    {
+        Dn dn1 = new Dn( schemaManager, "dc=directory,dc=apache,dc=org" );
+        Dn dn2 = new Dn( "dc=directory,dc=apache,dc=org" );
+
+        assertTrue( dn1.isSchemaAware() );
+        assertFalse( dn2.isSchemaAware() );
+    }
+{code}
+
+
+h5. isNullOrEmpty( Dn )
+
+Sometimes, it's important to check that a *Dn* is either null or empty, before trying to call a method on a null object. One can use this static method for that purpose.
+
+h5. isValid( Dn )
+
+This static method allows a user to check that a String *Dn* is valid, or not. It does not throw an exception, it just parses the *Dn* and return the result as a boolean. Don't overuse it, it's a costly method if you intend to transform this String *Dn* to a normal *Dn*, as you will just parse the *Dn* twice...
+
+h5. isRootDSE() and isEmpty()
+
+Tells if the *Dn* is empty, or if it's the RootDSE. In fact, both methods do the exact same thing, but the _isRootDSE_ method carries some semantic. 
+
+Here are some examples :
+{code:java}
+@Test
+    public void testIsRootDSE() throws Exception
+    {
+        Dn dn1 = new Dn();
+        Dn dn2 = new Dn( schemaManager );
+        Dn dn3 = new Dn( "" );
+        Dn dn4 = new Dn( "dc=apache, dc=org" );
+
+        assertTrue( dn1.isRootDSE() );
+        assertTrue( dn1.isEmpty() );
+
+        assertTrue( dn2.isRootDSE() );
+        assertTrue( dn2.isEmpty() );
+
+        assertTrue( dn3.isRootDSE() );
+        assertTrue( dn3.isEmpty() );
+
+        assertFalse( dn4.isRootDSE() );
+        assertFalse( dn4.isEmpty() );
+    }
+
+{code}
+
+h5. isAncestorOf( Dn )
+
+Checks if the current *Dn* is an ancestor of the given *Dn*. For instance :
+
+{code:java}
+@Test
+    public void testIsAncestorOfSchemaAware() throws Exception
+    {
+        Dn dn = new Dn( schemaManager, "dc=directory,dc=apache,dc=org" );
+        Dn dnApache = new Dn( schemaManager, "0.9.2342.19200300.100.1.25= APACHE ,dc=org" );
+        Dn dnOrg = new Dn( schemaManager, "DC = Org" );
+        Dn dnRoot = new Dn( schemaManager, "" );
+        Dn dnOther = new Dn( schemaManager, "dc=example,dc=com" );
+        
+        assertTrue( dn.isAncestorOf( dn ) );
+        assertTrue( dnApache.isAncestorOf( dn ) );
+        assertTrue( dnOrg.isAncestorOf( dn ) );
+        assertTrue( dnRoot.isAncestorOf( dn ) );
+        assertFalse( dnOther.isAncestorOf( dn ) );
+    }
+{code}
+
+One can notice that we can compare *Dn* which are using *[DIRAPI:Oid]*{*}s* or a upper case characters without any problem when the *Dns* are schema aware.
+
+The same code using schema agnostic *Dns* is a bit more limited :
+
+{code:java}
+@Test
+    public void testIsAncestorOfSchemaAware() throws Exception
+    {
+        Dn dn = new Dn( "dc=directory,dc=apache,dc=org" );
+        Dn dnApache = new Dn( "dc=apache,dc=org" );
+        Dn dnOrg = new Dn( "DC=org" );
+        Dn dnOrgOid = new Dn( "0.9.2342.19200300.100.1.25=org" );
+        Dn dnRoot = new Dn( "" );
+        Dn dnOther = new Dn( "dc=example,dc=com" );
+
+        assertTrue( dn.isAncestorOf( dn ) );
+        assertTrue( dnApache.isAncestorOf( dn ) );
+        assertTrue( dnOrg.isAncestorOf( dn ) );
+        assertTrue( dnRoot.isAncestorOf( dn ) );
+        assertFalse( dnOther.isAncestorOf( dn ) );
+
+        // Here, we try with an Oid, but it won't work
+        assertFalse( dnOrgOid.isAncestorOf( dn ) );
+    }
+{code}
+
+h5. getAncestorOf( Dn )
+
+This method is used to get the right part of a *Dn* when we have the right part of it. An example will help you to understand what it's all about :
+
+{code:java}
+@Test
+    public void testGetAncestorOfSchemaAware() throws Exception
+    {
+        Dn dn = new Dn( schemaManager, "dc=directory,dc=apache,dc=org" );
+        Dn dnApache = new Dn( schemaManager, "DC= APACHE ,dc=org" );
+
+        assertEquals( dnApache, dn.getAncestorOf( "DC=directory" ) );
+    }
+{code}
+
+h5. isDescendantOf( Dn )
+
+This method can be used to know if a *Dn* as the given *Dn* as a parent. Again, an example will be more explicit :
+
+{code:java}
+    @Test
+    public void testIsDescendantOfSchemaAware() throws Exception
+    {
+        Dn dn = new Dn( schemaManager, "dc=directory,dc=apache,dc=org" );
+
+        assertTrue( dn.isDescendantOf( "dc=apache,dc=org" ) );
+    }
+{code}
+
+
+h5. getDescendantOf( Dn )
+
+This method can be used to get the part od the *Dn* which is below a point in the *DiT*. This example will demonstrate the way it works :
+
+{code:java}
+    @Test
+    public void testGetDescendantOfSchemaAware() throws Exception
+    {
+        Dn dn = new Dn( schemaManager, "dc=directory,dc=apache,dc=org" );
+        Dn dnDirectory = new Dn( schemaManager, "dc=directory, dc=apache" );
+
+        assertEquals( dnDirectory, dn.getDescendantOf( "0.9.2342.19200300.100.1.25=org" ) );
+    }
+{code}
+
+h5. getName() and getNormName()
+
+Those two methods give back the user provided *Dn* and the normalized *Dn*. The result for the second method differs if the *Dn* is schema aware or not. Let's see with an example :
+
+{code:java}
+    @Test
+    public void testGetName() throws Exception
+    {
+        Dn dn1 = new Dn( "Ou = Apache, Ou = ORG" );
+        Dn dn2 = new Dn( schemaManager, "Ou = Apache, Ou = ORG" );
+        
+        assertEquals( "Ou = Apache, Ou = ORG", dn1.getName() );
+        assertEquals( "ou=Apache,ou=ORG", dn1.getNormName() );
+
+        assertEquals( "Ou = Apache, Ou = ORG", dn2.getName() );
+        assertEquals( "2.5.4.11=apache,2.5.4.11=org", dn2.getNormName() );
+    }
+{code}
+
+h5. getSchemaManager()
+
+Simply returns the *[SchemaManager (...)]* associated with the *Dn*, if any.
+
+h5. size()
+
+Returns the number of *[DIRAPI:Rdn]* contained in the *Dn*.

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-04-Rdn.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-04-Rdn.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-04-Rdn.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-04-Rdn.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,136 @@
+h2. Rdn
+
+A *RDN*, or *R{*}elative *D{*}istinguished *N{*}ame is a part of a *[Dn]*. It can be empty, but usually contains one *[Ava]*, but can have more than one.
+
+It's used to qualify an entry in the *DIT*, assuming that every element of a *RDN* must be present in the entry. It's important to understand that a *RDN* represents the entry, by naming it.
+
+This class can be schema aware, as soon as we inject a *[SchemaManager (...)] into it while creating an instance.
+
+It's an immutable class, and it implements the _externalizable_ interface.
+
+{tip:title=Info}
+The Rdn class is immutable.
+{tip}
+
+
+h4. Basic examples
+
+Let's see some examples :
+
+*{+}Simple RDN, not schema aware :+*
+
+{code}
+    // Create a simple Rdn
+    Rdn rdn = new Rdn( "CN = This   is a Test " );
+
+    System.out.println( "toString :           " + rdn.toString() );
+    System.out.println( "User Provided name : " + rdn.getName() );
+    System.out.println( "Normalized name :    " + rdn.getNormName() );
+{code}
+
+This code produces the output :
+
+{code}
+toString :           'CN = This   is a Test '
+User Provided name : 'CN = This   is a Test '
+Normalized name :    'cn=This   is a Test'
+{code}
+
+Note that the normalized form has a lower cased *[AttributeType (...)]* and that the value's heading and trailing spaces have been removed.
+
+*{+}Simple RDN, schema aware :+*
+
+{code}
+    // Create a schema aware Rdn
+    Rdn rdn = new Rdn( schemaManager, "CN = This   is a Test " );
+
+    System.out.println( "toString :           " + rdn.toString() );
+    System.out.println( "User Provided name : " + rdn.getName() );
+    System.out.println( "Normalized name :    " + rdn.getNormName() );
+{code}
+
+This code produces the output :
+
+{code}
+toString :           'CN = This   is a Test '
+User Provided name : 'CN = This   is a Test '
+Normalized name :    '2.5.4.3=this is a test'
+{code}
+
+Now, the normalized form uses the *[Oid]* instead of a *[AttributeType (...)]* ID, and the value is normalized accordingly to the *CN* equality matching rule.
+
+h4. Creating a RDN
+
+We can create a standard *RDN* or a schema aware *RDN*. It's just a matter to pass a *[SchemaManager (...)]* as a parameter. Here is an example of creation of a normal and schema aware ¬*RDN* :
+
+{code}
+    Rdn normalRdn = new Rdn( "CN = a simple RDN" );
+    Rdn schemaAwareRdn = new Rdn( schemaManager, "CN = a schema aware RDN" );
+{code}
+
+It's also possible to create a *RDN* by passing the *[AttributeType (...)]* and the value as two parameters :
+
+{code}
+    Rdn normalRdn = new Rdn( "CN", "a simple RDN" );
+    Rdn schemaAwareRdn = new Rdn( schemaManager, "CN", "a schema aware RDN" );
+{code}
+
+
+h4. Multiple RDN
+
+A *RDN* can contain more than one *[Ava]*. In order to access the *[Ava]s*, we can use an iterator :
+
+{code}
+    Rdn rdn = new Rdn( "cn=John + sn=Doe" );
+        
+    for ( Ava ava : rdn )
+    {
+        System.out.println( ava.toString() );
+    }
+{code}
+
+produces this output :
+
+{code}
+cn=John
+sn=Doe
+{code}
+
+However, there is no guarantee whatsoever about the order a user will get back the *[Ava]* when iterating through them.
+
+A user can also request the first *[Ava]* by calling the _getAva()_ method :
+
+{code}
+    Rdn rdn = new Rdn( "cn=John + sn=Doe" );
+        
+    System.out.println( rdn.getAva() );
+{code}
+
+produces this output :
+
+{code}
+cn=John
+{code}
+
+h4. Miscellaneous methods
+
+It's possible to make a non schema aware *RDN* by passing it a *[SchemaManager (...)]*. In order to know if a *RDN* is schema aware, we can call the _isSchemaAware()_ method. Here is some example where those methods are used :
+
+{code}
+    Rdn rdn = new Rdn( "cn=John" );
+        
+    System.out.println( "'" + rdn + "' is schema aware : " + rdn.isSchemaAware() );
+
+    System.out.println( "Applying a schemaManager to '" + rdn + "'");
+    rdn.applySchemaManager( schemaManager );
+
+    System.out.println( "'" + rdn + "' is schema aware : " + rdn.isSchemaAware() );
+{code}
+
+produces the output :
+
+{code}
+'cn=John' is schema aware : false
+Applying a schemaManager to 'cn=john'
+'cn=John' is schema aware : true
+{code}

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-05-Ava.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-05-Ava.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-05-Ava.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-05-Ava.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,49 @@
+h2. Ava
+
+*AVA* stands for _AttributeTypeAndValue_. It describes a container holding an *[AttributeType (...)]* associated with a *[DIRAPI:Value]* in a *[Rdn]*. An example would be :
+
+{code}
+dc=example
+{code}
+where 'dc' is the [AttributeType (...)] and 'example' the associated value.
+
+A user is not likely to manipulate such a class.
+
+*AVA* is a final class, it can be schema aware. It's also a _Externalizable_ class.
+
+
+h3. Usage
+
+As for the *[Dn]* and *[Rdn]* classes, we have to hold two representation for the interned *[AttributeType (...)]* and Value : the User Provided form, and the normalized form. If the *AVA* is schema aware, we will use the AttributeType's *[Oid]* as the normalized form for the *[AttributeType (...)]*, and the value will be normalized accordingly to the equality matching rule the *[AttributeType (...)]* defines, if any. Let's see some examples.
+
+
+*{+}Schema Aware :+*
+
+Here we will create an *{+}AVA{+}* and check that the user provided values are preserved. The _getUpName()_ and _getString()_ methods will give back this user provided form.
+
+{code}
+public void testAvaSimpleNorm() throws LdapException   
+{
+    Ava atav = new Ava( schemaManager, " CommonName ", " This is    a TEST " );
+    assertEquals( " CommonName = This is    a TEST ", atav.toString() );
+    assertEquals( "2.5.4.3=this is a test", atav.getNormName() );
+    assertEquals( " CommonName = This is    a TEST ", atav.getUpName() );
+}
+{code}
+
+Note that the normalized value has transformed the *[AttributeType (...)]* and now uses its *[Oid]*, and the value has been lower cased and the superfluous spaces have been removed, as dictated by the _CaseIgnoreMatch_ *[MatchingRule (e)]*
+
+
+*{+}Not Schema Aware{+}*
+
+The biggest difference in this case is that the *[AttributeType (...)]* will not be replaced by its *[Oid]*, but instead by a lower cased form of the provided ID. We also escape the leading and trailing spaces in the value.
+
+{code}
+public void testAvaSimpleNorm() throws LdapException
+{
+    Ava atav = new Ava( null, " CommonName ", " This is    a TEST " );
+    assertEquals( " CommonName = This is    a TEST ", atav.toString() );
+    assertEquals( "commonname=\\ This is    a TEST\\ ", atav.getNormName() );
+    assertEquals( " CommonName = This is    a TEST ", atav.getUpName() );
+}
+{code}

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-06-Value.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-06-Value.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-06-Value.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-06-Value.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,117 @@
+h2. Value
+
+The *Value* object is used to store attribute's values. Basically, we manage two kinds of *Value*s, *H/R* (*H{*}uman *R{*}eatable) and binary values. In the near future, we will add streamed values (ie, values storing a reference to a file on disk).
+
+h3. StringValue
+This is the most frequently used type of *Value*. It stores an _UTF-8_ String. Every *[Attribute]* or [DIRAPI:Ava]* associated with an *HR* *[AttributeType (...)]* will use such a *Value*.
+
+h3. BinaryValue
+More rarely, one would like to store some binary value into an *[Attribute]*, for instance to store a _userCertificate_ or a _jpegPhoto_, or even an _OctetString_ *[AttributeType (...)]*. In this case, the way to go is to use a *BinaryValue*. It stores an array of bytes.
+
+h3. Creating a Value
+First, a *Value* is immutable. That means the value *must* be stored while calling the constructor. In fact, we don't provide any constructor which does not take a value as a parameter (or they are package protected).
+
+Bottom line, you have two constructor per Class, whether the class is schema aware or not :
+* StringValue( String ) and BinaryValue( byte[] )
+* StringValue( AttributeType, String ) and BinaryValue( AttributeType, byte[] )
+
+The first constructor creates a simple Value storing some data without associating it with an *[AttributeType (...)]*. This is probably useful on the client side when dealing with data coming from a Ldap Server which does not exhibit the Schema.
+The second constructor creates Schema aware values, and the stored value *must* comply with the associated attributeType (ie, the *[AttributeType (...)]* syntax). Here are some example of both constructors :
+
+{code:java}
+    @Test
+    public void testCreateStringValue()
+    {
+        Value<String> value = new StringValue( "  A  test  " );
+        
+        assertNotNull( value );
+        assertEquals( "  A  test  ", value.getValue() );
+        assertEquals( "  A  test  ", value.getNormValue() );
+    }
+
+    
+    @Test
+    public void testCreateShemaAwareStringValue() throws LdapInvalidAttributeValueException
+    {
+        Value<String> value = new StringValue( atCn, "  A  test  " );
+        
+        assertNotNull( value );
+        assertEquals( "  A  test  ", value.getValue() );
+        assertEquals( "a test", value.getNormValue() );
+    }
+{code}
+
+As we can see, the biggest difference is the normalized value.
+
+If we use a schema aware *Value*, then the injected value will be checked against the associated *[AttributeType (...)]*, and normalized accordingly.
+
+Here is an example of the creation of an invalid value :
+
+{code:java}
+    @Test
+    public void testCreateShemaAwareBadStringValue()
+    {
+        try
+        {
+            new StringValue( telephoneNumber, "  A  test  " );
+            fail();
+        }
+        catch ( LdapInvalidAttributeValueException liave )
+        {
+            System.out.println( liave.getMessage() );
+        }
+    }
+{code}
+
+This test will print the following message :
+
+{code:java}
+ERR_04447_CANNOT_NORMALIZE_VALUE Cannot normalize the wrapped value ERR_04473_NOT_VALID_VALUE Not a valid value '  A  test  ' for the AttributeType 'ATTRIBUTE_TYPE ( 2.5.4.20
+ NAME 'telephoneNumber'
+ DESC RFC2256: Telephone Number
+ EQUALITY telephoneNumberMatch
+ SUBSTR telephoneNumberSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.50
+ USAGE userApplications
+ )
+'
+{code}
+
+The _BinaryValue_ creation is no different, except that its constructors only accept _byte[]_.
+
+h3. Value status methods
+
+There are a few status flags you may want to be interested in. Here are the list of methods available that give back some information about an instance :
+
+h5. isHumanReadable()
+This method tells if the *Value* contains a String or a byte[].
+
+h5. isNull()
+This method tells if the *Value* is null. Note that a schema aware *Value* can be null only if the *[AttributeType (...)]*'s syntax allows it.
+
+h5. isSchemaAware()
+Tells if the *Value* has an associated *[AttributeType (...)]*.
+
+h5. isValid( SyntaxChecker )
+Checks if the *Value* is valid. Note that if the *Value* is schema aware, calling this method does not make any sense, as the interned value has already been checked when the instance has been created.
+
+h5. isInstanceOf( AttributeType )
+Tells, for a schema aware *Value*, if the given *[AttributeType (...)]* is contained - or is a parent - of the interned *[AttributeType (...)]*.
+
+h3. Getters
+It's really a basic set of methods : 
+
+h5. getValue()
+Returns the interned user provided value. If we are dealing with a _StringValue_, returns a _String_. Of it's a _BinaryValue_, returns a _byte[]_.
+
+h5. getNormValue()
+Returns the normalized value, if the *Value* is schema aware. Otherwise, returns the exact same value than the _get()_ method.
+
+h5. getAttributeType()
+Return the interned *[AttributeType (...)]*, if the *Value* is schema aware.
+
+h5. getString()
+Returns the interned value as a _String_, if the *Value* contains a _String_.
+
+h5. getBytes()
+Returns the interned value as a _byte[]_, if the *Value* contains a _byte[]_.

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-07-Modification.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-07-Modification.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-07-Modification.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-07-Modification.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,45 @@
+h2. Modification
+
+A *Modification* is a class containing an operation applie don one *[DIRAPI:Attribute]* into an *[DIRAPI:Entry]*. This is used by the *[Modify|Message (...)#ModifyRequest]* message.
+
+We can apply more than one *Modification* on an *[DIRAPI:Entry]*.
+
+There are three kind of operation we can do:
+* Add : add a new value, or a new attribute if it does not exist already
+* Delete : remove a single value, or the attribute if we remove the last value or if the value is null
+* Replace : replace the existing values with the newly provided values, or delete the attribute if no values are provided
+
+As usual, we have two kind of *Modification*, schema aware and schema agnostic ones.
+
+h3. Creating a modification
+We have two parameters to provide to create a *Modification* :
+* an operation (add, delete or replace)
+* an *[DIRAPI:Attribute]* instance, containing the values and the attribute type
+
+We can also pass a *[SchemaManager (...)]* instance, if we want the *Modification* to be schema aware.
+
+Changing an operation to make it schema aware is just a matter to call the _apply()_ method.
+
+All the other methods are basic setters and getters.
+
+Let see a simple example :
+
+{code:java}
+    @Test
+    public void testModification()  throws LdapException
+    {
+        // Add the test1 and test2 values to the "cn" attribute
+        Attribute attribute = new DefaultAttribute( atCn, "test1", "test2" );
+        DefaultModification modCn1 = new DefaultModification( ModificationOperation.ADD_ATTRIBUTE, attribute );
+        
+        // Remove the "test2" value
+        attribute = new DefaultAttribute( atCn, "test2" );
+        DefaultModification modCn2 = new DefaultModification( ModificationOperation.REMOVE_ATTRIBUTE, attribute );
+
+        // Replace the "cn" values by the test4 "value"
+        attribute = new DefaultAttribute( atCn, "test4" );
+        DefaultModification modCn3 = new DefaultModification( ModificationOperation.REPLACE_ATTRIBUTE, attribute );
+    }
+{code}
+
+This code does nothing but creating some modifications. They have to be sent through a *[DIRAPI:Modify]* request to the server to be effective.
\ No newline at end of file

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-08-LdifEntry.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-08-LdifEntry.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-08-LdifEntry.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-08-LdifEntry.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,122 @@
+h2. LdifEntry
+
+A LdifEntry is used to store an entry after it has been parsed from a *LDIF* String. We can use a *LDIF* entry to add a new entry, delete an existing one, move an entry or modify an entry (adding, removing or changing some attributes or value).
+
+In any case, a *LdifEntry* has a *[DIRAPI:Dn]*, plus some attributes. If we don't have a _changeType_ *[DIRAPI:AttributeType]* (this is a special attribute used to indicate that we are going t modify an existing entry), then the *LdifEntry* is a new entry.
+
+An *LdifEntry* can also have controls, if the special *[DIRAPI:AttributeType]* _controls_ is present.
+
+Comments will be ignored, and we won't keep them when we build a new *LdifEntry*.
+
+The special *[DIRAPI:AttributeType]* _version_ is not mandatory, it would break too many *LDIF* files generated by most of the existing *LDAP* servers. It's simply ignored for the moment.
+
+We use an _enum_ to store the change type : _ChangeType_. The possible values are the following :
+
+{code:java}
+public enum ChangeType
+{
+    /** The Add changeType */
+    Add(0),
+
+    /** The Modify changeType */
+    Modify(1),
+
+    /** The ModDn changeType */
+    ModDn(2),
+
+    /** The ModRdn changeType */
+    ModRdn(3),
+
+    /** The Delete changeType */
+    Delete(4),
+
+    /** A place-holder when we have no changeType */
+    None(-1);
+    ...
+{code}
+
+h3. Constructors
+h4. _LdifEntry()_
+Creates a simple *LdifEntry*, with no information into it.
+
+h4. _LdifEntry(String, ObjectÉ)_, _ _LdifEntry(Dn, ObjectÉ)_
+Creates an entry with a *[DIRAPI:Dn]* and some attributes and values given in a *LDIF* format.
+
+Here is an example :
+
+{code:java}
+    @Test
+    public void testSimpleLdifEntry() throws Exception
+    {
+        String cn = "app1";
+        
+        LdifEntry ldifEntry = new LdifEntry( "cn=app1,dc=apache,dc=org", 
+            "cn", cn,
+            "objectClass: top", 
+            "objectClass: apApplication", 
+            "displayName:   app1   ",
+            "dependencies:",
+            "envVars:" );
+
+        assertNotNull( ldifEntry );
+        assertTrue( ldifEntry.isLdifContent() );
+        assertEquals( "cn=app1,dc=apache,dc=org", ldifEntry.getDn().getName() );
+
+        Attribute attr = ldifEntry.get( "displayname" );
+        assertTrue( attr.contains( "app1" ) );
+        
+        Attribute cnAttr = ldifEntry.get( "cn" );
+        assertTrue( cnAttr.contains( "app1" ) );
+    }
+{code}
+
+* _LdifEntry(Entry)_ 
+
+Creates an *LdifEntry* from an *[DIRAPI:Entry]*. We won't have any change type for the created *LdifEntry*. If you use this *LdifEntry* and inject it into a *LDAP* server, a new entry will be created.
+
+h4. Getters
+We have a set of getters :
+* _get(String)_: Gets the attribute which name is given.
+* _getChangeType()_: Returns the change type. 
+* _getControl(String)_: Returns the *[DIRAPI:Control]* with the specific *Oid*, if there is one in the *LdifEntry*.
+* _getControls()_: Returns the list of existing *[DIRAPI:Control]s*
+* _getDn()_: Returns the *LdifEntry* *[DIRAPI:Dn]*
+* _getEntry()_: Returns the stored entry, if any (this method will return null if the *LdifEntry* is used to encode a delete operation)
+* _getModifications()_: Returns the list of *[DIRAPI:Modification] applied in the *LdifEntry*, as a _List_
+* _getModificationArray()_: Returns the list of *[DIRAPI:Modification] applied in the *LdifEntry*, as an array
+* _getNewRdn()_: If the *LdifEntry* encodes for a mve operation, gets the new name.
+* _getNewSuperior()_: If the *LdifEntry* encodes for a mve operation, gets the new Parent.
+
+h4. Modifying an LdifEntry
+
+We have a set of methods used to modify the current *LdifEntry*
+* _addAttribute(Attribute)_: Adds an attribute to the *LdifEntry*
+* _addAttribute(String, Object...)_: Adds an attribute with some values in the *LdifEntry*
+* _addControl(Control...)_: Adds a *[DIRAPI:Control]* to the *LdifEntry*
+* _addModification(Modification)_: Adds a *[DIRAPI:Modificaton]* to the *LdifEntry*
+* _addModification(ModificationOperation, Attribute)_: Adds a new modification to the *LdifEntry*, created from the operation and attribute.
+* _addModification(ModificationOperation, String, Object)_: Adds a new modification to the *LdifEntry*, created from the operation, attribute type and values.
+* _putAttribute(String, Object)_: Adds a new attribute and values in the *LdifEntry*.
+* _removeAttribute(String...)_: Remove a set of attributes from the *LdifEntry*
+* _setChangeType(ChangeType)_: Set the type of change we apply on the *LdifEntry*.
+* _setChangeType(String)_: Same method, but using the *ChangeType* name ( "Add", "Modify", "ModDn", "ModRdn", "Delete")
+* _setDeleteOldRdn(boolean)_: Sets the flag requesting for the deletion of the old Rdn when it's a move operation.
+* _setDn(Dn)_: Sets the *LdifEntry* *[DIRAPI:Dn]*
+* _setDn(String)_: Sets the *LdifEntry* *[DIRAPI:Dn]*
+* _setNewRdn(String)_: Sets the new *LdifEntry* name if it's a move operation.
+* _setNewSuperior(String)_: Sets the new *LdifEntry* parent if it's a move operation.
+
+h4. LdifEntry status
+We now have a set of methods used to get some status of the current *LdifEntry* :
+
+* _hasControls()_: Tells if the *LdifEntry* has some controls.
+* _isChangeAdd()_: Tells if the *LdifEntry* is a modification with an _Add_ operation.
+* _isChangeDelete()_: Tells if the *LdifEntry* is a modification with a _Delete_ operation.
+* _isChangeModDn()_: Tells if the *LdifEntry* is a modification with an _ModDn_ operation.
+* _isChangeModify()_: Tells if the *LdifEntry* is a modification with an _Modify_ operation.
+* _isChangeModRdn()_: Tells if the *LdifEntry* is a modification with an _ModRdn_ operation.
+* _isDeleteOldRdn()_: Tells if the old *[DIRAPI:Rdn]* should be deleted
+* _isEntry()_: Tells if the *LdifEntry* encodes for a simple entry addition
+* _isLdifChange()_: Tells if the *LdifEntry* encodes for a modify operation or a delete operation
+* _isLdifContent()_: Tells if the *LdifEntry* is not a change operation nor a delete operation.
+* _size()_: Gives the number of modifications if it's a change operation

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-09-LdifControl.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-09-LdifControl.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-09-LdifControl.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-09-LdifControl.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1 @@
+h2. LdifControl

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-10-Oid.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-10-Oid.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-10-Oid.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-10-Oid.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,30 @@
+h2. Oid
+
+The *Oid* class represents the *IETF* ObjectIDentifier. It's a numerics/dots representation of a unique element in a hierarchy of objects. It's used in a few places in the *API*, like when one wants to send an _Extended operation_ (extended operations are identified by their *OID*).
+
+You are not likely to use and *Oid* or create an *Oid* instance, usually you will use a String containing an *OID*.
+
+However, this class contains an utility methods that can be useful when manipulating *OID* as Strings. It tells you if the String is a valid *OID* :
+
+
+
+{code}
+     public static boolean isOid( String oid )
+{code}
+
+It's easy to use&nbsp;:
+
+
+{code}
+        if ( Oid.isOid( Ç 1.2.3.4.5 È ) ) {
+            ...
+{code}
+
+Note that *Oids* have to respect a few rules&nbsp;:
+
+* each number must be separated by a dot
+* only dots and numbers are allowed
+* an *Oid* must start and end with a number
+* the first number must be 0, 1 or 2
+* the second number must be within&nbsp;\[0, 39\]
+* a number must always be greater or equal to 0
\ No newline at end of file

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-11-Csn.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-11-Csn.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-11-Csn.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-11-Csn.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,33 @@
+h2. Csn
+
+The *CSN* (Change Sequence Number) is used to track modifications done on an entry. It's used during replication. You are not likely to use it, unless you want to implement some replication system.
+
+*CSN* are described in [http://tools.ietf.org/html/draft-ietf-ldup-model-09]
+
+
+A *CSN* is seen as a String, which syntax is&nbsp;:
+
+{code}
+<CSN>            ::= <timestamp> # <changeCount> # <replicaId> # <modifierNumber>
+<timestamp>      ::= A GMT based time, YYYYmmddHHMMSS.uuuuuuZ
+<changeCount>    ::= 000000-ffffff
+<replicaId>      ::= 000-fff
+<modifierNumber> ::= 000000-ffffff
+{code}
+
+In order to create a *CSN*, the best is to use the *CsnFactory* class :
+
+
+{code}
+int replicaId = 001;
+CsnFactory defaultCSNFactory = new CsnFactory( replicaId );
+Csn csn = defaultCSNFactory.newInstance();
+System.out.println( csn );
+{code}
+
+produces :
+
+
+{code}
+20110318165008.941000Z#000000#001#000000
+{code}
\ No newline at end of file

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-12-ObjectClass.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-12-ObjectClass.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-12-ObjectClass.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-12-ObjectClass.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1 @@
+h2. ObjectClass

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-13-NameForm.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-13-NameForm.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-13-NameForm.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-13-NameForm.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1 @@
+h2. NameForm

Added: directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-14-Message.confluence
URL: http://svn.apache.org/viewvc/directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-14-Message.confluence?rev=1186334&view=auto
==============================================================================
--- directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-14-Message.confluence (added)
+++ directory/documentation/ldap-api-manuals/trunk/src/ldap-api-user-guide-confluence/chapter-7/7-14-Message.confluence Wed Oct 19 16:58:05 2011
@@ -0,0 +1,125 @@
+h2. Message
+
+The *Messages* are used to communicate with the *LDAP* server. We send requests, and receive responses. Both [#Request]s and [#Response]s are message.
+
+In this chapter, we will describe the *Messages* elements, and how to use them.
+
+h3. Existing messages
+We have 10 possible requests, and 11 possible responses, with one special response (*[#IntermediateResponse]*). This special response can be used for any request, assuming that the client has specified a control that requires such a response, and is able to handle it.
+
+*[#IntermediateResponse]s* are very specific, and a user should not expect to get it, except in some rare occasions, and it's very dependent o the Server the user is contacting. An example of *[#IntermediateResponse]* usage is when the server is implementing the [*Syncrepl|http://www.rfc-editor.org/rfc/rfc4533.txt] protocol
+
+Here is a list of all the existing requests and their associated responses :
+
+|| Request || Responses ||
+| [#AbandonRequest] | none ([#IntermediateResponse]) | 
+| [#AddRequest] | [#AddResponse] ([#IntermediateResponse]) |
+| [#BindRequest] | [#BindResponse] ([#IntermediateResponse]) |
+| [#CompareRequest] | [#CompareResponse] ([#IntermediateResponse]) |
+| [#DelRequest] | [#DelResponse] ([#IntermediateResponse]) |
+| [#ExtendedRequest] | [#ExtendedResponse], [#IntermediateResponse] |
+| [#ModifyRequest] | [#ModifyResponse] ([#IntermediateResponse]) |
+| [#ModifyDNRequest] | [#ModifyDNResponse] (IntermediateResponse]) |
+| [#SearchRequest] | [#SearchResultEntry], [#SearchResultDone], [#SearchResultReference] |
+| [#UnbindRequest] | None ([#IntermediateResponse]) |
+
+h3. Requests
+Here is the description of each request a user can send.
+
+h4. AbandonRequest
+
+The *AbandonRequest* is quite simple. It takes just one parameter, the *ID* of the message we want to abandon. Obviously, you need to know what this message *ID* is, and every message has an *ID* which can be retrieved by calling the _getMessageId()_ method.
+
+Also note that only requests can be abandoned, that if you take a response's *ID*, and use it in the *AbandonRequest*, you will abandon the associated request (which makes sense only for *SearchResultEntry*, *SearchReference* and *IntermediateResponse*), and that all requests can't be abandoned.
+
+h4. Using the AbandonRequest
+
+{code:java}
+        ... 
+        // We have added 100 entries in the serverbefore doing a search
+        // Launch the search now
+        Cursor<Response> cursor = connection.search( new Dn( "ou=system" ), "(cn=*)", SearchScope.ONELEVEL, "*" );
+
+        Response searchResponse = null;
+        int count = 0;
+
+        // Iterate over the results
+        while ( cursor.next() )
+        {
+            searchResponse = cursor.get();
+            count++;
+
+            if ( count > 10 )
+            {
+                // Abandon the search request when we have received the 10th entry
+                AbandonRequest abandon = new AbandonRequestImpl( searchResponse.getMessageId() );
+                connection.abandon( abandon );
+            }
+        }
+        
+        cursor.close();
+
+        System.out.println( "Responses received / expected : " + count + "/" + numEntries );
+        ...
+{code}
+
+This code produces this output :
+
+{code:java}
+Responses received / expected : 11/100
+{code}
+
+As we can see, the _cursor_next()_ call won't return any other entry as soon as the _abandonRequest_ is received by the server.
+
+h4. BindRequest
+The *BindRequest* is used to get authenticated on a *LDAP* server. Note that it has nothing to do with the connection itself : you can be connected, and even request the server, without being bound. 
+
+Once you are bound, you have a session with your credentials, and the server might behave accordingly to your set of authorizations.
+
+We have two kind of authentication, each of them being established through a *BindRequest* :
+* Simple authentication
+* SASL authentication
+
+h5. Simple Bind
+
+TODO : complete the description
+
+h5. SASL Bind
+
+A *SASL* bind can be a complex operation, with more than one exchange between the client and the server. One can feed the *BindRequest* data structure and send it to the server, but this is not really an option, as the following exchanges have to be handled.
+
+We provide some dedicated classes to manage many of the *SASL* bind :
+
+|| Mechanism || class ||
+| *CRAM-MD5* | *[DIRAPI:CramMd5Request]* |
+| *DIGEST-MD5* | *[DIRAPI:DigestMd5Request]* |
+| *GSSAPI* | *[DIRAPI:GssApiRequest]* |
+
+
+h4. AddRequest
+h4. BindRequest
+h4. CompareRequest
+h4. DelRequest
+h4. ExtendedRequest
+h4. ModifyRequest
+h4. ModifyDNRequest
+h4. SearchRequest
+h4. UnbindRequest
+
+h3. Responses
+Here is the description of each response a user can receive.
+
+h4. AddResponse
+h4. BindResponse
+h4. CompareResponse
+h4. DelResponse
+h4. ExtendedResponse
+h4. ModifyResponse
+h4. ModifyDNResponse
+h4. SearchResultEntry
+h4. SearchResultReference
+h4. SearchResultDone
+h4. IntermediateResponse
+
+
+



Mime
View raw message