From 2a52b482ba335b393356c00fac36d9ae597c8441 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 20 Jul 2007 08:43:07 +0000
Subject: [PATCH] Fix issues 1966 and 1792.

---
 opends/resource/admin/admin.xsd                                                             |   12 
 opends/src/server/org/opends/server/admin/OptionalRelationDefinition.java                   |   77 ++++-
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java |    6 
 opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java                   |    5 
 opends/resource/admin/metaMO.xsl                                                            |   86 +++--
 opends/src/server/org/opends/server/admin/SingletonRelationDefinition.java                  |   78 ++++-
 opends/src/server/org/opends/server/admin/RelationDefinition.java                           |  182 ++++++++++--
 opends/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml                   |    2 
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java    |   11 
 opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java               |  100 +++++-
 opends/src/server/org/opends/server/admin/RelationOption.java                               |   45 +++
 opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java                |  216 ++++++++++-----
 opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java              |   10 
 13 files changed, 615 insertions(+), 215 deletions(-)

diff --git a/opends/resource/admin/admin.xsd b/opends/resource/admin/admin.xsd
index b4144a7..071d824 100644
--- a/opends/resource/admin/admin.xsd
+++ b/opends/resource/admin/admin.xsd
@@ -672,6 +672,18 @@
         </xsd:documentation>
       </xsd:annotation>
     </xsd:attribute>
+    <xsd:attribute name="hidden" type="xsd:boolean" use="optional"
+      default="false">
+      <xsd:annotation>
+        <xsd:documentation>
+          Indicates whether or not this relation should be hidden from
+          client applications. Hidden relations should rarely be used
+          but are sometimes required in order to provide functionality
+          that needs to be exposed in management APIs but not in
+          front-ends such as CLIs.
+        </xsd:documentation>
+      </xsd:annotation>
+    </xsd:attribute>
   </xsd:complexType>
   <xsd:complexType name="admin-action-type">
     <xsd:annotation>
diff --git a/opends/resource/admin/metaMO.xsl b/opends/resource/admin/metaMO.xsl
index 638fd55..6c4cb38 100644
--- a/opends/resource/admin/metaMO.xsl
+++ b/opends/resource/admin/metaMO.xsl
@@ -793,57 +793,57 @@
         <xsl:with-param name="value" select="@managed-object-name" />
       </xsl:call-template>
     </xsl:variable>
+    <xsl:variable name="java-relation-builder-type">
+      <xsl:choose>
+        <xsl:when test="adm:one-to-one">
+          <xsl:text>SingletonRelationDefinition</xsl:text>
+        </xsl:when>
+        <xsl:when test="adm:one-to-zero-or-one">
+          <xsl:text>OptionalRelationDefinition</xsl:text>
+        </xsl:when>
+        <xsl:when test="adm:one-to-many">
+          <xsl:text>InstantiableRelationDefinition</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:message terminate="yes">
+            <xsl:value-of
+              select="concat('Unknown relation type &quot;', local-name(*), '&quot; in relation &quot;', @name, '&quot;.')" />
+          </xsl:message>
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:value-of
+        select="concat('.Builder&lt;', $java-managed-object-name, 'CfgClient, ', $java-managed-object-name, 'Cfg&gt;')" />
+    </xsl:variable>
     <xsl:value-of
       select="concat('  // Build the &quot;', $relation-name, '&quot; relation definition.&#xa;',
                      '  static {&#xa;',
-                     '    RD_', $java-relation-name, ' = new ')" />
-    <xsl:choose>
-      <xsl:when test="adm:one-to-one">
-        <xsl:text>SingletonRelationDefinition&lt;</xsl:text>
-      </xsl:when>
-      <xsl:when test="adm:one-to-zero-or-one">
-        <xsl:text>OptionalRelationDefinition&lt;</xsl:text>
-      </xsl:when>
-      <xsl:when test="adm:one-to-many">
-        <xsl:text>InstantiableRelationDefinition&lt;</xsl:text>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:message terminate="yes">
-          <xsl:value-of
-            select="concat('Unknown relation type &quot;', local-name(*), '&quot; in relation &quot;', @name, '&quot;.')" />
-        </xsl:message>
-      </xsl:otherwise>
-    </xsl:choose>
-    <xsl:value-of
-      select="concat($java-managed-object-name, 'CfgClient, ', $java-managed-object-name, 'Cfg&gt;(&#xa;',
-                     '        INSTANCE, &quot;', @name, '&quot;, ')" />
+                     '    ', $java-relation-builder-type, ' builder =&#xa;',
+                     '      new ', $java-relation-builder-type, '(INSTANCE, &quot;', @name, '&quot;, ')" />
     <xsl:if test="adm:one-to-many">
       <xsl:value-of
         select="concat('&quot;', adm:one-to-many/@plural-name, '&quot;, ')" />
     </xsl:if>
     <xsl:value-of
