From 6c6423cd20273cf4ddce2b44a496df0c531ada4a Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 02 Dec 2013 11:15:22 +0000
Subject: [PATCH] OpenDJ 3 : config framework

---
 opendj-admin/src/main/java/org/opends/server/admin/client/spi/AbstractManagedObject.java | 1684 +++++++++++++++++++++++++--------------------------------
 1 files changed, 749 insertions(+), 935 deletions(-)

diff --git a/opendj-admin/src/main/java/org/opends/server/admin/client/spi/AbstractManagedObject.java b/opendj-admin/src/main/java/org/opends/server/admin/client/spi/AbstractManagedObject.java
index a9c6085..f5b268e 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/client/spi/AbstractManagedObject.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/client/spi/AbstractManagedObject.java
@@ -26,8 +26,6 @@
  */
 package org.opends.server.admin.client.spi;
 
-
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedList;
@@ -36,7 +34,7 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import org.opends.messages.Message;
+import org.forgerock.i18n.LocalizableMessage;
 import org.opends.server.admin.AbstractManagedObjectDefinition;
 import org.opends.server.admin.Configuration;
 import org.opends.server.admin.ConfigurationClient;
@@ -74,975 +72,791 @@
 import org.opends.server.admin.client.OperationRejectedException;
 import org.opends.server.admin.client.OperationRejectedException.OperationType;
 
-
-
 /**
  * An abstract managed object implementation.
  *
  * @param <T>
- *          The type of client configuration represented by the client
- *          managed object.
+ *            The type of client configuration represented by the client managed
+ *            object.
  */
