From 73bf799efd605eca244e788d1655a31a5e1bd671 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Mon, 28 May 2007 15:31:13 +0000
Subject: [PATCH] Fix the following issues:

---
 opendj-sdk/opends/resource/admin/metaMO.xsl                                                                                    |  125 +
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java                             |  117 +
 opendj-sdk/opends/resource/admin/property-types.xsl                                                                            |   44 
 opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java                                                       |   23 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java                           |   42 
 opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java                                           |  723 +++++++----
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java                        |   20 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java                                 |   18 
 opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java                                                   |  584 +-------
 opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java                                                           |    5 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java                            |   15 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java                       |   76 
 opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java                             |   80 
 opendj-sdk/opends/resource/admin/preprocessor.xsl                                                                              |   30 
 opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java                                                    |  206 ++
 opendj-sdk/opends/resource/admin/clientMO.xsl                                                                                  |   77 
 opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java                             |   53 
 /dev/null                                                                                                                      |  111 -
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java                   |  115 +
 opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java                           |  120 +
 opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java                                             |   90 +
 opendj-sdk/opends/resource/admin/admin.xsd                                                                                     |   80 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java                          |   35 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java |   63 
 opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java                                        |  799 ++++++++----
 opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java                                                 |  124 -
 opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java                                                  |   32 
 27 files changed, 2,302 insertions(+), 1,505 deletions(-)

diff --git a/opendj-sdk/opends/resource/admin/admin.xsd b/opendj-sdk/opends/resource/admin/admin.xsd
index a2c9104..281d00a 100644
--- a/opendj-sdk/opends/resource/admin/admin.xsd
+++ b/opendj-sdk/opends/resource/admin/admin.xsd
@@ -308,8 +308,23 @@
       <xsd:annotation>
         <xsd:documentation>
           Indicates whether or not this property is read-only. By
-          default, properties are modifiable. Read-only monitoring
-          information is a good use-case for read-only properties.
+          default, properties are not read-only. Read-only properties
+          can only be initialized during construction of the associated
+          managed object and cannot be modified once the managed object
+          has been created.
+        </xsd:documentation>
+      </xsd:annotation>
+    </xsd:attribute>
+    <xsd:attribute name="monitoring" type="xsd:boolean" use="optional"
+      default="false">
+      <xsd:annotation>
+        <xsd:documentation>
+          Indicates whether or not this property is read-only and
+          generated automatically by the server as monitoring
+          information. By default, properties are not for monitoring.
+          Monitoring properties are always read-only because their
+          values are generated by the server. During construction of a
+          managed object their values are undefined.
         </xsd:documentation>
       </xsd:annotation>
     </xsd:attribute>
@@ -746,6 +761,25 @@
                     </xsd:restriction>
                   </xsd:simpleType>
                 </xsd:attribute>
+                <xsd:attribute name="managed-object-name"
+                  type="tns:name-type" use="required">
+                  <xsd:annotation>
+                    <xsd:documentation>
+                      The type of managed object providing the default
+                      values.
+                    </xsd:documentation>
+                  </xsd:annotation>
+                </xsd:attribute>
+                <xsd:attribute name="managed-object-package"
+                  type="tns:package-type" use="optional">
+                  <xsd:annotation>
+                    <xsd:documentation>
+                      The package containing the managed object
+                      definition if it is not the same as this managed
+                      object's package.
+                    </xsd:documentation>
+                  </xsd:annotation>
+                </xsd:attribute>
                 <xsd:attribute name="property-name" type="tns:name-type"
                   use="required">
                   <xsd:annotation>
@@ -765,16 +799,15 @@
                 </xsd:documentation>
               </xsd:annotation>
               <xsd:complexType>
-                <xsd:sequence>
-                  <xsd:element name="path">
-                    <xsd:annotation>
-                      <xsd:documentation>
-                        TODO: not sure what form this will take.
-                      </xsd:documentation>
-                    </xsd:annotation>
-                    <xsd:complexType />
-                  </xsd:element>
-                </xsd:sequence>
+                <xsd:attribute name="path" type="tns:path-type"
+                  use="required">
+                  <xsd:annotation>
+                    <xsd:documentation>
+                      The location of the managed object containing the
+                      default values.
+                    </xsd:documentation>
+                  </xsd:annotation>
+                </xsd:attribute>
                 <xsd:attribute name="property-name" type="tns:name-type"
                   use="required">
                   <xsd:annotation>
@@ -1237,19 +1270,28 @@
     <xsd:annotation>
       <xsd:documentation>
         A managed object path which can be used to specify the location
-        of refererenced managed objects. A managed object path has a
+        of referenced managed objects. A managed object path has a
         similar syntax to unix file system paths, and comprises of zero
         or more path elements separated by a forward slash "/". The root
         configuration is referenced using the path "/". Subsequent path
-        elements name either a relation or its subordinate named managed
-        object (for one-to-many relations). For example, the path
-        "/connection-handlers/LDAP connection handler" references the
-        LDAP connection handler managed object referenced by the root
-        configuration's connection-handlers relation.
+        elements identify subordinate managed objects. Each path element
+        is comprised of the relation name, an optional definition name,
+        and the name of the managed object instance if the relation is
+        one-to-many. The path "/relation=connection-handler+name=my
+        handler" identifies a connection handler called "my handler"
+        where "my handler" can be any type of connection handler. If "my
+        handler" must be an LDAP connection handler then the type needs
+        to be specified in the path:
+        "/relation=connection-handler+type=ldap-connection-handler+name=my
+        handler". The global configuration is identified by the path
+        "/relation=global-configuration" (no name is required because
+        the relation is one-to-one).
       </xsd:documentation>
     </xsd:annotation>
     <xsd:restriction base="xsd:string">
-      <xsd:pattern value="/([^/]+(/[^/]+)*)?"></xsd:pattern>
+      <xsd:pattern
+        value="/|(/relation=[^/+]+(\+type=[^/+]+)?(\+name=[^/]+)?)+">
+      </xsd:pattern>
     </xsd:restriction>
   </xsd:simpleType>
   <xsd:complexType name="profile-type">
diff --git a/opendj-sdk/opends/resource/admin/clientMO.xsl b/opendj-sdk/opends/resource/admin/clientMO.xsl
index 3db6324..2e6197e 100644
--- a/opendj-sdk/opends/resource/admin/clientMO.xsl
+++ b/opendj-sdk/opends/resource/admin/clientMO.xsl
@@ -176,34 +176,26 @@
           <xsl:with-param name="indent" select="2" />
           <xsl:with-param name="content"
             select="concat(
-                       'Creates the ', $ufn,' if it does not exist yet.&#xa;',
+                       'Creates a new ', $ufn,'. The new ', $ufn,' will initially ',
+                       'not contain any property values (including mandatory ',
+                       'properties). Once the ', $ufn,' has been configured it ',
+                       'can be added to the server using the {@link #commit()} ',
+                       'method.&#xa;',
                        '&#xa;',
                        '@param &lt;C&gt;&#xa;',
-                       '         The type of the ', $ufn,' being added.&#xa;',
+                       '         The type of the ', $ufn,' being created.&#xa;',
                        '@param d&#xa;',
                        '         The definition of the ', $ufn,' to be created.&#xa;',
-                       '@param p&#xa;',
-                       '         A property provider which can be used to initialize the property values of the new ', $ufn,'.&#xa;',
-                       '@return Returns the ', $ufn,' instance representing the ', $ufn,' that was created.&#xa;',
-                       '@throws ManagedObjectDecodingException&#xa;',
-                       '          If the ', $ufn,' could not be created because one or more of its properties are invalid.&#xa;',
-                       '@throws ManagedObjectAlreadyExistsException&#xa;',
-                       '          If the ', $ufn,' cannot be created because it already exists on the server.&#xa;',
-                       '@throws ConcurrentModificationException&#xa;',
-                       '          If this ', $ufn,' has been removed from the server by another client.&#xa;',
-                       '@throws OperationRejectedException&#xa;',
-                       '          If the server refuses to create the ', $ufn,' due to some server-side constraint which cannot be satisfied.&#xa;',
-                       '@throws AuthorizationException&#xa;',
-                       '          If the server refuses to create the ', $ufn,' because the client does not have the correct privileges.&#xa;',
-                       '@throws CommunicationException&#xa;',
-                       '          If the client cannot contact the server due to an underlying communication problem.&#xa;')" />
+                       '@param exceptions&#xa;',
+                       '         An optional collection in which to place any ',
+                       '{@link DefaultBehaviorException}s that occurred whilst ',
+                       'attempting to determine the default values of the ', $ufn,
+                       '. This argument can be &lt;code&gt;null&lt;code&gt;.&#xa;',
+                       '@return Returns a new ', $ufn,' configuration instance.&#xa;')" />
         </xsl:call-template>
         <xsl:value-of
           select="concat('  &lt;C extends ', $java-class-name,'CfgClient&gt; C create', $java-relation-name, '(&#xa;',
-                           '      ManagedObjectDefinition&lt;C, ?&gt; d, PropertyProvider p)&#xa;',
-                           '      throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,&#xa;',
-                           '      ConcurrentModificationException, OperationRejectedException,&#xa;',
-                           '      AuthorizationException, CommunicationException;&#xa;')" />
+                           '      ManagedObjectDefinition&lt;C, ?&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions);&#xa;')" />
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
@@ -297,36 +289,28 @@
           <xsl:with-param name="indent" select="2" />
           <xsl:with-param name="content"
             select="concat(
-                       'Creates a new ', $ufn,'.&#xa;',
+                       'Creates a new ', $ufn,'. The new ', $ufn,' will initially ',
+                       'not contain any property values (including mandatory ',
+                       'properties). Once the ', $ufn,' has been configured it ',
+                       'can be added to the server using the {@link #commit()} ',
+                       'method.&#xa;',
                        '&#xa;',
                        '@param &lt;C&gt;&#xa;',
-                       '         The type of the ', $ufn,' being added.&#xa;',
+                       '         The type of the ', $ufn,' being created.&#xa;',
                        '@param d&#xa;',
                        '         The definition of the ', $ufn,' to be created.&#xa;',
                        '@param name&#xa;',
                        '         The name of the new ', $ufn,'.&#xa;',
-                       '@param p&#xa;',
-                       '         A property provider which can be used to initialize the property values of the new ', $ufn,'.&#xa;',
-                       '@return Returns a new ', $ufn,' instance representing the ', $ufn,' that was created.&#xa;',
-                       '@throws ManagedObjectDecodingException&#xa;',
-                       '          If the ', $ufn,' could not be created because one or more of its properties are invalid.&#xa;',
-                       '@throws ManagedObjectAlreadyExistsException&#xa;',
-                       '          If the ', $ufn,' cannot be created because it already exists on the server.&#xa;',
-                       '@throws ConcurrentModificationException&#xa;',
-                       '          If this ', $ufn,' has been removed from the server by another client.&#xa;',
-                       '@throws OperationRejectedException&#xa;',
-                       '          If the server refuses to create the ', $ufn,' due to some server-side constraint which cannot be satisfied.&#xa;',
-                       '@throws AuthorizationException&#xa;',
-                       '          If the server refuses to create the ', $ufn,' because the client does not have the correct privileges.&#xa;',
-                       '@throws CommunicationException&#xa;',
-                       '          If the client cannot contact the server due to an underlying communication problem.&#xa;')" />
+                       '@param exceptions&#xa;',
+                       '         An optional collection in which to place any ',
+                       '{@link DefaultBehaviorException}s that occurred whilst ',
+                       'attempting to determine the default values of the ', $ufn,
+                       '. This argument can be &lt;code&gt;null&lt;code&gt;.&#xa;',
+                       '@return Returns a new ', $ufn,' configuration instance.&#xa;')" />
         </xsl:call-template>
         <xsl:value-of
           select="concat('  &lt;C extends ', $java-class-name,'CfgClient&gt; C create', $java-relation-name, '(&#xa;',
-                           '      ManagedObjectDefinition&lt;C, ?&gt; d, String name, PropertyProvider p)&#xa;',
-                           '      throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,&#xa;',
-                           '      ConcurrentModificationException, OperationRejectedException,&#xa;',
-                           '      AuthorizationException, CommunicationException;&#xa;')" />
+                           '      ManagedObjectDefinition&lt;C, ?&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions);&#xa;')" />
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
@@ -382,11 +366,14 @@
           <import>java.util.Collection</import>
           <import>java.util.SortedSet</import>
         </xsl:if>
-        <xsl:if test="$this-local-properties[not(@read-only='true')]">
+        <xsl:if test="$this-local-properties[not(@monitoring='true')]">
           <import>
             org.opends.server.admin.IllegalPropertyValueException
           </import>
         </xsl:if>
+        <xsl:if test="$this-local-properties[@read-only='true']">
+          <import>org.opends.server.admin.PropertyIsReadOnlyException</import>
+        </xsl:if>
         <xsl:if test="$this-local-relations">
           <import>
             org.opends.server.admin.DefinitionDecodingException
@@ -409,9 +396,9 @@
         </xsl:if>
         <xsl:if
           test="$this-local-relations/adm:one-to-zero-or-one|$this-local-relations/adm:one-to-many">
-          <import>org.opends.server.admin.PropertyProvider</import>
+          <import>java.util.Collection</import>
           <import>
-            org.opends.server.admin.ManagedObjectAlreadyExistsException
+            org.opends.server.admin.DefaultBehaviorException
           </import>
           <import>
             org.opends.server.admin.client.OperationRejectedException
diff --git a/opendj-sdk/opends/resource/admin/metaMO.xsl b/opendj-sdk/opends/resource/admin/metaMO.xsl
index 46a998d..9ba6a10 100644
--- a/opendj-sdk/opends/resource/admin/metaMO.xsl
+++ b/opendj-sdk/opends/resource/admin/metaMO.xsl
@@ -387,7 +387,8 @@
       select="concat('    /**&#xa;',
                      '     * {@inheritDoc}&#xa;',
                      '     */&#xa;',
-                     '    public void commit() throws ConcurrentModificationException,&#xa;',
+                     '    public void commit() throws ManagedObjectAlreadyExistsException,&#xa;',
+                     '        MissingMandatoryPropertiesException, ConcurrentModificationException,&#xa;',
                      '        OperationRejectedException, AuthorizationException,&#xa;',
                      '        CommunicationException {&#xa;',
                      '      impl.commit();&#xa;',
@@ -568,29 +569,33 @@
           select="concat('      ', $type, '.Builder builder = ', $type, '.createBuilder(INSTANCE, &quot;',@name, '&quot;);&#xa;')" />
       </xsl:otherwise>
     </xsl:choose>
-    <xsl:if test="string(@multi-valued) = 'true'">
+    <xsl:if test="@multi-valued='true'">
       <xsl:value-of
         select="'      builder.setOption(PropertyOption.MULTI_VALUED);&#xa;'" />
     </xsl:if>
-    <xsl:if test="string(@read-only) = 'true'">
+    <xsl:if test="@read-only='true'">
       <xsl:value-of
         select="'      builder.setOption(PropertyOption.READ_ONLY);&#xa;'" />
     </xsl:if>
+    <xsl:if test="@monitoring='true'">
+      <xsl:value-of
+        select="'      builder.setOption(PropertyOption.MONITORING);&#xa;'" />
+    </xsl:if>
     <xsl:if
       test="adm:requires-admin-action/adm:server-restart|adm:requires-admin-action/adm:component-restart|adm:requires-admin-action/adm:other">
       <xsl:value-of
         select="'      builder.setOption(PropertyOption.REQUIRES_ADMIN_ACTION);&#xa;'" />
     </xsl:if>
-    <xsl:if test="string(@mandatory) = 'true'">
+    <xsl:if test="@mandatory='true'">
       <xsl:value-of
         select="'      builder.setOption(PropertyOption.MANDATORY);&#xa;'" />
     </xsl:if>
-    <xsl:if test="string(@hidden) = 'true'">
+    <xsl:if test="@hidden='true'">
       <xsl:value-of
         select="'      builder.setOption(PropertyOption.HIDDEN);&#xa;'" />
     </xsl:if>
     <xsl:choose>
-      <xsl:when test="string(@mandatory) = 'true'">
+      <xsl:when test="@mandatory='true'">
         <xsl:value-of
           select="concat('      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider&lt;', $value-type,'&gt;());&#xa;')" />
       </xsl:when>
@@ -629,19 +634,37 @@
           </xsl:when>
           <xsl:when
             test="adm:default-behavior/adm:inherited/adm:relative">
-            <xsl:message terminate="yes">
-              <xsl:value-of
-                select="concat('Relative inherited property defaults not yet implemented (property &quot;', @name,
-                         '&quot;).')" />
-            </xsl:message>
+            <xsl:value-of
+              select="concat('      DefaultBehaviorProvider&lt;', $value-type,'&gt; provider = ',
+                             'new RelativeInheritedDefaultBehaviorProvider&lt;', $value-type,'&gt;(')" />
+            <xsl:variable name="managed-object-name">
+              <xsl:call-template name="name-to-java">
+                <xsl:with-param name="value"
+                  select="adm:default-behavior/adm:inherited/adm:relative/@managed-object-name" />
+              </xsl:call-template>
+            </xsl:variable>
+            <xsl:variable name="property-name"
+              select="adm:default-behavior/adm:inherited/adm:relative/@property-name" />
+            <xsl:variable name="offset"
+              select="adm:default-behavior/adm:inherited/adm:relative/@offset" />
+            <xsl:value-of
+              select="concat($managed-object-name, 'CfgDefn.getInstance(), &quot;', $property-name, '&quot;, ', $offset, ');&#xa;')" />
+            <xsl:value-of
+              select="'      builder.setDefaultBehaviorProvider(provider);&#xa;'" />
           </xsl:when>
           <xsl:when
             test="adm:default-behavior/adm:inherited/adm:absolute">
-            <xsl:message terminate="yes">
-              <xsl:value-of
-                select="concat('Absolute inherited property defaults not yet implemented (property &quot;', @name,
-                         '&quot;).')" />
-            </xsl:message>
+            <xsl:value-of
+              select="concat('      DefaultBehaviorProvider&lt;', $value-type,'&gt; provider = ',
+                             'new AbsoluteInheritedDefaultBehaviorProvider&lt;', $value-type,'&gt;(')" />
+            <xsl:variable name="property-name"
+              select="adm:default-behavior/adm:inherited/adm:absolute/@property-name" />
+            <xsl:variable name="path"
+              select="adm:default-behavior/adm:inherited/adm:absolute/@path" />
+            <xsl:value-of
+              select="concat('ManagedObjectPath.valueOf(&quot;', $path, '&quot;), &quot;', $property-name, '&quot;);&#xa;')" />
+            <xsl:value-of
+              select="'      builder.setDefaultBehaviorProvider(provider);&#xa;'" />
           </xsl:when>
           <xsl:otherwise>
             <xsl:message terminate="yes">
@@ -1017,7 +1040,7 @@
     Generate a property value setter.
   -->
   <xsl:template name="generate-property-setter">
-    <xsl:if test="string(@read-only) != 'true'">
+    <xsl:if test="not(@monitoring='true')">
       <xsl:variable name="java-prop-name">
         <xsl:call-template name="name-to-java">
           <xsl:with-param name="value" select="@name" />
@@ -1031,9 +1054,9 @@
                      $java-prop-name ,
                      '(')" />
       <xsl:choose>
-        <xsl:when test="string(@multi-valued) != 'true'">
+        <xsl:when test="not(@multi-valued='true')">
           <xsl:choose>
-            <xsl:when test="@mandatory = 'true'">
+            <xsl:when test="@mandatory='true'">
               <xsl:call-template
                 name="get-property-java-primitive-type" />
             </xsl:when>
@@ -1041,8 +1064,12 @@
               <xsl:call-template name="get-property-java-type" />
             </xsl:otherwise>
           </xsl:choose>
+          <xsl:value-of select="' value)'" />
+          <xsl:if test="@read-only='true'">
+            <xsl:value-of select="' throws PropertyIsReadOnlyException'" />
+          </xsl:if>
           <xsl:value-of
-            select="concat(' value) {&#xa;' ,
+            select="concat(' {&#xa;' ,
                      '      impl.setPropertyValue(INSTANCE.get',
                      $java-prop-name ,
                      'PropertyDefinition(), value);&#xa;',
@@ -1119,11 +1146,8 @@
                          '     * {@inheritDoc}&#xa;',
                          '     */&#xa;',
                          '    public &lt;M extends ', $java-class-name, 'CfgClient&gt; M create', $java-relation-name, '(&#xa;',
-                         '        ManagedObjectDefinition&lt;M, ?&gt; d, PropertyProvider p)&#xa;',
-                         '        throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,&#xa;',
-                         '        ConcurrentModificationException, OperationRejectedException,&#xa;',
-                         '        AuthorizationException, CommunicationException {&#xa;',
-                         '      return impl.createChild(INSTANCE.get', $java-relation-name,'RelationDefinition(), d, p).getConfiguration();&#xa;',
+                         '        ManagedObjectDefinition&lt;M, ?&gt; d, Collection&lt;DefaultBehaviorException&gt; exceptions) {&#xa;',
+                         '      return impl.createChild(INSTANCE.get', $java-relation-name,'RelationDefinition(), d, exceptions).getConfiguration();&#xa;',
                          '    }&#xa;')" />
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
@@ -1175,11 +1199,8 @@
                          '     * {@inheritDoc}&#xa;',
                          '     */&#xa;',
                          '    public &lt;M extends ', $java-class-name, 'CfgClient&gt; M create', $java-relation-name, '(&#xa;',
-                         '        ManagedObjectDefinition&lt;M, ?&gt; d, String name, PropertyProvider p)&#xa;',
-                         '        throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,&#xa;',
-                         '        ConcurrentModificationException, OperationRejectedException,&#xa;',
-                         '        AuthorizationException, CommunicationException {&#xa;',
-                         '      return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, p).getConfiguration();&#xa;',
+                         '        ManagedObjectDefinition&lt;M, ?&gt; d, String name, Collection&lt;DefaultBehaviorException&gt; exceptions) {&#xa;',
+                         '      return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, exceptions).getConfiguration();&#xa;',
                          '    }&#xa;')" />
         <xsl:text>&#xa;</xsl:text>
         <xsl:text>&#xa;</xsl:text>
@@ -1571,6 +1592,7 @@
         <xsl:if
           test="$this-local-properties[@multi-valued='true' or
                                        @read-only='true' or
+                                       @monitoring='true' or
                                        @hidden='true' or
                                        @mandatory='true']">
           <import>org.opends.server.admin.PropertyOption</import>
@@ -1589,6 +1611,34 @@
           </import>
         </xsl:if>
         <xsl:if