-      select="concat($java-managed-object-name, 'CfgDefn.getInstance()')" />
-    <xsl:if test="adm:one-to-many">
-      <xsl:value-of select="', '" />
-      <xsl:choose>
-        <xsl:when test="adm:one-to-many/@naming-property">
-          <xsl:variable name="java-property-name">
-            <xsl:call-template name="name-to-java">
-              <xsl:with-param name="value"
-                select="adm:one-to-many/@naming-property" />
-            </xsl:call-template>
-          </xsl:variable>
-          <xsl:value-of
-            select="concat($java-managed-object-name,
+      select="concat($java-managed-object-name, 'CfgDefn.getInstance());&#xa;')" />
+    <xsl:if test="adm:one-to-many/@naming-property">
+      <xsl:variable name="java-property-name">
+        <xsl:call-template name="name-to-java">
+          <xsl:with-param name="value"
+            select="adm:one-to-many/@naming-property" />
+        </xsl:call-template>
+      </xsl:variable>
+      <xsl:value-of
+        select="concat('    builder.setNamingProperty(',
+                           $java-managed-object-name,
                            'CfgDefn.getInstance().get',
-                           $java-property-name, 'PropertyDefinition()')" />
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:value-of select="'null'" />
-        </xsl:otherwise>
-      </xsl:choose>
+                           $java-property-name, 'PropertyDefinition());&#xa;')" />
     </xsl:if>
-    <xsl:value-of select="');&#xa;'" />
+    <xsl:if test="@hidden='true'">
+      <xsl:value-of
+        select="'    builder.setOption(RelationOption.HIDDEN);&#xa;'" />
+    </xsl:if>
+    <xsl:value-of
+      select="concat('    RD_', $java-relation-name, ' = builder.getInstance();&#xa;')" />
     <xsl:value-of
       select="concat('    INSTANCE.registerRelationDefinition(RD_', $java-relation-name,');&#xa;')" />
     <xsl:value-of select="'  }&#xa;'" />
@@ -1742,6 +1742,10 @@
               select="concat(@managed-object-package, '.server.', $java-class-name, 'Cfg')" />
           </xsl:element>
         </xsl:for-each>
+        <xsl:if
+          test="$this-local-relations[@hidden='true']">
+          <import>org.opends.server.admin.RelationOption</import>
+        </xsl:if>
         <xsl:if test="$this-all-relations/adm:one-to-many">
           <import>
             org.opends.server.admin.InstantiableRelationDefinition
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
index 355b606..846c6e6 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/RootDNConfiguration.xml
@@ -46,7 +46,7 @@
     </ldap:object-class>
   </adm:profile>
 
-  <adm:relation name="root-dn-user">
+  <adm:relation name="root-dn-user" hidden="true">
     <adm:one-to-many />
     <adm:profile name="ldap">
       <ldap:rdn-sequence />
diff --git a/opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java b/opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java
index 9b0f159..dbd9300 100644
--- a/opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java
+++ b/opends/src/server/org/opends/server/admin/AggregationRelationDefinition.java
@@ -29,7 +29,7 @@
 
 
 
-import static org.opends.server.util.Validator.ensureNotNull;
+import static org.opends.server.util.Validator.*;
 
 
 
