From c2d0d212b510d8e82b9b123b4d06a80b835c8cd4 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Fri, 06 Dec 2013 16:52:01 +0000
Subject: [PATCH] OpenDJ 3 : config framework

---
 opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java | 2375 ++++++++++++++++++++++++++---------------------------------
 1 files changed, 1,055 insertions(+), 1,320 deletions(-)

diff --git a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
index a38d04a..c6c7144 100644
--- a/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
+++ b/opendj-admin/src/main/java/org/opends/server/admin/ManagedObjectPath.java
@@ -28,8 +28,6 @@
 
 package org.opends.server.admin;
 
-
-
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -43,67 +41,58 @@
 import org.forgerock.opendj.ldap.RDN;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.DirectoryException;
-
 
 /**
- * A path which can be used to determine the location of a managed
- * object instance.
+ * 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.
+ * 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.
+ * {@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:
+ * 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
- * <li>an element representing a managed object associated with a
- * one-to-many (set) 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.
+ * <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
+ * <li>an element representing a managed object associated with a one-to-many
+ * (set) 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.
  * </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):
+ * 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>:
+ * 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
@@ -116,1333 +105,1079 @@
  * </pre>
  *
  * @param <C>
- *          The type of client managed object configuration that this
- *          path references.
+ *            The type of client managed object configuration that this path
+ *            references.
  * @param <S>
- *          The type of server managed object configuration that this
- *          path references.
+ *            The type of server managed object configuration that this path
+ *            references.
  */