+          test="$this-local-properties/adm:default-behavior/adm:inherited/adm:absolute">
+          <import>
+            org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider
+          </import>
+          <import>org.opends.server.admin.ManagedObjectPath</import>
+        </xsl:if>
+        <xsl:if
+          test="$this-local-properties/adm:default-behavior/adm:inherited/adm:relative">
+          <import>
+            org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider
+          </import>
+          <xsl:for-each
+            select="$this-local-properties/adm:default-behavior/adm:inherited/adm:relative">
+            <xsl:if test="@managed-object-package != $this-package">
+              <xsl:variable name="java-class-name">
+                <xsl:call-template name="name-to-java">
+                  <xsl:with-param name="value"
+                    select="@managed-object-name" />
+                </xsl:call-template>
+              </xsl:variable>
+              <xsl:element name="import">
+                <xsl:value-of
+                  select="concat(@managed-object-package, '.meta.', $java-class-name, 'CfgDefn')" />
+              </xsl:element>
+            </xsl:if>
+          </xsl:for-each>
+        </xsl:if>
+        <xsl:if
           test="$this-local-properties/adm:default-behavior/adm:defined">
           <import>
             org.opends.server.admin.DefinedDefaultBehaviorProvider
@@ -1655,6 +1705,12 @@
             </import>
             <import>org.opends.server.admin.PropertyProvider</import>
             <import>
+              org.opends.server.admin.client.MissingMandatoryPropertiesException
+            </import>
+            <import>
+              org.opends.server.admin.ManagedObjectAlreadyExistsException
+            </import>
+            <import>
               org.opends.server.admin.client.AuthorizationException
             </import>
             <import>
@@ -1692,8 +1748,9 @@
               </import>
             </xsl:if>
             <xsl:if test="$this-all-relations/adm:one-to-many">
+              <import>java.util.Collection</import>
               <import>
-                org.opends.server.admin.ManagedObjectAlreadyExistsException
+                org.opends.server.admin.DefaultBehaviorException
               </import>
               <import>
                 org.opends.server.admin.server.ConfigurationAddListener
@@ -1704,8 +1761,9 @@
               <import>org.opends.server.config.ConfigException</import>
             </xsl:if>
             <xsl:if test="$this-all-relations/adm:one-to-zero-or-one">
+              <import>java.util.Collection</import>
               <import>
-                org.opends.server.admin.ManagedObjectAlreadyExistsException
+                org.opends.server.admin.DefaultBehaviorException
               </import>
               <import>
                 org.opends.server.admin.server.ConfigurationAddListener
@@ -1722,6 +1780,9 @@
               <import>java.util.SortedSet</import>
               <import>java.util.Collection</import>
             </xsl:if>
+            <xsl:if test="$this-all-properties[@read-only='true']">
+              <import>org.opends.server.admin.PropertyIsReadOnlyException</import>
+            </xsl:if>
           </xsl:otherwise>
         </xsl:choose>
         <xsl:if test="$this/@extends">
diff --git a/opendj-sdk/opends/resource/admin/preprocessor.xsl b/opendj-sdk/opends/resource/admin/preprocessor.xsl
index 56a18f7..246a4e2 100644
--- a/opendj-sdk/opends/resource/admin/preprocessor.xsl
+++ b/opendj-sdk/opends/resource/admin/preprocessor.xsl
@@ -696,6 +696,36 @@
     </xsl:copy>
   </xsl:template>
   <!--
+    Process a relative inherited default behavior
+  -->
+  <xsl:template match="adm:relative" mode="pre-process">
+    <xsl:param name="mopackage" select="/.." />
+    <xsl:param name="moname" select="/.." />
+    <xsl:param name="hierarchy" select="/.." />
+    <xsl:copy>
+      <!--
+        Shallow copy.
+      -->
+      <xsl:copy-of select="@*" />
+      <!--
+        Add missing attribute managed-object-package if it is not provided.
+      -->
+      <xsl:if test="not(@managed-object-package)">
+        <xsl:attribute name="managed-object-package">
+          <xsl:value-of select="$mopackage" />
+        </xsl:attribute>
+      </xsl:if>
+      <!--
+        Apply templates to subordinate elements.
+      -->
+      <xsl:apply-templates mode="pre-process">
+        <xsl:with-param name="mopackage" select="$mopackage" />
+        <xsl:with-param name="moname" select="$moname" />
+        <xsl:with-param name="hierarchy" select="$hierarchy" />
+      </xsl:apply-templates>
+    </xsl:copy>
+  </xsl:template>
+  <!--
     Process a user-friendly-name element.
   -->
   <xsl:template match="adm:user-friendly-name"
diff --git a/opendj-sdk/opends/resource/admin/property-types.xsl b/opendj-sdk/opends/resource/admin/property-types.xsl
index 9dc2aac..69f94d0 100644
--- a/opendj-sdk/opends/resource/admin/property-types.xsl
+++ b/opendj-sdk/opends/resource/admin/property-types.xsl
@@ -270,7 +270,7 @@
     Generate the property setter declarations.
   -->
   <xsl:template name="generate-property-setter-declaration">
-    <xsl:if test="string(@read-only) != 'true'">
+    <xsl:if test="not(@monitoring='true')">
       <xsl:variable name="name" select="@name" />
       <xsl:variable name="java-property-name">
         <xsl:call-template name="name-to-java">
@@ -294,14 +294,28 @@
           <xsl:with-param name="content" select="adm:description" />
         </xsl:call-template>
       </xsl:if>
+      <xsl:if test="@read-only='true'">
+        <xsl:value-of select="'   * &lt;p&gt;&#xa;'" />
+        <xsl:value-of
+          select="concat(
+                     '   * This property is read-only and can only be modified during&#xa;',
+                     '   * creation of a ', $this-ufn, '.&#xa;')" />
+      </xsl:if>
       <xsl:choose>
-        <xsl:when test="string(@multi-valued) != 'true'">
+        <xsl:when test="not(@multi-valued='true')">
           <xsl:value-of
             select="concat('   *&#xa;',
                      '   * @param value The value of the &quot;', $name, '&quot; property.&#xa;',
                      '   * @throws IllegalPropertyValueException&#xa;',
-                     '   *           If the new value is invalid.&#xa;',
-                     '   *&#xa;',
+                     '   *           If the new value is invalid.&#xa;')" />
+          <xsl:if test="@read-only='true'">
+            <xsl:value-of
+              select="concat(
+                     '   * @throws PropertyIsReadOnlyException&#xa;',
+                     '   *           If this ', $this-ufn, ' is not being initialized.&#xa;')" />
+          </xsl:if>
+          <xsl:value-of
+            select="concat(
                      '   */&#xa;',
                      '  void set', $java-property-name, '(')" />
           <xsl:choose>
@@ -313,23 +327,33 @@
               <xsl:call-template name="get-property-java-type" />
             </xsl:otherwise>
           </xsl:choose>
-          <xsl:value-of
-            select="' value) throws IllegalPropertyValueException;&#xa;'" />
+          <xsl:value-of select="' value'" />
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of
             select="concat('   *&#xa;',
                      '   * @param values The values of the &quot;', $name, '&quot; property.&#xa;',
                      '   * @throws IllegalPropertyValueException&#xa;',
-                     '   *           If one or more of the new values are invalid.&#xa;',
-                     '   *&#xa;',
+                     '   *           If one or more of the new values are invalid.&#xa;')" />
+          <xsl:if test="@read-only='true'">
+            <xsl:value-of
+              select="concat(
+                     '   * @throws PropertyIsReadOnlyException&#xa;',
+                     '   *           If this ', $this-ufn, ' is not being initialized.&#xa;')" />
+          </xsl:if>
+          <xsl:value-of
+            select="concat(
                      '   */&#xa;',
                      '  void set', $java-property-name, '(Collection&lt;')" />
           <xsl:call-template name="get-property-java-type" />
-          <xsl:value-of
-            select="'&gt; values) throws IllegalPropertyValueException;&#xa;'" />
+          <xsl:value-of select="'&gt; values'" />
         </xsl:otherwise>
       </xsl:choose>
+      <xsl:value-of select="') throws IllegalPropertyValueException'" />
+      <xsl:if test="@read-only='true'">
+        <xsl:value-of select="', PropertyIsReadOnlyException'" />
+      </xsl:if>
+      <xsl:value-of select="';&#xa;'" />
     </xsl:if>
   </xsl:template>
 </xsl:stylesheet>
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
index a925d19..2fce4d3 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
@@ -32,7 +32,6 @@
 
 import javax.naming.ldap.InitialLdapContext;
 
-import org.opends.server.admin.client.InitialManagedObject;
 import org.opends.server.admin.client.ManagementContext;
 import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
 import org.opends.server.admin.client.ldap.LDAPManagementContext;
@@ -121,9 +120,7 @@
       if (backend == null)
       {
         BackendCfgDefn provider = BackendCfgDefn.getInstance();
-        backend = root.createBackend(provider, backendName,
-            new InitialManagedObject<BackendCfgClient>(
-                BackendCfgDefn.getInstance()));
+        backend = root.createBackend(provider, backendName, null);
       }
       SortedSet<DN> suffixes = backend.getBackendBaseDN();
       if (suffixes == null)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
index d6b82c5..c1671af 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
@@ -29,9 +29,10 @@
 
 
 /**
- * A default behavior provider which retrieves default values from a managed
- * object in an abolute location. It should be used by properties which inherit
- * their default value(s) from properties held in an other managed object.
+ * A default behavior provider which retrieves default values from a
+ * managed object in an abolute location. It should be used by
+ * properties which inherit their default value(s) from properties
+ * held in an other managed object.
  *
  * @param <T>
  *          The type of values represented by this provider.
@@ -48,16 +49,26 @@
 
 
   /**
-   * Create an absolute inherited default behavior provider associated with the
-   * managed object at the specified absolute location.
+   * Create an absolute inherited default behavior provider associated
+   * with the managed object at the specified absolute location.
    *
    * @param path
    *          The absolute location of the managed object.
    * @param propertyName
-   *          The name of the property containing the inherited default values.
+   *          The name of the property containing the inherited
+   *          default values.
+   * @throws IllegalArgumentException
+   *           If the named property is associated with the managed
+   *           object definition identified by the path.
+   * @throws ClassCastException
+   *           If the named property does not have the same type of
+   *           property values as this default behavior provider.
    */
+  @SuppressWarnings("unchecked")
   public AbsoluteInheritedDefaultBehaviorProvider(ManagedObjectPath path,
-      String propertyName) {
+      String propertyName) throws IllegalArgumentException, ClassCastException {
+    // We do not decode the property name now because the property
+    // might not have been constructed at this point.
     this.path = path;
     this.propertyName = propertyName;
   }