-public abstract class AbstractManagedObject<T extends ConfigurationClient>
-    implements ManagedObject<T> {
-
-  /**
-   * Creates any default managed objects associated with a relation
-   * definition.
-   */
-  private final class DefaultManagedObjectFactory implements
-      RelationDefinitionVisitor<Void, Void> {
-
-    // Possible exceptions.
-    private AuthorizationException ae = null;
-
-    private ManagedObjectAlreadyExistsException moaee = null;
-
-    private MissingMandatoryPropertiesException mmpe = null;
-
-    private ConcurrentModificationException cme = null;
-
-    private OperationRejectedException ore = null;
-
-    private CommunicationException ce = null;
-
-
+public abstract class AbstractManagedObject<T extends ConfigurationClient> implements ManagedObject<T> {
 
     /**
-     * {@inheritDoc}
+     * Creates any default managed objects associated with a relation
+     * definition.
      */
-    public <C extends ConfigurationClient, S extends Configuration>
-        Void visitInstantiable(
-        InstantiableRelationDefinition<C, S> rd, Void p) {
-      for (String name : rd.getDefaultManagedObjectNames()) {
-        DefaultManagedObject<? extends C, ? extends S> dmo = rd
-            .getDefaultManagedObject(name);
-        ManagedObjectDefinition<? extends C, ? extends S> d = dmo
-            .getManagedObjectDefinition();
-        ManagedObject<? extends C> child;
-        try {
-          child = createChild(rd, d, name, null);
-        } catch (IllegalManagedObjectNameException e) {
-          // This should not happen.
-          throw new RuntimeException(e);
+    private final class DefaultManagedObjectFactory implements RelationDefinitionVisitor<Void, Void> {
+
+        // Possible exceptions.
+        private AuthorizationException ae = null;
+
+        private ManagedObjectAlreadyExistsException moaee = null;
+
+        private MissingMandatoryPropertiesException mmpe = null;
+
+        private ConcurrentModificationException cme = null;
+
+        private OperationRejectedException ore = null;
+
+        private CommunicationException ce = null;
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> Void visitInstantiable(
+                InstantiableRelationDefinition<C, S> rd, Void p) {
+            for (String name : rd.getDefaultManagedObjectNames()) {
+                DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject(name);
+                ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
+                ManagedObject<? extends C> child;
+                try {
+                    child = createChild(rd, d, name, null);
+                } catch (IllegalManagedObjectNameException e) {
+                    // This should not happen.
+                    throw new RuntimeException(e);
+                }
+                createDefaultManagedObject(d, child, dmo);
+            }
+            return null;
         }
-        createDefaultManagedObject(d, child, dmo);
-      }
-      return null;
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> Void visitOptional(
+                OptionalRelationDefinition<C, S> rd, Void p) {
+            if (rd.getDefaultManagedObject() != null) {
+                DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject();
+                ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
+                ManagedObject<? extends C> child = createChild(rd, d, null);
+                createDefaultManagedObject(d, child, dmo);
+            }
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> Void visitSingleton(
+                SingletonRelationDefinition<C, S> rd, Void p) {
+            // Do nothing - not possible to create singletons
+            // dynamically.
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> Void visitSet(SetRelationDefinition<C, S> rd,
+                Void p) {
+            for (String name : rd.getDefaultManagedObjectNames()) {
+                DefaultManagedObject<? extends C, ? extends S> dmo = rd.getDefaultManagedObject(name);
+                ManagedObjectDefinition<? extends C, ? extends S> d = dmo.getManagedObjectDefinition();
+                ManagedObject<? extends C> child = createChild(rd, d, null);
+                createDefaultManagedObject(d, child, dmo);
+            }
+            return null;
+        }
+
+        // Create the child managed object.
+        private void createDefaultManagedObject(ManagedObjectDefinition<?, ?> d, ManagedObject<?> child,
+                DefaultManagedObject<?, ?> dmo) {
+            for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+                setPropertyValues(child, pd, dmo);
+            }
+
+            try {
+                child.commit();
+            } catch (AuthorizationException e) {
+                ae = e;
+            } catch (ManagedObjectAlreadyExistsException e) {
+                moaee = e;
+            } catch (MissingMandatoryPropertiesException e) {
+                mmpe = e;
+            } catch (ConcurrentModificationException e) {
+                cme = e;
+            } catch (OperationRejectedException e) {
+                ore = e;
+            } catch (CommunicationException e) {
+                ce = e;
+            }
+        }
+
+        /**
+         * Creates the default managed objects associated with the provided
+         * relation definition.
+         *
+         * @param rd
+         *            The relation definition.
+         */
+        private void createDefaultManagedObjects(RelationDefinition<?, ?> rd) throws AuthorizationException,
+                CommunicationException, ConcurrentModificationException, MissingMandatoryPropertiesException,
+                ManagedObjectAlreadyExistsException, OperationRejectedException {
+            rd.accept(this, null);
+
+            if (ae != null) {
+                throw ae;
+            } else if (ce != null) {
+                throw ce;
+            } else if (cme != null) {
+                throw cme;
+            } else if (mmpe != null) {
+                throw mmpe;
+            } else if (moaee != null) {
+                throw moaee;
+            } else if (ore != null) {
+                throw ore;
+            }
+        }
+
+        // Set property values.
+        private <PD> void setPropertyValues(ManagedObject<?> mo, PropertyDefinition<PD> pd,
+                DefaultManagedObject<?, ?> dmo) {
+            mo.setPropertyValues(pd, dmo.getPropertyValues(pd));
+        }
     }
 
+    // The managed object definition associated with this managed
+    // object.
+    private final ManagedObjectDefinition<T, ? extends Configuration> definition;
 
+    // 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;
+
+    // Optional naming property definition.
+    private final PropertyDefinition<?> namingPropertyDefinition;
+
+    // The path associated with this managed object.
+    private ManagedObjectPath<T, ? extends Configuration> path;
+
+    // The managed object's properties.
+    private final PropertySet properties;
 
     /**
-     * {@inheritDoc}
-     */
-    public <C extends ConfigurationClient, S extends Configuration>
-        Void visitOptional(
-        OptionalRelationDefinition<C, S> rd, Void p) {
-      if (rd.getDefaultManagedObject() != null) {
-        DefaultManagedObject<? extends C, ? extends S> dmo = rd
-            .getDefaultManagedObject();
-        ManagedObjectDefinition<? extends C, ? extends S> d = dmo
-            .getManagedObjectDefinition();
-        ManagedObject<? extends C> child = createChild(rd, d, null);
-        createDefaultManagedObject(d, child, dmo);
-      }
-      return null;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <C extends ConfigurationClient, S extends Configuration>
-        Void visitSingleton(
-        SingletonRelationDefinition<C, S> rd, Void p) {
-      // Do nothing - not possible to create singletons
-      // dynamically.
-      return null;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <C extends ConfigurationClient, S extends Configuration>
-        Void visitSet(
-        SetRelationDefinition<C, S> rd, Void p) {
-      for (String name : rd.getDefaultManagedObjectNames()) {
-        DefaultManagedObject<? extends C, ? extends S> dmo = rd
-            .getDefaultManagedObject(name);
-        ManagedObjectDefinition<? extends C, ? extends S> d = dmo
-            .getManagedObjectDefinition();
-        ManagedObject<? extends C> child = createChild(rd, d, null);
-        createDefaultManagedObject(d, child, dmo);
-      }
-      return null;
-    }
-
-
-
-    // Create the child managed object.
-    private void createDefaultManagedObject(ManagedObjectDefinition<?, ?> d,
-        ManagedObject<?> child, DefaultManagedObject<?, ?> dmo) {
-      for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
-        setPropertyValues(child, pd, dmo);
-      }
-
-      try {
-        child.commit();
-      } catch (AuthorizationException e) {
-        ae = e;
-      } catch (ManagedObjectAlreadyExistsException e) {
-        moaee = e;
-      } catch (MissingMandatoryPropertiesException e) {
-        mmpe = e;
-      } catch (ConcurrentModificationException e) {
-        cme = e;
-      } catch (OperationRejectedException e) {
-        ore = e;
-      } catch (CommunicationException e) {
-        ce = e;
-      }
-    }
-
-
-
-    /**
-     * Creates the default managed objects associated with the
-     * provided relation definition.
+     * Creates a new abstract managed object.
      *
-     * @param rd
-     *          The relation definition.
+     * @param d
+     *            The managed object's definition.
+     * @param path
+     *            The managed object's path.
+     * @param properties
+     *            The managed object's properties.
+     * @param existsOnServer
+     *            Indicates whether or not the managed object exists on the
+     *            server (false means the managed object is new and has not been
+     *            committed).
+     * @param namingPropertyDefinition
+     *            Optional naming property definition.
      */
-    private void createDefaultManagedObjects(RelationDefinition<?, ?> rd)
-        throws AuthorizationException, CommunicationException,
-        ConcurrentModificationException, MissingMandatoryPropertiesException,
-        ManagedObjectAlreadyExistsException, OperationRejectedException {
-      rd.accept(this, null);
-
-      if (ae != null) {
-        throw ae;
-      } else if (ce != null) {
-        throw ce;
-      } else if (cme != null) {
-        throw cme;
-      } else if (mmpe != null) {
-        throw mmpe;
-      } else if (moaee != null) {
-        throw moaee;
-      } else if (ore != null) {
-        throw ore;
-      }
+    protected AbstractManagedObject(ManagedObjectDefinition<T, ? extends Configuration> d,
+            ManagedObjectPath<T, ? extends Configuration> path, PropertySet properties, boolean existsOnServer,
+            PropertyDefinition<?> namingPropertyDefinition) {
+        this.definition = d;
+        this.path = path;
+        this.properties = properties;
+        this.existsOnServer = existsOnServer;
+        this.namingPropertyDefinition = namingPropertyDefinition;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public final void commit() throws ManagedObjectAlreadyExistsException, MissingMandatoryPropertiesException,
+            ConcurrentModificationException, OperationRejectedException, AuthorizationException, CommunicationException {
+        // First make sure all mandatory properties are defined.
+        List<PropertyIsMandatoryException> exceptions = new LinkedList<PropertyIsMandatoryException>();
 
+        for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+            Property<?> p = getProperty(pd);
+            if (pd.hasOption(PropertyOption.MANDATORY) && p.getEffectiveValues().isEmpty()) {
+                exceptions.add(new PropertyIsMandatoryException(pd));
+            }
+        }
 
-    // Set property values.
-    private <PD> void setPropertyValues(ManagedObject<?> mo,
-        PropertyDefinition<PD> pd, DefaultManagedObject<?, ?> dmo) {
-      mo.setPropertyValues(pd, dmo.getPropertyValues(pd));
-    }
-  }
+        if (!exceptions.isEmpty()) {
+            throw new MissingMandatoryPropertiesException(definition.getUserFriendlyName(), exceptions, !existsOnServer);
+        }
 
+        // Now enforce any constraints.
+        List<LocalizableMessage> messages = new LinkedList<LocalizableMessage>();
+        boolean isAcceptable = true;
+        ManagementContext context = getDriver().getManagementContext();
 
+        for (Constraint constraint : definition.getAllConstraints()) {
+            for (ClientConstraintHandler handler : constraint.getClientConstraintHandlers()) {
+                if (existsOnServer) {
+                    if (!handler.isModifyAcceptable(context, this, messages)) {
+                        isAcceptable = false;
+                    }
+                } else {
+                    if (!handler.isAddAcceptable(context, this, messages)) {
+                        isAcceptable = false;
+                    }
+                }
+            }
+            if (!isAcceptable) {
+                break;
+            }
+        }
 
-  // The managed object definition associated with this managed
-  // object.
-  private final ManagedObjectDefinition<T, ? extends Configuration> definition;
+        if (!isAcceptable) {
+            if (existsOnServer) {
+                throw new OperationRejectedException(OperationType.MODIFY, definition.getUserFriendlyName(), messages);
+            } else {
+                throw new OperationRejectedException(OperationType.CREATE, definition.getUserFriendlyName(), messages);
+            }
+        }
 
-  // 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;
-
-  // Optional naming property definition.
-  private final PropertyDefinition<?> namingPropertyDefinition;
-
-  // The path associated with this managed object.
-  private ManagedObjectPath<T, ? extends Configuration> path;
-
-  // The managed object's properties.
-  private final PropertySet properties;
-
-
-
-  /**
-   * Creates a new abstract managed object.
-   *
-   * @param d
-   *          The managed object's definition.
-   * @param path
-   *          The managed object's path.
-   * @param properties
-   *          The managed object's properties.
-   * @param existsOnServer
-   *          Indicates whether or not the managed object exists on
-   *          the server (false means the managed object is new and
-   *          has not been committed).
-   * @param namingPropertyDefinition
-   *          Optional naming property definition.
-   */
-  protected AbstractManagedObject(
-      ManagedObjectDefinition<T, ? extends Configuration> d,
-      ManagedObjectPath<T, ? extends Configuration> path,
-      PropertySet properties, boolean existsOnServer,
-      PropertyDefinition<?> namingPropertyDefinition) {
-    this.definition = d;
-    this.path = path;
-    this.properties = properties;
-    this.existsOnServer = existsOnServer;
-    this.namingPropertyDefinition = namingPropertyDefinition;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final void commit() throws ManagedObjectAlreadyExistsException,
-      MissingMandatoryPropertiesException, ConcurrentModificationException,
-      OperationRejectedException, AuthorizationException,
-      CommunicationException {
-    // First make sure all mandatory properties are defined.
-    List<PropertyIsMandatoryException> exceptions =
-      new LinkedList<PropertyIsMandatoryException>();
-
-    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
-      Property<?> p = getProperty(pd);
-      if (pd.hasOption(PropertyOption.MANDATORY)
-          && p.getEffectiveValues().isEmpty()) {
-        exceptions.add(new PropertyIsMandatoryException(pd));
-      }
-    }
-
-    if (!exceptions.isEmpty()) {
-      throw new MissingMandatoryPropertiesException(definition
-          .getUserFriendlyName(), exceptions, !existsOnServer);
-    }
-
-    // Now enforce any constraints.
-    List<Message> messages = new LinkedList<Message>();
-    boolean isAcceptable = true;
-    ManagementContext context = getDriver().getManagementContext();
-
-    for (Constraint constraint : definition.getAllConstraints()) {
-      for (ClientConstraintHandler handler : constraint
-          .getClientConstraintHandlers()) {
+        // Commit the managed object.
         if (existsOnServer) {
-          if (!handler.isModifyAcceptable(context, this, messages)) {
-            isAcceptable = false;
-          }
+            modifyExistingManagedObject();
         } else {
-          if (!handler.isAddAcceptable(context, this, messages)) {
-            isAcceptable = false;
-          }
+            addNewManagedObject();
         }
-      }
-      if (!isAcceptable) {
-        break;
-      }
-    }
 
-    if (!isAcceptable) {
-      if (existsOnServer) {
-        throw new OperationRejectedException(OperationType.MODIFY, definition
-            .getUserFriendlyName(), messages);
-      } else {
-        throw new OperationRejectedException(OperationType.CREATE, definition
-            .getUserFriendlyName(), messages);
-      }
-    }
+        // Make all pending property values active.
+        properties.commit();
 
-    // Commit the managed object.
-    if (existsOnServer) {
-      modifyExistingManagedObject();
-    } else {
-      addNewManagedObject();
-    }
+        // If the managed object was created make sure that any default
+        // subordinate managed objects are also created.
+        if (!existsOnServer) {
+            DefaultManagedObjectFactory factory = new DefaultManagedObjectFactory();
+            for (RelationDefinition<?, ?> rd : definition.getAllRelationDefinitions()) {
+                factory.createDefaultManagedObjects(rd);
+            }
 
-    // Make all pending property values active.
-    properties.commit();
-
-    // If the managed object was created make sure that any default
-    // subordinate managed objects are also created.
-    if (!existsOnServer) {
-      DefaultManagedObjectFactory factory = new DefaultManagedObjectFactory();
-      for (RelationDefinition<?, ?> rd :
-          definition.getAllRelationDefinitions()) {
-        factory.createDefaultManagedObjects(rd);
-      }
-
-      existsOnServer = true;
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration,
-                CC extends C>
-  ManagedObject<CC> createChild(
-      InstantiableRelationDefinition<C, S> r,
-      ManagedObjectDefinition<CC, ? extends S> d, String name,
-      Collection<DefaultBehaviorException> exceptions)
-      throws IllegalManagedObjectNameException, IllegalArgumentException {
-    validateRelationDefinition(r);
-
-    // Empty names are not allowed.
-    if (name.trim().length() == 0) {
-      throw new IllegalManagedObjectNameException(name);
-    }
-
-    // If the relation uses a naming property definition then it must
-    // be a valid value.
-    PropertyDefinition<?> pd = r.getNamingPropertyDefinition();
-    if (pd != null) {
-      try {
-        pd.decodeValue(name);
-      } catch (IllegalPropertyValueStringException e) {
-        throw new IllegalManagedObjectNameException(name, pd);
-      }
-    }
-
-    ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d, name);
-    return createNewManagedObject(d, childPath, pd, name, exceptions);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient,
-                S extends Configuration, CC extends C>
-  ManagedObject<CC> createChild(
-      OptionalRelationDefinition<C, S> r,
-      ManagedObjectDefinition<CC, ? extends S> d,
-      Collection<DefaultBehaviorException> exceptions)
-      throws IllegalArgumentException {
-    validateRelationDefinition(r);
-    ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d);
-    return createNewManagedObject(d, childPath, null, null, exceptions);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration,
-                CC extends C>
-  ManagedObject<CC> createChild(
-      SetRelationDefinition<C, S> r,
-      ManagedObjectDefinition<CC, ? extends S> d,
-      Collection<DefaultBehaviorException> exceptions)
-      throws IllegalArgumentException {
-    validateRelationDefinition(r);
-
-    ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d);
-    return createNewManagedObject(d, childPath, null, null, exceptions);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  ManagedObject<? extends C> getChild(
-      InstantiableRelationDefinition<C, S> r, String name)
-      throws IllegalArgumentException, DefinitionDecodingException,
-      ManagedObjectDecodingException, ManagedObjectNotFoundException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    validateRelationDefinition(r);
-    ensureThisManagedObjectExists();
-    Driver ctx = getDriver();
-    return ctx.getManagedObject(path.child(r, name));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  ManagedObject<? extends C> getChild(
-      OptionalRelationDefinition<C, S> r) throws IllegalArgumentException,
-      DefinitionDecodingException, ManagedObjectDecodingException,
-      ManagedObjectNotFoundException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    ensureThisManagedObjectExists();
-    Driver ctx = getDriver();
-    return ctx.getManagedObject(path.child(r));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  ManagedObject<? extends C> getChild(
-      SingletonRelationDefinition<C, S> r) throws IllegalArgumentException,
-      DefinitionDecodingException, ManagedObjectDecodingException,
-      ManagedObjectNotFoundException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    ensureThisManagedObjectExists();
-    Driver ctx = getDriver();
-    return ctx.getManagedObject(path.child(r));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  ManagedObject<? extends C> getChild(
-      SetRelationDefinition<C, S> r, String name)
-      throws IllegalArgumentException, DefinitionDecodingException,
-      ManagedObjectDecodingException, ManagedObjectNotFoundException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    validateRelationDefinition(r);
-    ensureThisManagedObjectExists();
-    Driver ctx = getDriver();
-
-    AbstractManagedObjectDefinition<C, S> d = r.getChildDefinition();
-    AbstractManagedObjectDefinition<? extends C, ? extends S> cd;
-
-    try
-    {
-      cd = d.getChild(name);
-    }
-    catch (IllegalArgumentException e)
-    {
-      // Unrecognized definition name - report this as a decoding
-      // exception.
-      throw new DefinitionDecodingException(d,
-          Reason.WRONG_TYPE_INFORMATION);
-    }
-
-    return ctx.getManagedObject(path.child(r, cd));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final T getConfiguration() {
-    return definition.createClientConfiguration(this);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final ManagedObjectDefinition<T, ? extends Configuration>
-  getManagedObjectDefinition() {
-    return definition;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final ManagedObjectPath<T, ? extends Configuration>
-  getManagedObjectPath() {
-    return path;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <PD> SortedSet<PD> getPropertyDefaultValues(
-      PropertyDefinition<PD> pd) throws IllegalArgumentException {
-    return new TreeSet<PD>(getProperty(pd).getDefaultValues());
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <PD> PD getPropertyValue(PropertyDefinition<PD> pd)
-      throws IllegalArgumentException {
-    Set<PD> values = getProperty(pd).getEffectiveValues();
-    if (values.isEmpty()) {
-      return null;
-    } else {
-      return values.iterator().next();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <PD> SortedSet<PD> getPropertyValues(PropertyDefinition<PD> pd)
-      throws IllegalArgumentException {
-    return new TreeSet<PD>(getProperty(pd).getEffectiveValues());
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  boolean hasChild(
-      OptionalRelationDefinition<C, S> r) throws IllegalArgumentException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    try {
-      return ctx.managedObjectExists(path.child(r));
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final boolean isPropertyPresent(PropertyDefinition<?> pd)
-      throws IllegalArgumentException {
-    return !getProperty(pd).isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  String[] listChildren(
-      InstantiableRelationDefinition<C, S> r) throws IllegalArgumentException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    return listChildren(r, r.getChildDefinition());
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  String[] listChildren(
-      InstantiableRelationDefinition<C, S> r,
-      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
-      throws IllegalArgumentException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    try {
-      return ctx.listManagedObjects(path, r, d);
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  String[] listChildren(
-      SetRelationDefinition<C, S> r) throws IllegalArgumentException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    return listChildren(r, r.getChildDefinition());
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  String[] listChildren(
-      SetRelationDefinition<C, S> r,
-      AbstractManagedObjectDefinition<? extends C, ? extends S> d)
-      throws IllegalArgumentException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    try {
-      return ctx.listManagedObjects(path, r, d);
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  void removeChild(
-      InstantiableRelationDefinition<C, S> r, String name)
-      throws IllegalArgumentException, ManagedObjectNotFoundException,
-      OperationRejectedException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    boolean found;
-
-    try {
-      found = ctx.deleteManagedObject(path, r, name);
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-
-    if (!found) {
-      throw new ManagedObjectNotFoundException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  void removeChild(
-      OptionalRelationDefinition<C, S> r) throws IllegalArgumentException,
-      ManagedObjectNotFoundException, OperationRejectedException,
-      ConcurrentModificationException, AuthorizationException,
-      CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    boolean found;
-
-    try {
-      found = ctx.deleteManagedObject(path, r);
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-
-    if (!found) {
-      throw new ManagedObjectNotFoundException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <C extends ConfigurationClient, S extends Configuration>
-  void removeChild(
-      SetRelationDefinition<C, S> r, String name)
-      throws IllegalArgumentException, ManagedObjectNotFoundException,
-      OperationRejectedException, ConcurrentModificationException,
-      AuthorizationException, CommunicationException {
-    validateRelationDefinition(r);
-    Driver ctx = getDriver();
-    boolean found;
-
-    try {
-      found = ctx.deleteManagedObject(path, r, name);
-    } catch (ManagedObjectNotFoundException e) {
-      throw new ConcurrentModificationException();
-    }
-
-    if (!found) {
-      throw new ManagedObjectNotFoundException();
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <PD> void setPropertyValue(PropertyDefinition<PD> pd, PD value)
-      throws IllegalPropertyValueException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
-    if (value == null) {
-      setPropertyValues(pd, Collections.<PD> emptySet());
-    } else {
-      setPropertyValues(pd, Collections.singleton(value));
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final <PD> void setPropertyValues(PropertyDefinition<PD> pd,
-      Collection<PD> values) throws IllegalPropertyValueException,
-      PropertyIsSingleValuedException, PropertyIsReadOnlyException,
-      PropertyIsMandatoryException, IllegalArgumentException {
-    if (pd.hasOption(PropertyOption.MONITORING)) {
-      throw new PropertyIsReadOnlyException(pd);
-    }
-
-    if (existsOnServer && pd.hasOption(PropertyOption.READ_ONLY)) {
-      throw new PropertyIsReadOnlyException(pd);
-    }
-
-    properties.setPropertyValues(pd, values);
-
-    // If this is a naming property then update the name.
-    if (pd.equals(namingPropertyDefinition)) {
-      // The property must be single-valued and mandatory.
-      String newName = pd.encodeValue(values.iterator().next());
-      path = path.rename(newName);
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-
-    builder.append("{ TYPE=");
-    builder.append(definition.getName());
-    builder.append(", PATH=\"");
-    builder.append(path);
-    builder.append('\"');
-    for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
-      builder.append(", ");
-      builder.append(pd.getName());
-      builder.append('=');
-      builder.append(getPropertyValues(pd));
-    }
-    builder.append(" }");
-
-    return builder.toString();
-  }
-
-
-
-  /**
-   * Adds this new managed object.
-   *
-   * @throws ManagedObjectAlreadyExistsException
-   *           If the managed object cannot be added to the server
-   *           because it already exists.
-   * @throws ConcurrentModificationException
-   *           If the managed object's parent has been removed by
-   *           another client.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be added due to some
-   *           client-side or server-side constraint which cannot be
-   *           satisfied.
-   * @throws AuthorizationException
-   *           If the server refuses to add 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.
-   */
-  protected abstract void addNewManagedObject() throws AuthorizationException,
-      CommunicationException, OperationRejectedException,
-      ConcurrentModificationException, ManagedObjectAlreadyExistsException;
-
-
-
-  /**
-   * Gets the management context driver associated with this managed
-   * object.
-   *
-   * @return Returns the management context driver associated with
-   *         this managed object.
-   */
-  protected abstract Driver getDriver();
-
-
-
-  /**
-   * Gets the naming property definition associated with this managed
-   * object.
-   *
-   * @return Returns the naming property definition associated with
-   *         this managed object, or <code>null</code> if this
-   *         managed object does not have a naming property.
-   */
-  protected final PropertyDefinition<?> getNamingPropertyDefinition() {
-    return namingPropertyDefinition;
-  }
-
-
-
-  /**
-   * Gets the property associated with the specified property
-   * definition.
-   *
-   * @param <PD>
-   *          The underlying type of the property.
-   * @param pd
-   *          The Property definition.
-   * @return Returns the property associated with the specified
-   *         property definition.
-   * @throws IllegalArgumentException
-   *           If this property provider does not recognize the
-   *           requested property definition.
-   */
-  protected final <PD> Property<PD> getProperty(PropertyDefinition<PD> pd)
-      throws IllegalArgumentException {
-    return properties.getProperty(pd);
-  }
-
-
-
-  /**
-   * Applies changes made to this managed object.
-   *
-   * @throws ConcurrentModificationException
-   *           If this managed object has been removed from the server
-   *           by another client.
-   * @throws OperationRejectedException
-   *           If the managed object cannot be added due to some
-   *           client-side or server-side constraint which cannot be
-   *           satisfied.
-   * @throws AuthorizationException
-   *           If the server refuses to 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.
-   */
-  protected abstract void modifyExistingManagedObject()
-      throws ConcurrentModificationException, OperationRejectedException,
-      AuthorizationException, CommunicationException;
-
-
-
-  /**
-   * Creates a new managed object.
-   *
-   * @param <M>
-   *          The type of client configuration represented by the
-   *          client managed object.
-   * @param d
-   *          The managed object's definition.
-   * @param path
-   *          The managed object's path.
-   * @param properties
-   *          The managed object's properties.
-   * @param existsOnServer
-   *          Indicates whether or not the managed object exists on
-   *          the server (false means the managed object is new and
-   *          has not been committed).
-   * @param namingPropertyDefinition
-   *          Optional naming property definition.
-   * @return Returns the new managed object.
-   */
-  protected abstract <M extends ConfigurationClient>
-  ManagedObject<M> newInstance(
-      ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> path,
-      PropertySet properties, boolean existsOnServer,
-      PropertyDefinition<?> namingPropertyDefinition);
-
-
-
-  // Creates a new managed object with no active values, just default
-  // values.
-  private <M extends ConfigurationClient, PD> ManagedObject<M>
-  createNewManagedObject(
-      ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> p,
-      PropertyDefinition<PD> namingPropertyDefinition, String name,
-      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);
+            existsOnServer = true;
         }
-      }
     }
 
-    // Set the naming property if there is one.
-    if (namingPropertyDefinition != null) {
-      PD value = namingPropertyDefinition.decodeValue(name);
-      childProperties.setPropertyValues(namingPropertyDefinition, Collections
-          .singleton(value));
-    }
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration, CC extends C> ManagedObject<CC> createChild(
+            InstantiableRelationDefinition<C, S> r, ManagedObjectDefinition<CC, ? extends S> d, String name,
+            Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException,
+            IllegalArgumentException {
+        validateRelationDefinition(r);
 
-    return newInstance(d, p, childProperties, false, namingPropertyDefinition);
-  }
-
-
-
-  // Create an empty property.
-  private <PD> void createProperty(PropertySet properties,
-      ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd)
-      throws DefaultBehaviorException {
-    try {
-      Driver context = getDriver();
-      Collection<PD> defaultValues = context.findDefaultValues(p, pd, true);
-      properties.addProperty(pd, defaultValues, Collections.<PD> emptySet());
-    } catch (DefaultBehaviorException e) {
-      // Make sure that we have still created the property.
-      properties.addProperty(pd, Collections.<PD> emptySet(), Collections
-          .<PD> emptySet());
-      throw e;
-    }
-  }
-
-
-
-  // Makes sure that this managed object exists.
-  private void ensureThisManagedObjectExists()
-      throws ConcurrentModificationException, CommunicationException,
-      AuthorizationException {
-    if (!path.isEmpty()) {
-      Driver ctx = getDriver();
-
-      try {
-        if (!ctx.managedObjectExists(path)) {
-          throw new ConcurrentModificationException();
+        // Empty names are not allowed.
+        if (name.trim().length() == 0) {
+            throw new IllegalManagedObjectNameException(name);
         }
-      } catch (ManagedObjectNotFoundException e) {
-        throw new ConcurrentModificationException();
-      }
+
+        // If the relation uses a naming property definition then it must
+        // be a valid value.
+        PropertyDefinition<?> pd = r.getNamingPropertyDefinition();
+        if (pd != null) {
+            try {
+                pd.decodeValue(name);
+            } catch (IllegalPropertyValueStringException e) {
+                throw new IllegalManagedObjectNameException(name, pd);
+            }
+        }
+
+        ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d, name);
+        return createNewManagedObject(d, childPath, pd, name, exceptions);
     }
-  }
 
-
-
-  // Validate that a relation definition belongs to this managed
-  // object.
-  private void validateRelationDefinition(RelationDefinition<?, ?> rd)
-      throws IllegalArgumentException {
-    ManagedObjectDefinition<T, ?> d = getManagedObjectDefinition();
-    RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
-    if (tmp != rd) {
-      throw new IllegalArgumentException("The relation " + rd.getName()
-          + " is not associated with a " + d.getName());
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration, CC extends C> ManagedObject<CC> createChild(
+            OptionalRelationDefinition<C, S> r, ManagedObjectDefinition<CC, ? extends S> d,
+            Collection<DefaultBehaviorException> exceptions) throws IllegalArgumentException {
+        validateRelationDefinition(r);
+        ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d);
+        return createNewManagedObject(d, childPath, null, null, exceptions);
     }
-  }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration, CC extends C> ManagedObject<CC> createChild(
+            SetRelationDefinition<C, S> r, ManagedObjectDefinition<CC, ? extends S> d,
+            Collection<DefaultBehaviorException> exceptions) throws IllegalArgumentException {
+        validateRelationDefinition(r);
+
+        ManagedObjectPath<CC, ? extends S> childPath = path.child(r, d);
+        return createNewManagedObject(d, childPath, null, null, exceptions);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
+            InstantiableRelationDefinition<C, S> r, String name) throws IllegalArgumentException,
+            DefinitionDecodingException, ManagedObjectDecodingException, ManagedObjectNotFoundException,
+            ConcurrentModificationException, AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        ensureThisManagedObjectExists();
+        Driver ctx = getDriver();
+        return ctx.getManagedObject(path.child(r, name));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
+            OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, DefinitionDecodingException,
+            ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        ensureThisManagedObjectExists();
+        Driver ctx = getDriver();
+        return ctx.getManagedObject(path.child(r));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
+            SingletonRelationDefinition<C, S> r) throws IllegalArgumentException, DefinitionDecodingException,
+            ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        ensureThisManagedObjectExists();
+        Driver ctx = getDriver();
+        return ctx.getManagedObject(path.child(r));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> ManagedObject<? extends C> getChild(
+            SetRelationDefinition<C, S> r, String name) throws IllegalArgumentException, DefinitionDecodingException,
+            ManagedObjectDecodingException, ManagedObjectNotFoundException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        ensureThisManagedObjectExists();
+        Driver ctx = getDriver();
+
+        AbstractManagedObjectDefinition<C, S> d = r.getChildDefinition();
+        AbstractManagedObjectDefinition<? extends C, ? extends S> cd;
+
+        try {
+            cd = d.getChild(name);
+        } catch (IllegalArgumentException e) {
+            // Unrecognized definition name - report this as a decoding
+            // exception.
+            throw new DefinitionDecodingException(d, Reason.WRONG_TYPE_INFORMATION);
+        }
+
+        return ctx.getManagedObject(path.child(r, cd));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final T getConfiguration() {
+        return definition.createClientConfiguration(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final ManagedObjectDefinition<T, ? extends Configuration> getManagedObjectDefinition() {
+        return definition;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final ManagedObjectPath<T, ? extends Configuration> getManagedObjectPath() {
+        return path;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <PD> SortedSet<PD> getPropertyDefaultValues(PropertyDefinition<PD> pd) throws IllegalArgumentException {
+        return new TreeSet<PD>(getProperty(pd).getDefaultValues());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <PD> PD getPropertyValue(PropertyDefinition<PD> pd) throws IllegalArgumentException {
+        Set<PD> values = getProperty(pd).getEffectiveValues();
+        if (values.isEmpty()) {
+            return null;
+        } else {
+            return values.iterator().next();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <PD> SortedSet<PD> getPropertyValues(PropertyDefinition<PD> pd) throws IllegalArgumentException {
+        return new TreeSet<PD>(getProperty(pd).getEffectiveValues());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> boolean hasChild(
+            OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        try {
+            return ctx.managedObjectExists(path.child(r));
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final boolean isPropertyPresent(PropertyDefinition<?> pd) throws IllegalArgumentException {
+        return !getProperty(pd).isEmpty();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
+            InstantiableRelationDefinition<C, S> r) throws IllegalArgumentException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        return listChildren(r, r.getChildDefinition());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
+            InstantiableRelationDefinition<C, S> r, AbstractManagedObjectDefinition<? extends C, ? extends S> d)
+            throws IllegalArgumentException, ConcurrentModificationException, AuthorizationException,
+            CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        try {
+            return ctx.listManagedObjects(path, r, d);
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
+            SetRelationDefinition<C, S> r) throws IllegalArgumentException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        return listChildren(r, r.getChildDefinition());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> String[] listChildren(
+            SetRelationDefinition<C, S> r, AbstractManagedObjectDefinition<? extends C, ? extends S> d)
+            throws IllegalArgumentException, ConcurrentModificationException, AuthorizationException,
+            CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        try {
+            return ctx.listManagedObjects(path, r, d);
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
+            InstantiableRelationDefinition<C, S> r, String name) throws IllegalArgumentException,
+            ManagedObjectNotFoundException, OperationRejectedException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        boolean found;
+
+        try {
+            found = ctx.deleteManagedObject(path, r, name);
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+
+        if (!found) {
+            throw new ManagedObjectNotFoundException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
+            OptionalRelationDefinition<C, S> r) throws IllegalArgumentException, ManagedObjectNotFoundException,
+            OperationRejectedException, ConcurrentModificationException, AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        boolean found;
+
+        try {
+            found = ctx.deleteManagedObject(path, r);
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+
+        if (!found) {
+            throw new ManagedObjectNotFoundException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <C extends ConfigurationClient, S extends Configuration> void removeChild(
+            SetRelationDefinition<C, S> r, String name) throws IllegalArgumentException,
+            ManagedObjectNotFoundException, OperationRejectedException, ConcurrentModificationException,
+            AuthorizationException, CommunicationException {
+        validateRelationDefinition(r);
+        Driver ctx = getDriver();
+        boolean found;
+
+        try {
+            found = ctx.deleteManagedObject(path, r, name);
+        } catch (ManagedObjectNotFoundException e) {
+            throw new ConcurrentModificationException();
+        }
+
+        if (!found) {
+            throw new ManagedObjectNotFoundException();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <PD> void setPropertyValue(PropertyDefinition<PD> pd, PD value) throws IllegalPropertyValueException,
+            PropertyIsReadOnlyException, PropertyIsMandatoryException, IllegalArgumentException {
+        if (value == null) {
+            setPropertyValues(pd, Collections.<PD> emptySet());
+        } else {
+            setPropertyValues(pd, Collections.singleton(value));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public final <PD> void setPropertyValues(PropertyDefinition<PD> pd, Collection<PD> values)
+            throws IllegalPropertyValueException, PropertyIsSingleValuedException, PropertyIsReadOnlyException,
+            PropertyIsMandatoryException, IllegalArgumentException {
+        if (pd.hasOption(PropertyOption.MONITORING)) {
+            throw new PropertyIsReadOnlyException(pd);
+        }
+
+        if (existsOnServer && pd.hasOption(PropertyOption.READ_ONLY)) {
+            throw new PropertyIsReadOnlyException(pd);
+        }
+
+        properties.setPropertyValues(pd, values);
+
+        // If this is a naming property then update the name.
+        if (pd.equals(namingPropertyDefinition)) {
+            // The property must be single-valued and mandatory.
+            String newName = pd.encodeValue(values.iterator().next());
+            path = path.rename(newName);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append("{ TYPE=");
+        builder.append(definition.getName());
+        builder.append(", PATH=\"");
+        builder.append(path);
+        builder.append('\"');
+        for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+            builder.append(", ");
+            builder.append(pd.getName());
+            builder.append('=');
+            builder.append(getPropertyValues(pd));
+        }
+        builder.append(" }");
+
+        return builder.toString();
+    }
+
+    /**
+     * Adds this new managed object.
+     *
+     * @throws ManagedObjectAlreadyExistsException
+     *             If the managed object cannot be added to the server because
+     *             it already exists.
+     * @throws ConcurrentModificationException
+     *             If the managed object's parent has been removed by another
+     *             client.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be added due to some client-side
+     *             or server-side constraint which cannot be satisfied.
+     * @throws AuthorizationException
+     *             If the server refuses to add 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.
+     */
+    protected abstract void addNewManagedObject() throws AuthorizationException, CommunicationException,
+            OperationRejectedException, ConcurrentModificationException, ManagedObjectAlreadyExistsException;
+
+    /**
+     * Gets the management context driver associated with this managed object.
+     *
+     * @return Returns the management context driver associated with this
+     *         managed object.
+     */
+    protected abstract Driver getDriver();
+
+    /**
+     * Gets the naming property definition associated with this managed object.
+     *
+     * @return Returns the naming property definition associated with this
+     *         managed object, or <code>null</code> if this managed object does
+     *         not have a naming property.
+     */
+    protected final PropertyDefinition<?> getNamingPropertyDefinition() {
+        return namingPropertyDefinition;
+    }
+
+    /**
+     * Gets the property associated with the specified property definition.
+     *
+     * @param <PD>
+     *            The underlying type of the property.
+     * @param pd
+     *            The Property definition.
+     * @return Returns the property associated with the specified property
+     *         definition.
+     * @throws IllegalArgumentException
+     *             If this property provider does not recognize the requested
+     *             property definition.
+     */
+    protected final <PD> Property<PD> getProperty(PropertyDefinition<PD> pd) throws IllegalArgumentException {
+        return properties.getProperty(pd);
+    }
+
+    /**
+     * Applies changes made to this managed object.
+     *
+     * @throws ConcurrentModificationException
+     *             If this managed object has been removed from the server by
+     *             another client.
+     * @throws OperationRejectedException
+     *             If the managed object cannot be added due to some client-side
+     *             or server-side constraint which cannot be satisfied.
+     * @throws AuthorizationException
+     *             If the server refuses to 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.
+     */
+    protected abstract void modifyExistingManagedObject() throws ConcurrentModificationException,
+            OperationRejectedException, AuthorizationException, CommunicationException;
+
+    /**
+     * Creates a new managed object.
+     *
+     * @param <M>
+     *            The type of client configuration represented by the client
+     *            managed object.
+     * @param d
+     *            The managed object's definition.
+     * @param path
+     *            The managed object's path.
+     * @param properties
+     *            The managed object's properties.
+     * @param existsOnServer
+     *            Indicates whether or not the managed object exists on the
+     *            server (false means the managed object is new and has not been
+     *            committed).
+     * @param namingPropertyDefinition
+     *            Optional naming property definition.
+     * @return Returns the new managed object.
+     */
+    protected abstract <M extends ConfigurationClient> ManagedObject<M> newInstance(ManagedObjectDefinition<M, ?> d,
+            ManagedObjectPath<M, ?> path, PropertySet properties, boolean existsOnServer,
+            PropertyDefinition<?> namingPropertyDefinition);
+
+    // Creates a new managed object with no active values, just default
+    // values.
+    private <M extends ConfigurationClient, PD> ManagedObject<M> createNewManagedObject(
+            ManagedObjectDefinition<M, ?> d, ManagedObjectPath<M, ?> p,
+            PropertyDefinition<PD> namingPropertyDefinition, String name,
+            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);
+                }
+            }
+        }
+
+        // Set the naming property if there is one.
+        if (namingPropertyDefinition != null) {
+            PD value = namingPropertyDefinition.decodeValue(name);
+            childProperties.setPropertyValues(namingPropertyDefinition, Collections.singleton(value));
+        }
+
+        return newInstance(d, p, childProperties, false, namingPropertyDefinition);
+    }
+
+    // Create an empty property.
+    private <PD> void createProperty(PropertySet properties, ManagedObjectPath<?, ?> p, PropertyDefinition<PD> pd)
+            throws DefaultBehaviorException {
+        try {
+            Driver context = getDriver();
+            Collection<PD> defaultValues = context.findDefaultValues(p, pd, true);
+            properties.addProperty(pd, defaultValues, Collections.<PD> emptySet());
+        } catch (DefaultBehaviorException e) {
+            // Make sure that we have still created the property.
+            properties.addProperty(pd, Collections.<PD> emptySet(), Collections.<PD> emptySet());
+            throw e;
+        }
+    }
+
+    // Makes sure that this managed object exists.
+    private void ensureThisManagedObjectExists() throws ConcurrentModificationException, CommunicationException,
+            AuthorizationException {
+        if (!path.isEmpty()) {
+            Driver ctx = getDriver();
+
+            try {
+                if (!ctx.managedObjectExists(path)) {
+                    throw new ConcurrentModificationException();
+                }
+            } catch (ManagedObjectNotFoundException e) {
+                throw new ConcurrentModificationException();
+            }
+        }
+    }
+
+    // Validate that a relation definition belongs to this managed
+    // object.
+    private void validateRelationDefinition(RelationDefinition<?, ?> rd) throws IllegalArgumentException {
+        ManagedObjectDefinition<T, ?> d = getManagedObjectDefinition();
+        RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
+        if (tmp != rd) {
+            throw new IllegalArgumentException("The relation " + rd.getName() + " is not associated with a "
+                    + d.getName());
+        }
+    }
 
 }

--
Gitblit v1.10.0