-public final class ManagedObjectPath<C extends ConfigurationClient,
-    S extends Configuration> {
-
-  /**
-   * A serialize which is used to generate the toDN representation.
-   */
-  private static final class DNSerializer implements
-      ManagedObjectPathSerializer {
-
-    // The current DN.
-    private DN dn;
-
-    // The LDAP profile.
-    private final LDAPProfile profile;
-
-
-
-    // Create a new DN builder.
-    private DNSerializer() {
-      this.dn = DN.rootDN();
-      this.profile = LDAPProfile.getInstance();
-    }
-
-
+public final class ManagedObjectPath<C extends ConfigurationClient, S extends Configuration> {
 
     /**
-     * {@inheritDoc}
+     * A serialize which is used to generate the toDN representation.
      */
-    public <C extends ConfigurationClient, S extends Configuration>
-    void appendManagedObjectPathElement(
-        InstantiableRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d, String name) {
-      // Add the RDN sequence representing the relation.
-      appendManagedObjectPathElement(r);
+    private static final class DNSerializer implements ManagedObjectPathSerializer {
 
-      // Now add the single RDN representing the named instance.
-      String type = profile.getRelationChildRDNType(r);
-      AttributeType atype = DirectoryServer.getAttributeType(
-          type.toLowerCase(), true);
-      AttributeValue avalue = AttributeValues.create(atype, name);
-      dn = dn.concat(RDN.create(atype, avalue));
+        // The current DN.
+        private DN dn;
+
+        // The LDAP profile.
+        private final LDAPProfile profile;
+
+        // Create a new DN builder.
+        private DNSerializer() {
+            this.dn = DN.rootDN();
+            this.profile = LDAPProfile.getInstance();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+                InstantiableRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d,
+                String name) {
+            // Add the RDN sequence representing the relation.
+            appendManagedObjectPathElement(r);
+
+            // Now add the single RDN representing the named instance.
+            String type = profile.getRelationChildRDNType(r);
+            AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true);
+            dn = dn.child(new RDN(attrType, name));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+                SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+            // Add the RDN sequence representing the relation.
+            appendManagedObjectPathElement(r);
+
+            // Now add the single RDN representing the instance.
+            String type = profile.getRelationChildRDNType(r);
+            AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true);
+            dn = dn.child(new RDN(attrType, d.getName()));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+                OptionalRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+            // Add the RDN sequence representing the relation.
+            appendManagedObjectPathElement(r);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement(
+                SingletonRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+            // Add the RDN sequence representing the relation.
+            appendManagedObjectPathElement(r);
+        }
+
+        // Appends the RDN sequence representing the provided relation.
+        private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
+            DN localName = DN.valueOf(profile.getRelationRDNSequence(r));
+            dn = dn.child(localName);
+        }
+
+        // Gets the serialized DN value.
+        private DN toDN() {
+            return dn;
+        }
     }
 
-
-
     /**
-     * {@inheritDoc}
+     * Abstract path element.
      */
-    public <C extends ConfigurationClient, S extends Configuration>
-    void appendManagedObjectPathElement(
-        SetRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      // Add the RDN sequence representing the relation.
-      appendManagedObjectPathElement(r);
+    private static abstract class Element<C extends ConfigurationClient, S extends Configuration> {
 
-      // Now add the single RDN representing the instance.
-      String type = profile.getRelationChildRDNType(r);
-      AttributeType atype = DirectoryServer.getAttributeType(
-          type.toLowerCase(), true);
-      AttributeValue avalue = AttributeValues.create(atype, d.getName());
-      dn = dn.concat(RDN.create(atype, avalue));
+        // The type of managed object referenced by this element.
+        private final AbstractManagedObjectDefinition<C, S> definition;
+
+        /**
+         * Protected constructor.
+         *
+         * @param definition
+         *            The type of managed object referenced by this element.
+         */
+        protected Element(AbstractManagedObjectDefinition<C, S> definition) {
+            this.definition = definition;
+        }
+
+        /**
+         * Get the managed object definition associated with this element.
+         *
+         * @return Returns the managed object definition associated with this
+         *         element.
+         */
+        public final AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
+            return definition;
+        }
+
+        /**
+         * Get the name associated with this element if applicable.
+         *
+         * @return Returns the name associated with this element if applicable.
+         */
+        public String getName() {
+            return null;
+        }
+
+        /**
+         * 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.
+         *
+         * @param serializer
+         *            The managed object path serialization strategy.
+         */
+        public abstract void serialize(ManagedObjectPathSerializer serializer);
     }
 
-
-
     /**
-     * {@inheritDoc}
+     * A path element representing an instantiable managed object.
      */
-    public <C extends ConfigurationClient, S extends Configuration>
-    void appendManagedObjectPathElement(
-        OptionalRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      // Add the RDN sequence representing the relation.
-      appendManagedObjectPathElement(r);
+    private static final class InstantiableElement<C extends ConfigurationClient, S extends Configuration> extends
+            Element<C, S> {
+
+        // Factory method.
+        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) {
+            return new InstantiableElement<C, S>(r, d, name);
+        }
+
+        // The name of the managed object.
+        private final String name;
+
+        // The instantiable relation.
+        private final InstantiableRelationDefinition<? super C, ? super S> r;
+
+        // Private constructor.
+        private InstantiableElement(InstantiableRelationDefinition<? super C, ? super S> r,
+                AbstractManagedObjectDefinition<C, S> d, String name) {
+            super(d);
+            this.r = r;
+            this.name = name;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public InstantiableRelationDefinition<? super C, ? super S> getRelationDefinition() {
+            return r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void serialize(ManagedObjectPathSerializer serializer) {
+            serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition(), name);
+        }
     }
 
-
-
     /**
-     * {@inheritDoc}
+     * A path element representing an optional managed object.
      */
-    public <C extends ConfigurationClient, S extends Configuration>
-    void appendManagedObjectPathElement(
-        SingletonRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      // Add the RDN sequence representing the relation.
-      appendManagedObjectPathElement(r);
+    private static final class OptionalElement<C extends ConfigurationClient, S extends Configuration> extends
+            Element<C, S> {
+
+        // Factory method.
+        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);
+        }
+
+        // The optional relation.
+        private final OptionalRelationDefinition<? super C, ? super S> r;
+
+        // Private constructor.
+        private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r,
+                AbstractManagedObjectDefinition<C, S> d) {
+            super(d);
+            this.r = r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public OptionalRelationDefinition<? super C, ? super S> getRelationDefinition() {
+            return r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void serialize(ManagedObjectPathSerializer serializer) {
+            serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+        }
     }
 
-
-
-    // Appends the RDN sequence representing the provided relation.
-    private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) {
-      // Add the RDN sequence representing the relation.
-      try {
-        DN localName = DN.decode(profile.getRelationRDNSequence(r));
-        dn = dn.concat(localName);
-      } catch (DirectoryException e) {
-        throw new RuntimeException(e);
-      }
-    }
-
-
-
-    // Gets the serialized DN value.
-    private DN toDN() {
-      return dn;
-    }
-  }
-
-
-
-  /**
-   * Abstract path element.
-   */
-  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;
-
-
-
     /**
-     * Protected constructor.
+     * A path element representing an set managed object.
+     */
+    private static final class SetElement<C extends ConfigurationClient, S extends Configuration> extends Element<C, S> {
+
+        // Factory method.
+        private static final <C extends ConfigurationClient, S extends Configuration> SetElement<C, S> create(
+                SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+            return new SetElement<C, S>(r, d);
+        }
+
+        // The set relation.
+        private final SetRelationDefinition<? super C, ? super S> r;
+
+        // Private constructor.
+        private SetElement(SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) {
+            super(d);
+            this.r = r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public SetRelationDefinition<? super C, ? super S> getRelationDefinition() {
+            return r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void serialize(ManagedObjectPathSerializer serializer) {
+            serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+        }
+    }
+
+    /**
+     * A path element representing a singleton managed object.
+     */
+    private static final class SingletonElement<C extends ConfigurationClient, S extends Configuration> extends
+            Element<C, S> {
+
+        // Factory method.
+        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);
+        }
+
+        // The singleton relation.
+        private final SingletonRelationDefinition<? super C, ? super S> r;
+
+        // Private constructor.
+        private SingletonElement(SingletonRelationDefinition<? super C, ? super S> r,
+                AbstractManagedObjectDefinition<C, S> d) {
+            super(d);
+            this.r = r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public SingletonRelationDefinition<? super C, ? super S> getRelationDefinition() {
+            return r;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void serialize(ManagedObjectPathSerializer serializer) {
+            serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition());
+        }
+    }
+
+    /**
+     * A serialize which is used to generate the toString representation.
+     */
+    private static final class StringSerializer implements ManagedObjectPathSerializer {
+
+        // Serialize to this string builder.
+        private final StringBuilder builder;
+
+        // Private constructor.
+        private StringSerializer(StringBuilder builder) {
+            this.builder = builder;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+                InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d,
+                String name) {
+            serializeElement(r, d);
+
+            // Be careful to escape any forward slashes in the name.
+            builder.append("+name=");
+            builder.append(name.replace("/", "//"));
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+                OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+            serializeElement(r, d);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+                SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+            serializeElement(r, d);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement(
+                SetRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+            serializeElement(r, d);
+        }
+
+        // Common element serialization.
+        private <M, N> void serializeElement(RelationDefinition<?, ?> r, AbstractManagedObjectDefinition<?, ?> d) {
+            // Always specify the relation name.
+            builder.append("/relation=");
+            builder.append(r.getName());
+
+            // Only specify the type if it is a sub-type of the relation's
+            // type.
+            if (r.getChildDefinition() != d) {
+                builder.append("+type=");
+                builder.append(d.getName());
+            }
+        }
+    }
+
+    // Single instance of a root path.
+    private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH = 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.compile("^\\s*relation=\\s*([^+]+)\\s*"
+            + "(\\+\\s*type=\\s*([^+]+)\\s*)?" + "(\\+\\s*name=\\s*([^+]+)\\s*)?$");
+
+    /**
+     * Creates a new managed object path representing the configuration root.
      *
-     * @param definition
-     *          The type of managed object referenced by this element.
+     * @return Returns a new managed object path representing the configuration
+     *         root.
      */
-    protected Element(AbstractManagedObjectDefinition<C, S> definition) {
-      this.definition = definition;
+    public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() {
+        return EMPTY_PATH;
     }
 
-
-
     /**
-     * Get the managed object definition associated with this element.
+     * Returns a managed object path holding the value of the specified string.
      *
-     * @return Returns the managed object definition associated with
-     *         this element.
+     * @param s
+     *            The string to be parsed.
+     * @return Returns a managed object path holding the value of the specified
+     *         string.
+     * @throws IllegalArgumentException
+     *             If the string could not be parsed.
      */
-    public final AbstractManagedObjectDefinition<C, S>
-        getManagedObjectDefinition() {
-      return definition;
+    public static ManagedObjectPath<?, ?> valueOf(String s) throws IllegalArgumentException {
+        String ns = s.trim();
+
+        // Check for root special case.
+        if (ns.equals("/")) {
+            return EMPTY_PATH;
+        }
+
+        // Parse the elements.
+        LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
+        Element<?, ?> lastElement = null;
+        AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn.getInstance();
+
+        if (!ns.startsWith("/")) {
+            throw new IllegalArgumentException("Invalid path \"" + ns + "\": must begin with a \"/\"");
+        }
+
+        int start = 1;
+        while (true) {
+            // Get the next path element.
+            int end;
+            for (end = start; end < ns.length(); end++) {
+                char c = ns.charAt(end);
+                if (c == '/') {
+                    if (end == (ns.length() - 1)) {
+                        throw new IllegalArgumentException("Invalid path \"" + ns
+                                + "\": must not end with a trailing \"/\"");
+                    }
+
+                    if (ns.charAt(end + 1) == '/') {
+                        // Found an escaped forward slash.
+                        end++;
+                    } else {
+                        // Found the end of this path element.
+                        break;
+                    }
+                }
+            }
+
+            // Get the next element.
+            String es = ns.substring(start, end);
+
+            Matcher m = PE_REGEXP.matcher(es);
+            if (!m.matches()) {
+                throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns + "\"");
+            }
+
+            // 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;
+            try {
+                r = definition.getRelationDefinition(relation);
+            } catch (IllegalArgumentException e) {
+                throw new IllegalArgumentException("Invalid path element \"" + es + "\" in path \"" + ns
+                        + "\": unknown relation \"" + relation + "\"");
+            }
+
+            // Append the next element.
+            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()) {
+                // Skip to the beginning of the next element
+                start = end + 1;
+            } else {
+                // We reached the end of the string.
+                break;
+            }
+        }
+
+        // Construct the new path.
+        return create(elements, lastElement);
     }
 
+    // Factory method required in order to allow generic wild-card
+    // construction of new paths.
+    private static <C extends ConfigurationClient, S extends Configuration> ManagedObjectPath<C, S> create(
+            LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
+        return new ManagedObjectPath<C, S>(elements, lastElement.getRelationDefinition(),
+                lastElement.getManagedObjectDefinition());
+    }
 
+    // Decode an element.
+    private static <C extends ConfigurationClient, S extends Configuration> Element<? extends C, ? extends S> createElement(
+            RelationDefinition<C, S> r, String path, String element, String type, String name) {
+        // First determine the managed object definition.
+        AbstractManagedObjectDefinition<? extends C, ? extends S> d = null;
+
+        if (type != null) {
+            for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r.getChildDefinition()
+                    .getAllChildren()) {
+                if (child.getName().equals(type)) {
+                    d = child;
+                    break;
+                }
+            }
+
+            if (d == null) {
+                throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                        + "\": unknown sub-type \"" + type + "\"");
+            }
+        } else {
+            d = r.getChildDefinition();
+        }
+
+        if (r instanceof InstantiableRelationDefinition) {
+            InstantiableRelationDefinition<C, S> ir = (InstantiableRelationDefinition<C, S>) r;
+
+            if (name == null) {
+                throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                        + "\": no instance name for instantiable relation");
+            }
+
+            return InstantiableElement.create(ir, d, name);
+        } else if (r instanceof SetRelationDefinition) {
+            SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r;
+
+            if (name != null) {
+                throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                        + "\": instance name specified for set relation");
+            }
+
+            return SetElement.create(ir, d);
+        } else if (r instanceof OptionalRelationDefinition) {
+            OptionalRelationDefinition<C, S> or = (OptionalRelationDefinition<C, S>) r;
+
+            if (name != null) {
+                throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                        + "\": instance name specified for optional relation");
+            }
+
+            return OptionalElement.create(or, d);
+        } else if (r instanceof SingletonRelationDefinition) {
+            SingletonRelationDefinition<C, S> sr = (SingletonRelationDefinition<C, S>) r;
+
+            if (name != null) {
+                throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                        + "\": instance name specified for singleton relation");
+            }
+
+            return SingletonElement.create(sr, d);
+        } else {
+            throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path
+                    + "\": unsupported relation type");
+        }
+    }
+
+    // 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, RelationDefinition<? super C, ? super S> r,
+            AbstractManagedObjectDefinition<C, S> d) {
+        this.elements = Collections.unmodifiableList(elements);
+        this.r = r;
+        this.d = d;
+    }
 
     /**
-     * Get the name associated with this element if applicable.
+     * Creates a new managed object path which has the same structure as this
+     * path except that the final path element is associated with the specified
+     * managed object definition.
      *
-     * @return Returns the name associated with this element if
-     *         applicable.
+     * @param <CC>
+     *            The type of client managed object configuration that this path
+     *            will reference.
+     * @param <SS>
+     *            The type of server managed object configuration that this path
+     *            will reference.
+     * @param nd
+     *            The new managed object definition.
+     * @return Returns a new managed object path which has the same structure as
+     *         this path except that the final path element is associated with
+     *         the specified managed object definition.
+     */
+    @SuppressWarnings("unchecked")
+    public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(AbstractManagedObjectDefinition<CC, SS> nd) {
+        if (r instanceof InstantiableRelationDefinition) {
+            InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r;
+            if (elements.size() == 0) {
+                return parent().child(ir, nd, "null");
+            } else {
+                return parent().child(ir, nd, elements.get(elements.size() - 1).getName());
+            }
+        } else if (r instanceof SetRelationDefinition) {
+            SetRelationDefinition<? super C, ? super S> sr = (SetRelationDefinition<? super C, ? super S>) r;
+            return parent().child(sr, nd);
+        } else if (r instanceof OptionalRelationDefinition) {
+            OptionalRelationDefinition<? super C, ? super S> or = (OptionalRelationDefinition<? super C, ? super S>) r;
+            return parent().child(or, nd);
+        } else {
+            SingletonRelationDefinition<? super C, ? super S> sr = (SingletonRelationDefinition<? super C, ? super S>) r;
+            return parent().child(sr, nd);
+        }
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * having the specified managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The instantiable relation referencing the child.
+     * @param d
+     *            The managed object definition associated with the child (must
+     *            be a sub-type of the relation).
+     * @param name
+     *            The relative name of the child managed object.
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     * @throws IllegalArgumentException
+     *             If the provided name is empty or blank.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d, String name)
+            throws IllegalArgumentException {
+        if (name.trim().length() == 0) {
+            throw new IllegalArgumentException("Empty or blank managed object names are not allowed");
+        }
+        LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+        celements.add(new InstantiableElement<M, N>(r, d, name));
+        return new ManagedObjectPath<M, N>(celements, r, d);
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * using the relation's child managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The instantiable relation referencing the child.
+     * @param name
+     *            The relative name of the child managed object.
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     * @throws IllegalArgumentException
+     *             If the provided name is empty or blank.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            InstantiableRelationDefinition<M, N> r, String name) throws IllegalArgumentException {
+        return child(r, r.getChildDefinition(), name);
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * having the specified managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The optional relation referencing the child.
+     * @param d
+     *            The managed object definition associated with the child (must
+     *            be a sub-type of the relation).
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            OptionalRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+        LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+        celements.add(new OptionalElement<M, N>(r, d));
+        return new ManagedObjectPath<M, N>(celements, r, d);
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * using the relation's child managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The optional relation referencing the child.
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            OptionalRelationDefinition<M, N> r) {
+        return child(r, r.getChildDefinition());
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * having the specified managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The singleton relation referencing the child.
+     * @param d
+     *            The managed object definition associated with the child (must
+     *            be a sub-type of the relation).
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            SingletonRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) {
+        LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+        celements.add(new SingletonElement<M, N>(r, d));
+        return new ManagedObjectPath<M, N>(celements, r, d);
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * using the relation's child managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The singleton relation referencing the child.
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            SingletonRelationDefinition<M, N> r) {
+        return child(r, r.getChildDefinition());
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * having the specified managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The set relation referencing the child.
+     * @param d
+     *            The managed object definition associated with the child (must
+     *            be a sub-type of the relation).
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     * @throws IllegalArgumentException
+     *             If the provided name is empty or blank.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            SetRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d)
+            throws IllegalArgumentException {
+        LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements);
+        celements.add(new SetElement<M, N>(r, d));
+        return new ManagedObjectPath<M, N>(celements, r, d);
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * having the managed object definition indicated by <code>name</code>.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the path
+     *            references.
+     * @param <N>
+     *            The type of server managed object configuration that the path
+     *            references.
+     * @param r
+     *            The set relation referencing the child.
+     * @param name
+     *            The name of the managed object definition associated with the
+     *            child (must be a sub-type of the relation).
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     * @throws IllegalArgumentException
+     *             If the provided name is empty or blank or specifies a managed
+     *             object definition which is not a sub-type of the relation's
+     *             child definition.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<? extends M, ? extends N> child(
+            SetRelationDefinition<M, N> r, String name) throws IllegalArgumentException {
+        AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition();
+        return child(r, d.getChild(name));
+    }
+
+    /**
+     * Creates a new child managed object path beneath the provided parent path
+     * using the relation's child managed object definition.
+     *
+     * @param <M>
+     *            The type of client managed object configuration that the child
+     *            path references.
+     * @param <N>
+     *            The type of server managed object configuration that the child
+     *            path references.
+     * @param r
+     *            The set relation referencing the child.
+     * @return Returns a new child managed object path beneath the provided
+     *         parent path.
+     * @throws IllegalArgumentException
+     *             If the provided name is empty or blank.
+     */
+    public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child(
+            SetRelationDefinition<M, N> r) throws IllegalArgumentException {
+        return child(r, r.getChildDefinition());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj instanceof ManagedObjectPath) {
+            ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj;
+            return toString().equals(other.toString());
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Get the definition of the managed object referred to by this path.
+     * <p>
+     * When the path is empty, the {@link RootCfgDefn} is returned.
+     *
+     * @return Returns the definition of the managed object referred to by this
+     *         path, or the {@link RootCfgDefn} if the path is empty.
+     */
+    public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
+        return d;
+    }
+
+    /**
+     * Get the name of the managed object referred to by this path if
+     * applicable.
+     * <p>
+     * If there path does not refer to an instantiable managed object
+     * <code>null</code> is returned.
+     *
+     * @return Returns the name of the managed object referred to by this path,
+     *         or <code>null</code> if the managed object does not have a name.
      */
     public String getName() {
-      return null;
+        if (elements.isEmpty()) {
+            return null;
+        } else {
+            return elements.get(elements.size() - 1).getName();
+        }
     }
 