@@ -74,11 +85,24 @@
 
 
   /**
-   * Get the absolute path of the managed object containing the property which
-   * has the default values.
+   * Get the definition of the parent managed object containing the
+   * inherited default values.
    *
-   * @return Returns the absolute path of the managed object containing the
-   *         property which has the default values.
+   * @return Returns the definition of the parent managed object
+   *         containing the inherited default values.
+   */
+  public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() {
+    return path.getManagedObjectDefinition();
+  }
+
+
+
+  /**
+   * Get the absolute path of the managed object containing the
+   * property which has the default values.
+   *
+   * @return Returns the absolute path of the managed object
+   *         containing the property which has the default values.
    */
   public ManagedObjectPath getManagedObjectPath() {
     return path;
@@ -87,10 +111,11 @@
 
 
   /**
-   * Get the name of the property containing the inherited default values.
+   * Get the name of the property containing the inherited default
+   * values.
    *
-   * @return Returns the name of the property containing the inherited default
-   *         values.
+   * @return Returns the name of the property containing the inherited
+   *         default values.
    */
   public String getPropertyName() {
     return propertyName;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java b/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
index b5e5ba5..d5a1341 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
@@ -27,9 +27,12 @@
 
 package org.opends.server.admin;
 
+
+
 import org.opends.server.admin.client.AuthorizationException;
 import org.opends.server.admin.client.CommunicationException;
 import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
 import org.opends.server.admin.client.OperationRejectedException;
 
 
@@ -62,22 +65,35 @@
 
 
   /**
-   * Commit any changes made to this configuration client.
+   * If this is a new configuration this method will attempt to add it
+   * to the server, otherwise it will commit any changes made to this
+   * configuration.
    *
+   * @throws ManagedObjectAlreadyExistsException
+   *           If this is a new configuration but it could not be
+   *           added to the server because it already exists.
+   * @throws MissingMandatoryPropertiesException
+   *           If this configuration contains some mandatory
+   *           properties which have been left undefined.
    * @throws ConcurrentModificationException
-   *           If this configuration has been removed from the server
-   *           by another client.
+   *           If this is a new configuration which is being added to
+   *           the server but its parent has been removed by another
+   *           client, or if this configuration is being modified but
+   *           it has been removed from the server by another client.
    * @throws OperationRejectedException
-   *           If the server refuses to apply the changes due to some
-   *           server-side constraint which cannot be satisfied.
+   *           If the server refuses to add or modify this
+   *           configuration due to some server-side constraint which
+   *           cannot be satisfied.
    * @throws AuthorizationException
-   *           If the server refuses to apply the changes because the
-   *           client does not have the correct privileges.
+   *           If the server refuses to add or modify this
+   *           configuration because the client does not have the
+   *           correct privileges.
    * @throws CommunicationException
    *           If the client cannot contact the server due to an
    *           underlying communication problem.
    */
-  void commit() throws ConcurrentModificationException,
+  void commit() throws ManagedObjectAlreadyExistsException,
+      MissingMandatoryPropertiesException, ConcurrentModificationException,
       OperationRejectedException, AuthorizationException,
       CommunicationException;
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java
new file mode 100644
index 0000000..1ecc04a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java
@@ -0,0 +1,90 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+
+
+/**
+ * This exception is thrown when a property's default values cannot be
+ * determined. This can occur in the following situations:
+ * <ul>
+ * <li>the property has a well-defined set of default values but they
+ * are invalid according to the property's syntax
+ * <li>the property inherits its default values from another managed
+ * object but they could not be retrieved, perhaps because of a
+ * communication problem.
+ * </ul>
+ */
+public class DefaultBehaviorException extends PropertyException {
+
+  /**
+   * Serialization ID.
+   */
+  private static final long serialVersionUID = -2542117466747573053L;
+
+  // The cause of this exception.
+  private final Throwable cause;
+
+
+
+  /**
+   * Create a new default behavior exception with a cause.
+   *
+   * @param pd
+   *          The property definition whose default values could not
+   *          be determined.
+   * @param cause
+   *          The exception that prevented the default values from
+   *          being determined.
+   */
+  public DefaultBehaviorException(PropertyDefinition pd, Throwable cause) {
+    super(pd);
+    this.cause = cause;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Throwable getCause() {
+    return cause;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getMessage() {
+    return "The default values could not be determined "
+        + "for the property \"" + getPropertyDefinition().getName() + "\"";
+  }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java
deleted file mode 100644
index c06c24e..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.admin;
-
-
-
-/**
- * Thrown to indicate that a property's default values were invalid.
- */
-public class DefaultBehaviorPropertyValueException extends PropertyException {
-
-  /**
-   * Serialization ID.
-   */
-  private static final long serialVersionUID = 8653244240567431537L;
-
-  // The underlying property exception that caused this exception
-  private final PropertyException cause;
-
-
-
-  /**
-   * Create a new default behavior property value exception.
-   *
-   * @param d
-   *          The property definition.
-   * @param cause
-   *          The property exception that caused this exception.
-   */
-  public DefaultBehaviorPropertyValueException(PropertyDefinition d,
-      PropertyException cause) {
-    super(d);
-    this.cause = cause;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Throwable getCause() {
-    return cause;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String getMessage() {
-    return "The default values could not be determined "
-        + "for the property \"" + getPropertyDefinition().getName() + "\"";
-  }
-
-
-
-  /**
-   * Get the property exception that caused this exception.
-   *
-   * @return Returns the property exception that caused this exception.
-   */
-  public final PropertyException getPropertyException() {
-    return cause;
-  }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java
deleted file mode 100644
index 1793271..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.admin;
-
-
-
-/**
- * Thrown to indicate that a property's inherited default values could not be
- * determined due to some underlying operations exception which occurred when
- * attempting to retrieve them.
- */
-public class InheritedDefaultValueException extends PropertyException {
-
-  /**
-   * Serialization ID.
-   */
-  private static final long serialVersionUID = 7228186032995472371L;
-
-  // The operations exception that caused default value look up to fail.
-  private final OperationsException cause;
-
-
-
-  /**
-   * Create a new inherited default value exception.
-   *
-   * @param d
-   *          The property definition.
-   * @param cause
-   *          The operations exception that caused default value look up to
-   *          fail.
-   */
-  public InheritedDefaultValueException(PropertyDefinition d,
-      OperationsException cause) {
-    super(d);
-    this.cause = cause;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public Throwable getCause() {
-    return cause;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String getMessage() {
-    return "The inherited default values could not be determined "
-        + "for the property \"" + getPropertyDefinition().getName() + "\"";
-  }
-
-
-
-  /**
-   * Get the operations exception that caused default value look up to fail.
-   *
-   * @return Returns the operations exception that caused default value look up
-   *         to fail.
-   */
-  public final OperationsException getOperationsException() {
-    return cause;
-  }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java
deleted file mode 100644
index 75e5a25..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.admin;
-
-
-
-import java.util.Collection;
-
-
-
-/**
- * An interface for retrieving inherited default property values.
- */
-public interface InheritedDefaultValueProvider {
-
-  /**
-   * Get the path of the managed object which should be used as the base for
-   * determining parent managed objects.
-   *
-   * @return Returns the path of the managed object which should be used as the
-   *         base for determining parent managed objects.
-   */
-  ManagedObjectPath getManagedObjectPath();
-
-
-
-  /**
-   * Retrieves the values of a property from a managed object at the specified
-   * location.
-   *
-   * @param path
-   *          The location of the managed object containing the property.
-   * @param propertyName
-   *          The name of the property containing the default values.
-   * @return Returns the values of a property from a managed object at the
-   *         specified location.
-   * @throws OperationsException
-   *           If the managed object could not be read due to some underlying
-   *           communication problem.
-   * @throws PropertyNotFoundException
-   *           If the property name was not recognized.
-   */
-  Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
-      String propertyName) throws OperationsException,
-      PropertyNotFoundException;
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java b/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
index 1571cbb..ced9e0e8 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
@@ -44,6 +44,64 @@
 /**
  * A path which can be used to determine the location of a managed
  * object instance.
+ * <p>
+ * A path is made up of zero or more elements each of which represents
+ * a managed object. Managed objects are arranged hierarchically with
+ * the root configuration being the top-most managed object. Elements
+ * are ordered such that the root configuration managed object is the
+ * first element and subsequent elements representing managed objects
+ * further down the hierarchy.
+ * <p>
+ * A path can be encoded into a string representation using the
+ * {@link #toString()} and {@link #toString(StringBuilder)} methods.
+ * Conversely, this string representation can be parsed using the
+ * {@link #valueOf(String)} method.
+ * <p>
+ * The string representation of a managed object path is similar in
+ * principle to a UNIX file-system path and is defined as follows:
+ * <ul>
+ * <li>the root element is represented by the string <code>/</code>
+ * <li>subordinate elements are arranged in big-endian order
+ * separated by a forward slash <code>/</code> character
+ * <li>an element representing a managed object associated with a
+ * one-to-one (singleton) or one-to-zero-or-one (optional) relation
+ * has the form <code>relation=</code><i>relation</i>
+ * <code>[+type=</code><i>definition</i><code>]</code>, where
+ * <i>relation</i> is the name of the relation and <i>definition</i>
+ * is the name of the referenced managed object's definition if
+ * required (usually this is implied by the relation itself)
+ * <li>an element representing a managed object associated with a
+ * one-to-many (instantiable) relation has the form
+ * <code>relation=</code><i>relation</i><code>[+type=</code>
+ * <i>definition</i><code>]</code><code>+name=</code><i>name</i>,
+ * where <i>relation</i> is the name of the relation and
+ * <i>definition</i> is the name of the referenced managed object's
+ * definition if required (usually this is implied by the relation
+ * itself), and <i>name</i> is the name of the managed object
+ * instance.
+ * </ul>
+ * The following path string representation identifies a connection
+ * handler instance (note that the <code>type</code> is not
+ * specified indicating that the path identifies a connection handler
+ * called <i>my handler</i> which can be any type of connection
+ * handler):
+ *
+ * <pre>
+ *  /relation=connection-handler+name=my handler
+ * </pre>
+ *
+ * If the identified connection handler must be an LDAP connection
+ * handler then the above path should include the <code>type</code>:
+ *
+ * <pre>
+ *  /relation=connection-handler+type=ldap-connection-handler+name=my handler
+ * </pre>
+ *
+ * The final example identifies the global configuration:
+ *
+ * <pre>
+ *  /relation=global-configuration
+ * </pre>
  *
  * @param <C>
  *          The type of client managed object configuration that this
@@ -52,14 +110,14 @@
  *          The type of server managed object configuration that this
  *          path references.
  */
-public final class ManagedObjectPath
-    <C extends ConfigurationClient, S extends Configuration> {
+public final class ManagedObjectPath<C extends ConfigurationClient,
+    S extends Configuration> {
 
   /**
    * Abstract path element.
    */
-  private static abstract class Element
-      <C extends ConfigurationClient, S extends Configuration> {
+  private static abstract class Element<C extends ConfigurationClient,
+      S extends Configuration> {
 
     // The type of managed object referenced by this element.
     private final AbstractManagedObjectDefinition<C, S> definition;
@@ -92,6 +150,17 @@
 
 
     /**
+     * Get the relation definition associated with this element.
+     *
+     * @return Returns the relation definition associated with this
+     *         element.
+     */
+    public abstract RelationDefinition<? super C, ? super S>
+        getRelationDefinition();
+
+
+
+    /**
      * Serialize this path element using the provided serialization
      * strategy.
      *
@@ -111,8 +180,8 @@
       extends Element<C, S> {
 
     // Factory method.
-    private static final
-        <C extends ConfigurationClient, S extends Configuration>
+    private static final <C extends ConfigurationClient,
+        S extends Configuration>
         InstantiableElement<C, S> create(
         InstantiableRelationDefinition<? super C, ? super S> r,
         AbstractManagedObjectDefinition<C, S> d, String name) {
@@ -142,6 +211,17 @@
      * {@inheritDoc}
      */
     @Override
+    public InstantiableRelationDefinition<? super C, ? super S>
+        getRelationDefinition() {
+      return r;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void serialize(ManagedObjectPathSerializer serializer) {
       serializer.appendManagedObjectPathElement(r,
           getManagedObjectDefinition(), name);
@@ -158,9 +238,8 @@
       extends Element<C, S> {
 
     // Factory method.
-    private static final
-        <C extends ConfigurationClient, S extends Configuration>
-        OptionalElement<C, S> create(
+    private static final <C extends ConfigurationClient,
+        S extends Configuration> OptionalElement<C, S> create(
         OptionalRelationDefinition<? super C, ? super S> r,
         AbstractManagedObjectDefinition<C, S> d) {
       return new OptionalElement<C, S>(r, d);
@@ -184,6 +263,17 @@
      * {@inheritDoc}
      */
     @Override
+    public OptionalRelationDefinition<? super C, ? super S>
+        getRelationDefinition() {
+      return r;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void serialize(ManagedObjectPathSerializer serializer) {
       serializer
           .appendManagedObjectPathElement(r, getManagedObjectDefinition());
@@ -200,9 +290,8 @@
       extends Element<C, S> {
 
     // Factory method.
-    private static final
-        <C extends ConfigurationClient, S extends Configuration>
-        SingletonElement<C, S> create(
+    private static final <C extends ConfigurationClient,
+        S extends Configuration> SingletonElement<C, S> create(
         SingletonRelationDefinition<? super C, ? super S> r,
         AbstractManagedObjectDefinition<C, S> d) {
       return new SingletonElement<C, S>(r, d);
@@ -227,6 +316,17 @@
      * {@inheritDoc}
      */
     @Override
+    public SingletonRelationDefinition<? super C, ? super S>
+        getRelationDefinition() {
+      return r;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void serialize(ManagedObjectPathSerializer serializer) {
       serializer
           .appendManagedObjectPathElement(r, getManagedObjectDefinition());
@@ -312,8 +412,8 @@
 
   // Single instance of a root path.
   private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH =
-    new ManagedObjectPath<RootCfgClient, RootCfg>(
-      new LinkedList<Element<?, ?>>(), RootCfgDefn.getInstance());
+      new ManagedObjectPath<RootCfgClient, RootCfg>(
+      new LinkedList<Element<?, ?>>(), null, RootCfgDefn.getInstance());
 
   // A regular expression used to parse path elements.
   private static final Pattern PE_REGEXP = Pattern
@@ -358,6 +458,7 @@
 
     // Parse the elements.
     LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
+    Element<?, ?> lastElement = null;
     AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn
         .getInstance();
 
@@ -397,10 +498,14 @@
             + "\" in path \"" + ns + "\"");
       }
 
-      String relation = m.group(1); // Mandatory.
-      String type = m.group(3); // Optional.
-      String name = m.group(5); // Mandatory if relation is
-      // instantiable.
+      // Mandatory.
+      String relation = m.group(1);
+
+      // Optional.
+      String type = m.group(3);
+
+      // Mandatory if relation is instantiable.
+      String name = m.group(5);
 
       // Get the relation definition.
       RelationDefinition<?, ?> r;
@@ -413,9 +518,9 @@
       }
 
       // Append the next element.
-      Element<?, ?> e = createElement(r, ns, es, type, name);
-      elements.add(e);
-      definition = e.getManagedObjectDefinition();
+      lastElement = createElement(r, ns, es, type, name);
+      elements.add(lastElement);
+      definition = lastElement.getManagedObjectDefinition();
 
       // Update start to point to the beginning of the next element.
       if (end < ns.length()) {
@@ -428,7 +533,7 @@
     }
 
     // Construct the new path.
-    return create(elements, definition);
+    return create(elements, lastElement);
   }
 
 
@@ -437,9 +542,9 @@
   // construction of new paths.
   private static <C extends ConfigurationClient, S extends Configuration>
       ManagedObjectPath<C, S> create(
-      LinkedList<Element<?, ?>> elements,
-      AbstractManagedObjectDefinition<C, S> definition) {
-    return new ManagedObjectPath<C, S>(elements, definition);
+      LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
+    return new ManagedObjectPath<C, S>(elements, lastElement
+        .getRelationDefinition(), lastElement.getManagedObjectDefinition());
   }
 
 
@@ -508,19 +613,24 @@
     }
   }
 
-  // The last element in this path.
-  private final AbstractManagedObjectDefinition<C, S> definition;
+  // The managed object definition in this path.
+  private final AbstractManagedObjectDefinition<C, S> d;
 
   // The list of path elements in this path.
   private final List<Element<?, ?>> elements;
 
+  // The last relation definition in this path.
+  private final RelationDefinition<? super C, ? super S> r;
+
 
 
   // Private constructor.
   private ManagedObjectPath(LinkedList<Element<?, ?>> elements,
-      AbstractManagedObjectDefinition<C, S> definition) {
+      RelationDefinition<? super C, ? super S> r,
+      AbstractManagedObjectDefinition<C, S> d) {
     this.elements = Collections.unmodifiableList(elements);
-    this.definition = definition;
+    this.r = r;
+    this.d = d;
   }
 
 
@@ -552,7 +662,7 @@
     LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
         elements);
     celements.add(new InstantiableElement<M, N>(r, d, name));
-    return new ManagedObjectPath<M, N>(celements, d);
+    return new ManagedObjectPath<M, N>(celements, r, d);
   }
 
 
@@ -607,7 +717,7 @@
     LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
         elements);
     celements.add(new OptionalElement<M, N>(r, d));
-    return new ManagedObjectPath<M, N>(celements, d);
+    return new ManagedObjectPath<M, N>(celements, r, d);
   }
 
 
@@ -628,8 +738,7 @@
    *         provided parent path.
    */
   public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      OptionalRelationDefinition<M, N> r) {
+      ManagedObjectPath<M, N> child(OptionalRelationDefinition<M, N> r) {
     return child(r, r.getChildDefinition());
   }
 
@@ -660,7 +769,7 @@
     LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
         elements);
     celements.add(new SingletonElement<M, N>(r, d));
-    return new ManagedObjectPath<M, N>(celements, d);
+    return new ManagedObjectPath<M, N>(celements, r, d);
   }
 
 
@@ -681,8 +790,7 @@
    *         provided parent path.
    */
   public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      SingletonRelationDefinition<M, N> r) {
+      ManagedObjectPath<M, N> child(SingletonRelationDefinition<M, N> r) {
     return child(r, r.getChildDefinition());
   }
 
@@ -716,7 +824,23 @@
    *         empty.
    */
   public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
-    return definition;
+    return d;
+  }
+
+
+
+  /**
+   * Get the relation definition of the managed object referred to by
+   * this path.
+   * <p>
+   * When the path is empty, the <code>null</code> is returned.
+   *
+   * @return Returns the relation definition of the managed object
+   *         referred to by this path, or the <code>null</code> if
+   *         the path is empty.
+   */
+  public RelationDefinition<? super C, ? super S> getRelationDefinition() {
+    return r;
   }
 
 
@@ -745,8 +869,8 @@
 
   /**
    * Creates a new parent managed object path representing the
-   * immediate parent of this path. This method is a short-hand
-   * for <code>parent(1)</code>.
+   * immediate parent of this path. This method is a short-hand for
+   * <code>parent(1)</code>.
    *
    * @return Returns a new parent managed object path representing the
    *         immediate parent of this path.
@@ -796,9 +920,7 @@
 
     LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
         elements.subList(0, elements.size() - offset));
-    AbstractManagedObjectDefinition<?, ?> definition = celements.getLast()
-        .getManagedObjectDefinition();
-    return create(celements, definition);
+    return create(celements, celements.getLast());
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
index 2d4341e..9f97611 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
@@ -30,13 +30,13 @@
 
 
 /**
- * This enumeration contains various options that can be associated with
- * property definitions.
+ * This enumeration contains various options that can be associated
+ * with property definitions.
  */
 public enum PropertyOption {
   /**
-   * Use this option to identify properties which must not be directly exposed
-   * in client applications.
+   * Use this option to identify properties which must not be directly
+   * exposed in client applications.
    */
   HIDDEN,
 
@@ -51,14 +51,21 @@
   MULTI_VALUED,
 
   /**
-   * Use this option to identify properties which cannot be modified.
+   * Use this option to identify properties which can be initialized
+   * once only and are read-only thereafter.
    */
   READ_ONLY,
 
   /**
-   * Use this option to identify properties which, when modified, will require
-   * some additiona administrator action in order for the changes to take
-   * effect.
+   * Use this option to identify properties which are for monitoring
+   * purposes only and are generated automatically by the server..
+   */
+  MONITORING,
+
+  /**
+   * Use this option to identify properties which, when modified, will
+   * require some additiona administrator action in order for the
+   * changes to take effect.
    */
   REQUIRES_ADMIN_ACTION
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
index 49c52e9..ee9468a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
@@ -29,9 +29,10 @@
 
 
 /**
- * A default behavior provider which retrieves default values from a parent
- * managed object. It should be used by properties which inherit their default
- * value(s) from properties held in an other managed object.
+ * A default behavior provider which retrieves default values from a
+ * parent managed object. It should be used by properties which
+ * inherit their default value(s) from properties held in an other
+ * managed object.
  *
  * @param <T>
  *          The type of values represented by this provider.
@@ -39,8 +40,11 @@
 public final class RelativeInheritedDefaultBehaviorProvider<T> implements
     DefaultBehaviorProvider<T> {
 
-  // The relative offset (where 1 = parent, 2 = grandparent) of the managed
-  // object containing the property.
+  // The type of managed object expected at the relative offset.
+  private final AbstractManagedObjectDefinition<?, ?> d;
+
+  // The relative offset (where 1 = parent, 2 = grandparent) of the
+  // managed object containing the property.
   private final int offset;
 
   // The name of the property containing the inherited default values.
@@ -49,23 +53,33 @@
 
 
   /**
-   * Create a relative inherited default behavior provider associated with a
-   * parent managed object.
+   * Create a relative inherited default behavior provider associated
+   * with a parent managed object.
    *
-   * @param offset
-   *          The relative location of the parent managed object (where 0 is the
-   *          managed object itself, 1 is the parent, and 2 is the
-   *          grand-parent).
+   * @param d
+   *          The type of parent managed object expected at the
+   *          relative location.
    * @param propertyName
-   *          The name of the property containing the inherited default values.
+   *          The name of the property containing the inherited
+   *          default values.
+   * @param offset
+   *          The relative location of the parent managed object
+   *          (where 0 is the managed object itself, 1 is the parent,
+   *          and 2 is the grand-parent).
    * @throws IllegalArgumentException
    *           If the offset is less than 0.
    */
-  public RelativeInheritedDefaultBehaviorProvider(int offset,
-      String propertyName) throws IllegalArgumentException {
+  @SuppressWarnings("unchecked")
+  public RelativeInheritedDefaultBehaviorProvider(
+      AbstractManagedObjectDefinition<?, ?> d, String propertyName, int offset)
+      throws IllegalArgumentException {
+    // We do not decode the property name now because the property
+    // might not have been constructed at this point (e.g. when the
+    // offset is 0).
     if (offset < 0) {
       throw new IllegalArgumentException("Negative offset");
     }
+    this.d = d;
     this.propertyName = propertyName;
     this.offset = offset;
   }
@@ -82,14 +96,27 @@
 
 
   /**
-   * Get the absolute path of the managed object containing the property which
-   * has the default values.
+   * Get the definition of the parent managed object containing the
+   * inherited default values.
+   *
+   * @return Returns the definition of the parent managed object
+   *         containing the inherited default values.
+   */
+  public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() {
+    return d;
+  }
+
+
+
+  /**
+   * Get the absolute path of the managed object containing the
+   * property which has the default values.
    *
    * @param path
-   *          The path of the current managed object from which the relative
-   *          path should be determined.
-   * @return Returns the absolute path of the managed object containing the
-   *         property which has the default values.
+   *          The path of the current managed object from which the
+   *          relative path should be determined.
+   * @return Returns the absolute path of the managed object
+   *         containing the property which has the default values.
    */
   public ManagedObjectPath getManagedObjectPath(ManagedObjectPath path) {
     return path.parent(offset);
@@ -98,10 +125,11 @@
 
 
   /**
-   * Get the name of the property containing the inherited default values.
+   * Get the name of the property containing the inherited default
+   * values.
    *
-   * @return Returns the name of the property containing the inherited default
-   *         values.
+   * @return Returns the name of the property containing the inherited
+   *         default values.
    */
   public String getPropertyName() {
     return propertyName;
@@ -112,9 +140,9 @@
   /**
    * Get the relative location of the parent managed object.
    *
-   * @return Returns the relative location of the parent managed object (where 0
-   *         is the managed object itself, 1 is the parent, and 2 is the
-   *         grand-parent).
+   * @return Returns the relative location of the parent managed
+   *         object (where 0 is the managed object itself, 1 is the
+   *         parent, and 2 is the grand-parent).
    */
   public int getRelativeOffset() {
     return offset;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java
deleted file mode 100644
index 6597197..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.admin;
-
-
-
-import java.util.Collection;
-import java.util.Collections;
-
-
-
-/**
- * An interface which can be used to initialize the contents of a managed object
- * using the string representation of property values.
- */
-public interface StringPropertyProvider {
-
-  /**
-   * A property provider which always returns empty property values, indicating
-   * default behavior.
-   */
-  public static final StringPropertyProvider DEFAULT_PROVIDER =
-    new StringPropertyProvider() {
-
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<String> getPropertyValues(PropertyDefinition<?> d)
-        throws IllegalArgumentException {
-      return Collections.<String> emptySet();
-    }
-
-  };
-
-
-
-  /**
-   * Get the property string values associated with the specified property
-   * definition.
-   * <p>
-   * Implementations are not required to validate the values that they provide.
-   * Specifically:
-   * <ul>
-   * <li>they do not need to guarantee that the provided values are valid
-   * according to the property's syntax
-   * <li>they do not need to provide values for mandatory properties
-   * <li>they do not need to ensure that single-valued properties do contain at
-   * most one value.
-   * </ul>
-   * The returned set of values is allowed to contain duplicates.
-   *
-   * @param d
-   *          The Property definition.
-   * @return Returns a newly allocated set containing a copy of the property's
-   *         string values. An empty set indicates that the property has no
-   *         values defined and any default behavior is applicable.
-   * @throws IllegalArgumentException
-   *           If this property provider does not recognise the requested
-   *           property definition.
-   */
-  Collection<String> getPropertyValues(PropertyDefinition<?> d)
-      throws IllegalArgumentException;
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java
deleted file mode 100644
index b5a7c64..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-package org.opends.server.admin.client;
-
-
-
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.SortedSet;
-
-import org.opends.server.admin.ConfigurationClient;
-import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
-import org.opends.server.admin.InstantiableRelationDefinition;
-import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
-import org.opends.server.admin.OptionalRelationDefinition;
-import org.opends.server.admin.PropertyDefinition;
-import org.opends.server.admin.PropertyException;
-import org.opends.server.admin.PropertyIsMandatoryException;
-import org.opends.server.admin.PropertyIsReadOnlyException;
-import org.opends.server.admin.PropertyIsSingleValuedException;
-import org.opends.server.admin.PropertyNotFoundException;
-import org.opends.server.admin.PropertyProvider;
-import org.opends.server.admin.SingletonRelationDefinition;
-
-
-
-/**
- * A managed object which is not bound to any underlying management
- * context.
- * <p>
- * The purpose of this managed object implementation is to facilitate
- * the construction of new configuration objects. Once all appropriate
- * properties are set, the initial managed object can be used as a
- * property provider during an invocation of
- * <code>ManagedObject#createChild</code>.
- * <p>
- * Any attempt to commit, retrieve, list, remove, or add new child
- * managed objects will result in an
- * {@link UnsupportedOperationException}.
- *
- * @param <C>
- *          The type of client configuration represented by the client
- *          managed object.
- */
-public final class InitialManagedObject<C extends ConfigurationClient>
-    implements ManagedObject<C> {
-
-  /**
-   * Internal inherited default value provider implementation.
-   * <p>
-   * FIXME: very dumb implementation which always throws a
-   * PropertyNotFoundException.
-   */
-  private static class MyInheritedDefaultValueProvider implements
-      InheritedDefaultValueProvider {
-
-    // Private constructor.
-    private MyInheritedDefaultValueProvider() {
-      // No implementation required.
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
-        String propertyName) throws OperationsException,
-        PropertyNotFoundException {
-      throw new PropertyNotFoundException(propertyName);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ManagedObjectPath getManagedObjectPath() {
-      return ManagedObjectPath.emptyPath();
-    }
-  }
-
-  // The managed object definition associated with this managed
-  // object.
-  private final ManagedObjectDefinition<C, ?> definition;
-
-  // The managed object's properties.
-  private final PropertySet properties;
-
-
-
-  /**
-   * Creates a new initial managed object associated with the
-   * specified definition.
-   *
-   * @param definition
-   *          The managed object definition.
-   */
-  public InitialManagedObject(ManagedObjectDefinition<C, ?> definition) {
-    this.definition = definition;
-
-    // FIXME: how will we cope with inherited default values?
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    this.properties = PropertySet.create(definition,
-        PropertyProvider.DEFAULT_PROVIDER,
-        new MyInheritedDefaultValueProvider(), exceptions);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public void commit() throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient, N extends M>
-      ManagedObject<N> createChild(
-      InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      String name, PropertyProvider p) throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient, N extends M>
-      ManagedObject<N> createChild(
-      OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      PropertyProvider p) throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
-      InstantiableRelationDefinition<M, ?> d, String name)
-      throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
-      OptionalRelationDefinition<M, ?> d) throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
-      SingletonRelationDefinition<M, ?> d)
-      throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public C getConfiguration() {
-    return definition.createClientConfiguration(this);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public ManagedObjectDefinition<C, ?> getManagedObjectDefinition() {
-    return definition;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public ManagedObjectPath getManagedObjectPath() {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public <T> T getPropertyValue(PropertyDefinition<T> d)
-      throws IllegalArgumentException {
-    return properties.getPropertyValue(d);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
-      throws IllegalArgumentException {
-    return properties.getPropertyValues(d);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public boolean hasChild(OptionalRelationDefinition<?, ?> d)
-      throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public String[] listChildren(InstantiableRelationDefinition<?, ?> d)
-      throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient> void removeChild(
-      InstantiableRelationDefinition<M, ?> d, String name)
-      throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   * <p>
-   * This implementation throws an
-   * {@link UnsupportedOperationException}.
-   */
-  public <M extends ConfigurationClient> void removeChild(
-      OptionalRelationDefinition<M, ?> d) throws UnsupportedOperationException {
-    throw new UnsupportedOperationException();
-
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
-      throws IllegalPropertyValueException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
-    properties.setPropertyValue(d, value);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public <T> void setPropertyValues(PropertyDefinition<T> d,
-      Collection<T> values) throws IllegalPropertyValueException,
-      PropertyIsSingleValuedException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
-    properties.setPropertyValues(d, values);
-  }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
index 63694e0..857c634 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
@@ -32,6 +32,7 @@
 import java.util.Collection;
 import java.util.SortedSet;
 
+import org.opends.server.admin.DefaultBehaviorException;
 import org.opends.server.admin.DefinitionDecodingException;
 import org.opends.server.admin.IllegalPropertyValueException;
 import org.opends.server.admin.InstantiableRelationDefinition;
@@ -91,27 +92,40 @@
     PropertyProvider {
 
   /**
-   * Commit any changes made to this managed object. Pending property
-   * values will be committed to the managed object. If successful,
-   * the pending values will become active values.
+   * Adds this managed object to the server or commits any changes
+   * made to it depending on whether or not the managed object already
+   * exists on the server. Pending property values will be committed
+   * to the managed object. If successful, the pending values will
+   * become active values.
    * <p>
    * See the class description for more information regarding pending
    * and active values.
    *
+   * @throws ManagedObjectAlreadyExistsException
+   *           If the managed object cannot be added to the server
+   *           because it already exists.
+   * @throws MissingMandatoryPropertiesException
+   *           If the managed object contains some mandatory
+   *           properties which have been left undefined.
    * @throws ConcurrentModificationException
-   *           If this managed object has been removed from the server
-   *           by another client.
+   *           If the managed object is being added to the server but
+   *           its parent has been removed by another client, or if
+   *           this managed object is being modified but it has been
+   *           removed from the server by another client.
    * @throws OperationRejectedException
-   *           If the server refuses to apply the changes due to some
-   *           server-side constraint which cannot be satisfied.
+   *           If the server refuses to add or modify this managed
+   *           object due to some server-side constraint which cannot
+   *           be satisfied.
    * @throws AuthorizationException
-   *           If the server refuses to apply the changes because the
-   *           client does not have the correct privileges.
+   *           If the server refuses to add or modify this managed
+   *           object because the client does not have the correct
+   *           privileges.
    * @throws CommunicationException
    *           If the client cannot contact the server due to an
    *           underlying communication problem.
    */
-  void commit() throws ConcurrentModificationException,
+  void commit() throws ManagedObjectAlreadyExistsException,
+      MissingMandatoryPropertiesException, ConcurrentModificationException,
       OperationRejectedException, AuthorizationException,
       CommunicationException;
 
@@ -119,10 +133,10 @@
 
   /**
    * Creates a new child managed object bound to the specified
-   * instantiable relation. The new managed object instance will be
-   * created with values taken from a property provider. The caller
-   * must make sure that the property provider provides values for
-   * mandatory properties.
+   * instantiable relation. The new managed object will initially not
+   * contain any property values (including mandatory properties).
+   * Once the managed object has been configured it can be added to
+   * the server using the {@link #commit()} method.
    *
    * @param <M>
    *          The expected type of the child managed object
@@ -136,50 +150,30 @@
    *          The definition of the managed object to be created.
    * @param name
    *          The name of the child managed object.
-   * @param p
-   *          A property provider which should be used to initialize
-   *          property values of the new managed object.
+   * @param exceptions
+   *          A collection in which to place any
+   *          {@link DefaultBehaviorException}s that occurred whilst
+   *          attempting to determine the managed object's default
+   *          values.
    * @return Returns a new child managed object bound to the specified
    *         instantiable relation.
    * @throws IllegalArgumentException
    *           If the relation definition is not associated with this
    *           managed object's definition.
-   * @throws ManagedObjectDecodingException
-   *           If the managed object could not be create because one
-   *           or more of its properties are invalid.
-   * @throws ManagedObjectAlreadyExistsException
-   *           If the managed object cannot be created because it
-   *           already exists on the server.
-   * @throws ConcurrentModificationException
-   *           If this managed object has been removed from the server
-   *           by another client.
-   * @throws OperationRejectedException
-   *           If the server refuses to create the managed object due
-   *           to some server-side constraint which cannot be
-   *           satisfied.
-   * @throws AuthorizationException
-   *           If the server refuses to create the managed object
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
    */
   <M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
       InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      String name, PropertyProvider p) throws IllegalArgumentException,
-      ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
-      ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException;
+      String name, Collection<DefaultBehaviorException> exceptions)
+      throws IllegalArgumentException;
 
 
 
   /**
    * Creates a new child managed object bound to the specified
-   * optional relation. The new managed object instance will be
-   * created with values taken from a property provider. The caller
-   * must make sure that the property provider provides values for
-   * mandatory properties.
+   * optional relation. The new managed object will initially not
+   * contain any property values (including mandatory properties).
+   * Once the managed object has been configured it can be added to
+   * the server using the {@link #commit()} method.
    *
    * @param <M>
    *          The expected type of the child managed object
@@ -191,41 +185,21 @@
    *          The optional relation definition.
    * @param d
    *          The definition of the managed object to be created.
-   * @param p
-   *          A property provider which should be used to initialize
-   *          property values of the new managed object.
+   * @param exceptions
+   *          A collection in which to place any
+   *          {@link DefaultBehaviorException}s that occurred whilst
+   *          attempting to determine the managed object's default
+   *          values.
    * @return Returns a new child managed object bound to the specified
    *         optional relation.
    * @throws IllegalArgumentException
    *           If the relation definition is not associated with this
    *           managed object's definition.
-   * @throws ManagedObjectDecodingException
-   *           If the managed object could not be created because one
-   *           or more of its properties are invalid.
-   * @throws ManagedObjectAlreadyExistsException
-   *           If the managed object cannot be created because it
-   *           already exists on the server.
-   * @throws ConcurrentModificationException
-   *           If this managed object has been removed from the server
-   *           by another client.
-   * @throws OperationRejectedException
-   *           If the server refuses to create the managed object due
-   *           to some server-side constraint which cannot be
-   *           satisfied.
-   * @throws AuthorizationException
-   *           If the server refuses to create the managed object
-   *           because the client does not have the correct
-   *           privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
    */
   <M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
       OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      PropertyProvider p) throws IllegalArgumentException,
-      ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
-      ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException;
+      Collection<DefaultBehaviorException> exceptions)
+      throws IllegalArgumentException;
 
 
 
@@ -576,7 +550,8 @@
    *           If the new pending value is deemed to be invalid
    *           according to the property definition.
    * @throws PropertyIsReadOnlyException
-   *           If an attempt was made to modify a read-only property.
+   *           If this is not a new managed object and the property is
+   *           read-only or for monitoring purposes.
    * @throws PropertyIsMandatoryException
    *           If an attempt was made to remove a mandatory property.
    * @throws IllegalArgumentException
@@ -611,7 +586,8 @@
    *           If an attempt was made to add multiple pending values
    *           to a single-valued property.
    * @throws PropertyIsReadOnlyException
-   *           If an attempt was made to modify a read-only property.
+   *           If this is not a new managed object and the property is
+   *           read-only or for monitoring purposes.
    * @throws PropertyIsMandatoryException
    *           If an attempt was made to remove a mandatory property.
    * @throws IllegalArgumentException
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java
new file mode 100644
index 0000000..4b9f02a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java
@@ -0,0 +1,120 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin.client;
+
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opends.server.admin.OperationsException;
+import org.opends.server.admin.PropertyIsMandatoryException;
+import org.opends.server.util.Validator;
+
+
+
+/**
+ * This exception is thrown when an attempt is made to add or modify a
+ * managed object when one or more of its mandatory properties are
+ * undefined.
+ */
+public class MissingMandatoryPropertiesException extends OperationsException {
+
+  /**
+   * Serialization ID.
+   */
+  private static final long serialVersionUID = 6342522125252055588L;
+
+  // The causes of this exception.
+  private final Collection<PropertyIsMandatoryException> causes;
+
+
+
+  /**
+   * Creates a new missing mandatory properties exception with the
+   * provided causes.
+   *
+   * @param causes
+   *          The causes of this exception (must be non-<code>null</code>
+   *          and non-empty).
+   */
+  public MissingMandatoryPropertiesException(
+      Collection<PropertyIsMandatoryException> causes) {
+    Validator.ensureNotNull(causes);
+    Validator.ensureTrue(!causes.isEmpty());
+
+    this.causes = new ArrayList<PropertyIsMandatoryException>(causes);
+  }
+
+
+
+  /**
+   * Gets the first exception that caused this exception.
+   *
+   * @return Returns the first exception that caused this exception.
+   */
+  @Override
+  public PropertyIsMandatoryException getCause() {
+    return causes.iterator().next();
+  }
+
+
+
+  /**
+   * Gets an unmodifiable collection view of the causes of this
+   * exception.
+   *
+   * @return Returns an unmodifiable collection view of the causes of
+   *         this exception.
+   */
+  public Collection<PropertyIsMandatoryException> getCauses() {
+    return Collections.unmodifiableCollection(causes);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getMessage() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("The following properties are mandatory: ");
+    boolean isFirst = true;
+    for (PropertyIsMandatoryException e : causes) {
+      if (!isFirst) {
+        builder.append(", ");
+      }
+      builder.append(e.getPropertyDefinition().getName());
+      isFirst = false;
+    }
+    return builder.toString();
+  }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
index 155ad0b..963b125 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
@@ -32,41 +32,23 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
-import org.opends.server.admin.AliasDefaultBehaviorProvider;
-import org.opends.server.admin.DefaultBehaviorPropertyValueException;
-import org.opends.server.admin.DefaultBehaviorProviderVisitor;
-import org.opends.server.admin.DefinedDefaultBehaviorProvider;
 import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.IllegalPropertyValueStringException;
-import org.opends.server.admin.InheritedDefaultValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
-import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
 import org.opends.server.admin.PropertyDefinition;
-import org.opends.server.admin.PropertyException;
 import org.opends.server.admin.PropertyIsMandatoryException;
-import org.opends.server.admin.PropertyIsReadOnlyException;
 import org.opends.server.admin.PropertyIsSingleValuedException;
 import org.opends.server.admin.PropertyOption;
 import org.opends.server.admin.PropertyProvider;
-import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
-import org.opends.server.admin.StringPropertyProvider;
-import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
 
 
 
 /**
- * A set of properties. Instances of this class can be used as the core of a
- * managed object implementation.
+ * A set of properties. Instances of this class can be used as the
+ * core of a managed object implementation.
  */
 public final class PropertySet implements PropertyProvider {
 
@@ -78,50 +60,65 @@
    */
   private static final class MyProperty<T> implements Property<T> {
 
+    // The active set of values.
+    private final SortedSet<T> activeValues;
+
     // The definition associated with this property.
     private final PropertyDefinition<T> d;
 
     // The default set of values (read-only).
     private final SortedSet<T> defaultValues;
 
-    // The active set of values (read-only).
-    private final SortedSet<T> activeValues;
-
     // The pending set of values.
     private final SortedSet<T> pendingValues;
 
 
 
     /**
-     * Create a property with the provided sets of pre-validated default and
-     * active values.
-     * <p>
-     * This constructor takes ownership of the provided value sets.
+     * Create a property with the provided sets of pre-validated
+     * default and active values.
      *
-     * @param d
+     * @param pd
      *          The property definition.
      * @param defaultValues
      *          The set of default values for the property.
      * @param activeValues
      *          The set of active values for the property.
      */
-    public MyProperty(PropertyDefinition<T> d, SortedSet<T> defaultValues,
-        SortedSet<T> activeValues) {
-      this.d = d;
-      this.defaultValues = Collections.unmodifiableSortedSet(defaultValues);
-      this.activeValues = Collections.unmodifiableSortedSet(activeValues);
+    public MyProperty(PropertyDefinition<T> pd, Collection<T> defaultValues,
+        Collection<T> activeValues) {
+      this.d = pd;
 
-      // Initially the pending values is the same as the active values.
+      SortedSet<T> sortedDefaultValues = new TreeSet<T>(pd);
+      sortedDefaultValues.addAll(defaultValues);
+      this.defaultValues = Collections
+          .unmodifiableSortedSet(sortedDefaultValues);
+
+      this.activeValues = new TreeSet<T>(pd);
+      this.activeValues.addAll(activeValues);
+
+      // Initially the pending values is the same as the active
+      // values.
       this.pendingValues = new TreeSet<T>(this.activeValues);
     }
 
 
 
     /**
+     * Makes the pending values active.
+     */
+    public void commit() {
+      activeValues.clear();
+      activeValues.addAll(pendingValues);
+    }
+
+
+
+    /**
      * {@inheritDoc}
      */
     public SortedSet<T> getActiveValues() {
-      return activeValues;
+      return Collections.unmodifiableSortedSet(activeValues);
     }
 
 
@@ -181,21 +178,18 @@
      * {@inheritDoc}
      */
     public boolean isModified() {
-      if (activeValues == pendingValues) {
+      if (activeValues.size() == pendingValues.size()
+          && activeValues.containsAll(pendingValues)) {
         return false;
-      } else if (activeValues.size() != pendingValues.size()) {
-        return true;
-      } else if (activeValues.containsAll(pendingValues)) {
-        return false;
-      } else {
-        return true;
       }
+      return true;
     }
 
 
 
     /**
-     * Replace all pending values of this property with the provided values.
+     * Replace all pending values of this property with the provided
+     * values.
      *
      * @param c
      *          The new set of pending property values.
@@ -210,376 +204,19 @@
     /**
      * {@inheritDoc}
      */
-    public boolean wasEmpty() {
-      return activeValues.isEmpty();
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public String toString() {
       return getEffectiveValues().toString();
     }
-  }
-
-
-
-  /**
-   * Internal default behavior visitor implementation.
-   *
-   * @param <T>
-   *          The type of the default property values.
-   */
-  private static final class DefaultVisitor<T> implements
-      DefaultBehaviorProviderVisitor<T, SortedSet<T>,
-      Collection<PropertyException>> {
-
-    // The property definition.
-    private final PropertyDefinition<T> pd;
-
-    // Used to retrieve inherited properties.
-    private final InheritedDefaultValueProvider provider;
-
-
-
-    // Private constructor.
-    private DefaultVisitor(PropertyDefinition<T> pd,
-        InheritedDefaultValueProvider provider) {
-      this.pd = pd;
-      this.provider = provider;
-    }
-
-
-
-    // Cast a set of objects to the required type.
-    private Collection<T> castValues(Collection<?> values,
-        Collection<PropertyException> exceptions) {
-      List<T> castValues = new LinkedList<T>();
-      for (Object value : values) {
-        try {
-          castValues.add(pd.castValue(value));
-        } catch (ClassCastException e) {
-          exceptions.add(new IllegalPropertyValueException(pd, value));
-        }
-      }
-      return castValues;
-    }
-
-
-
-    // Build set of default values and validate them.
-    private SortedSet<T> validateStrings(Collection<String> values,
-        Collection<PropertyException> exceptions) {
-      TreeSet<T> defaultValues = new TreeSet<T>(pd);
-      for (String value : values) {
-        try {
-          defaultValues.add(pd.decodeValue(value));
-        } catch (IllegalPropertyValueStringException e) {
-          exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
-        }
-      }
-
-      if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
-        if (defaultValues.size() > 1) {
-          PropertyException e = new PropertyIsSingleValuedException(pd);
-          exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
-        }
-      }
-
-      return defaultValues;
-    }
-
-
-
-    // Build set of default values and validate them.
-    private SortedSet<T> validate(Collection<T> values,
-        Collection<PropertyException> exceptions) {
-      TreeSet<T> defaultValues = new TreeSet<T>(pd);
-      for (T value : values) {
-        try {
-          pd.validateValue(value);
-          defaultValues.add(value);
-        } catch (IllegalPropertyValueException e) {
-          exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
-        }
-      }
-
-      if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
-        if (defaultValues.size() > 1) {
-          PropertyException e = new PropertyIsSingleValuedException(pd);
-          exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
-        }
-      }
-
-      return defaultValues;
-    }
 
 
 
     /**
      * {@inheritDoc}
      */
-    public SortedSet<T> visitAbsoluteInherited(
-        AbsoluteInheritedDefaultBehaviorProvider<T> d,
-        Collection<PropertyException> p) {
-      // Get the values from the managed object at the specified path.
-      try {
-        // Get the property values/defaults.
-        ManagedObjectPath path = d.getManagedObjectPath();
-        Collection<?> values = provider.getDefaultPropertyValues(path, d
-            .getPropertyName());
-        return validate(castValues(values, p), p);
-      } catch (OperationsException e) {
-        p.add(new InheritedDefaultValueException(pd, e));
-        return new TreeSet<T>(pd);
-      }
+    public boolean wasEmpty() {
+      return activeValues.isEmpty();
     }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public SortedSet<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
-        Collection<PropertyException> p) {
-      // No values applicable - just return the empty set.
-      return new TreeSet<T>(pd);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public SortedSet<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
-        Collection<PropertyException> p) {
-      return validateStrings(d.getDefaultValues(), p);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public SortedSet<T> visitRelativeInherited(
-        RelativeInheritedDefaultBehaviorProvider<T> d,
-        Collection<PropertyException> p) {
-      if (d.getRelativeOffset() == 0) {
-        // TODO: we're inheriting default values from another property in this
-        // property set. Logging is a good use-case: there is a general logging
-        // level for all categories and then category specific levels which can
-        // override. Should the default values be determined dynamically every
-        // time they are accessed? If dynamically, how will decoding errors be
-        // handled? Dynamically: we could return a SortedSet<T> which is lazily
-        // computed.
-        return new TreeSet<T>(pd);
-      } else {
-        // Inheriting default values from a parent managed object.
-        try {
-          ManagedObjectPath base = provider.getManagedObjectPath();
-          ManagedObjectPath path = d.getManagedObjectPath(base);
-          Collection<?> values = provider.getDefaultPropertyValues(path, d
-              .getPropertyName());
-          return validate(castValues(values, p), p);
-        } catch (OperationsException e) {
-          p.add(new InheritedDefaultValueException(pd, e));
-          return new TreeSet<T>(pd);
-        }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public SortedSet<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
-        Collection<PropertyException> p) {
-      // No values applicable - just return the empty set.
-      return new TreeSet<T>(pd);
-    }
-  }
-
-
-
-  /**
-   * Create a new property set using a property provider to supply the active
-   * property values. This constructor takes care of validation of the property
-   * values and retrieval of any default values.
-   * <p>
-   * Any exceptions that occurred whilst processing the properties will be
-   * placed in the provided exception collection. Properties that caused the
-   * exceptions will be created with an empty set of values (note that this
-   * could mean that the resulting property set might contain empty mandatory
-   * properties).
-   *
-   * @param d
-   *          The managed object definition.
-   * @param p
-   *          The property provider.
-   * @param i
-   *          An inherited managed object provider for retrieving inherited
-   *          properties.
-   * @param exceptions
-   *          A collection in which any property exceptions can be placed.
-   * @return Returns the new property set.
-   */
-  public static PropertySet create(ManagedObjectDefinition<?, ?> d,
-      PropertyProvider p, InheritedDefaultValueProvider i,
-      Collection<PropertyException> exceptions) {
-    Map<PropertyDefinition, MyProperty> properties =
-      new HashMap<PropertyDefinition, MyProperty>();
-
-    // Copy the properties from the provider.
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-      createProperty(pd, p, i, properties, exceptions);
-    }
-
-    return new PropertySet(properties);
-  }
-
-
-
-  /**
-   * Create a new property set using a string property provider to supply the
-   * active property values. This constructor takes care of validation of the
-   * property values and retrieval of any default values.
-   * <p>
-   * Any exceptions that occurred whilst processing the properties will be
-   * placed in the provided exception collection. Properties that caused the
-   * exceptions will be created with an empty set of values (note that this
-   * could mean that the resulting property set might contain empty mandatory
-   * properties).
-   *
-   * @param d
-   *          The managed object definition.
-   * @param p
-   *          The string property provider.
-   * @param i
-   *          An inherited managed object provider for retrieving inherited
-   *          properties.
-   * @param exceptions
-   *          A collection in which any property exceptions can be placed.
-   * @return Returns the new property set.
-   */
-  public static PropertySet create(ManagedObjectDefinition<?, ?> d,
-      StringPropertyProvider p, InheritedDefaultValueProvider i,
-      Collection<PropertyException> exceptions) {
-    Map<PropertyDefinition, MyProperty> properties =
-      new HashMap<PropertyDefinition, MyProperty>();
-
-    // Copy the properties from the provider.
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-      createProperty(pd, p, i, properties, exceptions);
-    }
-
-    return new PropertySet(properties);
-  }
-
-
-
-  // Create new property using string values taken from a property provider.
-  private static <T> void createProperty(PropertyDefinition<T> pd,
-      StringPropertyProvider p, InheritedDefaultValueProvider i,
-      Map<PropertyDefinition, MyProperty> properties,
-      Collection<PropertyException> exceptions) {
-
-    // Get the active values for this property.
-    Collection<String> activeStringValues;
-
-    try {
-      activeStringValues = p.getPropertyValues(pd);
-    } catch (IllegalArgumentException e) {
-      // Default to empty set of values.
-      activeStringValues = Collections.<String> emptySet();
-    }
-
-    SortedSet<T> activeValues = new TreeSet<T>(pd);
-    boolean gotException = false;
-    for (String stringValue : activeStringValues) {
-      try {
-        activeValues.add(pd.decodeValue(stringValue));
-      } catch (IllegalPropertyValueStringException e) {
-        exceptions.add(e);
-        gotException = true;
-      }
-    }
-
-    if (gotException == false) {
-      if (pd.hasOption(PropertyOption.MANDATORY)) {
-        if (activeValues.isEmpty()) {
-          exceptions.add(new PropertyIsMandatoryException(pd));
-        }
-      }
-    }
-
-    createProperty(pd, activeValues, i, properties, exceptions);
-  }
-
-
-
-  // Create new property using values taken from a property provider.
-  private static <T> void createProperty(PropertyDefinition<T> pd,
-      PropertyProvider p, InheritedDefaultValueProvider i,
-      Map<PropertyDefinition, MyProperty> properties,
-      Collection<PropertyException> exceptions) {
-    // Get the active values for this property.
-    Collection<T> activeValues;
-
-    try {
-      activeValues = p.getPropertyValues(pd);
-    } catch (IllegalArgumentException e) {
-      // Default to empty set of values.
-      activeValues = Collections.<T> emptySet();
-    }
-
-    SortedSet<T> validActiveValues = new TreeSet<T>(pd);
-    boolean gotException = false;
-    for (T value : activeValues) {
-      try {
-        pd.validateValue(value);
-        validActiveValues.add(value);
-      } catch (IllegalPropertyValueException e) {
-        exceptions.add(e);
-        gotException = true;
-      }
-    }
-
-    if (gotException == false) {
-      if (pd.hasOption(PropertyOption.MANDATORY)) {
-        if (validActiveValues.isEmpty()) {
-          exceptions.add(new PropertyIsMandatoryException(pd));
-        }
-      }
-    }
-
-    createProperty(pd, validActiveValues, i, properties, exceptions);
-  }
-
-
-
-  // Create new property using the provided validated values.
-  private static <T> void createProperty(PropertyDefinition<T> pd,
-      SortedSet<T> activeValues, InheritedDefaultValueProvider i,
-      Map<PropertyDefinition, MyProperty> properties,
-      Collection<PropertyException> exceptions) {
-    // Do remaining validation of active values.
-    if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
-      if (activeValues.size() > 1) {
-        exceptions.add(new PropertyIsSingleValuedException(pd));
-      }
-    }
-
-    // Get the default values for this property.
-    DefaultVisitor<T> visitor = new DefaultVisitor<T>(pd, i);
-    SortedSet<T> defaultValues = pd.getDefaultBehaviorProvider().accept(
-        visitor, exceptions);
-
-    // Create the property.
-    properties.put(pd, new MyProperty<T>(pd, defaultValues, activeValues));
   }
 
   // The properties.
@@ -587,25 +224,60 @@
 
 
 
-  // Private constructor.
-  private PropertySet(Map<PropertyDefinition, MyProperty> properties) {
-    this.properties = properties;
+  /**
+   * Creates a new empty property set.
+   */
+  public PropertySet() {
+    this.properties = new HashMap<PropertyDefinition, MyProperty>();
   }
 
 
 
   /**
-   * Get the property associated with the specified property definition.
+   * Creates a property with the provided sets of pre-validated
+   * default and active values.
+   *
+   * @param <T>
+   *          The type of the property.
+   * @param pd
+   *          The property definition.
+   * @param defaultValues
+   *          The set of default values for the property.
+   * @param activeValues
+   *          The set of active values for the property.
+   */
+  public <T> void addProperty(PropertyDefinition<T> pd,
+      Collection<T> defaultValues, Collection<T> activeValues) {
+    MyProperty<T> p = new MyProperty<T>(pd, defaultValues, activeValues);
+    properties.put(pd, p);
+  }
+
+
+
+  /**
+   * Makes all pending values active.
+   */
+  public void commit() {
+    for (MyProperty<?> p : properties.values()) {
+      p.commit();
+    }
+  }
+
+
+
+  /**
+   * Get the property associated with the specified property
+   * definition.
    *
    * @param <T>
    *          The underlying type of the property.
    * @param d
    *          The Property definition.
-   * @return Returns the property associated with the specified property
-   *         definition.
+   * @return Returns the property associated with the specified
+   *         property definition.
    * @throws IllegalArgumentException
-   *           If this property provider does not recognise the requested
-   *           property definition.
+   *           If this property provider does not recognise the
+   *           requested property definition.
    */
   @SuppressWarnings("unchecked")
   public <T> Property<T> getProperty(PropertyDefinition<T> d)
@@ -622,18 +294,19 @@
   /**
    * Get the effective value of the specified property.
    * <p>
-   * See the class description for more information about how the effective
-   * property value is derived.
+   * See the class description for more information about how the
+   * effective property value is derived.
    *
    * @param <T>
    *          The type of the property to be retrieved.
    * @param d
    *          The property to be retrieved.
-   * @return Returns the property's effective value, or <code>null</code> if
-   *         there is no effective value defined.
+   * @return Returns the property's effective value, or
+   *         <code>null</code> if there is no effective value
+   *         defined.
    * @throws IllegalArgumentException
-   *           If the property definition is not associated with this managed
-   *           object's definition.
+   *           If the property definition is not associated with this
+   *           managed object's definition.
    */
   public <T> T getPropertyValue(PropertyDefinition<T> d)
       throws IllegalArgumentException {
@@ -650,18 +323,18 @@
   /**
    * Get the effective values of the specified property.
    * <p>
-   * See the class description for more information about how the effective
-   * property values are derived.
+   * See the class description for more information about how the
+   * effective property values are derived.
    *
    * @param <T>
    *          The type of the property to be retrieved.
    * @param d
    *          The property to be retrieved.
-   * @return Returns the property's effective values, or an empty set if there
-   *         are no effective values defined.
+   * @return Returns the property's effective values, or an empty set
+   *         if there are no effective values defined.
    * @throws IllegalArgumentException
-   *           If the property definition is not associated with this managed
-   *           object's definition.
+   *           If the property definition is not associated with this
+   *           managed object's definition.
    */
   public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
       throws IllegalArgumentException {
@@ -674,29 +347,29 @@
   /**
    * Set a new pending value for the specified property.
    * <p>
-   * See the class description for more information regarding pending values.
+   * See the class description for more information regarding pending
+   * values.
    *
    * @param <T>
    *          The type of the property to be modified.
    * @param d
    *          The property to be modified.
    * @param value
-   *          The new pending value for the property, or <code>null</code> if
-   *          the property should be reset to its default behavior.
+   *          The new pending value for the property, or
+   *          <code>null</code> if the property should be reset to
+   *          its default behavior.
    * @throws IllegalPropertyValueException
-   *           If the new pending value is deemed to be invalid according to the
-   *           property definition.
-   * @throws PropertyIsReadOnlyException
-   *           If an attempt was made to modify a read-only property.
+   *           If the new pending value is deemed to be invalid
+   *           according to the property definition.
    * @throws PropertyIsMandatoryException
    *           If an attempt was made to remove a mandatory property.
    * @throws IllegalArgumentException
-   *           If the specified property definition is not associated with this
-   *           managed object.
+   *           If the specified property definition is not associated
+   *           with this managed object.
    */
   public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
-      throws IllegalPropertyValueException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
+      throws IllegalPropertyValueException, PropertyIsMandatoryException,
+      IllegalArgumentException {
     if (value == null) {
       setPropertyValues(d, Collections.<T> emptySet());
     } else {
@@ -709,51 +382,42 @@
   /**
    * Set a new pending values for the specified property.
    * <p>
-   * See the class description for more information regarding pending values.
+   * See the class description for more information regarding pending
+   * values.
    *
    * @param <T>
    *          The type of the property to be modified.
    * @param d
    *          The property to be modified.
    * @param values
-   *          A non-<code>null</code> set of new pending values for the
-   *          property (an empty set indicates that the property should be reset
-   *          to its default behavior). The set will not be referenced by this
-   *          managed object.
+   *          A non-<code>null</code> set of new pending values for
+   *          the property (an empty set indicates that the property
+   *          should be reset to its default behavior). The set will
+   *          not be referenced by this managed object.
    * @throws IllegalPropertyValueException
-   *           If a new pending value is deemed to be invalid according to the
-   *           property definition.
+   *           If a new pending value is deemed to be invalid
+   *           according to the property definition.
    * @throws PropertyIsSingleValuedException
-   *           If an attempt was made to add multiple pending values to a
-   *           single-valued property.
-   * @throws PropertyIsReadOnlyException
-   *           If an attempt was made to modify a read-only property.
+   *           If an attempt was made to add multiple pending values
+   *           to a single-valued property.
    * @throws PropertyIsMandatoryException
    *           If an attempt was made to remove a mandatory property.
    * @throws IllegalArgumentException
-   *           If the specified property definition is not associated with this
-   *           managed object.
+   *           If the specified property definition is not associated
+   *           with this managed object.
    */
   public <T> void setPropertyValues(PropertyDefinition<T> d,
       Collection<T> values) throws IllegalPropertyValueException,
-      PropertyIsSingleValuedException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
+      PropertyIsSingleValuedException, PropertyIsMandatoryException,
+      IllegalArgumentException {
     MyProperty<T> property = (MyProperty<T>) getProperty(d);
 
-    if (d.hasOption(PropertyOption.READ_ONLY)) {
-      throw new PropertyIsReadOnlyException(d);
+    if (values.size() > 1 && !d.hasOption(PropertyOption.MULTI_VALUED)) {
+      throw new PropertyIsSingleValuedException(d);
     }
 
-    if (!d.hasOption(PropertyOption.MULTI_VALUED)) {
-      if (values.size() > 1) {
-        throw new PropertyIsSingleValuedException(d);
-      }
-    }
-
-    if (d.hasOption(PropertyOption.MANDATORY)) {
-      if (values.isEmpty()) {
-        throw new PropertyIsMandatoryException(d);
-      }
+    if (values.isEmpty() && d.hasOption(PropertyOption.MANDATORY)) {
+      throw new PropertyIsMandatoryException(d);
     }
 
     // Validate each value.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index d2f3d56..a0a5bfc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -51,18 +51,22 @@
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
 import org.opends.server.admin.ConfigurationClient;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.DefaultBehaviorProviderVisitor;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
 import org.opends.server.admin.DefinitionDecodingException;
 import org.opends.server.admin.DefinitionResolver;
 import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
+import org.opends.server.admin.IllegalPropertyValueStringException;
 import org.opends.server.admin.InstantiableRelationDefinition;
 import org.opends.server.admin.ManagedObjectAlreadyExistsException;
 import org.opends.server.admin.ManagedObjectDefinition;
 import org.opends.server.admin.ManagedObjectNotFoundException;
 import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
 import org.opends.server.admin.OptionalRelationDefinition;
 import org.opends.server.admin.PropertyDefinition;
 import org.opends.server.admin.PropertyException;
@@ -70,16 +74,18 @@
 import org.opends.server.admin.PropertyIsReadOnlyException;
 import org.opends.server.admin.PropertyIsSingleValuedException;
 import org.opends.server.admin.PropertyNotFoundException;
-import org.opends.server.admin.PropertyProvider;
+import org.opends.server.admin.PropertyOption;
 import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.SingletonRelationDefinition;
-import org.opends.server.admin.StringPropertyProvider;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
 import org.opends.server.admin.DefinitionDecodingException.Reason;
 import org.opends.server.admin.client.AuthorizationException;
 import org.opends.server.admin.client.CommunicationException;
 import org.opends.server.admin.client.ConcurrentModificationException;
 import org.opends.server.admin.client.ManagedObject;
 import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.client.Property;
 import org.opends.server.admin.client.PropertySet;
@@ -99,31 +105,66 @@
     ManagedObject<C> {
 
   /**
-   * Internal inherited default value provider implementation.
+   * A default behavior visitor used for retrieving the default values
+   * of a property.
+   *
+   * @param <T>
+   *          The type of the property.
    */
-  private static class MyInheritedDefaultValueProvider implements
-      InheritedDefaultValueProvider {
+  private static class DefaultValueFinder<T> implements
+      DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> {
+
+    /**
+     * Get the default values for the specified property.
+     *
+     * @param <T>
+     *          The type of the property.
+     * @param context
+     *          The LDAP management context.
+     * @param p
+     *          The managed object path of the current managed object.
+     * @param pd
+     *          The property definition.
+     * @return Returns the default values for the specified property.
+     * @throws DefaultBehaviorException
+     *           If the default values could not be retrieved or
+     *           decoded properly.
+     */
+    public static <T> Collection<T> getDefaultValues(
+        LDAPManagementContext context, ManagedObjectPath p,
+        PropertyDefinition<T> pd) throws DefaultBehaviorException {
+      DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, pd);
+      Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p);
+
+      if (v.exception != null) {
+        throw v.exception;
+      }
+
+      if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+        throw new DefaultBehaviorException(pd,
+            new PropertyIsSingleValuedException(pd));
+      }
+
+      return values;
+    }
 
     // The LDAP management context.
     private final LDAPManagementContext context;
 
-    // The base path.
-    private final ManagedObjectPath path;
+    // Any exception that occurred whilst retrieving inherited default
+    // values.
+    private DefaultBehaviorException exception = null;
+
+    // The property definition whose default values are required.
+    private final PropertyDefinition<T> pd;
 
 
 
-    /**
-     * Create a new inherited default value provider.
-     *
-     * @param context
-     *          The LDAP management context.
-     * @param path
-     *          The base path.
-     */
-    public MyInheritedDefaultValueProvider(LDAPManagementContext context,
-        ManagedObjectPath path) {
+    // Private constructor.
+    private DefaultValueFinder(LDAPManagementContext context,
+        PropertyDefinition<T> pd) {
       this.context = context;
-      this.path = path;
+      this.pd = pd;
     }
 
 
@@ -131,26 +172,15 @@
     /**
      * {@inheritDoc}
      */
-    public Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
-        String propertyName) throws OperationsException,
-        PropertyNotFoundException {
-      ManagedObjectPath<?, ?> tmp = path;
-      ManagedObject<?> mo;
+    public Collection<T> visitAbsoluteInherited(
+        AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
       try {
-        mo = readEntry(context, tmp, tmp.getManagedObjectDefinition());
-      } catch (AuthorizationException e) {
-        throw new OperationsException(e);
-      } catch (CommunicationException e) {
-        throw new OperationsException(e);
+        return getInheritedProperty(d.getManagedObjectPath(), d
+            .getManagedObjectDefinition(), d.getPropertyName());
+      } catch (DefaultBehaviorException e) {
+        exception = new DefaultBehaviorException(pd, e);
       }
-      ManagedObjectDefinition<?, ?> mod = mo.getManagedObjectDefinition();
-
-      try {
-        PropertyDefinition<?> dpd = mod.getPropertyDefinition(propertyName);
-        return mo.getPropertyValues(dpd);
-      } catch (IllegalArgumentException e) {
-        throw new PropertyNotFoundException(propertyName);
-      }
+      return Collections.emptySet();
     }
 
 
@@ -158,10 +188,133 @@
     /**
      * {@inheritDoc}
      */
-    public ManagedObjectPath getManagedObjectPath() {
-      return path;
+    public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      return Collections.emptySet();
     }
-  }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      Collection<String> stringValues = d.getDefaultValues();
+      List<T> values = new ArrayList<T>(stringValues.size());
+
+      for (String stringValue : stringValues) {
+        try {
+          values.add(pd.decodeValue(stringValue));
+        } catch (IllegalPropertyValueStringException e) {
+          exception = new DefaultBehaviorException(pd, e);
+          break;
+        }
+      }
+
+      return values;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitRelativeInherited(
+        RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+      try {
+        return getInheritedProperty(d.getManagedObjectPath(p), d
+            .getManagedObjectDefinition(), d.getPropertyName());
+      } catch (DefaultBehaviorException e) {
+        exception = new DefaultBehaviorException(pd, e);
+      }
+      return Collections.emptySet();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      return Collections.emptySet();
+    }
+
+
+
+    // Get an inherited property value.
+    private Collection<T> getInheritedProperty(ManagedObjectPath target,
+        AbstractManagedObjectDefinition<?, ?> d, String propertyName)
+        throws DefaultBehaviorException {
+      try {
+        // First check that the requested type of managed object
+        // corresponds to the path.
+        AbstractManagedObjectDefinition<?, ?> supr = target
+            .getManagedObjectDefinition();
+        if (!supr.isParentOf(d)) {
+          throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION);
+        }
+
+        // Get the actual managed object definition.
+        LdapName dn = LDAPNameBuilder.create(target, context.getLDAPProfile());
+        ManagedObjectDefinition<?, ?> mod = getEntryDefinition(context, d, dn);
+
+        PropertyDefinition<?> pd2;
+        try {
+          pd2 = mod.getPropertyDefinition(propertyName);
+        } catch (IllegalArgumentException e) {
+          throw new PropertyNotFoundException(propertyName);
+        }
+
+        String attrID = context.getLDAPProfile().getAttributeName(mod, pd2);
+        Attributes attributes = context.getLDAPConnection().readEntry(dn,
+            Collections.singleton(attrID));
+        Attribute attr = attributes.get(attrID);
+        if (attr == null || attr.size() == 0) {
+          // Recursively retrieve this property's default values.
+          Collection<?> tmp = getDefaultValues(context, target, pd2);
+          Collection<T> values = new ArrayList<T>(tmp.size());
+          for (Object o : tmp) {
+            T value;
+            try {
+              value = pd.castValue(o);
+            } catch (ClassCastException e) {
+              throw new IllegalPropertyValueException(pd, o);
+            }
+            pd.validateValue(value);
+            values.add(value);
+          }
+          return values;
+        } else {
+          Collection<T> values = new LinkedList<T>();
+          NamingEnumeration<?> ne = attr.getAll();
+          while (ne.hasMore()) {
+            Object value = ne.next();
+            if (value != null) {
+              values.add(pd.decodeValue(value.toString()));
+            }
+          }
+          return values;
+        }
+      } catch (DefinitionDecodingException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (PropertyNotFoundException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (IllegalPropertyValueException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (IllegalPropertyValueStringException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (NameNotFoundException e) {
+        throw new DefaultBehaviorException(pd,
+            new ManagedObjectNotFoundException());
+      } catch (NoPermissionException e) {
+        throw new DefaultBehaviorException(pd, new AuthorizationException(e));
+      } catch (NamingException e) {
+        throw new DefaultBehaviorException(pd, new CommunicationException(e));
+      }
+    }
+  };
 
 
 
@@ -176,30 +329,8 @@
    */
   static ManagedObject<RootCfgClient> getRootManagedObject(
       LDAPManagementContext context) {
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        context, ManagedObjectPath.emptyPath());
-    PropertySet properties = PropertySet.create(RootCfgDefn.getInstance(),
-        PropertyProvider.DEFAULT_PROVIDER, i, exceptions);
-
-    // Should never get any exceptions.
-    if (!exceptions.isEmpty()) {
-      throw new RuntimeException(
-          "Got exceptions when creating root managed object");
-    }
-
     return new LDAPManagedObject<RootCfgClient>(context, RootCfgDefn
-        .getInstance(), ManagedObjectPath.emptyPath(), properties);
-  }
-
-
-
-  // Create a new child LDAP managed object.
-  private static <M extends ConfigurationClient>
-      ManagedObject<M> createLDAPManagedObject(
-      LDAPManagementContext context, ManagedObjectDefinition<M, ?> d,
-      ManagedObjectPath p, PropertySet properties) {
-    return new LDAPManagedObject<M>(context, d, p, properties);
+        .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true);
   }
 
 
@@ -247,104 +378,17 @@
     return d.resolveManagedObjectDefinition(resolver);
   }
 
-
-
-  // Read the entry identified by the path and which is a sub-type of
-  // the specified definition.
-  private static <M extends ConfigurationClient>
-      ManagedObject<? extends M> readEntry(
-      final LDAPManagementContext context, ManagedObjectPath p,
-      AbstractManagedObjectDefinition<M, ?> d)
-      throws DefinitionDecodingException, ManagedObjectDecodingException,
-      ManagedObjectNotFoundException, AuthorizationException,
-      CommunicationException {
-    LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
-
-    final ManagedObjectDefinition<? extends M, ?> mod;
-    final Attributes attributes;
-    try {
-      mod = getEntryDefinition(context, d, dn);
-      ArrayList<String> attrIds = new ArrayList<String>();
-      for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
-        String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
-        attrIds.add(attrId);
-      }
-      attributes = context.getLDAPConnection().readEntry(dn, attrIds);
-    } catch (NameNotFoundException e) {
-      throw new ManagedObjectNotFoundException();
-    } catch (NoPermissionException e) {
-      throw new AuthorizationException(e);
-    } catch (NamingException e) {
-      throw new CommunicationException(e);
-    }
-
-    // Create a provider which uses LDAP string representations.
-
-    // TODO: the exception handling is a bit of a hack here.
-    final List<NamingException> nelist = new LinkedList<NamingException>();
-    StringPropertyProvider provider = new StringPropertyProvider() {
-
-      public Collection<String> getPropertyValues(PropertyDefinition<?> d)
-          throws IllegalArgumentException {
-        String attrID = context.getLDAPProfile().getAttributeName(mod, d);
-        Attribute attribute = attributes.get(attrID);
-        List<String> values = new LinkedList<String>();
-
-        if (attribute != null && attribute.size() != 0) {
-          try {
-            NamingEnumeration<?> ldapValues = attribute.getAll();
-            while (ldapValues.hasMore()) {
-              Object obj = ldapValues.next();
-              if (obj != null) {
-                values.add(obj.toString());
-              }
-            }
-          } catch (NamingException e) {
-            nelist.add(e);
-          }
-        }
-
-        return values;
-      }
-
-    };
-
-    // There can only be at most one exception.
-    if (!nelist.isEmpty()) {
-      try {
-        throw nelist.get(0);
-      } catch (NameNotFoundException e) {
-        throw new ManagedObjectNotFoundException();
-      } catch (NoPermissionException e) {
-        throw new AuthorizationException(e);
-      } catch (NamingException e) {
-        throw new CommunicationException(e);
-      }
-    }
-
-    // Now decode the properties using the provider.
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        context, p);
-    PropertySet properties = PropertySet.create(mod, provider, i, exceptions);
-    ManagedObject<? extends M> mo = createLDAPManagedObject(context, mod, p,
-        properties);
-
-    // If there were no decoding problems then return the object,
-    // otherwise throw an operations exception.
-    if (exceptions.isEmpty()) {
-      return mo;
-    } else {
-      throw new ManagedObjectDecodingException(mo, exceptions);
-    }
-  }
+  // The LDAP management context used for the ldap connection.
+  private final LDAPManagementContext context;
 
   // The managed object definition associated with this managed
   // object.
   private final ManagedObjectDefinition<C, ?> definition;
 
-  // The LDAP management context used for the ldap connection.
-  private final LDAPManagementContext context;
+  // Indicates whether or not this managed object exists on the server
+  // (false means the managed object is new and has not been
+  // committed).
+  private boolean existsOnServer;
 
   // The path associated with this managed object.
   private final ManagedObjectPath<?, ?> path;
@@ -357,11 +401,12 @@
   // Create an new LDAP managed object with the provided JNDI context.
   private LDAPManagedObject(LDAPManagementContext context,
       ManagedObjectDefinition<C, ?> d, ManagedObjectPath path,
-      PropertySet properties) {
+      PropertySet properties, boolean existsOnServer) {
     this.definition = d;
     this.context = context;
     this.path = path;
     this.properties = properties;
+    this.existsOnServer = existsOnServer;
   }
 
 
@@ -369,36 +414,30 @@
   /**
    * {@inheritDoc}
    */
-  public void commit() throws ConcurrentModificationException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException {
-    // Build the list of modified attributes.
-    ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition();
-    Attributes mods = new BasicAttributes();
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+  public void commit() throws MissingMandatoryPropertiesException,
+      ConcurrentModificationException, OperationRejectedException,
+      AuthorizationException, CommunicationException,
+      ManagedObjectAlreadyExistsException {
+    // First make sure all mandatory properties are defined.
+    List<PropertyIsMandatoryException> exceptions =
+      new LinkedList<PropertyIsMandatoryException>();
+
+    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
       Property<?> p = properties.getProperty(pd);
-      if (p.isModified()) {
-        String attrID = context.getLDAPProfile().getAttributeName(d, pd);
-        Attribute attribute = new BasicAttribute(attrID);
-        encodeProperty(attribute, pd, properties);
-        mods.put(attribute);
+      if (pd.hasOption(PropertyOption.MANDATORY) && p.isEmpty()) {
+        exceptions.add(new PropertyIsMandatoryException(pd));
       }
     }
 
-    // Perform the LDAP modification if something has changed.
-    if (mods.size() > 0) {
-      try {
-        LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
-        context.getLDAPConnection().modifyEntry(dn, mods);
-      } catch (NoPermissionException e) {
-        throw new AuthorizationException(e);
-      } catch (OperationNotSupportedException e) {
-        // Unwilling to perform.
-        throw new OperationRejectedException(e);
-      } catch (NamingException e) {
-        // Just treat it as a communication problem.
-        throw new CommunicationException(e);
-      }
+    if (!exceptions.isEmpty()) {
+      throw new MissingMandatoryPropertiesException(exceptions);
+    }
+
+    // Commit the managed object.
+    if (existsOnServer) {
+      commitExistingManagedObject();
+    } else {
+      commitNewManagedObject();
     }
   }
 
@@ -410,60 +449,11 @@
   public <M extends ConfigurationClient, N extends M>
       ManagedObject<N> createChild(
       InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      String name, PropertyProvider p) throws IllegalArgumentException,
-      ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
-      ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException {
+      String name, Collection<DefaultBehaviorException> exceptions)
+      throws IllegalArgumentException {
     validateRelationDefinition(r);
-
     ManagedObjectPath childPath = path.child(r, name);
-
-    // First make sure all the properties are valid.
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        context, childPath);
-    PropertySet properties = PropertySet.create(d, p, i, exceptions);
-    if (!exceptions.isEmpty()) {
-      ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
-          properties);
-      throw new ManagedObjectDecodingException(mo, exceptions);
-    }
-
-    ensureThisManagedObjectExists();
-
-    // TODO: this implementation does not handle relations which
-    // comprise of more than one RDN arc (this will probably never
-    // be required anyway).
-    LdapName dn = LDAPNameBuilder.create(path, r, context.getLDAPProfile());
-    if (!entryExists(dn)) {
-      // Need to create the child managed object's parent entry i.e.
-      // the entry representing the relation itself.
-      Attributes attributes = new BasicAttributes();
-
-      // Create the branch's object class attribute.
-      Attribute oc = new BasicAttribute("objectClass");
-      for (String objectClass : context.getLDAPProfile()
-          .getInstantiableRelationObjectClasses(r)) {
-        oc.add(objectClass);
-      }
-      attributes.put(oc);
-
-      // Create the branch's naming attribute.
-      Rdn rdn = dn.getRdn(dn.size() - 1);
-      attributes.put(rdn.getType(), rdn.getValue().toString());
-
-      // Create the entry.
-      try {
-        context.getLDAPConnection().createEntry(dn, attributes);
-      } catch (OperationNotSupportedException e) {
-        // Unwilling to perform.
-        throw new OperationRejectedException(e);
-      } catch (NamingException e) {
-        adaptNamingException(e);
-      }
-    }
-
-    return createManagedObject(childPath, d, properties);
+    return createNewManagedObject(d, childPath, exceptions);
   }
 
 
@@ -474,28 +464,11 @@
   public <M extends ConfigurationClient, N extends M>
       ManagedObject<N> createChild(
       OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
-      PropertyProvider p) throws IllegalArgumentException,
-      ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
-      ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException {
+      Collection<DefaultBehaviorException> exceptions)
+      throws IllegalArgumentException {
     validateRelationDefinition(r);
-
     ManagedObjectPath childPath = path.child(r);
-
-    // First make sure all the properties are valid.
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        context, childPath);
-    PropertySet properties = PropertySet.create(d, p, i, exceptions);
-    if (!exceptions.isEmpty()) {
-      ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
-          properties);
-      throw new ManagedObjectDecodingException(mo, exceptions);
-    }
-
-    ensureThisManagedObjectExists();
-
-    return createManagedObject(childPath, d, properties);
+    return createNewManagedObject(d, childPath, exceptions);
   }
 
 
@@ -511,7 +484,7 @@
       CommunicationException {
     validateRelationDefinition(d);
     ensureThisManagedObjectExists();
-    return readEntry(context, path.child(d, name), d.getChildDefinition());
+    return readManagedObject(d.getChildDefinition(), path.child(d, name));
   }
 
 
@@ -526,7 +499,7 @@
       AuthorizationException, CommunicationException {
     validateRelationDefinition(d);
     ensureThisManagedObjectExists();
-    return readEntry(context, path.child(d), d.getChildDefinition());
+    return readManagedObject(d.getChildDefinition(), path.child(d));
   }
 
 
@@ -541,7 +514,7 @@
       AuthorizationException, CommunicationException {
     validateRelationDefinition(d);
     ensureThisManagedObjectExists();
-    return readEntry(context, path.child(d), d.getChildDefinition());
+    return readManagedObject(d.getChildDefinition(), path.child(d));
   }
 
 
@@ -674,6 +647,14 @@
   public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
       throws IllegalPropertyValueException, PropertyIsReadOnlyException,
       PropertyIsMandatoryException, IllegalArgumentException {
+    if (d.hasOption(PropertyOption.MONITORING)) {
+      throw new PropertyIsReadOnlyException(d);
+    }
+
+    if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+      throw new PropertyIsReadOnlyException(d);
+    }
+
     properties.setPropertyValue(d, value);
   }
 
@@ -686,6 +667,14 @@
       Collection<T> values) throws IllegalPropertyValueException,
       PropertyIsSingleValuedException, PropertyIsReadOnlyException,
       PropertyIsMandatoryException, IllegalArgumentException {
+    if (d.hasOption(PropertyOption.MONITORING)) {
+      throw new PropertyIsReadOnlyException(d);
+    }
+
+    if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+      throw new PropertyIsReadOnlyException(d);
+    }
+
     properties.setPropertyValues(d, values);
   }
 
@@ -711,30 +700,118 @@
 
 
 
-  // Creates a new managed object. The parent LDAP entry is assumed to
-  // already exist.
-  private <N extends ConfigurationClient> ManagedObject<N> createManagedObject(
-      ManagedObjectPath path, ManagedObjectDefinition<N, ?> d,
-      PropertySet properties) throws ManagedObjectAlreadyExistsException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException {
+  // Commit modifications made to this managed object.
+  private void commitExistingManagedObject()
+      throws ConcurrentModificationException, OperationRejectedException,
+      AuthorizationException, CommunicationException {
+    // Build the list of modified attributes.
+    Attributes mods = new BasicAttributes();
+    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+      Property<?> p = properties.getProperty(pd);
+      if (p.isModified()) {
+        String attrID = context.getLDAPProfile().getAttributeName(definition,
+            pd);
+        Attribute attribute = new BasicAttribute(attrID);
+        encodeProperty(attribute, pd, properties);
+        mods.put(attribute);
+      }
+    }
+
+    // Perform the LDAP modification if something has changed.
+    if (mods.size() > 0) {
+      try {
+        LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+        context.getLDAPConnection().modifyEntry(dn, mods);
+      } catch (NoPermissionException e) {
+        throw new AuthorizationException(e);
+      } catch (OperationNotSupportedException e) {
+        // Unwilling to perform.
+        throw new OperationRejectedException(e);
+      } catch (NamingException e) {
+        // Just treat it as a communication problem.
+        throw new CommunicationException(e);
+      }
+    }
+
+    // The changes were committed successfully so update this managed
+    // object's state.
+    properties.commit();
+  }
+
+
+
+  // Commit this new managed object.
+  private void commitNewManagedObject() throws AuthorizationException,
+      CommunicationException, OperationRejectedException,
+      ConcurrentModificationException, ManagedObjectAlreadyExistsException {
+    // First make sure that the parent managed object still exists.
+    ManagedObjectPath<?, ?> parent = path.parent();
+    if (!parent.isEmpty()) {
+      LdapName dn = LDAPNameBuilder.create(parent, context.getLDAPProfile());
+      if (!entryExists(dn)) {
+        throw new ConcurrentModificationException();
+      }
+    }
+
+    // We may need to create the parent "relation" entry if this is a
+    // child of an instantiable relation.
+    RelationDefinition<?, ?> r = path.getRelationDefinition();
+    if (r instanceof InstantiableRelationDefinition) {
+      InstantiableRelationDefinition<?, ?> ir =
+        (InstantiableRelationDefinition<?, ?>) r;
+
+      // TODO: this implementation does not handle relations which
+      // comprise of more than one RDN arc (this will probably never
+      // be required anyway).
+      LdapName dn = LDAPNameBuilder
+          .create(parent, ir, context.getLDAPProfile());
+      if (!entryExists(dn)) {
+        // We need to create the entry.
+        Attributes attributes = new BasicAttributes();
+
+        // Create the branch's object class attribute.
+        Attribute oc = new BasicAttribute("objectClass");
+        for (String objectClass : context.getLDAPProfile()
+            .getInstantiableRelationObjectClasses(ir)) {
+          oc.add(objectClass);
+        }
+        attributes.put(oc);
+
+        // Create the branch's naming attribute.
+        Rdn rdn = dn.getRdn(dn.size() - 1);
+        attributes.put(rdn.getType(), rdn.getValue().toString());
+
+        // Create the entry.
+        try {
+          context.getLDAPConnection().createEntry(dn, attributes);
+        } catch (OperationNotSupportedException e) {
+          // Unwilling to perform.
+          throw new OperationRejectedException(e);
+        } catch (NamingException e) {
+          adaptNamingException(e);
+        }
+      }
+    }
+
+    // Now add the entry representing this new managed object.
     LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
     Attributes attributes = new BasicAttributes(true);
 
-    // Create the child's object class attribute.
+    // Create the object class attribute.
     Attribute oc = new BasicAttribute("objectclass");
-    for (String objectClass : context.getLDAPProfile().getObjectClasses(d)) {
+    for (String objectClass : context.getLDAPProfile().getObjectClasses(
+        definition)) {
       oc.add(objectClass);
     }
     attributes.put(oc);
 
-    // Create the child's naming attribute.
+    // Create the naming attribute.
     Rdn rdn = dn.getRdn(dn.size() - 1);
     attributes.put(rdn.getType(), rdn.getValue().toString());
 
     // Create the remaining attributes.
-    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-      String attrID = context.getLDAPProfile().getAttributeName(d, pd);
+    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+      String attrID = context.getLDAPProfile().getAttributeName(definition, pd);
       Attribute attribute = new BasicAttribute(attrID);
       encodeProperty(attribute, pd, properties);
       if (attribute.size() != 0) {
@@ -754,7 +831,108 @@
       adaptNamingException(e);
     }
 
-    return new LDAPManagedObject<N>(context, d, path, properties);
+    // The entry was created successfully so update this managed
+    // object's state.
+    properties.commit();
+    existsOnServer = true;
+  }
+
+
+
+  // Create a managed object which already exists on the server.
+  private <M extends ConfigurationClient>
+      ManagedObject<M> createExistingManagedObject(
+      ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+      PropertySet properties) {
+    return new LDAPManagedObject<M>(context, d, p, properties, true);
+  }
+
+
+
+  // Creates a new managed object with no active values, just default
+  // values.
+  private <M extends ConfigurationClient>
+      ManagedObject<M> createNewManagedObject(
+      ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+      Collection<DefaultBehaviorException> exceptions) {
+    PropertySet childProperties = new PropertySet();
+    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+      try {
+        createProperty(childProperties, p, pd);
+      } catch (DefaultBehaviorException e) {
+        // Add the exception if requested.
+        if (exceptions != null) {
+          exceptions.add(e);
+        }
+      }
+    }
+
+    return new LDAPManagedObject<M>(context, d, p, childProperties, false);
+  }
+
+
+
+  // Create an empty property.
+  private <T> void createProperty(PropertySet properties, ManagedObjectPath p,
+      PropertyDefinition<T> pd) throws DefaultBehaviorException {
+    try {
+      Collection<T> defaultValues = DefaultValueFinder.getDefaultValues(
+          context, p, pd);
+      properties.addProperty(pd, defaultValues, Collections.<T> emptySet());
+    } catch (DefaultBehaviorException e) {
+      // Make sure that we have still created the property.
+      properties.addProperty(pd, Collections.<T> emptySet(), Collections
+          .<T> emptySet());
+      throw e;
+    }
+  }
+
+
+
+  // Create a property using the provided string values.
+  private <T> void decodeProperty(PropertySet newProperties,
+      ManagedObjectPath p, PropertyDefinition<T> pd, List<String> values)
+      throws PropertyException {
+    PropertyException exception = null;
+
+    // Get the property's active values.
+    Collection<T> activeValues = new ArrayList<T>(values.size());
+    for (String value : values) {
+      try {
+        activeValues.add(pd.decodeValue(value));
+      } catch (IllegalPropertyValueStringException e) {
+        exception = e;
+      }
+    }
+
+    if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+      // This exception takes precedence over previous exceptions.
+      exception = new PropertyIsSingleValuedException(pd);
+      T value = activeValues.iterator().next();
+      activeValues.clear();
+      activeValues.add(value);
+    }
+
+    if (activeValues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+      // The active values maybe empty because of a previous exception.
+      if (exception == null) {
+        exception = new PropertyIsMandatoryException(pd);
+      }
+    }
+
+    // Get the property's default values.
+    Collection<T> defaultValues;
+    try {
+      defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd);
+    } catch (DefaultBehaviorException e) {
+      defaultValues = Collections.emptySet();
+      exception = e;
+    }
+
+    newProperties.addProperty(pd, defaultValues, activeValues);
+    if (exception != null) {
+      throw exception;
+    }
   }
 
 
@@ -775,9 +953,11 @@
   private void ensureThisManagedObjectExists()
       throws ConcurrentModificationException, CommunicationException,
       AuthorizationException {
-    LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
-    if (!entryExists(dn)) {
-      throw new ConcurrentModificationException();
+    if (!path.isEmpty()) {
+      LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+      if (!entryExists(dn)) {
+        throw new ConcurrentModificationException();
+      }
     }
   }
 
@@ -796,6 +976,75 @@
 
 
 
+  // Read the entry identified by the path and which is a sub-type of
+  // the specified definition.
+  private <M extends ConfigurationClient>
+      ManagedObject<? extends M> readManagedObject(
+      AbstractManagedObjectDefinition<M, ?> d, ManagedObjectPath p)
+      throws DefinitionDecodingException, ManagedObjectDecodingException,
+      ManagedObjectNotFoundException, AuthorizationException,
+      CommunicationException {
+    try {
+      // Read the entry associated with the managed object.
+      LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
+      ManagedObjectDefinition<? extends M, ?> mod = getEntryDefinition(context,
+          d, dn);
+
+      ArrayList<String> attrIds = new ArrayList<String>();
+      for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+        String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
+        attrIds.add(attrId);
+      }
+
+      Attributes attributes = context.getLDAPConnection()
+          .readEntry(dn, attrIds);
+
+      // Build the managed object's properties.
+      List<PropertyException> exceptions = new LinkedList<PropertyException>();
+      PropertySet newProperties = new PropertySet();
+      for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+        String attrID = context.getLDAPProfile().getAttributeName(mod, pd);
+        Attribute attribute = attributes.get(attrID);
+        List<String> values = new LinkedList<String>();
+
+        if (attribute != null && attribute.size() != 0) {
+          NamingEnumeration<?> ldapValues = attribute.getAll();
+          while (ldapValues.hasMore()) {
+            Object obj = ldapValues.next();
+            if (obj != null) {
+              values.add(obj.toString());
+            }
+          }
+        }
+
+        try {
+          decodeProperty(newProperties, p, pd, values);
+        } catch (PropertyException e) {
+          exceptions.add(e);
+        }
+      }
+
+      // If there were no decoding problems then return the object,
+      // otherwise throw an operations exception.
+      ManagedObject<? extends M> mo = createExistingManagedObject(mod, p,
+          newProperties);
+
+      if (exceptions.isEmpty()) {
+        return mo;
+      } else {
+        throw new ManagedObjectDecodingException(mo, exceptions);
+      }
+    } catch (NameNotFoundException e) {
+      throw new ManagedObjectNotFoundException();
+    } catch (NoPermissionException e) {
+      throw new AuthorizationException(e);
+    } catch (NamingException e) {
+      throw new CommunicationException(e);
+    }
+  }
+
+
+
   // Remove the named managed object.
   private void removeManagedObject(ManagedObjectPath p)
       throws CommunicationException, AuthorizationException,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
index 654b806..6cc2865 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -29,38 +29,49 @@
 
 
 
-import org.opends.server.loggers.debug.DebugTracer;
 import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.StaticUtils.*;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
+import java.util.TreeSet;
 
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
 import org.opends.server.admin.Configuration;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.DefaultBehaviorProviderVisitor;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
 import org.opends.server.admin.DefinitionDecodingException;
 import org.opends.server.admin.DefinitionResolver;
-import org.opends.server.admin.InheritedDefaultValueProvider;
+import org.opends.server.admin.IllegalPropertyValueException;
+import org.opends.server.admin.IllegalPropertyValueStringException;
 import org.opends.server.admin.InstantiableRelationDefinition;
 import org.opends.server.admin.LDAPProfile;
 import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectNotFoundException;
 import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
 import org.opends.server.admin.OptionalRelationDefinition;
 import org.opends.server.admin.PropertyDefinition;
 import org.opends.server.admin.PropertyException;
+import org.opends.server.admin.PropertyIsMandatoryException;
+import org.opends.server.admin.PropertyIsSingleValuedException;
 import org.opends.server.admin.PropertyNotFoundException;
+import org.opends.server.admin.PropertyOption;
 import org.opends.server.admin.PropertyProvider;
 import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
 import org.opends.server.admin.SingletonRelationDefinition;
-import org.opends.server.admin.StringPropertyProvider;
-import org.opends.server.admin.client.PropertySet;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
+import org.opends.server.admin.DefinitionDecodingException.Reason;
 import org.opends.server.admin.std.meta.RootCfgDefn;
 import org.opends.server.admin.std.server.RootCfg;
 import org.opends.server.api.AttributeValueDecoder;
@@ -70,6 +81,7 @@
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.messages.AdminMessages;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeValue;
@@ -78,6 +90,7 @@
 import org.opends.server.types.DirectoryException;
 
 
+
 /**
  * A server-side managed object.
  *
@@ -85,81 +98,246 @@
  *          The type of server configuration represented by the server
  *          managed object.
  */
-public final class ServerManagedObject<S extends Configuration>
-    implements PropertyProvider {
+public final class ServerManagedObject<S extends Configuration> implements
+    PropertyProvider {
+
+  /**
+   * A default behavior visitor used for retrieving the default values
+   * of a property.
+   *
+   * @param <T>
+   *          The type of the property.
+   */
+  private static class DefaultValueFinder<T> implements
+      DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> {
+
+    /**
+     * Get the default values for the specified property.
+     *
+     * @param <T>
+     *          The type of the property.
+     * @param p
+     *          The managed object path of the current managed object.
+     * @param pd
+     *          The property definition.
+     * @return Returns the default values for the specified property.
+     * @throws DefaultBehaviorException
+     *           If the default values could not be retrieved or
+     *           decoded properly.
+     */
+    public static <T> Collection<T> getDefaultValues(ManagedObjectPath p,
+        PropertyDefinition<T> pd) throws DefaultBehaviorException {
+      DefaultValueFinder<T> v = new DefaultValueFinder<T>(pd);
+      Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p);
+
+      if (v.exception != null) {
+        throw v.exception;
+      }
+
+      if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+        throw new DefaultBehaviorException(pd,
+            new PropertyIsSingleValuedException(pd));
+      }
+
+      return values;
+    }
+
+    // Any exception that occurred whilst retrieving inherited default
+    // values.
+    private DefaultBehaviorException exception = null;
+
+    // The property definition whose default values are required.
+    private final PropertyDefinition<T> pd;
+
+
+
+    // Private constructor.
+    private DefaultValueFinder(PropertyDefinition<T> pd) {
+      this.pd = pd;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitAbsoluteInherited(
+        AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+      try {
+        return getInheritedProperty(d.getManagedObjectPath(), d
+            .getManagedObjectDefinition(), d.getPropertyName());
+      } catch (DefaultBehaviorException e) {
+        exception = new DefaultBehaviorException(pd, e);
+      }
+      return Collections.emptySet();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      return Collections.emptySet();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      Collection<String> stringValues = d.getDefaultValues();
+      List<T> values = new ArrayList<T>(stringValues.size());
+
+      for (String stringValue : stringValues) {
+        try {
+          values.add(pd.decodeValue(stringValue));
+        } catch (IllegalPropertyValueStringException e) {
+          exception = new DefaultBehaviorException(pd, e);
+          break;
+        }
+      }
+
+      return values;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitRelativeInherited(
+        RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+      try {
+        return getInheritedProperty(d.getManagedObjectPath(p), d
+            .getManagedObjectDefinition(), d.getPropertyName());
+      } catch (DefaultBehaviorException e) {
+        exception = new DefaultBehaviorException(pd, e);
+      }
+      return Collections.emptySet();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
+        ManagedObjectPath p) {
+      return Collections.emptySet();
+    }
+
+
+
+    // Get an inherited property value.
+    private Collection<T> getInheritedProperty(ManagedObjectPath target,
+        AbstractManagedObjectDefinition<?, ?> d, String propertyName)
+        throws DefaultBehaviorException {
+      try {
+        // First check that the requested type of managed object
+        // corresponds to the path.
+        AbstractManagedObjectDefinition<?, ?> supr = target
+            .getManagedObjectDefinition();
+        if (!supr.isParentOf(d)) {
+          throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION);
+        }
+
+        // Get the actual managed object definition.
+        DN dn = DNBuilder.create(target);
+        ConfigEntry configEntry = getManagedObjectConfigEntry(dn);
+        DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
+        ManagedObjectDefinition<?, ?> mod = d
+            .resolveManagedObjectDefinition(resolver);
+
+        PropertyDefinition<?> pd2;
+        try {
+          pd2 = mod.getPropertyDefinition(propertyName);
+        } catch (IllegalArgumentException e) {
+          throw new PropertyNotFoundException(propertyName);
+        }
+
+        List<String> stringValues = getAttribute(mod, pd2, configEntry);
+        if (stringValues.isEmpty()) {
+          // Recursively retrieve this property's default values.
+          Collection<?> tmp = getDefaultValues(target, pd2);
+          Collection<T> values = new ArrayList<T>(tmp.size());
+          for (Object o : tmp) {
+            T value;
+            try {
+              value = pd.castValue(o);
+            } catch (ClassCastException e) {
+              throw new IllegalPropertyValueException(pd, o);
+            }
+            pd.validateValue(value);
+            values.add(value);
+          }
+          return values;
+        } else {
+          Collection<T> values = new ArrayList<T>(stringValues.size());
+          for (String s : stringValues) {
+            values.add(pd.decodeValue(s));
+          }
+          return values;
+        }
+      } catch (DefinitionDecodingException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (PropertyNotFoundException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (IllegalPropertyValueException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (IllegalPropertyValueStringException e) {
+        throw new DefaultBehaviorException(pd, e);
+      } catch (ConfigException e) {
+        throw new DefaultBehaviorException(pd, e);
+      }
+    }
+  }
+
+
+
+  /**
+   * A definition resolver that determines the managed object
+   * definition from the object classes of a ConfigEntry.
+   */
+  private static class MyDefinitionResolver implements DefinitionResolver {
+
+    // The config entry.
+    private final ConfigEntry entry;
+
+
+
+    // Private constructor.
+    private MyDefinitionResolver(ConfigEntry entry) {
+      this.entry = entry;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean matches(AbstractManagedObjectDefinition<?, ?> d) {
+      String oc = LDAPProfile.getInstance().getObjectClass(d);
+      return entry.hasObjectClass(oc);
+    }
+  };
+
+  /**
+   * The root server managed object.
+   */
+  private static final ServerManagedObject<RootCfg> ROOT =
+    new ServerManagedObject<RootCfg>(
+      ManagedObjectPath.emptyPath(), RootCfgDefn.getInstance(), Collections
+          .<PropertyDefinition<?>, SortedSet<?>> emptyMap(), null);
 
   /**
    * The tracer object for the debug logger.
    */
   private static final DebugTracer TRACER = getTracer();
 
-  /**
-   * Internal inherited default value provider implementation.
-   */
-  private static class MyInheritedDefaultValueProvider implements
-      InheritedDefaultValueProvider {
-
-    // The base path.
-    private final ManagedObjectPath<?, ?> path;
-
-
-
-    /**
-     * Create a new inherited default value provider.
-     *
-     * @param path
-     *          The base path.
-     */
-    public MyInheritedDefaultValueProvider(ManagedObjectPath path) {
-      this.path = path;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Collection<?> getDefaultPropertyValues(
-        ManagedObjectPath path, String propertyName)
-        throws OperationsException, PropertyNotFoundException {
-      // Get the configuration entry.
-      DN targetDN = DNBuilder.create(path);
-      final ConfigEntry configEntry;
-      try {
-        configEntry = DirectoryServer.getConfigEntry(targetDN);
-      } catch (ConfigException e) {
-        throw new ManagedObjectNotFoundException(e);
-      }
-
-      if (configEntry == null) {
-        throw new ManagedObjectNotFoundException();
-      }
-
-      ManagedObjectPath<?, ?> tmp = path;
-      ServerManagedObject<?> mo = decode(tmp, tmp
-          .getManagedObjectDefinition(), configEntry);
-      ManagedObjectDefinition<?, ?> mod = mo
-          .getManagedObjectDefinition();
-      try {
-        PropertyDefinition<?> dpd = mod
-            .getPropertyDefinition(propertyName);
-        return mo.getPropertyValues(dpd);
-      } catch (IllegalArgumentException e) {
-        throw new PropertyNotFoundException(propertyName);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public ManagedObjectPath getManagedObjectPath() {
-      return path;
-    }
-
-  }
-
 
 
   /**
@@ -183,74 +361,34 @@
    *           If one or more of the managed object's properties could
    *           not be decoded.
    */
-  static <S extends Configuration>
-  ServerManagedObject<? extends S> decode(
-      ManagedObjectPath path,
-      AbstractManagedObjectDefinition<?, S> definition,
-      final ConfigEntry configEntry)
-      throws DefinitionDecodingException,
+  static <S extends Configuration> ServerManagedObject<? extends S> decode(
+      ManagedObjectPath path, AbstractManagedObjectDefinition<?, S> definition,
+      ConfigEntry configEntry) throws DefinitionDecodingException,
       ServerManagedObjectDecodingException {
     // First determine the correct definition to use for the entry.
     // This could either be the provided definition, or one of its
     // sub-definitions.
-    DefinitionResolver resolver = new DefinitionResolver() {
-
-      public boolean matches(AbstractManagedObjectDefinition<?, ?> d) {
-        String oc = LDAPProfile.getInstance().getObjectClass(d);
-        return configEntry.hasObjectClass(oc);
-      }
-
-    };
-
-    final ManagedObjectDefinition<?, ? extends S> mod = definition
+    DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
+    ManagedObjectDefinition<?, ? extends S> mod = definition
         .resolveManagedObjectDefinition(resolver);
 
-    // Use a string-based property provider to pull in the property
-    // values.
-    StringPropertyProvider provider = new StringPropertyProvider() {
-
-      public Collection<String> getPropertyValues(
-          PropertyDefinition<?> d) throws IllegalArgumentException {
-        String attrID = LDAPProfile.getInstance().getAttributeName(
-            mod, d);
-        // TODO: we create a default attribute type if it is
-        // undefined. We should log a warning here if this is the case
-        // since the attribute should have been defined.
-        AttributeType type = DirectoryServer.getAttributeType(attrID, true);
-        AttributeValueDecoder<String> decoder =
-          new AttributeValueDecoder<String>() {
-
-          public String decode(AttributeValue value)
-              throws DirectoryException {
-            return value.getStringValue();
-          }
-        };
-
-        try {
-          Collection<String> values = new LinkedList<String>();
-          configEntry.getEntry().getAttributeValues(type, decoder,
-              values);
-          return values;
-        } catch (DirectoryException e) {
-          // Should not happen.
-          throw new RuntimeException(e);
-        }
-      }
-
-    };
-
-    // Create the new managed object's property set, saving any
-    // decoding exceptions.
+    // Build the managed object's properties.
     List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        path);
-    PropertySet properties = PropertySet.create(mod, provider, i,
-        exceptions);
-    ServerManagedObject<? extends S> mo = decodeAux(path, mod,
-        properties, configEntry);
+    Map<PropertyDefinition<?>, SortedSet<?>> properties =
+      new HashMap<PropertyDefinition<?>, SortedSet<?>>();
+    for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+      List<String> values = getAttribute(mod, pd, configEntry);
+      try {
+        decodeProperty(properties, path, pd, values);
+      } catch (PropertyException e) {
+        exceptions.add(e);
+      }
+    }
 
-    // If there were no decoding problems then return the object,
-    // otherwise throw an operations exception.
+    // If there were no decoding problems then return the managed
+    // object, otherwise throw an operations exception.
+    ServerManagedObject<? extends S> mo = decodeAux(path, mod, properties,
+        configEntry);
     if (exceptions.isEmpty()) {
       return mo;
     } else {
@@ -261,28 +399,12 @@
 
 
   /**
-   * Construct a root server managed object.
+   * Gets the root server managed object.
    *
-   * @return Returns a root server managed object.
+   * @return Returns the root server managed object.
    */
   static ServerManagedObject<RootCfg> getRootManagedObject() {
-    ManagedObjectPath path = ManagedObjectPath.emptyPath();
-    List<PropertyException> exceptions = new LinkedList<PropertyException>();
-    InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
-        path);
-    PropertySet properties = PropertySet.create(
-        RootCfgDefn.getInstance(),
-        PropertyProvider.DEFAULT_PROVIDER, i, exceptions);
-
-    // Should never get any exceptions.
-    if (!exceptions.isEmpty()) {
-      throw new RuntimeException(
-          "Got exceptions when creating root managed object");
-    }
-
-    return new ServerManagedObject<RootCfg>(path,
-        RootCfgDefn.getInstance(), properties,
-        null);
+    return ROOT;
   }
 
 
@@ -290,11 +412,125 @@
   // Decode helper method required to avoid generics warning.
   private static <S extends Configuration> ServerManagedObject<S> decodeAux(
       ManagedObjectPath path, ManagedObjectDefinition<?, S> d,
-      PropertySet properties, ConfigEntry configEntry) {
-    return new ServerManagedObject<S>(path, d, properties,
-        configEntry);
+      Map<PropertyDefinition<?>, SortedSet<?>> properties,
+      ConfigEntry configEntry) {
+    return new ServerManagedObject<S>(path, d, properties, configEntry);
   }
 
+
+
+  // Create a property using the provided string values.
+  private static <T> void decodeProperty(
+      Map<PropertyDefinition<?>, SortedSet<?>> properties,
+      ManagedObjectPath path, PropertyDefinition<T> pd,
+      List<String> stringValues) throws PropertyException {
+    PropertyException exception = null;
+    SortedSet<T> values = new TreeSet<T>(pd);
+
+    if (!stringValues.isEmpty()) {
+      // The property has values defined for it.
+      for (String value : stringValues) {
+        try {
+          values.add(pd.decodeValue(value));
+        } catch (IllegalPropertyValueStringException e) {
+          exception = e;
+        }
+      }
+    } else {
+      // No values defined so get the defaults.
+      try {
+        values.addAll(DefaultValueFinder.getDefaultValues(path, pd));
+      } catch (DefaultBehaviorException e) {
+        exception = e;
+      }
+    }
+
+    if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+      // This exception takes precedence over previous exceptions.
+      exception = new PropertyIsSingleValuedException(pd);
+      T value = values.first();
+      values.clear();
+      values.add(value);
+    }
+
+    if (values.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+      // The values maybe empty because of a previous exception.
+      if (exception == null) {
+        exception = new PropertyIsMandatoryException(pd);
+      }
+    }
+
+    // TODO: If an exception occurs should we leave the property
+    // empty?
+    properties.put(pd, values);
+    if (exception != null) {
+      throw exception;
+    }
+  }
+
+
+
+  // Gets the attribute associated with a property from a ConfigEntry.
+  private static List<String> getAttribute(ManagedObjectDefinition<?, ?> d,
+      PropertyDefinition<?> pd, ConfigEntry configEntry) {
+    // TODO: we create a default attribute type if it is
+    // undefined. We should log a warning here if this is the case
+    // since the attribute should have been defined.
+    String attrID = LDAPProfile.getInstance().getAttributeName(d, pd);
+    AttributeType type = DirectoryServer.getAttributeType(attrID, true);
+    AttributeValueDecoder<String> decoder =
+      new AttributeValueDecoder<String>() {
+
+      public String decode(AttributeValue value) throws DirectoryException {
+        return value.getStringValue();
+      }
+    };
+
+    List<String> values = new LinkedList<String>();
+    try {
+      configEntry.getEntry().getAttributeValues(type, decoder, values);
+    } catch (DirectoryException e) {
+      // Should not happen.
+      throw new RuntimeException(e);
+    }
+    return values;
+  }
+
+
+
+  // Gets a config entry required for a managed object and throws a
+  // config exception on failure.
+  private static ConfigEntry getManagedObjectConfigEntry(DN dn)
+      throws ConfigException {
+    ConfigEntry configEntry;
+    try {
+      configEntry = DirectoryServer.getConfigEntry(dn);
+    } catch (ConfigException e) {
+      if (debugEnabled()) {
+        TRACER.debugCaught(DebugLogLevel.ERROR, e);
+      }
+
+      int msgID = AdminMessages.MSGID_ADMIN_CANNOT_GET_MANAGED_OBJECT;
+      String message = getMessage(msgID, String.valueOf(dn),
+          stackTraceToSingleLineString(e));
+      throw new ConfigException(msgID, message, e);
+    }
+
+    // The configuration handler is free to return null indicating
+    // that the entry does not exist.
+    if (configEntry == null) {
+      int msgID = AdminMessages.MSGID_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST;
+      String message = getMessage(msgID, String.valueOf(dn));
+      throw new ConfigException(msgID, message);
+    }
+
+    return configEntry;
+  }
+
+  // The configuration entry associated with this server managed
+  // object (null if root).
+  private ConfigEntry configEntry;
+
   // The managed object's definition.
   private final ManagedObjectDefinition<?, S> definition;
 
@@ -303,17 +539,14 @@
   private final ManagedObjectPath<?, ?> path;
 
   // The managed object's properties.
-  private final PropertySet properties;
-
-  // The configuration entry associated with this server managed
-  // object (null if root).
-  private ConfigEntry configEntry;
+  private final Map<PropertyDefinition<?>, SortedSet<?>> properties;
 
 
 
   // Create an new server side managed object.
   private ServerManagedObject(ManagedObjectPath path,
-      ManagedObjectDefinition<?, S> d, PropertySet properties,
+      ManagedObjectDefinition<?, S> d,
+      Map<PropertyDefinition<?>, SortedSet<?>> properties,
       ConfigEntry configEntry) {
     this.definition = d;
     this.path = path;
@@ -338,8 +571,7 @@
    */
   public <M extends Configuration> void deregisterAddListener(
       InstantiableRelationDefinition<?, M> d,
-      ConfigurationAddListener<M> listener)
-      throws IllegalArgumentException {
+      ConfigurationAddListener<M> listener) throws IllegalArgumentException {
     validateRelationDefinition(d);
 
     DN baseDN = DNBuilder.create(path, d);
@@ -362,8 +594,7 @@
    *           with this managed object's definition.
    */
   public <M extends Configuration> void deregisterAddListener(
-      OptionalRelationDefinition<?, M> d,
-      ConfigurationAddListener<M> listener)
+      OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener)
       throws IllegalArgumentException {
     validateRelationDefinition(d);
 
@@ -408,8 +639,7 @@
    */
   public <M extends Configuration> void deregisterDeleteListener(
       InstantiableRelationDefinition<?, M> d,
-      ConfigurationDeleteListener<M> listener)
-      throws IllegalArgumentException {
+      ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
     validateRelationDefinition(d);
 
     DN baseDN = DNBuilder.create(path, d);
@@ -433,8 +663,7 @@
    */
   public <M extends Configuration> void deregisterDeleteListener(
       OptionalRelationDefinition<?, M> d,
-      ConfigurationDeleteListener<M> listener)
-      throws IllegalArgumentException {
+      ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
     validateRelationDefinition(d);
 
     DN baseDN = DNBuilder.create(path);
@@ -465,7 +694,6 @@
       InstantiableRelationDefinition<?, M> d, String name)
       throws IllegalArgumentException, ConfigException {
     validateRelationDefinition(d);
-
     ManagedObjectPath childPath = path.child(d, name);
     return getChild(childPath, d);
   }
@@ -489,11 +717,9 @@
    *           could not be decoded.
    */
   public <M extends Configuration> ServerManagedObject<? extends M> getChild(
-      OptionalRelationDefinition<?, M> d)
-      throws IllegalArgumentException, ConfigException {
+      OptionalRelationDefinition<?, M> d) throws IllegalArgumentException,
+      ConfigException {
     validateRelationDefinition(d);
-
-    // Get the configuration entry.
     ManagedObjectPath childPath = path.child(d);
     return getChild(childPath, d);
   }
@@ -517,11 +743,9 @@
    *           could not be decoded.
    */
   public <M extends Configuration> ServerManagedObject<? extends M> getChild(
-      SingletonRelationDefinition<?, M> d)
-      throws IllegalArgumentException, ConfigException {
+      SingletonRelationDefinition<?, M> d) throws IllegalArgumentException,
+      ConfigException {
     validateRelationDefinition(d);
-
-    // Get the configuration entry.
     ManagedObjectPath childPath = path.child(d);
     return getChild(childPath, d);
   }
@@ -582,44 +806,49 @@
 
 
   /**
-   * Get the current value of the specified property.
-   * <p>
-   * If the value has been modified then the new value is returned,
-   * otherwise the original value will be returned.
+   * Get the effective value of the specified property. If the
+   * property is multi-valued then just the first value is returned.
+   * If the property does not have a value then its default value is
+   * returned if it has one, or <code>null</code> indicating that
+   * any default behavior is applicable.
    *
    * @param <T>
    *          The type of the property to be retrieved.
    * @param d
    *          The property to be retrieved.
-   * @return Returns the property's current value, or
-   *         <code>null</code> if there is no value(s) associated
-   *         with the property and any default behavior is
-   *         applicable.
+   * @return Returns the property's effective value, or
+   *         <code>null</code> indicating that any default behavior
+   *         is applicable.
    * @throws IllegalArgumentException
    *           If the property definition is not associated with this
    *           managed object's definition.
    */
   public <T> T getPropertyValue(PropertyDefinition<T> d)
       throws IllegalArgumentException {
-    return properties.getPropertyValue(d);
+    Set<T> values = getPropertyValues(d);
+    if (values.isEmpty()) {
+      return null;
+    } else {
+      return values.iterator().next();
+    }
   }
 
 
 
   /**
-   * Get the current values of the specified property.
-   * <p>
-   * If the property has been modified then the new values are
-   * returned, otherwise the original values will be returned.
+   * Get the effective values of the specified property. If the
+   * property does not have any values then its default values are
+   * returned if it has any, or an empty set indicating that any
+   * default behavior is applicable.
    *
    * @param <T>
    *          The type of the property to be retrieved.
    * @param d
    *          The property to be retrieved.
    * @return Returns a newly allocated set containing a copy of the
-   *         property's current values. An empty set indicates that
-   *         the property has no values defined and any default
-   *         behavior is applicable.
+   *         property's effective values. An empty set indicates that
+   *         the property has no default values defined and any
+   *         default behavior is applicable.
    * @throws IllegalArgumentException
    *           If the property definition is not associated with this
    *           managed object's definition.
@@ -627,7 +856,10 @@
   @SuppressWarnings("unchecked")
   public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
       throws IllegalArgumentException {
-    return properties.getPropertyValues(d);
+    if (!properties.containsKey(d)) {
+      throw new IllegalArgumentException("Unknown property " + d.getName());
+    }
+    return new TreeSet<T>((SortedSet<T>) properties.get(d));
   }
 
 
@@ -721,14 +953,14 @@
    */
   public <M extends Configuration> void registerAddListener(
       InstantiableRelationDefinition<?, M> d,
-      ConfigurationAddListener<M> listener)
-      throws IllegalArgumentException, ConfigException {
+      ConfigurationAddListener<M> listener) throws IllegalArgumentException,
+      ConfigException {
     validateRelationDefinition(d);
 
     DN baseDN = DNBuilder.create(path, d);
     ConfigEntry relationEntry = getListenerConfigEntry(baseDN);
-    ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path,
-        d, listener);
+    ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d,
+        listener);
 
     if (relationEntry != null) {
       relationEntry.registerAddListener(adaptor);
@@ -758,13 +990,12 @@
    *           with this managed object's definition.
    */
   public <M extends Configuration> void registerAddListener(
-      OptionalRelationDefinition<?, M> d,
-      ConfigurationAddListener<M> listener)
+      OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener)
       throws IllegalArgumentException {
     validateRelationDefinition(d);
 
-    ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path,
-        d, listener);
+    ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d,
+        listener);
     configEntry.registerAddListener(adaptor);
   }
 
@@ -779,8 +1010,8 @@
    */
   public void registerChangeListener(
       ConfigurationChangeListener<? super S> listener) {
-    ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(
-        path, definition, listener);
+    ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(path,
+        definition, listener);
     configEntry.registerChangeListener(adaptor);
   }
 
@@ -805,14 +1036,14 @@
    */
   public <M extends Configuration> void registerDeleteListener(
       InstantiableRelationDefinition<?, M> d,
-      ConfigurationDeleteListener<M> listener)
-      throws IllegalArgumentException, ConfigException {
+      ConfigurationDeleteListener<M> listener) throws IllegalArgumentException,
+      ConfigException {
     validateRelationDefinition(d);
 
     DN baseDN = DNBuilder.create(path, d);
     ConfigEntry relationEntry = getListenerConfigEntry(baseDN);
-    ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(
-        path, d, listener);
+    ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d,
+        listener);
 
     if (relationEntry != null) {
       relationEntry.registerDeleteListener(adaptor);
@@ -843,12 +1074,11 @@
    */
   public <M extends Configuration> void registerDeleteListener(
       OptionalRelationDefinition<?, M> d,
-      ConfigurationDeleteListener<M> listener)
-      throws IllegalArgumentException {
+      ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
     validateRelationDefinition(d);
 
-    ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(
-        path, d, listener);
+    ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d,
+        listener);
     configEntry.registerDeleteListener(adaptor);
   }
 
@@ -870,8 +1100,8 @@
 
 
   // Deregister an add listener.
-  private <M extends Configuration> void deregisterAddListener(
-      DN baseDN, ConfigurationAddListener<M> listener) {
+  private <M extends Configuration> void deregisterAddListener(DN baseDN,
+      ConfigurationAddListener<M> listener) {
     try {
       ConfigEntry configEntry = getListenerConfigEntry(baseDN);
       if (configEntry != null) {
@@ -886,8 +1116,7 @@
       }
     } catch (ConfigException e) {
       // Ignore the exception since this implies deregistration.
-      if (debugEnabled())
-      {
+      if (debugEnabled()) {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
     }
@@ -901,8 +1130,7 @@
     try {
       ConfigEntry configEntry = getListenerConfigEntry(baseDN);
       if (configEntry != null) {
-        for (ConfigDeleteListener l : configEntry
-            .getDeleteListeners()) {
+        for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
           if (l instanceof ConfigDeleteListenerAdaptor) {
             ConfigDeleteListenerAdaptor adaptor =
               (ConfigDeleteListenerAdaptor) l;
@@ -914,8 +1142,7 @@
       }
     } catch (ConfigException e) {
       // Ignore the exception since this implies deregistration.
-      if (debugEnabled())
-      {
+      if (debugEnabled()) {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
     }
@@ -945,15 +1172,13 @@
 
   // Gets a config entry required for a listener and throws a config
   // exception on failure or returns null if the entry does not exist.
-  private ConfigEntry getListenerConfigEntry(DN dn)
-      throws ConfigException {
+  private ConfigEntry getListenerConfigEntry(DN dn) throws ConfigException {
     // Attempt to retrieve the listener base entry.
     ConfigEntry configEntry;
     try {
       configEntry = DirectoryServer.getConfigEntry(dn);
     } catch (ConfigException e) {
-      if (debugEnabled())
-      {
+      if (debugEnabled()) {
         TRACER.debugCaught(DebugLogLevel.ERROR, e);
       }
 
@@ -968,48 +1193,14 @@
 
 
 
-  // Gets a config entry required for a managed object and throws a
-  // config exception on failure.
-  private ConfigEntry getManagedObjectConfigEntry(DN dn)
-      throws ConfigException {
-    ConfigEntry configEntry;
-    try {
-      configEntry = DirectoryServer.getConfigEntry(dn);
-    } catch (ConfigException e) {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int msgID = AdminMessages.MSGID_ADMIN_CANNOT_GET_MANAGED_OBJECT;
-      String message = getMessage(msgID, String.valueOf(dn),
-          stackTraceToSingleLineString(e));
-      throw new ConfigException(msgID, message, e);
-    }
-
-    // The configuration handler is free to return null indicating
-    // that the entry does not exist.
-    if (configEntry == null) {
-      int msgID = AdminMessages.MSGID_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST;
-      String message = getMessage(msgID, String.valueOf(dn));
-      throw new ConfigException(msgID, message);
-    }
-
-    return configEntry;
-  }
-
-
-
   // Validate that a relation definition belongs to this managed
   // object.
   private void validateRelationDefinition(RelationDefinition<?, ?> rd)
       throws IllegalArgumentException {
-    RelationDefinition tmp = definition.getRelationDefinition(rd
-        .getName());
+    RelationDefinition tmp = definition.getRelationDefinition(rd.getName());
     if (tmp != rd) {
-      throw new IllegalArgumentException("The relation "
-          + rd.getName() + " is not associated with a "
-          + definition.getName());
+      throw new IllegalArgumentException("The relation " + rd.getName()
+          + " is not associated with a " + definition.getName());
     }
   }
 }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
index 6b65d80..ab16299 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
@@ -116,6 +116,17 @@
 
 
   /**
+   * Tests that the empty path represents has no relation.
+   */
+  @Test
+  public void testEmptyPathHasNoRelation() {
+    ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+    assertEquals(path.getRelationDefinition(), null);
+  }
+
+
+
+  /**
    * Tests that the empty path has a string representation of "/".
    */
   @Test
@@ -152,6 +163,8 @@
     assertEquals(child.parent(), path);
     assertEquals(child.getManagedObjectDefinition(), GlobalCfgDefn
         .getInstance());
+    assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+        .getGlobalConfigurationRelationDefinition());
     assertEquals(child.toString(), "/relation=global-configuration");
     assertEquals(child, ManagedObjectPath
         .valueOf("/relation=global-configuration"));
@@ -175,6 +188,8 @@
     assertEquals(child.parent(), path);
     assertEquals(child.getManagedObjectDefinition(), ConnectionHandlerCfgDefn
         .getInstance());
+    assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+        .getConnectionHandlersRelationDefinition());
     assertEquals(child.toString(),
         "/relation=connection-handler+name=LDAP connection handler");
     assertEquals(child, ManagedObjectPath
@@ -200,6 +215,8 @@
     assertEquals(child.parent(), path);
     assertEquals(child.getManagedObjectDefinition(),
         LDAPConnectionHandlerCfgDefn.getInstance());
+    assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+        .getConnectionHandlersRelationDefinition());
     assertEquals(
         child.toString(),
         "/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler");
@@ -229,6 +246,9 @@
     assertEquals(domain.parent(2), root);
     assertEquals(domain.getManagedObjectDefinition(), MultimasterDomainCfgDefn
         .getInstance());
+    assertEquals(domain.getRelationDefinition(),
+        MultimasterSynchronizationProviderCfgDefn.getInstance()
+            .getMultimasterDomainsRelationDefinition());
     assertEquals(
         domain.toString(),
         "/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain");
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
index cc4043d..5ab5dd1 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
@@ -27,61 +27,104 @@
 
 package org.opends.server.admin;
 
+
+
 import static org.testng.Assert.assertEquals;
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeClass;
 
+
+
 /**
  * RelativeInheritedDefaultBehaviorProvider Tester.
  */
 public class RelativeInheritedDefaultBehaviorProviderTest {
 
-  static private final String PROPERTY_NAME = "test-property";
-  static private final int OFFSET = 0;
+  private static final int OFFSET = 0;
 
-  private RelativeInheritedDefaultBehaviorProvider<Object> ridbp = null;
+  private static final TestParentCfgDefn d = TestParentCfgDefn.getInstance();
 
+  private RelativeInheritedDefaultBehaviorProvider<Integer> ridbp = null;
+
+
+
+  /**
+   * Creates the default behavior provider.
+   */
   @BeforeClass
   public void setUp() {
-    this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Object>(OFFSET, PROPERTY_NAME);
+    this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Integer>(d, d
+        .getMaximumLengthPropertyDefinition().getName(), OFFSET);
   }
 
+
+
+  /**
+   * Tests the accept method.
+   */
   @Test
   public void testAccept() {
-    ridbp.accept(new DefaultBehaviorProviderVisitor<Object,Object,Object>(){
+    ridbp.accept(new DefaultBehaviorProviderVisitor<Integer, Object, Object>() {
 
-      public Object visitAbsoluteInherited(AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
+      public Object visitAbsoluteInherited(
+          AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
         return null;
       }
 
+
+
       public Object visitAlias(AliasDefaultBehaviorProvider d, Object o) {
         return null;
       }
 
+
+
       public Object visitDefined(DefinedDefaultBehaviorProvider d, Object o) {
         return null;
       }
 
-      public Object visitRelativeInherited(RelativeInheritedDefaultBehaviorProvider d, Object o) {
+
+
+      public Object visitRelativeInherited(
+          RelativeInheritedDefaultBehaviorProvider d, Object o) {
         return null;
       }
 
+
+
       public Object visitUndefined(UndefinedDefaultBehaviorProvider d, Object o) {
         return null;
       }
     }, new Object());
   }
 
+
+
+  /**
+   * Tests the getManagedObjectPath method.
+   */
   @Test
   public void testGetManagedObjectPath() {
-    ridbp.getManagedObjectPath(ManagedObjectPath.emptyPath());
+    assertEquals(ridbp.getManagedObjectPath(ManagedObjectPath.emptyPath()),
+        ManagedObjectPath.emptyPath());
   }
 
+
+
+  /**
+   * Tests the getPropertyDefinition method.
+   */
   @Test
-  public void testGetPropertyName() {
-    assertEquals(ridbp.getPropertyName(), PROPERTY_NAME);
+  public void testGetPropertyDefinition() {
+    assertEquals(ridbp.getPropertyName(), d
+        .getMaximumLengthPropertyDefinition().getName());
   }
 
+
+
+  /**
+   * Tests the getRelativeOffset method.
+   */
   @Test
   public void testGetRelativeOffset() {
     assertEquals(ridbp.getRelativeOffset(), OFFSET);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
index 9272699..03648f2 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
@@ -51,4 +51,22 @@
    * @return Returns the value of the "heartbeat-interval" property.
    */
   long getHeartbeatInterval();
+
+
+
+  /**
+   * Get the "maximum-length" property.
+   *
+   * @return Returns the value of the "maximum-length" property.
+   */
+  int getMaximumLength();
+
+
+
+  /**
+   * Get the "minimum-length" property.
+   *
+   * @return Returns the value of the "minimum-length" property.
+   */
+  int getMinimumLength();
 }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
index ea53db8..816dea1 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
@@ -63,4 +63,46 @@
    *           If the new value is invalid.
    */
   void setHeartbeatInterval(Long value) throws IllegalPropertyValueException;
+
+
+
+  /**
+   * Get the "maximum-length" property.
+   *
+   * @return Returns the value of the "maximum-length" property.
+   */
+  int getMaximumLength();
+
+
+
+  /**
+   * Set the "maximum-length" property.
+   *
+   * @param value
+   *          The value of the "maximum-length" property.
+   * @throws IllegalPropertyValueException
+   *           If the new value is invalid.
+   */
+  void setMaximumLength(Integer value) throws IllegalPropertyValueException;
+
+
+
+  /**
+   * Get the "minimum-length" property.
+   *
+   * @return Returns the value of the "minimum-length" property.
+   */
+  int getMinimumLength();
+
+
+
+  /**
+   * Set the "minimum-length" property.
+   *
+   * @param value
+   *          The value of the "minimum-length" property.
+   * @throws IllegalPropertyValueException
+   *           If the new value is invalid.
+   */
+  void setMinimumLength(Integer value) throws IllegalPropertyValueException;
 }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
index 46ee42f..84c16f0 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
@@ -32,6 +32,7 @@
 import org.opends.server.admin.client.CommunicationException;
 import org.opends.server.admin.client.ConcurrentModificationException;
 import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.server.ServerManagedObject;
 import org.opends.server.types.DN;
@@ -47,9 +48,40 @@
   // The singleton configuration definition instance.
   private static final TestChildCfgDefn INSTANCE = new TestChildCfgDefn();
 
+  // The "maximum-length" property definition.
+  private static final IntegerPropertyDefinition PD_MAXIMUM_LENGTH;
+
+  // The "minimum-length" property definition.
+  private static final IntegerPropertyDefinition PD_MINIMUM_LENGTH;
+
   // The "heartbeat-interval" property definition.
   private static final DurationPropertyDefinition PD_HEARTBEAT_INTERVAL;
 
+  // Build the "maximum-length" property definition.
+  static {
+    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
+        .createBuilder(INSTANCE, "maximum-length");
+    DefaultBehaviorProvider<Integer> provider = new RelativeInheritedDefaultBehaviorProvider<Integer>(
+        TestParentCfgDefn.getInstance(), "maximum-length", 1);
+    builder.setDefaultBehaviorProvider(provider);
+    builder.setLowerLimit(0);
+    PD_MAXIMUM_LENGTH = builder.getInstance();
+    INSTANCE.registerPropertyDefinition(PD_MAXIMUM_LENGTH);
+  }
+
+  // Build the "minimum-length" property definition.
+  static {
+    IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
+        .createBuilder(INSTANCE, "minimum-length");
+    DefaultBehaviorProvider<Integer> provider = new AbsoluteInheritedDefaultBehaviorProvider<Integer>(
+        ManagedObjectPath.valueOf("/relation=test-parent+name=test parent 2"),
+        "minimum-length");
+    builder.setDefaultBehaviorProvider(provider);
+    builder.setLowerLimit(0);
+    PD_MINIMUM_LENGTH = builder.getInstance();
+    INSTANCE.registerPropertyDefinition(PD_MINIMUM_LENGTH);
+  }
+
   // Build the "heartbeat-interval" property definition.
   static {
     DurationPropertyDefinition.Builder builder = DurationPropertyDefinition
@@ -127,6 +159,28 @@
 
 
   /**
+   * Get the "maximum-length" property definition.
+   *
+   * @return Returns the "maximum-length" property definition.
+   */
+  public IntegerPropertyDefinition getMaximumLengthPropertyDefinition() {
+    return PD_MAXIMUM_LENGTH;
+  }
+
+
+
+  /**
+   * Get the "minimum-length" property definition.
+   *
+   * @return Returns the "minimum-length" property definition.
+   */
+  public IntegerPropertyDefinition getMinimumLengthPropertyDefinition() {
+    return PD_MINIMUM_LENGTH;
+  }
+
+
+
+  /**
    * Managed object client implementation.
    */
   private static class TestChildCfgClientImpl implements TestChildCfgClient {
@@ -167,6 +221,46 @@
     /**
      * {@inheritDoc}
      */
+    public int getMaximumLength() {
+      return impl.getPropertyValue(INSTANCE
+          .getMaximumLengthPropertyDefinition());
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMaximumLength(Integer value) {
+      impl.setPropertyValue(INSTANCE.getMaximumLengthPropertyDefinition(),
+          value);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMinimumLength() {
+      return impl.getPropertyValue(INSTANCE
+          .getMinimumLengthPropertyDefinition());
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setMinimumLength(Integer value) {
+      impl.setPropertyValue(INSTANCE.getMinimumLengthPropertyDefinition(),
+          value);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
     public ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition() {
       return INSTANCE;
     }
@@ -187,7 +281,8 @@
      */
     public void commit() throws ConcurrentModificationException,
         OperationRejectedException, AuthorizationException,
-        CommunicationException {
+        CommunicationException, ManagedObjectAlreadyExistsException,
+        MissingMandatoryPropertiesException {
       impl.commit();
     }
   }
@@ -225,6 +320,26 @@
     /**
      * {@inheritDoc}
      */
+    public int getMaximumLength() {
+      return impl.getPropertyValue(INSTANCE
+          .getMaximumLengthPropertyDefinition());
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getMinimumLength() {
+      return impl.getPropertyValue(INSTANCE
+          .getMinimumLengthPropertyDefinition());
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
     public ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition() {
       return INSTANCE;
     }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
index 5a27cdc..b83125e 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
@@ -28,6 +28,8 @@
 
 
 
+import java.util.Collection;
+
 import org.opends.server.admin.ConfigurationClient;
 import org.opends.server.admin.ManagedObjectDefinition;
 import org.opends.server.admin.client.AuthorizationException;
@@ -111,36 +113,17 @@
    *          The definition of the test child to be created.
    * @param name
    *          The name of the new test child.
-   * @param p
-   *          A property provider which can be used to initialize the
-   *          property values of the new test child.
+   * @param exceptions
+   *          An optional collection in which to place any {@link
+   *          DefaultBehaviorException}s that occurred whilst
+   *          attempting to determine the default values of the test
+   *          child. This argument can be <code>null<code>.
    * @return Returns a new test child instance representing the test
    *         child that was created.
-   * @throws ManagedObjectDecodingException
-   *           If the test child could not be created because one or
-   *           more of its properties are invalid.
-   * @throws ManagedObjectAlreadyExistsException
-   *           If the test child cannot be created because it already
-   *           exists on the server.
-   * @throws ConcurrentModificationException
-   *           If this test parent has been removed from the server by
-   *           another client.
-   * @throws OperationRejectedException
-   *           If the server refuses to create the test child due to
-   *           some server-side constraint which cannot be satisfied.
-   * @throws AuthorizationException
-   *           If the server refuses to create the test child because
-   *           the client does not have the correct privileges.
-   * @throws CommunicationException
-   *           If the client cannot contact the server due to an
-   *           underlying communication problem.
    */
   <C extends TestChildCfgClient> C createTestChild(
-      ManagedObjectDefinition<C, ?> d, String name, PropertyProvider p)
-      throws ManagedObjectDecodingException,
-      ManagedObjectAlreadyExistsException, ConcurrentModificationException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException;
+      ManagedObjectDefinition<C, ?> d, String name,
+      Collection<DefaultBehaviorException> exceptions);
 
 
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
index 8fdd739..48b7a2b 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -28,11 +28,14 @@
 
 
 
+import java.util.Collection;
+
 import org.opends.server.admin.client.AuthorizationException;
 import org.opends.server.admin.client.CommunicationException;
 import org.opends.server.admin.client.ConcurrentModificationException;
 import org.opends.server.admin.client.ManagedObject;
 import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.server.ServerManagedObject;
 import org.opends.server.admin.std.meta.RootCfgDefn;
@@ -266,7 +269,8 @@
      */
     public void commit() throws ConcurrentModificationException,
         OperationRejectedException, AuthorizationException,
-        CommunicationException {
+        CommunicationException, ManagedObjectAlreadyExistsException,
+        MissingMandatoryPropertiesException {
       impl.commit();
     }
 
@@ -276,13 +280,10 @@
      * {@inheritDoc}
      */
     public <C extends TestChildCfgClient> C createTestChild(
-        ManagedObjectDefinition<C, ?> d, String name, PropertyProvider p)
-        throws ManagedObjectDecodingException,
-        ManagedObjectAlreadyExistsException, ConcurrentModificationException,
-        OperationRejectedException, AuthorizationException,
-        CommunicationException {
+        ManagedObjectDefinition<C, ?> d, String name,
+        Collection<DefaultBehaviorException> exceptions) {
       return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d,
-          name, p).getConfiguration();
+          name, exceptions).getConfiguration();
     }
 
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
index 007a896..5633837 100755
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
@@ -140,16 +140,6 @@
   }
 
   /**
-   * Tests basic property set creation with a string
-   * property provider
-   */
-  @Test
-  public void testCreate1() {
-    PropertySet ps = createTestPropertySet(StringPropertyProvider.DEFAULT_PROVIDER);
-    assertNotNull(ps);
-  }
-
-  /**
    * Tests setting and getting property values
    * @param pd PropertyDefinition for which values are set and gotten
    * @param values property values to test
@@ -229,9 +219,9 @@
     PropertySet ps = createTestPropertySet();
     Property<T> p = ps.getProperty(pd);
     SortedSet<T> ss = p.getDefaultValues();
-    assertTrue(ss.size() == expected.size());
+    assertEquals(ss.size(), expected.size());
     for (T v : expected) {
-      ss.contains(v);
+      assertTrue(ss.contains(v), "does not contain " + v);
     }
   }
 
@@ -282,9 +272,9 @@
     // before setting any values, the effective data
     // is supposed to just be the defaults
     Set<T> ev1 = p.getEffectiveValues();
-    assertTrue(ev1.size() == expectedDefaults.size());
+    assertEquals(ev1.size(), expectedDefaults.size());
     for(T v : ev1) {
-      assertTrue(expectedDefaults.contains(v));
+      assertTrue(expectedDefaults.contains(v), "does not contain " + v);
     }
 
     // now set some data and make sure the effective
@@ -292,9 +282,9 @@
     ps.setPropertyValues(pd, newValues);
 
     Set<T> ev2 = p.getEffectiveValues();
-    assertTrue(ev2.size() == newValues.size());
+    assertEquals(ev2.size(), newValues.size());
     for(T v : ev2) {
-      assertTrue(newValues.contains(v));
+      assertTrue(newValues.contains(v), "does not contain " + v);
     }
 
   }
@@ -391,21 +381,27 @@
   }
 
   private PropertySet createTestPropertySet(PropertyProvider pp) {
-    return PropertySet.create(
-            new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod",null),
-            pp,
-            new InheritedDefaultValueProvider() {
-              public ManagedObjectPath getManagedObjectPath() {
-                System.out.println("getManagedObjectPath");
-                return null;
-              }
-              public Collection<?> getDefaultPropertyValues(ManagedObjectPath path, String propertyName) throws OperationsException {
-                System.out.println("getDefPrV path=" + path + " pn=" + propertyName);
-                return null;
-              }
-            },
-            new HashSet<PropertyException>()
-    );
+    ManagedObjectDefinition<?, ?> d = new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod", null);
+    PropertySet ps = new PropertySet();
+    for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+      addProperty(ps, pd, pp);
+    }
+    return ps;
+  }
+
+  private <T> void addProperty(PropertySet ps, PropertyDefinition<T> pd, PropertyProvider pp) {
+    Collection<T> defaultValues = new LinkedList<T>();
+    DefaultBehaviorProvider<T> dbp = pd.getDefaultBehaviorProvider();
+    if (dbp instanceof DefinedDefaultBehaviorProvider) {
+      DefinedDefaultBehaviorProvider<T> ddbp = (DefinedDefaultBehaviorProvider<T>) dbp;
+      Collection<String> stringValues = ddbp.getDefaultValues();
+      for (String sv : stringValues) {
+        defaultValues.add(pd.decodeValue(sv));
+      }
+    }
+    
+    Collection<T> activeValues = pp.getPropertyValues(pd);
+    ps.addProperty(pd, defaultValues, activeValues);
   }
 
   private class TestManagedObjectDefinition<C extends ConfigurationClient,S extends Configuration> extends
@@ -476,23 +472,5 @@
     return createTestPropertySet(PropertyProvider.DEFAULT_PROVIDER);
   }
 
-  private PropertySet createTestPropertySet(StringPropertyProvider pp) {
-    return PropertySet.create(
-            new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod", null),
-            pp,
-            new InheritedDefaultValueProvider() {
-              public ManagedObjectPath getManagedObjectPath() {
-                System.out.println("getManagedObjectPath");
-                return null;
-              }
-              public Collection<?> getDefaultPropertyValues(ManagedObjectPath path, String propertyName) throws OperationsException {
-                System.out.println("getDefPrV path=" + path + " pn=" + propertyName);
-                return null;
-              }
-            },
-            new HashSet<PropertyException>()
-    );
-  }
-
 }
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
index f31742f..2b0a7c8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
@@ -41,7 +41,6 @@
 import org.opends.server.admin.ManagedObjectAlreadyExistsException;
 import org.opends.server.admin.ManagedObjectNotFoundException;
 import org.opends.server.admin.MockLDAPProfile;
-import org.opends.server.admin.PropertyProvider;
 import org.opends.server.admin.TestChildCfgClient;
 import org.opends.server.admin.TestChildCfgDefn;
 import org.opends.server.admin.TestParentCfgClient;
@@ -77,13 +76,16 @@
       "ds-cfg-maximum-length: 20000", "",
       "dn:cn=test-children,cn=test parent 1,cn=test-parents",
       "objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
+      "", "dn:cn=test-children,cn=test parent 2,cn=test-parents",
+      "objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
       "",
       "dn: cn=test child 1,cn=test-children,cn=test parent 1,cn=test-parents",
       "objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 1",
       "",
       "dn: cn=test child 2,cn=test-children,cn=test parent 1,cn=test-parents",
       "objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 2",
-      "ds-cfg-heartbeat-interval: 12345s", "" };
+      "ds-cfg-heartbeat-interval: 12345s", "ds-cfg-minimum-length: 11111",
+      "ds-cfg-maximum-length: 22222", "" };
 
 
 
@@ -159,7 +161,6 @@
    */
   @Test
   public void testCreateChildManagedObject() throws Exception {
-    MockPropertyProvider p = new MockPropertyProvider();
     CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
         "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
     c.importLDIF(TEST_LDIF);
@@ -167,13 +168,16 @@
     c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
 
     // LDAP encoding uses base unit.
-    p.addProperty("heartbeat-interval", "10s");
     c.addExpectedAttribute("ds-cfg-heartbeat-interval", "10000ms");
 
     ManagementContext ctx = LDAPManagementContext.createFromContext(c,
         new MockLDAPProfile());
     TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
-    parent.createTestChild(TestChildCfgDefn.getInstance(), "test child 3", p);
+    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+        .getInstance(), "test child 3", null);
+    child.setHeartbeatInterval(10000L);
+    child.commit();
+
     c.assertEntryIsCreated();
   }
 
@@ -196,8 +200,10 @@
     ManagementContext ctx = LDAPManagementContext.createFromContext(c,
         new MockLDAPProfile());
     TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
-    parent.createTestChild(TestChildCfgDefn.getInstance(), "test child 3",
-        new MockPropertyProvider());
+    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+        .getInstance(), "test child 3", null);
+    child.commit();
+
     c.assertEntryIsCreated();
   }
 
@@ -231,7 +237,8 @@
     ManagementContext ctx = LDAPManagementContext.createFromContext(c,
         new MockLDAPProfile());
     try {
-      createTestParent(ctx, "test parent 3", new MockPropertyProvider());
+      TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+      parent.commit();
     } catch (Exception e) {
       Assert.assertEquals(e.getClass(), expected);
     }
@@ -247,21 +254,20 @@
    */
   @Test
   public void testCreateTopLevelManagedObject() throws Exception {
-    MockPropertyProvider p = new MockPropertyProvider();
     CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
         "cn=test parent 3,cn=test-parents");
     c.importLDIF(TEST_LDIF);
     c.addExpectedAttribute("cn", "test parent 3");
     c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-parent");
-
-    p.addProperty("maximum-length", "54321");
     c.addExpectedAttribute("ds-cfg-maximum-length", "54321");
-    p.addProperty("minimum-length", "12345");
     c.addExpectedAttribute("ds-cfg-minimum-length", "12345");
 
     ManagementContext ctx = LDAPManagementContext.createFromContext(c,
         new MockLDAPProfile());
-    createTestParent(ctx, "test parent 3", p);
+    TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+    parent.setMaximumLength(54321);
+    parent.setMinimumLength(12345);
+    parent.commit();
     c.assertEntryIsCreated();
   }
 
@@ -283,7 +289,8 @@
 
     ManagementContext ctx = LDAPManagementContext.createFromContext(c,
         new MockLDAPProfile());
-    createTestParent(ctx, "test parent 3", new MockPropertyProvider());
+    TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+    parent.commit();
     c.assertEntryIsCreated();
   }
 
@@ -302,6 +309,8 @@
     TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
     TestChildCfgClient child = parent.getTestChild("test child 2");
     Assert.assertEquals(child.getHeartbeatInterval(), 12345000);
+    Assert.assertEquals(child.getMinimumLength(), 11111);
+    Assert.assertEquals(child.getMaximumLength(), 22222);
   }
 
 
@@ -318,6 +327,8 @@
     TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
     TestChildCfgClient child = parent.getTestChild("test child 1");
     Assert.assertEquals(child.getHeartbeatInterval(), 1000);
+    Assert.assertEquals(child.getMinimumLength(), 10000);
+    Assert.assertEquals(child.getMaximumLength(), 456);
   }
 
 
@@ -565,16 +576,84 @@
 
 
 
+  /**
+   * Tests retrieval of relative inherited default values.
+   *
+   * @throws Exception
+   *           If an unexpected error occurred.
+   */
+  @Test
+  public void testInheritedDefaultValues1() throws Exception {
+    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+        "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
+    c.importLDIF(TEST_LDIF);
+    c.addExpectedAttribute("cn", "test child 3");
+    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
+
+    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
+        new MockLDAPProfile());
+    TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+        .getInstance(), "test child 3", null);
+
+    // Inherits from parent (test parent 1).
+    Assert.assertEquals(child.getMinimumLength(), 10000);
+
+    // Inherits from test parent 2.
+    Assert.assertEquals(child.getMaximumLength(), 456);
+
+    // Check that the default values are not committed.
+    child.commit();
+
+    c.assertEntryIsCreated();
+  }
+
+
+
+  /**
+   * Tests retrieval of relative inherited default values.
+   *
+   * @throws Exception
+   *           If an unexpected error occurred.
+   */
+  @Test
+  public void testInheritedDefaultValues2() throws Exception {
+    CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+        "cn=test child 3,cn=test-children,cn=test parent 2,cn=test-parents");
+    c.importLDIF(TEST_LDIF);
+    c.addExpectedAttribute("cn", "test child 3");
+    c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
+
+    ManagementContext ctx = LDAPManagementContext.createFromContext(c,
+        new MockLDAPProfile());
+    TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
+    TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+        .getInstance(), "test child 3", null);
+
+    // Inherits from parent (test parent 2).
+    Assert.assertEquals(child.getMinimumLength(), 10000);
+
+    // Inherits from test parent 2.
+    Assert.assertEquals(child.getMaximumLength(), 20000);
+
+    // Check that the default values are not committed.
+    child.commit();
+
+    c.assertEntryIsCreated();
+  }
+
+
+
   // Create the named test parent managed object.
-  private void createTestParent(ManagementContext context, String name,
-      PropertyProvider p) throws ManagedObjectDecodingException,
+  private TestParentCfgClient createTestParent(ManagementContext context,
+      String name) throws ManagedObjectDecodingException,
       AuthorizationException, ManagedObjectAlreadyExistsException,
       ConcurrentModificationException, OperationRejectedException,
       CommunicationException {
     ManagedObject<RootCfgClient> root = context
         .getRootConfigurationManagedObject();
-    root.createChild(TestParentCfgDefn.RD_TEST_PARENT, TestParentCfgDefn
-        .getInstance(), name, p);
+    return root.createChild(TestParentCfgDefn.RD_TEST_PARENT,
+        TestParentCfgDefn.getInstance(), name, null).getConfiguration();
   }
 
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java
deleted file mode 100644
index 765a2b8..0000000
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
- */
-package org.opends.server.admin.client.ldap;
-
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.opends.server.admin.PropertyDefinition;
-import org.opends.server.admin.PropertyProvider;
-import org.opends.server.util.Validator;
-
-
-
-/**
- * A mock property provider which simplifies creation of managed
- * objects and LDAP attribute comparisons.
- */
-public final class MockPropertyProvider implements PropertyProvider {
-
-  // The properties.
-  private final Map<String, List<String>> properties = new HashMap<String, List<String>>();
-
-
-
-  /**
-   * Default constructor.
-   */
-  public MockPropertyProvider() {
-    // No implementation required.
-  }
-
-
-
-  /**
-   * Add a property.
-   *
-   * @param name
-   *          The name of the property.
-   * @param values
-   *          The property's values.
-   */
-  public void addProperty(String name, String... values) {
-    Validator.ensureNotNull(name);
-    Validator.ensureNotNull(values);
-    Validator.ensureTrue(values.length > 0);
-    properties.put(name, Arrays.asList(values));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public <T> Collection<T> getPropertyValues(PropertyDefinition<T> d)
-      throws IllegalArgumentException {
-    List<String> values = properties.get(d.getName());
-
-    if (values == null) {
-      return Collections.<T> emptySet();
-    }
-
-    List<T> encodedValues = new ArrayList<T>(values.size());
-    for (String value : values) {
-      encodedValues.add(d.decodeValue(value));
-    }
-
-    return encodedValues;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString() {
-    return properties.toString();
-  }
-
-}

--
Gitblit v1.10.0