@@ -47,61 +47,137 @@
     <C extends ConfigurationClient, S extends Configuration>
     extends RelationDefinition<C, S> {
 
-  // The plural name of the relation.
-  private final String pluralName;
+  /**
+   * An interface for incrementally constructing aggregation relation
+   * definitions.
+   *
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
+   */
+  public static class Builder
+      <C extends ConfigurationClient, S extends Configuration>
+      extends AbstractBuilder<C, S, AggregationRelationDefinition<C, S>> {
+
+    // The maximum number of referenced managed objects.
+    private int maxOccurs = 0;
+
+    // The minimum number of referenced managed objects.
+    private int minOccurs = 0;
+
+    // The path identifying the location of the referenced managed
+    // objects.
+    private ManagedObjectPath path;
+
+    // The plural name of the relation.
+    private final String pluralName;
+
+
+
+    /**
+     * Creates a new builder which can be used to incrementally build
+     * an aggregation relation definition.
+     *
+     * @param pd
+     *          The parent managed object definition.
+     * @param name
+     *          The name of the relation.
+     * @param pluralName
+     *          The plural name of the relation.
+     * @param cd
+     *          The child managed object definition.
+     */
+    public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name,
+        String pluralName, AbstractManagedObjectDefinition<C, S> cd) {
+      super(pd, name, cd);
+      this.pluralName = pluralName;
+    }
+
+
+
+    /**
+     * Set the maximum number of referenced managed objects.
+     *
+     * @param maxOccurs
+     *          The maximum number of referenced managed objects (or
+     *          zero if there is no upper limit).
+     */
+    public void setMaxOccurs(int maxOccurs) {
+      this.maxOccurs = maxOccurs;
+    }
+
+
+
+    /**
+     * Set the minimum number of referenced managed objects.
+     *
+     * @param minOccurs
+     *          The minimum number of referenced managed objects.
+     */
+    public void setMinOccurs(int minOccurs) {
+      this.minOccurs = minOccurs;
+    }
+
+
+
+    /**
+     * Set the path identifying the location of the referenced managed
+     * objects.
+     *
+     * @param path
+     *          The path identifying the location of the referenced
+     *          managed objects.
+     */
+    public void setPath(ManagedObjectPath path) {
+      this.path = path;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected AggregationRelationDefinition<C, S> buildInstance(
+        Common<C, S> common) {
+      return new AggregationRelationDefinition<C, S>(common, pluralName, path,
+          minOccurs, maxOccurs);
+    }
+
+  }
+
+  // The maximum number of referenced managed objects.
+  private final int maxOccurs;
+
+  // The minimum number of referenced managed objects.
+  private final int minOccurs;
 
   // The path identifying the location of the referenced managed
   // objects.
   private final ManagedObjectPath path;
 
-  // The minimum number of referenced managed objects.
-  private final int minOccurs;
-
-  // The maximum number of referenced managed objects.
-  private final int maxOccurs;
+  // The plural name of the relation.
+  private final String pluralName;
 
 
 
-  /**
-   * Create a new aggregation managed object relation definition.
-   *
-   * @param pd
-   *          The parent managed object definition.
-   * @param name
-   *          The name of this relation.
-   * @param pluralName
-   *          The plural name of the relation.
-   * @param cd
-   *          The child managed object definition.
-   * @param path
-   *          The path identifying the location of the referenced
-   *          managed objects.
-   * @param minOccurs
-   *          The minimum number of referenced managed objects.
-   * @param maxOccurs
-   *          The maximum number of referenced managed objects (or
-   *          zero if there is no upper limit).
-   * @throws IllegalArgumentException
-   *           If minOccurs is less than zero or maxOccurs is less
-   *           than minOccurs.
-   */
-  public AggregationRelationDefinition(
-      AbstractManagedObjectDefinition<?, ?> pd, String name, String pluralName,
-      AbstractManagedObjectDefinition<C, S> cd,
+  // Private constructor.
+  private AggregationRelationDefinition(Common<C, S> common, String pluralName,
       ManagedObjectPath path, int minOccurs, int maxOccurs)
       throws IllegalArgumentException {
-    super(pd, name, cd);
+    super(common);
 
     ensureNotNull(path);
 
     if (minOccurs < 0) {
-      throw new IllegalArgumentException(
-          "minOccurs is less than zero");
+      throw new IllegalArgumentException("minOccurs is less than zero");
     }
 
     if (maxOccurs != 0 && maxOccurs < minOccurs) {
-      throw new IllegalArgumentException(
-          "maxOccurs is less than minOccurs");
+      throw new IllegalArgumentException("maxOccurs is less than minOccurs");
     }
 
     this.pluralName = pluralName;
@@ -113,12 +189,34 @@
 
 
   /**
-   * Get the plural name of the relation.
-   *
-   * @return Returns the plural name of the relation.
+   * {@inheritDoc}
    */
-  public final String getPluralName() {
-    return pluralName;
+  @Override
+  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
+    return v.visitAggregation(this, p);
+  }
+
+
+
+  /**
+   * Get the maximum number of referenced managed objects.
+   *
+   * @return Returns the maximum number of referenced managed objects
+   *         (or zero if there is no upper limit).
+   */
+  public int getMaxOccurs() {
+    return maxOccurs;
+  }
+
+
+
+  /**
+   * Get the minimum number of referenced managed objects.
+   *
+   * @return Returns the minimum number of referenced managed objects.
+   */
+  public int getMinOccurs() {
+    return minOccurs;
   }
 
 
@@ -137,24 +235,12 @@
 
 
   /**
-   * Get the minimum number of referenced managed objects.
+   * Get the plural name of the relation.
    *
-   * @return Returns the minimum number of referenced managed objects.
+   * @return Returns the plural name of the relation.
    */
-  public int getMinOccurs() {
-    return minOccurs;
-  }
-
-
-
-  /**
-   * Get the maximum number of referenced managed objects.
-   *
-   * @return Returns the maximum number of referenced managed objects
-   *         (or zero if there is no upper limit).
-   */
-  public int getMaxOccurs() {
-    return maxOccurs;
+  public final String getPluralName() {
+    return pluralName;
   }
 
 
@@ -177,14 +263,4 @@
       builder.append(maxOccurs);
     }
   }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
-    return v.visitAggregation(this, p);
-  }
 }