-
-
     /**
-     * Get the relation definition associated with this element.
+     * 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 associated with this
-     *         element.
+     * @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 abstract RelationDefinition<? super C, ? super S>
-        getRelationDefinition();
-
-
+    public RelationDefinition<? super C, ? super S> getRelationDefinition() {
+        return r;
+    }
 
     /**
-     * Serialize this path element using the provided serialization
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return toString().hashCode();
+    }
+
+    /**
+     * Determine whether or not this path contains any path elements.
+     *
+     * @return Returns <code>true</code> if this path does not contain any path
+     *         elements.
+     */
+    public boolean isEmpty() {
+        return elements.isEmpty();
+    }
+
+    /**
+     * Determines whether this managed object path references the same location
+     * as the provided managed object path.
+     * <p>
+     * This method differs from <code>equals</code> in that it ignores sub-type
+     * definitions.
+     *
+     * @param other
+     *            The managed object path to be compared.
+     * @return Returns <code>true</code> if this managed object path references
+     *         the same location as the provided managed object path.
+     */
+    public boolean matches(ManagedObjectPath<?, ?> other) {
+        DN thisDN = toDN();
+        DN otherDN = other.toDN();
+        return thisDN.equals(otherDN);
+    }
+
+    /**
+     * 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>.
+     *
+     * @return Returns a new parent managed object path representing the
+     *         immediate parent of this path.
+     * @throws IllegalArgumentException
+     *             If this path does not have a parent (i.e. it is the empty
+     *             path).
+     */
+    public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException {
+        return parent(1);
+    }
+
+    /**
+     * Creates a new parent managed object path the specified number of path
+     * elements above this path.
+     *
+     * @param offset
+     *            The number of path elements (0 - means no offset, 1 means the
+     *            parent, and 2 means the grand-parent).
+     * @return Returns a new parent managed object path the specified number of
+     *         path elements above this path.
+     * @throws IllegalArgumentException
+     *             If the offset is less than 0, or greater than the number of
+     *             path elements in this path.
+     */
+    public ManagedObjectPath<?, ?> parent(int offset) throws IllegalArgumentException {
+        if (offset < 0) {
+            throw new IllegalArgumentException("Negative offset");
+        }
+
+        if (offset > elements.size()) {
+            throw new IllegalArgumentException("Offset is greater than the number of path elements");
+        }
+
+        // An offset of 0 leaves the path unchanged.
+        if (offset == 0) {
+            return this;
+        }
+
+        // Return the empty path if the parent has zero elements.
+        if (elements.size() == offset) {
+            return emptyPath();
+        }
+
+        LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements.subList(0, elements.size()
+                - offset));
+        return create(celements, celements.getLast());
+    }
+
+    /**
+     * Creates a new managed object path which has the same structure as this
+     * path except that the final path element is renamed. The final path
+     * element must comprise of an instantiable relation.
+     *
+     * @param newName
+     *            The new name of the final path element.
+     * @return Returns a new managed object path which has the same structure as
+     *         this path except that the final path element is renamed.
+     * @throws IllegalStateException
+     *             If this managed object path is empty or if its final path
+     *             element does not comprise of an instantiable relation.
+     */
+    @SuppressWarnings("unchecked")
+    public ManagedObjectPath<C, S> rename(String newName) throws IllegalStateException {
+        if (elements.size() == 0) {
+            throw new IllegalStateException("Cannot rename an empty path");
+        }
+
+        if (r instanceof InstantiableRelationDefinition) {
+            InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r;
+            return parent().child(ir, d, newName);
+        } else {
+            throw new IllegalStateException("Not an instantiable relation");
+        }
+    }
+
+    /**
+     * Serialize this managed object path using the provided serialization
      * strategy.
+     * <p>
+     * The path elements will be passed to the serializer in big-endian order:
+     * starting from the root element and proceeding down to the leaf.
      *
      * @param serializer
-     *          The managed object path serialization strategy.
+     *            The managed object path serialization strategy.
      */