diff --git a/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java b/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
index 2035206..89228f7 100644
--- a/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
+++ b/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
@@ -29,6 +29,8 @@
 
 
 
+import static org.opends.server.util.Validator.*;
+
 import java.util.Locale;
 
 
@@ -48,6 +50,79 @@
     <C extends ConfigurationClient, S extends Configuration>
     extends RelationDefinition<C, S> {
 
+  /**
+   * An interface for incrementally constructing instantiable relation
+   * definitions.
+   *
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
+   */
+  public static class Builder
+      <C extends ConfigurationClient, S extends Configuration>
+      extends AbstractBuilder<C, S, InstantiableRelationDefinition<C, S>> {
+
+    // The optional naming property definition.
+    private PropertyDefinition<?> namingPropertyDefinition;
+
+    // The plural name of the relation.
+    private final String pluralName;
+
+
+
+    /**
+     * Creates a new builder which can be used to incrementally build
+     * an instantiable relation definition.
+     *
+     * @param pd
+     *          The parent managed object definition.
+     * @param name
+     *          The name of the relation.
+     * @param pluralName
+     *          The plural name of the relation.
+     * @param cd
+     *          The child managed object definition.
+     */
+    public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name,
+        String pluralName, AbstractManagedObjectDefinition<C, S> cd) {
+      super(pd, name, cd);
+      this.pluralName = pluralName;
+    }
+
+
+
+    /**
+     * Sets the naming property for the instantiable relation
+     * definition.
+     *
+     * @param namingPropertyDefinition
+     *          The property of the child managed object definition
+     *          which should be used for naming, or <code>null</code>
+     *          if this relation does not use a property for naming.
+     */
+    public final void setNamingProperty(
+        PropertyDefinition<?> namingPropertyDefinition) {
+      ensureNotNull(namingPropertyDefinition);
+      this.namingPropertyDefinition = namingPropertyDefinition;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected InstantiableRelationDefinition<C, S> buildInstance(
+        Common<C, S> common) {
+      return new InstantiableRelationDefinition<C, S>(common, pluralName,
+          namingPropertyDefinition);
+    }
+
+  }
+
   // The optional naming property definition.
   private final PropertyDefinition<?> namingPropertyDefinition;
 
@@ -56,27 +131,10 @@
 
 
 
-  /**
-   * Create a new instantiable managed object relation definition.
-   *
-   * @param pd
-   *          The parent managed object definition.
-   * @param name
-   *          The name of the relation.
-   * @param pluralName
-   *          The plural name of the relation.
-   * @param cd
-   *          The child managed object definition.
-   * @param namingPropertyDefinition
-   *          The property of the child managed object definition
-   *          which should be used for naming, or <code>null</code>
-   *          if this relation does not use a property for naming.
-   */
-  public InstantiableRelationDefinition(
-      AbstractManagedObjectDefinition<?, ?> pd, String name, String pluralName,
-      AbstractManagedObjectDefinition<C, S> cd,
-      PropertyDefinition<?> namingPropertyDefinition) {
-    super(pd, name, cd);
+  // Private constructor.
+  private InstantiableRelationDefinition(Common<C, S> common,
+      String pluralName, PropertyDefinition<?> namingPropertyDefinition) {
+    super(common);
     this.pluralName = pluralName;
     this.namingPropertyDefinition = namingPropertyDefinition;
   }
diff --git a/opends/src/server/org/opends/server/admin/OptionalRelationDefinition.java b/opends/src/server/org/opends/server/admin/OptionalRelationDefinition.java
index 7212e35..7a5a6c5 100644
--- a/opends/src/server/org/opends/server/admin/OptionalRelationDefinition.java
+++ b/opends/src/server/org/opends/server/admin/OptionalRelationDefinition.java
@@ -46,19 +46,64 @@
     extends RelationDefinition<C, S> {
 
   /**
-   * Create a new optional managed object relation definition.
+   * An interface for incrementally constructing optional relation
+   * definitions.
    *
-   * @param pd
-   *          The parent managed object definition.
-   * @param name
-   *          The name of the relation.
-   * @param cd
-   *          The child managed object definition.
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
    */
-  public OptionalRelationDefinition(
-      AbstractManagedObjectDefinition<?, ?> pd, String name,
-      AbstractManagedObjectDefinition<C, S> cd) {
-    super(pd, name, cd);
+  public static class Builder
+      <C extends ConfigurationClient, S extends Configuration>
+      extends AbstractBuilder<C, S, OptionalRelationDefinition<C, S>> {
+
+    /**
+     * Creates a new builder which can be used to incrementally build
+     * an optional relation definition.
+     *
+     * @param pd
+     *          The parent managed object definition.
+     * @param name
+     *          The name of the relation.
+     * @param cd
+     *          The child managed object definition.
+     */
+    public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name,
+        AbstractManagedObjectDefinition<C, S> cd) {
+      super(pd, name, cd);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected OptionalRelationDefinition<C, S> buildInstance(
+        Common<C, S> common) {
+      return new OptionalRelationDefinition<C, S>(common);
+    }
+
+  }
+
+
+
+  // Private constructor.
+  private OptionalRelationDefinition(Common<C, S> common) {
+    super(common);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
+    return v.visitOptional(this, p);
   }
 
 
@@ -77,14 +122,4 @@
     builder.append(" minOccurs=0 maxOccurs=1");
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
-    return v.visitOptional(this, p);
-  }
-
 }
diff --git a/opends/src/server/org/opends/server/admin/RelationDefinition.java b/opends/src/server/org/opends/server/admin/RelationDefinition.java
index 72e16a6..05e4332 100644
--- a/opends/src/server/org/opends/server/admin/RelationDefinition.java
+++ b/opends/src/server/org/opends/server/admin/RelationDefinition.java
@@ -29,8 +29,12 @@
 
 
 
+import static org.opends.server.util.Validator.*;
+
+import java.util.EnumSet;
 import java.util.Locale;
 import java.util.MissingResourceException;
+import java.util.Set;
 
 
 
@@ -79,34 +83,135 @@
 public abstract class RelationDefinition
     <C extends ConfigurationClient, S extends Configuration> {
 
-  // The name of the relation.
-  private final String name;
+  /**
+   * An interface for incrementally constructing relation definitions.
+   *
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
+   * @param <D>
+   *          The type of relation definition constructed by this
+   *          builder.
+   */
+  protected abstract static class AbstractBuilder
+      <C extends ConfigurationClient, S extends Configuration,
+       D extends RelationDefinition<C, S>> {
 
-  // The definition of the parent managed object.
-  private final AbstractManagedObjectDefinition<?, ?> pd;
+    // Common fields.
+    private final Common<C, S> common;
 
-  // The definition of the child managed object.
-  private final AbstractManagedObjectDefinition<C, S> cd;
+
+
+    /**
+     * Create a property definition builder.
+     *
+     * @param pd
+     *          The parent managed object definition.
+     * @param name
+     *          The name of the relation.
+     * @param cd
+     *          The child managed object definition.
+     */
+    protected AbstractBuilder(AbstractManagedObjectDefinition<?, ?> pd,
+        String name, AbstractManagedObjectDefinition<C, S> cd) {
+      this.common = new Common<C, S>(pd, name, cd);
+    }
+
+
+
+    /**
+     * Construct a relation definition based on the properties of this
+     * builder.
+     *
+     * @return The new relation definition.
+     */
+    public final D getInstance() {
+      return buildInstance(common);
+    }
+
+
+
+    /**
+     * Add a relation definition option.
+     *
+     * @param option
+     *          The relation option.
+     */
+    public final void setOption(RelationOption option) {
+      ensureNotNull(option);
+      common.options.add(option);
+    }
+
+
+
+    /**
+     * Build a relation definition based on the properties of this
+     * builder.
+     *
+     * @param common
+     *          The common fields of the new relation definition.
+     * @return The new relation definition.
+     */
+    protected abstract D buildInstance(Common<C, S> common);
+  }
+
+
+
+  /**
+   * Opaque structure containing fields common to all relation
+   * definition types.
+   *
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
+   */
+  protected static final class Common
+    <C extends ConfigurationClient, S extends Configuration> {
+
+    // The definition of the child managed object.
+    private final AbstractManagedObjectDefinition<C, S> cd;
+
+    // The name of the relation.
+    private final String name;
+
+    // Options applicable to this definition.
+    private final Set<RelationOption> options;
+
+    // The definition of the parent managed object.
+    private final AbstractManagedObjectDefinition<?, ?> pd;
+
+
+
+    // Private constructor.
+    private Common(AbstractManagedObjectDefinition<?, ?> pd, String name,
+        AbstractManagedObjectDefinition<C, S> cd) {
+      this.name = name;
+      this.pd = pd;
+      this.cd = cd;
+      this.options = EnumSet.noneOf(RelationOption.class);
+    }
+  }
+
+  // Common fields.
+  private final Common<C, S> common;
 
 
 
   /**
    * Create a new managed object relation definition with the
-   * specified name and referenced managed object definition.
+   * specified common fields.
    *
-   * @param pd
-   *          The parent managed object definition.
-   * @param name
-   *          The name of the relation.
-   * @param cd
-   *          The child managed object definition.
+   * @param common
+   *          The common fields of the new relation definition.
    */
-  protected RelationDefinition(
-      AbstractManagedObjectDefinition<?, ?> pd, String name,
-      AbstractManagedObjectDefinition<C, S> cd) {
-    this.name = name;
-    this.pd = pd;
-    this.cd = cd;
+  protected RelationDefinition(Common<C, S> common) {
+    this.common = common;
   }
 
 
@@ -135,7 +240,7 @@
    * @return Returns the definition of the child managed object.
    */
   public final AbstractManagedObjectDefinition<C, S> getChildDefinition() {
-    return cd;
+    return common.cd;
   }
 
 
@@ -166,9 +271,9 @@
    */
   public final String getDescription(Locale locale) {
     try {
-      String property = "relation." + name + ".description";
-      return ManagedObjectDefinitionI18NResource.getInstance()
-          .getMessage(getParentDefinition(), property, locale);
+      String property = "relation." + common.name + ".description";
+      return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
+          getParentDefinition(), property, locale);
     } catch (MissingResourceException e) {
       return null;
     }
@@ -182,7 +287,7 @@
    * @return Returns the name of the relation.
    */
   public final String getName() {
-    return name;
+    return common.name;
   }
 
 
@@ -193,7 +298,7 @@
    * @return Returns the definition of the parent managed object.
    */
   public final AbstractManagedObjectDefinition<?, ?> getParentDefinition() {
-    return pd;
+    return common.pd;
   }
 
 
@@ -221,9 +326,9 @@
    *         specified locale.
    */
   public final String getSynopsis(Locale locale) {
-    String property = "relation." + name + ".synopsis";
-    return ManagedObjectDefinitionI18NResource.getInstance()
-        .getMessage(getParentDefinition(), property, locale);
+    String property = "relation." + common.name + ".synopsis";
+    return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
+        getParentDefinition(), property, locale);
   }
 
 
@@ -251,9 +356,24 @@
    *         definition in the specified locale.
    */
   public final String getUserFriendlyName(Locale locale) {
-    String property = "relation." + name + ".user-friendly-name";
-    return ManagedObjectDefinitionI18NResource.getInstance()
-        .getMessage(getParentDefinition(), property, locale);
+    String property = "relation." + common.name + ".user-friendly-name";
+    return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
+        getParentDefinition(), property, locale);
+  }
+
+
+
+  /**
+   * Check if the specified option is set for this relation
+   * definition.
+   *
+   * @param option
+   *          The option to test.
+   * @return Returns <code>true</code> if the option is set, or
+   *         <code>false</code> otherwise.
+   */
+  public final boolean hasOption(RelationOption option) {
+    return common.options.contains(option);
   }
 
 
diff --git a/opends/src/server/org/opends/server/admin/RelationOption.java b/opends/src/server/org/opends/server/admin/RelationOption.java
new file mode 100644
index 0000000..1624f2b
--- /dev/null
+++ b/opends/src/server/org/opends/server/admin/RelationOption.java
@@ -0,0 +1,45 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+
+
+/**
+ * This enumeration contains various options that can be associated
+ * with relation definitions.
+ * <p>
+ * Only one option is supported at the moment, but others may be added
+ * in future.
+ */
+public enum RelationOption {
+  /**
+   * Use this option to identify relations which must not be directly
+   * exposed in client applications.
+   */
+  HIDDEN;
+}
diff --git a/opends/src/server/org/opends/server/admin/SingletonRelationDefinition.java b/opends/src/server/org/opends/server/admin/SingletonRelationDefinition.java
index c0638bc..a2eccaa 100644
--- a/opends/src/server/org/opends/server/admin/SingletonRelationDefinition.java
+++ b/opends/src/server/org/opends/server/admin/SingletonRelationDefinition.java
@@ -31,7 +31,7 @@
 
 /**
  * A managed object composite relationship definition which represents
- * a compososition of a single managed object (i.e. the managed object
+ * a composition of a single managed object (i.e. the managed object
  * must be present).
  *
  * @param <C>
@@ -46,18 +46,64 @@
     extends RelationDefinition<C, S> {
 
   /**
-   * Create a new singleton managed object relation definition.
+   * An interface for incrementally constructing singleton relation
+   * definitions.
    *
-   * @param pd
-   *          The parent managed object definition.
-   * @param name
-   *          The name of the relation.
-   * @param cd
-   *          The child managed object definition.
+   * @param <C>
+   *          The type of client managed object configuration that
+   *          this relation definition refers to.
+   * @param <S>
+   *          The type of server managed object configuration that
+   *          this relation definition refers to.
    */
-  public SingletonRelationDefinition(AbstractManagedObjectDefinition<?, ?> pd,
-      String name, AbstractManagedObjectDefinition<C, S> cd) {
-    super(pd, name, cd);
+  public static class Builder
+      <C extends ConfigurationClient, S extends Configuration>
+      extends AbstractBuilder<C, S, SingletonRelationDefinition<C, S>> {
+
+    /**
+     * Creates a new builder which can be used to incrementally build
+     * an singleton relation definition.
+     *
+     * @param pd
+     *          The parent managed object definition.
+     * @param name
+     *          The name of the relation.
+     * @param cd
+     *          The child managed object definition.
+     */
+    public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name,
+        AbstractManagedObjectDefinition<C, S> cd) {
+      super(pd, name, cd);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected SingletonRelationDefinition<C, S> buildInstance(
+        Common<C, S> common) {
+      return new SingletonRelationDefinition<C, S>(common);
+    }
+
+  }
+
+
+
+  // Private constructor.
+  private SingletonRelationDefinition(Common<C, S> common) {
+    super(common);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
+    return v.visitSingleton(this, p);
   }
 
 
@@ -76,14 +122,4 @@
     builder.append(" minOccurs=1 maxOccurs=1");
   }
 
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
-    return v.visitSingleton(this, p);
-  }
-
 }