-    public abstract void serialize(ManagedObjectPathSerializer serializer);
-  }
-
-
-
-  /**
-   * A path element representing an instantiable managed object.
-   */
-  private static final class InstantiableElement
-      <C extends ConfigurationClient, S extends Configuration>
-      extends Element<C, S> {
-
-    // Factory method.
-    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) {
-      return new InstantiableElement<C, S>(r, d, name);
-    }
-
-    // The name of the managed object.
-    private final String name;
-
-    // The instantiable relation.
-    private final InstantiableRelationDefinition<? super C, ? super S> r;
-
-
-
-    // Private constructor.
-    private InstantiableElement(
-        InstantiableRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d, String name) {
-      super(d);
-      this.r = r;
-      this.name = name;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public String getName() {
-      return name;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public InstantiableRelationDefinition<? super C, ? super S>
-        getRelationDefinition() {
-      return r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public void serialize(ManagedObjectPathSerializer serializer) {
-      serializer.appendManagedObjectPathElement(r,
-          getManagedObjectDefinition(), name);
-    }
-  }
-
-
-
-  /**
-   * A path element representing an optional managed object.
-   */
-  private static final class OptionalElement
-      <C extends ConfigurationClient, S extends Configuration>
-      extends Element<C, S> {
-
-    // Factory method.
-    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);
-    }
-
-    // The optional relation.
-    private final OptionalRelationDefinition<? super C, ? super S> r;
-
-
-
-    // Private constructor.
-    private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      super(d);
-      this.r = r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public OptionalRelationDefinition<? super C, ? super S>
-        getRelationDefinition() {
-      return r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void serialize(ManagedObjectPathSerializer serializer) {
-      serializer
-          .appendManagedObjectPathElement(r, getManagedObjectDefinition());
-    }
-  }
-
-
-
-  /**
-   * A path element representing an set managed object.
-   */
-  private static final class SetElement
-      <C extends ConfigurationClient, S extends Configuration>
-      extends Element<C, S> {
-
-    // Factory method.
-    private static final <C extends ConfigurationClient,
-        S extends Configuration>
-        SetElement<C, S> create(
-        SetRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      return new SetElement<C, S>(r, d);
-    }
-
-    // The set relation.
-    private final SetRelationDefinition<? super C, ? super S> r;
-
-
-
-    // Private constructor.
-    private SetElement(
-        SetRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      super(d);
-      this.r = r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SetRelationDefinition<? super C, ? super S>
-        getRelationDefinition() {
-      return r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void serialize(ManagedObjectPathSerializer serializer) {
-      serializer.appendManagedObjectPathElement(r,
-          getManagedObjectDefinition());
-    }
-  }
-
-
-
-  /**
-   * A path element representing a singleton managed object.
-   */
-  private static final class SingletonElement
-      <C extends ConfigurationClient, S extends Configuration>
-      extends Element<C, S> {
-
-    // Factory method.
-    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);
-    }
-
-    // The singleton relation.
-    private final SingletonRelationDefinition<? super C, ? super S> r;
-
-
-
-    // Private constructor.
-    private SingletonElement(
-        SingletonRelationDefinition<? super C, ? super S> r,
-        AbstractManagedObjectDefinition<C, S> d) {
-      super(d);
-      this.r = r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public SingletonRelationDefinition<? super C, ? super S>
-        getRelationDefinition() {
-      return r;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void serialize(ManagedObjectPathSerializer serializer) {
-      serializer
-          .appendManagedObjectPathElement(r, getManagedObjectDefinition());
-    }
-  }
-
-
-
-  /**
-   * A serialize which is used to generate the toString
-   * representation.
-   */
-  private static final class StringSerializer implements
-      ManagedObjectPathSerializer {
-
-    // Serialize to this string builder.
-    private final StringBuilder builder;
-
-
-
-    // Private constructor.
-    private StringSerializer(StringBuilder builder) {
-      this.builder = builder;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <M extends ConfigurationClient, N extends Configuration>
-        void appendManagedObjectPathElement(
-        InstantiableRelationDefinition<? super M, ? super N> r,
-        AbstractManagedObjectDefinition<M, N> d, String name) {
-      serializeElement(r, d);
-
-      // Be careful to escape any forward slashes in the name.
-      builder.append("+name=");
-      builder.append(name.replace("/", "//"));
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <M extends ConfigurationClient, N extends Configuration>
-        void appendManagedObjectPathElement(
-        OptionalRelationDefinition<? super M, ? super N> r,
-        AbstractManagedObjectDefinition<M, N> d) {
-      serializeElement(r, d);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <M extends ConfigurationClient, N extends Configuration>
-        void appendManagedObjectPathElement(
-        SingletonRelationDefinition<? super M, ? super N> r,
-        AbstractManagedObjectDefinition<M, N> d) {
-      serializeElement(r, d);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public <M extends ConfigurationClient, N extends Configuration>
-        void appendManagedObjectPathElement(
-        SetRelationDefinition<? super M, ? super N> r,
-        AbstractManagedObjectDefinition<M, N> d) {
-      serializeElement(r, d);
-    }
-
-
-
-    // Common element serialization.
-    private <M, N> void serializeElement(RelationDefinition<?, ?> r,
-        AbstractManagedObjectDefinition<?, ?> d) {
-      // Always specify the relation name.
-      builder.append("/relation=");
-      builder.append(r.getName());
-
-      // Only specify the type if it is a sub-type of the relation's
-      // type.
-      if (r.getChildDefinition() != d) {
-        builder.append("+type=");
-        builder.append(d.getName());
-      }
-    }
-  }
-
-  // Single instance of a root path.
-  private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH =
-      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
-      .compile("^\\s*relation=\\s*([^+]+)\\s*"
-          + "(\\+\\s*type=\\s*([^+]+)\\s*)?"
-          + "(\\+\\s*name=\\s*([^+]+)\\s*)?$");
-
-
-
-  /**
-   * Creates a new managed object path representing the configuration
-   * root.
-   *
-   * @return Returns a new managed object path representing the
-   *         configuration root.
-   */
-  public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() {
-    return EMPTY_PATH;
-  }
-
-
-
-  /**
-   * Returns a managed object path holding the value of the specified
-   * string.
-   *
-   * @param s
-   *          The string to be parsed.
-   * @return Returns a managed object path holding the value of the
-   *         specified string.
-   * @throws IllegalArgumentException
-   *           If the string could not be parsed.
-   */
-  public static ManagedObjectPath<?, ?> valueOf(String s)
-      throws IllegalArgumentException {
-    String ns = s.trim();
-
-    // Check for root special case.
-    if (ns.equals("/")) {
-      return EMPTY_PATH;
-    }
-
-    // Parse the elements.
-    LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
-    Element<?, ?> lastElement = null;
-    AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn
-        .getInstance();
-
-    if (!ns.startsWith("/")) {
-      throw new IllegalArgumentException("Invalid path \"" + ns
-          + "\": must begin with a \"/\"");
-    }
-
-    int start = 1;
-    while (true) {
-      // Get the next path element.
-      int end;
-      for (end = start; end < ns.length(); end++) {
-        char c = ns.charAt(end);
-        if (c == '/') {
-          if (end == (ns.length() - 1)) {
-            throw new IllegalArgumentException("Invalid path \"" + ns
-                + "\": must not end with a trailing \"/\"");
-          }
-
-          if (ns.charAt(end + 1) == '/') {
-            // Found an escaped forward slash.
-            end++;
-          } else {
-            // Found the end of this path element.
-            break;
-          }
+        for (Element<?, ?> element : elements) {
+            element.serialize(serializer);
         }
-      }
-
-      // Get the next element.
-      String es = ns.substring(start, end);
-
-      Matcher m = PE_REGEXP.matcher(es);
-      if (!m.matches()) {
-        throw new IllegalArgumentException("Invalid path element \"" + es
-            + "\" in path \"" + ns + "\"");
-      }
-
-      // 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;
-      try {
-        r = definition.getRelationDefinition(relation);
-      } catch (IllegalArgumentException e) {
-        throw new IllegalArgumentException("Invalid path element \"" + es
-            + "\" in path \"" + ns + "\": unknown relation \"" + relation
-            + "\"");
-      }
-
-      // Append the next element.
-      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()) {
-        // Skip to the beginning of the next element
-        start = end + 1;
-      } else {
-        // We reached the end of the string.
-        break;
-      }
     }
 
-    // Construct the new path.
-    return create(elements, lastElement);
-  }
+    /**
+     * Get the number of path elements in this managed object path.
+     *
+     * @return Returns the number of path elements (0 - means no offset, 1 means
+     *         the parent, and 2 means the grand-parent).
+     */
+    public int size() {
+        return elements.size();
+    }
 
+    /**
+     * Creates a DN representation of this managed object path.
+     *
+     * @return Returns a DN representation of this managed object path.
+     */
+    public DN toDN() {
+        // Use a simple serializer to create the contents.
+        DNSerializer serializer = new DNSerializer();
+        serialize(serializer);
+        return serializer.toDN();
+    }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        toString(builder);
+        return builder.toString();
+    }
 
-  // Factory method required in order to allow generic wild-card
-  // construction of new paths.
-  private static <C extends ConfigurationClient, S extends Configuration>
-      ManagedObjectPath<C, S> create(
-      LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
-    return new ManagedObjectPath<C, S>(elements, lastElement
-        .getRelationDefinition(), lastElement.getManagedObjectDefinition());
-  }
-
-
-
-  // Decode an element.
-  private static <C extends ConfigurationClient, S extends Configuration>
-      Element<? extends C, ? extends S> createElement(
-      RelationDefinition<C, S> r, String path, String element, String type,
-      String name) {
-    // First determine the managed object definition.
-    AbstractManagedObjectDefinition<? extends C, ? extends S> d = null;
-
-    if (type != null) {
-      for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r
-          .getChildDefinition().getAllChildren()) {
-        if (child.getName().equals(type)) {
-          d = child;
-          break;
+    /**
+     * Appends a string representation of this managed object path to the
+     * provided string builder.
+     *
+     * @param builder
+     *            Append the string representation to this builder.
+     * @see #toString()
+     */
+    public void toString(final StringBuilder builder) {
+        if (isEmpty()) {
+            // Special treatment of root configuration paths.
+            builder.append('/');
+        } else {
+            // Use a simple serializer to create the contents.
+            ManagedObjectPathSerializer serializer = new StringSerializer(builder);
+            serialize(serializer);
         }
-      }
-
-      if (d == null) {
-        throw new IllegalArgumentException("Invalid path element \"" + element
-            + "\" in path \"" + path + "\": unknown sub-type \"" + type + "\"");
-      }
-    } else {
-      d = r.getChildDefinition();
     }
 
-    if (r instanceof InstantiableRelationDefinition) {
-      InstantiableRelationDefinition<C, S> ir =
-        (InstantiableRelationDefinition<C, S>) r;
-
-      if (name == null) {
-        throw new IllegalArgumentException("Invalid path element \"" + element
-            + "\" in path \"" + path
-            + "\": no instance name for instantiable relation");
-      }
-
-      return InstantiableElement.create(ir, d, name);
-    } else if (r instanceof SetRelationDefinition) {
-      SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r;
-
-      if (name != null) {
-        throw new IllegalArgumentException("Invalid path element \"" + element
-            + "\" in path \"" + path
-            + "\": instance name specified for set relation");
-      }
-
-      return SetElement.create(ir, d);
-    } else if (r instanceof OptionalRelationDefinition) {
-      OptionalRelationDefinition<C, S> or =
-        (OptionalRelationDefinition<C, S>) r;
-
-      if (name != null) {
-        throw new IllegalArgumentException("Invalid path element \"" + element
-            + "\" in path \"" + path
-            + "\": instance name specified for optional relation");
-      }
-
-      return OptionalElement.create(or, d);
-    } else if (r instanceof SingletonRelationDefinition) {
-      SingletonRelationDefinition<C, S> sr =
-        (SingletonRelationDefinition<C, S>) r;
-
-      if (name != null) {
-        throw new IllegalArgumentException("Invalid path element \"" + element
-            + "\" in path \"" + path
-            + "\": instance name specified for singleton relation");
-      }
-
-      return SingletonElement.create(sr, d);
-    } else {
-      throw new IllegalArgumentException("Invalid path element \"" + element
-          + "\" in path \"" + path + "\": unsupported relation type");
-    }
-  }
-
-  // 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,
-      RelationDefinition<? super C, ? super S> r,
-      AbstractManagedObjectDefinition<C, S> d) {
-    this.elements = Collections.unmodifiableList(elements);
-    this.r = r;
-    this.d = d;
-  }
-
-
-
-  /**
-   * Creates a new managed object path which has the same structure as
-   * this path except that the final path element is associated with
-   * the specified managed object definition.
-   *
-   * @param <CC>
-   *          The type of client managed object configuration that
-   *          this path will reference.
-   * @param <SS>
-   *          The type of server managed object configuration that
-   *          this path will reference.
-   * @param nd
-   *          The new managed object definition.
-   * @return Returns a new managed object path which has the same
-   *         structure as this path except that the final path element
-   *         is associated with the specified managed object
-   *         definition.
-   */
-  @SuppressWarnings("unchecked")
-  public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(
-      AbstractManagedObjectDefinition<CC, SS> nd) {
-    if (r instanceof InstantiableRelationDefinition) {
-      InstantiableRelationDefinition<? super C, ? super S> ir =
-        (InstantiableRelationDefinition<? super C, ? super S>) r;
-      if (elements.size() == 0) {
-        return parent().child(ir, nd, "null");
-      } else {
-        return parent().child(ir, nd,
-            elements.get(elements.size() - 1).getName());
-      }
-    } else if (r instanceof SetRelationDefinition) {
-      SetRelationDefinition<? super C, ? super S> sr =
-        (SetRelationDefinition<? super C, ? super S>) r;
-      return parent().child(sr, nd);
-    } else if (r instanceof OptionalRelationDefinition) {
-      OptionalRelationDefinition<? super C, ? super S> or =
-        (OptionalRelationDefinition<? super C, ? super S>) r;
-      return parent().child(or, nd);
-    } else {
-      SingletonRelationDefinition<? super C, ? super S> sr =
-        (SingletonRelationDefinition<? super C, ? super S>) r;
-      return parent().child(sr, nd);
-    }
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path having the specified managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The instantiable relation referencing the child.
-   * @param d
-   *          The managed object definition associated with the child
-   *          (must be a sub-type of the relation).
-   * @param name
-   *          The relative name of the child managed object.
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   * @throws IllegalArgumentException
-   *           If the provided name is empty or blank.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      InstantiableRelationDefinition<? super M, ? super N> r,
-      AbstractManagedObjectDefinition<M, N> d, String name)
-      throws IllegalArgumentException {
-    if (name.trim().length() == 0) {
-      throw new IllegalArgumentException(
-          "Empty or blank managed object names are not allowed");
-    }
-    LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
-        elements);
-    celements.add(new InstantiableElement<M, N>(r, d, name));
-    return new ManagedObjectPath<M, N>(celements, r, d);
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path using the relation's child managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The instantiable relation referencing the child.
-   * @param name
-   *          The relative name of the child managed object.
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   * @throws IllegalArgumentException
-   *           If the provided name is empty or blank.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      InstantiableRelationDefinition<M, N> r, String name)
-      throws IllegalArgumentException {
-    return child(r, r.getChildDefinition(), name);
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path having the specified managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The optional relation referencing the child.
-   * @param d
-   *          The managed object definition associated with the child
-   *          (must be a sub-type of the relation).
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      OptionalRelationDefinition<? super M, ? super N> r,
-      AbstractManagedObjectDefinition<M, N> d) {
-    LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
-        elements);
-    celements.add(new OptionalElement<M, N>(r, d));
-    return new ManagedObjectPath<M, N>(celements, r, d);
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path using the relation's child managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The optional relation referencing the child.
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(OptionalRelationDefinition<M, N> r) {
-    return child(r, r.getChildDefinition());
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path having the specified managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The singleton relation referencing the child.
-   * @param d
-   *          The managed object definition associated with the child
-   *          (must be a sub-type of the relation).
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      SingletonRelationDefinition<? super M, ? super N> r,
-      AbstractManagedObjectDefinition<M, N> d) {
-    LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
-        elements);
-    celements.add(new SingletonElement<M, N>(r, d));
-    return new ManagedObjectPath<M, N>(celements, r, d);
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path using the relation's child managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The singleton relation referencing the child.
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(SingletonRelationDefinition<M, N> r) {
-    return child(r, r.getChildDefinition());
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path having the specified managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The set relation referencing the child.
-   * @param d
-   *          The managed object definition associated with the child
-   *          (must be a sub-type of the relation).
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   * @throws IllegalArgumentException
-   *           If the provided name is empty or blank.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      SetRelationDefinition<? super M, ? super N> r,
-      AbstractManagedObjectDefinition<M, N> d)
-      throws IllegalArgumentException {
-    LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
-        elements);
-    celements.add(new SetElement<M, N>(r, d));
-    return new ManagedObjectPath<M, N>(celements, r, d);
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided parent
-   * path having the managed object definition indicated by
-   * <code>name</code>.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          path references.
-   * @param r
-   *          The set relation referencing the child.
-   * @param name
-   *          The name of the managed object definition associated with
-   *          the child (must be a sub-type of the relation).
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   * @throws IllegalArgumentException
-   *           If the provided name is empty or blank or specifies a
-   *           managed object definition which is not a sub-type of the
-   *           relation's child definition.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<? extends M, ? extends N> child(
-      SetRelationDefinition<M, N> r,
-      String name)
-      throws IllegalArgumentException {
-    AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition();
-    return child(r, d.getChild(name));
-  }
-
-
-
-  /**
-   * Creates a new child managed object path beneath the provided
-   * parent path using the relation's child managed object definition.
-   *
-   * @param <M>
-   *          The type of client managed object configuration that the
-   *          child path references.
-   * @param <N>
-   *          The type of server managed object configuration that the
-   *          child path references.
-   * @param r
-   *          The set relation referencing the child.
-   * @return Returns a new child managed object path beneath the
-   *         provided parent path.
-   * @throws IllegalArgumentException
-   *           If the provided name is empty or blank.
-   */
-  public <M extends ConfigurationClient, N extends Configuration>
-      ManagedObjectPath<M, N> child(
-      SetRelationDefinition<M, N> r)
-      throws IllegalArgumentException {
-    return child(r, r.getChildDefinition());
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean equals(Object obj) {
-    if (obj == this) {
-      return true;
-    } else if (obj instanceof ManagedObjectPath) {
-      ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj;
-      return toString().equals(other.toString());
-    } else {
-      return false;
-    }
-  }
-
-
-
-  /**
-   * Get the definition of the managed object referred to by this
-   * path.
-   * <p>
-   * When the path is empty, the {@link RootCfgDefn} is returned.
-   *
-   * @return Returns the definition of the managed object referred to
-   *         by this path, or the {@link RootCfgDefn} if the path is
-   *         empty.
-   */
-  public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
-    return d;
-  }
-
-
-
-  /**
-   * Get the name of the managed object referred to by this path if
-   * applicable.
-   * <p>
-   * If there path does not refer to an instantiable managed object
-   * <code>null</code> is returned.
-   *
-   * @return Returns the name of the managed object referred to by
-   *         this path, or <code>null</code> if the managed object
-   *         does not have a name.
-   */
-  public String getName() {
-    if (elements.isEmpty()) {
-      return null;
-    } else {
-      return elements.get(elements.size() - 1).getName();
-    }
-  }
-
-
-
-  /**
-   * 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;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public int hashCode() {
-    return toString().hashCode();
-  }
-
-
-
-  /**
-   * Determine whether or not this path contains any path elements.
-   *
-   * @return Returns <code>true</code> if this path does not contain
-   *         any path elements.
-   */
-  public boolean isEmpty() {
-    return elements.isEmpty();
-  }
-
-
-
-  /**
-   * Determines whether this managed object path references the same
-   * location as the provided managed object path.
-   * <p>
-   * This method differs from <code>equals</code> in that it ignores
-   * sub-type definitions.
-   *
-   * @param other
-   *          The managed object path to be compared.
-   * @return Returns <code>true</code> if this managed object path
-   *         references the same location as the provided managed
-   *         object path.
-   */
-  public boolean matches(ManagedObjectPath<?, ?> other) {
-    DN thisDN = toDN();
-    DN otherDN = other.toDN();
-    return thisDN.equals(otherDN);
-  }
-
-
-
-  /**
-   * 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>.
-   *
-   * @return Returns a new parent managed object path representing the
-   *         immediate parent of this path.
-   * @throws IllegalArgumentException
-   *           If this path does not have a parent (i.e. it is the
-   *           empty path).
-   */
-  public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException {
-    return parent(1);
-  }
-
-
-
-  /**
-   * Creates a new parent managed object path the specified number of
-   * path elements above this path.
-   *
-   * @param offset
-   *          The number of path elements (0 - means no offset, 1
-   *          means the parent, and 2 means the grand-parent).
-   * @return Returns a new parent managed object path the specified
-   *         number of path elements above this path.
-   * @throws IllegalArgumentException
-   *           If the offset is less than 0, or greater than the
-   *           number of path elements in this path.
-   */
-  public ManagedObjectPath<?, ?> parent(int offset)
-      throws IllegalArgumentException {
-    if (offset < 0) {
-      throw new IllegalArgumentException("Negative offset");
-    }
-
-    if (offset > elements.size()) {
-      throw new IllegalArgumentException(
-          "Offset is greater than the number of path elements");
-    }
-
-    // An offset of 0 leaves the path unchanged.
-    if (offset == 0) {
-      return this;
-    }
-
-    // Return the empty path if the parent has zero elements.
-    if (elements.size() == offset) {
-      return emptyPath();
-    }
-
-    LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
-        elements.subList(0, elements.size() - offset));
-    return create(celements, celements.getLast());
-  }
-
-
-
-  /**
-   * Creates a new managed object path which has the same structure as
-   * this path except that the final path element is renamed. The
-   * final path element must comprise of an instantiable relation.
-   *
-   * @param newName
-   *          The new name of the final path element.
-   * @return Returns a new managed object path which has the same
-   *         structure as this path except that the final path element
-   *         is renamed.
-   * @throws IllegalStateException
-   *           If this managed object path is empty or if its final
-   *           path element does not comprise of an instantiable
-   *           relation.
-   */
-  @SuppressWarnings("unchecked")
-  public ManagedObjectPath<C, S> rename(String newName)
-      throws IllegalStateException {
-    if (elements.size() == 0) {
-      throw new IllegalStateException("Cannot rename an empty path");
-    }
-
-    if (r instanceof InstantiableRelationDefinition) {
-      InstantiableRelationDefinition<? super C, ? super S> ir =
-        (InstantiableRelationDefinition<? super C, ? super S>) r;
-      return parent().child(ir, d, newName);
-    } else {
-      throw new IllegalStateException("Not an instantiable relation");
-    }
-  }
-
-
-
-  /**
-   * Serialize this managed object path using the provided
-   * serialization strategy.
-   * <p>
-   * The path elements will be passed to the serializer in big-endian
-   * order: starting from the root element and proceeding down to the
-   * leaf.
-   *
-   * @param serializer
-   *          The managed object path serialization strategy.
-   */
-  public void serialize(ManagedObjectPathSerializer serializer) {
-    for (Element<?, ?> element : elements) {
-      element.serialize(serializer);
-    }
-  }
-
-
-
-  /**
-   * Get the number of path elements in this managed object path.
-   *
-   * @return Returns the number of path elements (0 - means no offset,
-   *         1 means the parent, and 2 means the grand-parent).
-   */
-  public int size() {
-    return elements.size();
-  }
-
-
-
-  /**
-   * Creates a DN representation of this managed object path.
-   *
-   * @return Returns a DN representation of this managed object path.
-   */
-  public DN toDN() {
-    // Use a simple serializer to create the contents.
-    DNSerializer serializer = new DNSerializer();
-    serialize(serializer);
-    return serializer.toDN();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder();
-    toString(builder);
-    return builder.toString();
-  }
-
-
-
-  /**
-   * Appends a string representation of this managed object path to
-   * the provided string builder.
-   *
-   * @param builder
-   *          Append the string representation to this builder.
-   * @see #toString()
-   */
-  public void toString(final StringBuilder builder) {
-    if (isEmpty()) {
-      // Special treatment of root configuration paths.
-      builder.append('/');
-    } else {
-      // Use a simple serializer to create the contents.
-      ManagedObjectPathSerializer serializer = new StringSerializer(builder);
-      serialize(serializer);
-    }
-  }
-
 }

--
Gitblit v1.10.0