diff --git a/opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java b/opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java
index 6a5defb..30dd180 100644
--- a/opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java
+++ b/opends/src/server/org/opends/server/tools/dsconfig/SubCommandBuilder.java
@@ -41,6 +41,7 @@
 import org.opends.server.admin.OptionalRelationDefinition;
 import org.opends.server.admin.RelationDefinition;
 import org.opends.server.admin.RelationDefinitionVisitor;
+import org.opends.server.admin.RelationOption;
 import org.opends.server.admin.SingletonRelationDefinition;
 import org.opends.server.util.args.ArgumentException;
 import org.opends.server.util.args.SubCommandArgumentParser;
@@ -198,7 +199,9 @@
 
       // Do not process inherited relation definitions.
       for (RelationDefinition<?, ?> r : d.getRelationDefinitions()) {
-        r.accept(this, path);
+        if (!r.hasOption(RelationOption.HIDDEN)) {
+          r.accept(this, path);
+        }
       }
     }
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
index d1daf3d..3745d18 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
@@ -51,16 +51,20 @@
 
   // Create a one-to-many relation for test-parent components.
   static {
-    RD_TEST_ONE_TO_MANY_PARENT = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
+    InstantiableRelationDefinition.Builder<TestParentCfgClient, TestParentCfg> builder =
+      new InstantiableRelationDefinition.Builder<TestParentCfgClient, TestParentCfg>(
         RootCfgDefn.getInstance(), "test-one-to-many-parent",
-        "test-one-to-many-parents", TestParentCfgDefn.getInstance(), null);
+        "test-one-to-many-parents", TestParentCfgDefn.getInstance());
+    RD_TEST_ONE_TO_MANY_PARENT = builder.getInstance();
   }
 
   // Create a one-to-many relation for test-parent components.
   static {
-    RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT = new OptionalRelationDefinition<TestParentCfgClient, TestParentCfg>(
+    OptionalRelationDefinition.Builder<TestParentCfgClient, TestParentCfg> builder =
+      new OptionalRelationDefinition.Builder<TestParentCfgClient, TestParentCfg>(
         RootCfgDefn.getInstance(), "test-one-to-zero-or-one-parent",
         TestParentCfgDefn.getInstance());
+    RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT = builder.getInstance();
   }
 
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
index 2c076a8..f169502 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -164,8 +164,11 @@
 
   // Build the "test-children" relation definition.
   static {
-    RD_TEST_CHILDREN = new InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg>(
-        INSTANCE, "multiple-children", "test-children", TestChildCfgDefn.getInstance(), null);
+    InstantiableRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> builder =
+      new InstantiableRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>(
+        INSTANCE, "multiple-children", "test-children", TestChildCfgDefn
+            .getInstance());
+    RD_TEST_CHILDREN = builder.getInstance();
     INSTANCE.registerRelationDefinition(RD_TEST_CHILDREN);
   }
 
@@ -173,8 +176,10 @@
 
   // Build the "optional-test-child" relation definition.
   static {
-    RD_OPTIONAL_TEST_CHILD = new OptionalRelationDefinition<TestChildCfgClient, TestChildCfg>(
+    OptionalRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> builder =
+      new OptionalRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>(
         INSTANCE, "optional-test-child", TestChildCfgDefn.getInstance());
+    RD_OPTIONAL_TEST_CHILD = builder.getInstance();
     INSTANCE.registerRelationDefinition(RD_OPTIONAL_TEST_CHILD);
   }
 
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java
index 8668350..545c6f4 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/DNBuilderTest.java
@@ -124,10 +124,12 @@
     // First create the path.
     ManagedObjectPath<? extends ConfigurationClient, ? extends Configuration> path = ManagedObjectPath
         .emptyPath();
-
-    final SingletonRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = new SingletonRelationDefinition<TestChildCfgClient, TestChildCfg>(
+    
+    SingletonRelationDefinition.Builder<TestChildCfgClient, TestChildCfg> b =
+      new SingletonRelationDefinition.Builder<TestChildCfgClient, TestChildCfg>(
         TestParentCfgDefn.getInstance(), "singleton-test-child",
         TestChildCfgDefn.getInstance());
+    final SingletonRelationDefinition<TestChildCfgClient, TestChildCfg> r2 = b.getInstance();
     LDAPProfile.Wrapper wrapper = new LDAPProfile.Wrapper() {
 
       /**

--
Gitblit v1.10.0