mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Nicolas Capponi
02.47.2013 2fef5aa0046548cb88034553f522d907195a19f7
opendj-admin/src/main/java/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -27,8 +27,6 @@
package org.opends.server.admin;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -41,13 +39,11 @@
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.Vector;
import org.forgerock.i18n.LocalizableMessage;
import org.opends.server.admin.DefinitionDecodingException.Reason;
/**
 * Defines the structure of an abstract managed object. Abstract managed objects
 * cannot be instantiated.
@@ -56,1103 +52,924 @@
 * overall configuration model of an application.
 *
 * @param <C>
 *          The type of client managed object configuration that this definition
 *          represents.
 *            The type of client managed object configuration that this
 *            definition represents.
 * @param <S>
 *          The type of server managed object configuration that this definition
 *          represents.
 *            The type of server managed object configuration that this
 *            definition represents.
 */
public abstract class AbstractManagedObjectDefinition
    <C extends ConfigurationClient, S extends Configuration> {
public abstract class AbstractManagedObjectDefinition<C extends ConfigurationClient, S extends Configuration> {
  // The name of the definition.
  private final String name;
    // The name of the definition.
    private final String name;
  // The parent managed object definition if applicable.
  private final AbstractManagedObjectDefinition<? super C, ? super S> parent;
    // The parent managed object definition if applicable.
    private final AbstractManagedObjectDefinition<? super C, ? super S> parent;
  // The set of constraints associated with this managed object
  // definition.
  private final Collection<Constraint> constraints;
    // The set of constraints associated with this managed object
    // definition.
    private final Collection<Constraint> constraints;
  // The set of property definitions applicable to this managed object
  // definition.
  private final Map<String, PropertyDefinition<?>> propertyDefinitions;
    // The set of property definitions applicable to this managed object
    // definition.
    private final Map<String, PropertyDefinition<?>> propertyDefinitions;
  // The set of relation definitions applicable to this managed object
  // definition.
  private final Map<String, RelationDefinition<?, ?>> relationDefinitions;
    // The set of relation definitions applicable to this managed object
    // definition.
    private final Map<String, RelationDefinition<?, ?>> relationDefinitions;
  // The set of relation definitions directly referencing this managed
  // object definition.
  private final Set<RelationDefinition<C, S>> reverseRelationDefinitions;
    // The set of relation definitions directly referencing this managed
    // object definition.
    private final Set<RelationDefinition<C, S>> reverseRelationDefinitions;
  // The set of all property definitions associated with this managed
  // object definition including inherited property definitions.
  private final Map<String, PropertyDefinition<?>> allPropertyDefinitions;
    // The set of all property definitions associated with this managed
    // object definition including inherited property definitions.
    private final Map<String, PropertyDefinition<?>> allPropertyDefinitions;
  // The set of all relation definitions associated with this managed
  // object definition including inherited relation definitions.
  private final Map<String, RelationDefinition<?, ?>> allRelationDefinitions;
    // The set of all relation definitions associated with this managed
    // object definition including inherited relation definitions.
    private final Map<String, RelationDefinition<?, ?>> allRelationDefinitions;
  // The set of aggregation property definitions applicable to this
  // managed object definition.
  private final Map<String, AggregationPropertyDefinition<?, ?>>
    aggregationPropertyDefinitions;
    // The set of aggregation property definitions applicable to this
    // managed object definition.
    private final Map<String, AggregationPropertyDefinition<?, ?>> aggregationPropertyDefinitions;
  // The set of aggregation property definitions directly referencing this
  // managed object definition.
  private final Vector<AggregationPropertyDefinition<?, ?>>
    reverseAggregationPropertyDefinitions;
    // The set of aggregation property definitions directly referencing this
    // managed object definition.
    private final Vector<AggregationPropertyDefinition<?, ?>> reverseAggregationPropertyDefinitions;
  // The set of all aggregation property definitions associated with this
  // managed object definition including inherited relation definitions.
  private final Map<String, AggregationPropertyDefinition<?, ?>>
    allAggregationPropertyDefinitions;
    // The set of all aggregation property definitions associated with this
    // managed object definition including inherited relation definitions.
    private final Map<String, AggregationPropertyDefinition<?, ?>> allAggregationPropertyDefinitions;
  // The set of tags associated with this managed object.
  private final Set<Tag> allTags;
    // The set of tags associated with this managed object.
    private final Set<Tag> allTags;
  // Options applicable to this definition.
  private final Set<ManagedObjectOption> options;
    // Options applicable to this definition.
    private final Set<ManagedObjectOption> options;
  // The set of managed object definitions which inherit from this definition.
  private final Map<String,
    AbstractManagedObjectDefinition<? extends C, ? extends S>> children;
    // The set of managed object definitions which inherit from this definition.
    private final Map<String, AbstractManagedObjectDefinition<? extends C, ? extends S>> children;
    /**
     * Create a new abstract managed object definition.
     *
     * @param name
     *            The name of the definition.
     * @param parent
     *            The parent definition, or <code>null</code> if there is no
     *            parent (only the {@link TopCfgDefn} should have a
     *            <code>null</code> parent, unless the definition is being used
     *            for testing).
     */
    protected AbstractManagedObjectDefinition(String name, AbstractManagedObjectDefinition<? super C, ? super S> parent) {
        this.name = name;
        this.parent = parent;
        this.constraints = new LinkedList<Constraint>();
        this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
        this.relationDefinitions = new HashMap<String, RelationDefinition<?, ?>>();
        this.reverseRelationDefinitions = new HashSet<RelationDefinition<C, S>>();
        this.allPropertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
        this.allRelationDefinitions = new HashMap<String, RelationDefinition<?, ?>>();
        this.aggregationPropertyDefinitions = new HashMap<String, AggregationPropertyDefinition<?, ?>>();
        this.reverseAggregationPropertyDefinitions = new Vector<AggregationPropertyDefinition<?, ?>>();
        this.allAggregationPropertyDefinitions = new HashMap<String, AggregationPropertyDefinition<?, ?>>();
        this.allTags = new HashSet<Tag>();
        this.options = EnumSet.noneOf(ManagedObjectOption.class);
        this.children = new HashMap<String, AbstractManagedObjectDefinition<? extends C, ? extends S>>();
  /**
   * Create a new abstract managed object definition.
   *
   * @param name
   *          The name of the definition.
   * @param parent
   *          The parent definition, or <code>null</code> if there
   *          is no parent (only the {@link TopCfgDefn} should have a
   *          <code>null</code> parent, unless the definition is
   *          being used for testing).
   */
  protected AbstractManagedObjectDefinition(String name,
      AbstractManagedObjectDefinition<? super C, ? super S> parent) {
    this.name = name;
    this.parent = parent;
    this.constraints = new LinkedList<Constraint>();
    this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
    this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>();
    this.reverseRelationDefinitions = new HashSet<RelationDefinition<C,S>>();
    this.allPropertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
    this.allRelationDefinitions =
      new HashMap<String, RelationDefinition<?, ?>>();
    this.aggregationPropertyDefinitions =
      new HashMap<String, AggregationPropertyDefinition<?,?>>();
    this.reverseAggregationPropertyDefinitions =
      new Vector<AggregationPropertyDefinition<?,?>>();
    this.allAggregationPropertyDefinitions =
      new HashMap<String, AggregationPropertyDefinition<?, ?>>();
    this.allTags = new HashSet<Tag>();
    this.options = EnumSet.noneOf(ManagedObjectOption.class);
        // If we have a parent definition then inherit its features.
        if (parent != null) {
            registerInParent();
    this.children = new HashMap<String,
        AbstractManagedObjectDefinition<? extends C, ? extends S>>();
            for (PropertyDefinition<?> pd : parent.getAllPropertyDefinitions()) {
                allPropertyDefinitions.put(pd.getName(), pd);
            }
    // If we have a parent definition then inherit its features.
    if (parent != null) {
      registerInParent();
            for (RelationDefinition<?, ?> rd : parent.getAllRelationDefinitions()) {
                allRelationDefinitions.put(rd.getName(), rd);
            }
      for (PropertyDefinition<?> pd : parent.getAllPropertyDefinitions()) {
        allPropertyDefinitions.put(pd.getName(), pd);
      }
            for (AggregationPropertyDefinition<?, ?> apd : parent.getAllAggregationPropertyDefinitions()) {
      for (RelationDefinition<?, ?> rd : parent.getAllRelationDefinitions()) {
        allRelationDefinitions.put(rd.getName(), rd);
      }
                allAggregationPropertyDefinitions.put(apd.getName(), apd);
            }
      for (AggregationPropertyDefinition<?, ?> apd :
        parent.getAllAggregationPropertyDefinitions()) {
        allAggregationPropertyDefinitions.put(apd.getName(), apd);
      }
      // Tag inheritance is performed during preprocessing.
    }
  }
  /**
   * Get all the child managed object definitions which inherit from
   * this managed object definition.
   *
   * @return Returns an unmodifiable collection containing all the
   *         subordinate managed object definitions which inherit from
   *         this managed object definition.
   */
  public final Collection<AbstractManagedObjectDefinition
      <? extends C, ? extends S>> getAllChildren() {
    List<AbstractManagedObjectDefinition<? extends C, ? extends S>> list =
      new ArrayList<AbstractManagedObjectDefinition<? extends C, ? extends S>>(
        children.values());
    for (AbstractManagedObjectDefinition<? extends C, ? extends S> child :
        children.values()) {
      list.addAll(child.getAllChildren());
    }
    return Collections.unmodifiableCollection(list);
  }
  /**
   * Get all the constraints associated with this type of managed
   * object. The returned collection will contain inherited
   * constraints.
   *
   * @return Returns a collection containing all the constraints
   *         associated with this type of managed object. The caller
   *         is free to modify the collection if required.
   */
  public final Collection<Constraint> getAllConstraints() {
    // This method does not used a cached set of constraints because
    // constraints may be updated after child definitions have been
    // defined.
    List<Constraint> allConstraints = new LinkedList<Constraint>();
    if (parent != null) {
      allConstraints.addAll(parent.getAllConstraints());
    }
    allConstraints.addAll(constraints);
    return allConstraints;
  }
  /**
   * Get all the property definitions associated with this type of
   * managed object. The returned collection will contain inherited
   * property definitions.
   *
   * @return Returns an unmodifiable collection containing all the
   *         property definitions associated with this type of managed
   *         object.
   */
  public final Collection<PropertyDefinition<?>> getAllPropertyDefinitions() {
    return Collections.unmodifiableCollection(allPropertyDefinitions.values());
  }
  /**
   * Get all the relation definitions associated with this type of
   * managed object. The returned collection will contain inherited
   * relation definitions.
   *
   * @return Returns an unmodifiable collection containing all the
   *         relation definitions associated with this type of managed
   *         object.
   */
  public final Collection<RelationDefinition<?, ?>>
      getAllRelationDefinitions() {
    return Collections.unmodifiableCollection(allRelationDefinitions.values());
  }
  /**
   * Get all the relation definitions which refer to this managed
   * object definition. The returned collection will contain relation
   * definitions which refer to parents of this managed object
   * definition.
   *
   * @return Returns a collection containing all the relation
   *         definitions which refer to this managed object
   *         definition. The caller is free to modify the collection
   *         if required.
   */
  public final Collection<RelationDefinition<? super C, ? super S>>
  getAllReverseRelationDefinitions() {
    // This method does not used a cached set of relations because
    // relations may be updated after child definitions have been
    // defined.
    List<RelationDefinition<? super C, ? super S>> rdlist =
      new LinkedList<RelationDefinition<? super C, ? super S>>();
    if (parent != null) {
      rdlist.addAll(parent.getAllReverseRelationDefinitions());
    }
    rdlist.addAll(reverseRelationDefinitions);
    return rdlist;
  }
  /**
   * Get all the aggregation property definitions associated with this type of
   * managed object. The returned collection will contain inherited
   * aggregation property definitions.
   *
   * @return Returns an unmodifiable collection containing all the
   *         aggregation property definitions associated with this type of
   *         managed object.
   */
  public final Collection<AggregationPropertyDefinition<?, ?>>
      getAllAggregationPropertyDefinitions() {
    return Collections.unmodifiableCollection(
      allAggregationPropertyDefinitions.values());
  }
  /**
   * Get all the aggregation property definitions which refer to this managed
   * object definition. The returned collection will contain aggregation
   * property definitions which refer to parents of this managed object
   * definition.
   *
   * @return Returns a collection containing all the aggregation property
   *         definitions which refer to this managed object
   *         definition. The caller is free to modify the collection
   *         if required.
   */
  public final Collection<AggregationPropertyDefinition<?, ?>>
  getAllReverseAggregationPropertyDefinitions() {
    // This method does not used a cached set of aggregation properties because
    // aggregation properties may be updated after child definitions have been
    // defined.
    List<AggregationPropertyDefinition<?, ?>> apdlist =
      new LinkedList<AggregationPropertyDefinition<?, ?>>();
    if (parent != null) {
      apdlist.addAll(parent.getAllReverseAggregationPropertyDefinitions());
    }
    apdlist.addAll(reverseAggregationPropertyDefinitions);
    return apdlist;
  }
  /**
   * Get all the tags associated with this type of managed object. The
   * returned collection will contain inherited tags.
   *
   * @return Returns an unmodifiable collection containing all the
   *         tags associated with this type of managed object.
   */
  public final Collection<Tag> getAllTags() {
    return Collections.unmodifiableCollection(allTags);
  }
  /**
   * Get the named child managed object definition which inherits from
   * this managed object definition. This method will recursively
   * search down through the inheritance hierarchy.
   *
   * @param name
   *          The name of the managed object definition sub-type.
   * @return Returns the named child managed object definition which
   *         inherits from this managed object definition.
   * @throws IllegalArgumentException
   *           If the specified managed object definition name was
   *           null or empty or if the requested subordinate managed
   *           object definition was not found.
   */
  public final AbstractManagedObjectDefinition<? extends C, ? extends S>
      getChild(String name) throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException("null or empty managed object name");
    }
    AbstractManagedObjectDefinition<? extends C, ? extends S> d = children
        .get(name);
    if (d == null) {
      // Recursively search.
      for (AbstractManagedObjectDefinition<? extends C, ? extends S> child :
          children.values()) {
        try {
          d = child.getChild(name);
          break;
        } catch (IllegalArgumentException e) {
          // Try the next child.
            // Tag inheritance is performed during preprocessing.
        }
      }
    }
    if (d == null) {
      throw new IllegalArgumentException("child managed object definition \""
          + name + "\" not found");
    /**
     * Get all the child managed object definitions which inherit from this
     * managed object definition.
     *
     * @return Returns an unmodifiable collection containing all the subordinate
     *         managed object definitions which inherit from this managed object
     *         definition.
     */
    public final Collection<AbstractManagedObjectDefinition<? extends C, ? extends S>> getAllChildren() {
        List<AbstractManagedObjectDefinition<? extends C, ? extends S>> list = new ArrayList<AbstractManagedObjectDefinition<? extends C, ? extends S>>(
                children.values());
        for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) {
            list.addAll(child.getAllChildren());
        }
        return Collections.unmodifiableCollection(list);
    }
    return d;
  }
    /**
     * Get all the constraints associated with this type of managed object. The
     * returned collection will contain inherited constraints.
     *
     * @return Returns a collection containing all the constraints associated
     *         with this type of managed object. The caller is free to modify
     *         the collection if required.
     */
    public final Collection<Constraint> getAllConstraints() {
        // This method does not used a cached set of constraints because
        // constraints may be updated after child definitions have been
        // defined.
        List<Constraint> allConstraints = new LinkedList<Constraint>();
        if (parent != null) {
            allConstraints.addAll(parent.getAllConstraints());
        }
        allConstraints.addAll(constraints);
  /**
   * Get the child managed object definitions which inherit directly
   * from this managed object definition.
   *
   * @return Returns an unmodifiable collection containing the
   *         subordinate managed object definitions which inherit
   *         directly from this managed object definition.
   */
  public final Collection<AbstractManagedObjectDefinition
      <? extends C, ? extends S>> getChildren() {
    return Collections.unmodifiableCollection(children.values());
  }
  /**
   * Get the constraints defined by this managed object definition.
   * The returned collection will not contain inherited constraints.
   *
   * @return Returns an unmodifiable collection containing the
   *         constraints defined by this managed object definition.
   */
  public final Collection<Constraint> getConstraints() {
    return Collections.unmodifiableCollection(constraints);
  }
  /**
   * Gets the optional description of this managed object definition
   * in the default locale.
   *
   * @return Returns the description of this managed object definition
   *         in the default locale, or <code>null</code> if there is
   *         no description.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getDescription() throws UnsupportedOperationException {
    return getDescription(Locale.getDefault());
  }
  /**
   * Gets the optional description of this managed object definition
   * in the specified locale.
   *
   * @param locale
   *          The locale.
   * @return Returns the description of this managed object definition
   *         in the specified locale, or <code>null</code> if there
   *         is no description.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getDescription(Locale locale)
      throws UnsupportedOperationException {
    try {
      return ManagedObjectDefinitionI18NResource.getInstance()
        .getMessage(this, "description", locale);
    } catch (MissingResourceException e) {
      return null;
    }
  }
  /**
   * Get the name of the definition.
   *
   * @return Returns the name of the definition.
   */
  public final String getName() {
    return name;
  }
  /**
   * Get the parent managed object definition, if applicable.
   *
   * @return Returns the parent of this managed object definition, or
   *         <code>null</code> if this definition is the
   *         {@link TopCfgDefn}.
   */
  public final AbstractManagedObjectDefinition<? super C,
      ? super S> getParent() {
    return parent;
  }
  /**
   * Get the specified property definition associated with this type
   * of managed object. The search will include any inherited property
   * definitions.
   *
   * @param name
   *          The name of the property definition to be retrieved.
   * @return Returns the specified property definition associated with
   *         this type of managed object.
   * @throws IllegalArgumentException
   *           If the specified property name was null or empty or if
   *           the requested property definition was not found.
   */
  public final PropertyDefinition<?> getPropertyDefinition(String name)
      throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException("null or empty property name");
        return allConstraints;
    }
    PropertyDefinition<?> d = allPropertyDefinitions.get(name);
    if (d == null) {
      throw new IllegalArgumentException("property definition \"" + name
          + "\" not found");
    /**
     * Get all the property definitions associated with this type of managed
     * object. The returned collection will contain inherited property
     * definitions.
     *
     * @return Returns an unmodifiable collection containing all the property
     *         definitions associated with this type of managed object.
     */
    public final Collection<PropertyDefinition<?>> getAllPropertyDefinitions() {
        return Collections.unmodifiableCollection(allPropertyDefinitions.values());
    }
    return d;
  }
  /**
   * Get the property definitions defined by this managed object
   * definition. The returned collection will not contain inherited
   * property definitions.
   *
   * @return Returns an unmodifiable collection containing the
   *         property definitions defined by this managed object
   *         definition.
   */
  public final Collection<PropertyDefinition<?>> getPropertyDefinitions() {
    return Collections.unmodifiableCollection(propertyDefinitions
        .values());
  }
  /**
   * Get the specified relation definition associated with this type
   * of managed object.The search will include any inherited relation
   * definitions.
   *
   * @param name
   *          The name of the relation definition to be retrieved.
   * @return Returns the specified relation definition associated with
   *         this type of managed object.
   * @throws IllegalArgumentException
   *           If the specified relation name was null or empty or if
   *           the requested relation definition was not found.
   */
  public final RelationDefinition<?, ?> getRelationDefinition(String name)
      throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException("null or empty relation name");
    /**
     * Get all the relation definitions associated with this type of managed
     * object. The returned collection will contain inherited relation
     * definitions.
     *
     * @return Returns an unmodifiable collection containing all the relation
     *         definitions associated with this type of managed object.
     */
    public final Collection<RelationDefinition<?, ?>> getAllRelationDefinitions() {
        return Collections.unmodifiableCollection(allRelationDefinitions.values());
    }
    RelationDefinition<?, ?> d = allRelationDefinitions.get(name);
    if (d == null) {
      throw new IllegalArgumentException("relation definition \"" + name
          + "\" not found");
    /**
     * Get all the relation definitions which refer to this managed object
     * definition. The returned collection will contain relation definitions
     * which refer to parents of this managed object definition.
     *
     * @return Returns a collection containing all the relation definitions
     *         which refer to this managed object definition. The caller is free
     *         to modify the collection if required.
     */
    public final Collection<RelationDefinition<? super C, ? super S>> getAllReverseRelationDefinitions() {
        // This method does not used a cached set of relations because
        // relations may be updated after child definitions have been
        // defined.
        List<RelationDefinition<? super C, ? super S>> rdlist = new LinkedList<RelationDefinition<? super C, ? super S>>();
        if (parent != null) {
            rdlist.addAll(parent.getAllReverseRelationDefinitions());
        }
        rdlist.addAll(reverseRelationDefinitions);
        return rdlist;
    }
    return d;
  }
  /**
   * Get the relation definitions defined by this managed object
   * definition. The returned collection will not contain inherited
   * relation definitions.
   *
   * @return Returns an unmodifiable collection containing the
   *         relation definitions defined by this managed object
   *         definition.
   */
  public final Collection<RelationDefinition<?,?>> getRelationDefinitions() {
    return Collections.unmodifiableCollection(relationDefinitions.values());
  }
  /**
   * Get the relation definitions which refer directly to this managed
   * object definition. The returned collection will not contain
   * relation definitions which refer to parents of this managed
   * object definition.
   *
   * @return Returns an unmodifiable collection containing the
   *         relation definitions which refer directly to this managed
   *         object definition.
   */
  public final Collection<RelationDefinition<C, S>>
      getReverseRelationDefinitions() {
    return Collections.unmodifiableCollection(reverseRelationDefinitions);
  }
  /**
   * Get the specified aggregation property definition associated with this type
   * of managed object.The search will include any inherited aggregation
   * property definitions.
   *
   * @param name
   *          The name of the aggregation property definition to be retrieved.
   * @return Returns the specified aggregation property definition associated
   *         with this type of managed object.
   * @throws IllegalArgumentException
   *           If the specified aggregation property name was null or empty or
   *           if the requested aggregation property definition was not found.
   */
  public final AggregationPropertyDefinition<?, ?>
    getAggregationPropertyDefinition(String name)
    throws IllegalArgumentException {
    if ((name == null) || (name.length() == 0)) {
      throw new IllegalArgumentException(
        "null or empty aggregation property name");
    /**
     * Get all the aggregation property definitions associated with this type of
     * managed object. The returned collection will contain inherited
     * aggregation property definitions.
     *
     * @return Returns an unmodifiable collection containing all the aggregation
     *         property definitions associated with this type of managed object.
     */
    public final Collection<AggregationPropertyDefinition<?, ?>> getAllAggregationPropertyDefinitions() {
        return Collections.unmodifiableCollection(allAggregationPropertyDefinitions.values());
    }
    AggregationPropertyDefinition<?, ?> d =
      allAggregationPropertyDefinitions.get(name);
    if (d == null) {
      throw new IllegalArgumentException("aggregation property definition \""
        + name + "\" not found");
    /**
     * Get all the aggregation property definitions which refer to this managed
     * object definition. The returned collection will contain aggregation
     * property definitions which refer to parents of this managed object
     * definition.
     *
     * @return Returns a collection containing all the aggregation property
     *         definitions which refer to this managed object definition. The
     *         caller is free to modify the collection if required.
     */
    public final Collection<AggregationPropertyDefinition<?, ?>> getAllReverseAggregationPropertyDefinitions() {
        // This method does not used a cached set of aggregation properties
        // because
        // aggregation properties may be updated after child definitions have
        // been
        // defined.
        List<AggregationPropertyDefinition<?, ?>> apdlist = new LinkedList<AggregationPropertyDefinition<?, ?>>();
        if (parent != null) {
            apdlist.addAll(parent.getAllReverseAggregationPropertyDefinitions());
        }
        apdlist.addAll(reverseAggregationPropertyDefinitions);
        return apdlist;
    }
    return d;
  }
  /**
   * Get the aggregation property definitions defined by this managed object
   * definition. The returned collection will not contain inherited
   * aggregation property definitions.
   *
   * @return Returns an unmodifiable collection containing the
   *         aggregation property definitions defined by this managed object
   *         definition.
   */
  public final Collection<AggregationPropertyDefinition<?, ?>>
    getAggregationPropertyDefinitions() {
    return Collections.unmodifiableCollection(
      aggregationPropertyDefinitions.values());
  }
  /**
   * Get the aggregation property definitions which refer directly to this
   * managed object definition. The returned collection will not contain
   * aggregation property definitions which refer to parents of this managed
   * object definition.
   *
   * @return Returns an unmodifiable collection containing the
   *         aggregation property definitions which refer directly to this
   *         managed object definition.
   */
  public final Collection<AggregationPropertyDefinition<?, ?>>
    getReverseAggregationPropertyDefinitions() {
    return Collections.unmodifiableCollection(
      reverseAggregationPropertyDefinitions);
  }
  /**
   * Gets the synopsis of this managed object definition in the
   * default locale.
   *
   * @return Returns the synopsis of this managed object definition in
   *         the default locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getSynopsis() throws UnsupportedOperationException {
    return getSynopsis(Locale.getDefault());
  }
  /**
   * Gets the synopsis of this managed object definition in the
   * specified locale.
   *
   * @param locale
   *          The locale.
   * @return Returns the synopsis of this managed object definition in
   *         the specified locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getSynopsis(Locale locale)
      throws UnsupportedOperationException {
    return ManagedObjectDefinitionI18NResource.getInstance()
        .getMessage(this, "synopsis", locale);
  }
  /**
   * Gets the user friendly name of this managed object definition in
   * the default locale.
   *
   * @return Returns the user friendly name of this managed object
   *         definition in the default locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getUserFriendlyName()
      throws UnsupportedOperationException {
    return getUserFriendlyName(Locale.getDefault());
  }
  /**
   * Gets the user friendly name of this managed object definition in
   * the specified locale.
   *
   * @param locale
   *          The locale.
   * @return Returns the user friendly name of this managed object
   *         definition in the specified locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getUserFriendlyName(Locale locale)
      throws UnsupportedOperationException {
    // TODO: have admin framework getMessage return a Message
    return Message.raw(ManagedObjectDefinitionI18NResource.getInstance()
        .getMessage(this, "user-friendly-name", locale));
  }
  /**
   * Gets the user friendly plural name of this managed object
   * definition in the default locale.
   *
   * @return Returns the user friendly plural name of this managed
   *         object definition in the default locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getUserFriendlyPluralName()
      throws UnsupportedOperationException {
    return getUserFriendlyPluralName(Locale.getDefault());
  }
  /**
   * Gets the user friendly plural name of this managed object
   * definition in the specified locale.
   *
   * @param locale
   *          The locale.
   * @return Returns the user friendly plural name of this managed
   *         object definition in the specified locale.
   * @throws UnsupportedOperationException
   *           If this managed object definition is the
   *           {@link TopCfgDefn}.
   */
  public final Message getUserFriendlyPluralName(Locale locale)
      throws UnsupportedOperationException {
    return ManagedObjectDefinitionI18NResource.getInstance()
        .getMessage(this, "user-friendly-plural-name", locale);
  }
  /**
   * Determine whether there are any child managed object definitions which
   * inherit from this managed object definition.
   *
   * @return Returns <code>true</code> if this type of managed object has any
   *         child managed object definitions, <code>false</code> otherwise.
   */
  public final boolean hasChildren() {
    return !children.isEmpty();
  }
  /**
   * Determines whether or not this managed object definition has the
   * specified option.
   *
   * @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(ManagedObjectOption option) {
    return options.contains(option);
  }
  /**
   * Determines whether or not this managed object definition has the
   * specified tag.
   *
   * @param t
   *          The tag definition.
   * @return Returns <code>true</code> if this managed object
   *         definition has the specified tag.
   */
  public final boolean hasTag(Tag t) {
    return allTags.contains(t);
  }
  /**
   * Determines whether or not this managed object definition is a
   * sub-type of the provided managed object definition. This managed
   * object definition is a sub-type of the provided managed object
   * definition if they are both the same or if the provided managed
   * object definition can be obtained by recursive invocations of the
   * {@link #getParent()} method.
   *
   * @param d
   *          The managed object definition to be checked.
   * @return Returns <code>true</code> if this managed object
   *         definition is a sub-type of the provided managed object
   *         definition.
   */
  public final boolean isChildOf(AbstractManagedObjectDefinition<?, ?> d) {
    AbstractManagedObjectDefinition<?, ?> i;
    for (i = this; i != null; i = i.parent) {
      if (i == d) {
        return true;
      }
    }
    return false;
  }
  /**
   * Determines whether or not this managed object definition is a
   * super-type of the provided managed object definition. This
   * managed object definition is a super-type of the provided managed
   * object definition if they are both the same or if the provided
   * managed object definition is a member of the set of children
   * returned from {@link #getAllChildren()}.
   *
   * @param d
   *          The managed object definition to be checked.
   * @return Returns <code>true</code> if this managed object
   *         definition is a super-type of the provided managed object
   *         definition.
   */
  public final boolean isParentOf(AbstractManagedObjectDefinition<?, ?> d) {
    return d.isChildOf(this);
  }
  /**
   * Determines whether or not this managed object definition is the
   * {@link TopCfgDefn}.
   *
   * @return Returns <code>true</code> if this managed object
   *         definition is the {@link TopCfgDefn}.
   */
  public final boolean isTop() {
    return (this instanceof TopCfgDefn);
  }
  /**
   * Finds a sub-type of this managed object definition which most closely
   * corresponds to the matching criteria of the provided definition resolver.
   *
   * @param r
   *          The definition resolver.
   * @return Returns the sub-type of this managed object definition which most
   *         closely corresponds to the matching criteria of the provided
   *         definition resolver.
   * @throws DefinitionDecodingException
   *           If no matching sub-type could be found or if the resolved
   *           definition was abstract.
   * @see DefinitionResolver
   */
  @SuppressWarnings("unchecked")
  public final ManagedObjectDefinition<? extends C, ? extends S>
      resolveManagedObjectDefinition(
      DefinitionResolver r) throws DefinitionDecodingException {
    AbstractManagedObjectDefinition<? extends C, ? extends S> rd;
    rd = resolveManagedObjectDefinitionAux(this, r);
    if (rd == null) {
      // Unable to resolve the definition.
      throw new DefinitionDecodingException(this,
          Reason.WRONG_TYPE_INFORMATION);
    } else if (rd instanceof ManagedObjectDefinition) {
      return (ManagedObjectDefinition<? extends C, ? extends S>) rd;
    } else {
      // Resolved definition was abstract.
      throw new DefinitionDecodingException(this,
          Reason.ABSTRACT_TYPE_INFORMATION);
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public final String toString() {
    StringBuilder builder = new StringBuilder();
    toString(builder);
    return builder.toString();
  }
  /**
   * Append a string representation of the managed object definition to the
   * provided string builder.
   *
   * @param builder
   *          The string builder where the string representation should be
   *          appended.
   */
  public final void toString(StringBuilder builder) {
    builder.append(getName());
  }
  /**
   * Initializes all of the components associated with this managed
   * object definition.
   *
   * @throws Exception
   *           If this managed object definition could not be
   *           initialized.
   */
  protected final void initialize() throws Exception {
    for (PropertyDefinition<?> pd : getAllPropertyDefinitions()) {
      pd.initialize();
      pd.getDefaultBehaviorProvider().initialize();
    /**
     * Get all the tags associated with this type of managed object. The
     * returned collection will contain inherited tags.
     *
     * @return Returns an unmodifiable collection containing all the tags
     *         associated with this type of managed object.
     */
    public final Collection<Tag> getAllTags() {
        return Collections.unmodifiableCollection(allTags);
    }
    for (RelationDefinition<?, ?> rd : getAllRelationDefinitions()) {
      rd.initialize();
    /**
     * Get the named child managed object definition which inherits from this
     * managed object definition. This method will recursively search down
     * through the inheritance hierarchy.
     *
     * @param name
     *            The name of the managed object definition sub-type.
     * @return Returns the named child managed object definition which inherits
     *         from this managed object definition.
     * @throws IllegalArgumentException
     *             If the specified managed object definition name was null or
     *             empty or if the requested subordinate managed object
     *             definition was not found.
     */
    public final AbstractManagedObjectDefinition<? extends C, ? extends S> getChild(String name)
            throws IllegalArgumentException {
        if ((name == null) || (name.length() == 0)) {
            throw new IllegalArgumentException("null or empty managed object name");
        }
        AbstractManagedObjectDefinition<? extends C, ? extends S> d = children.get(name);
        if (d == null) {
            // Recursively search.
            for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) {
                try {
                    d = child.getChild(name);
                    break;
                } catch (IllegalArgumentException e) {
                    // Try the next child.
                }
            }
        }
        if (d == null) {
            throw new IllegalArgumentException("child managed object definition \"" + name + "\" not found");
        }
        return d;
    }
    for (AggregationPropertyDefinition<?, ?> apd :
      getAllAggregationPropertyDefinitions()) {
      apd.initialize();
      // Now register the aggregation property in the referenced managed object
      // definition for reverse lookups.
      registerReverseAggregationPropertyDefinition(apd);
    /**
     * Get the child managed object definitions which inherit directly from this
     * managed object definition.
     *
     * @return Returns an unmodifiable collection containing the subordinate
     *         managed object definitions which inherit directly from this
     *         managed object definition.
     */
    public final Collection<AbstractManagedObjectDefinition<? extends C, ? extends S>> getChildren() {
        return Collections.unmodifiableCollection(children.values());
    }
    for (Constraint constraint : getAllConstraints()) {
      constraint.initialize();
    }
  }
  /**
   * Register a constraint with this managed object definition.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param constraint
   *          The constraint to be registered.
   */
  protected final void registerConstraint(Constraint constraint) {
    constraints.add(constraint);
  }
  /**
   * Register a property definition with this managed object definition,
   * overriding any existing property definition with the same name.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param d
   *          The property definition to be registered.
   */
  protected final void registerPropertyDefinition(PropertyDefinition<?> d) {
    String propName = d.getName();
    propertyDefinitions.put(propName, d);
    allPropertyDefinitions.put(propName, d);
    if (d instanceof AggregationPropertyDefinition<?,?>) {
      AggregationPropertyDefinition<?, ?> apd =
        (AggregationPropertyDefinition<?, ?>) d;
      aggregationPropertyDefinitions.put(propName, apd);
      // The key must also contain the managed object name, since several MOs
      // in an inheritance tree may aggregate the same aggregation property name
      allAggregationPropertyDefinitions.put(
        apd.getManagedObjectDefinition().getName() + ":" + propName, apd);
    }
  }
  /**
   * Register a relation definition with this managed object definition,
   * overriding any existing relation definition with the same name.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param d
   *          The relation definition to be registered.
   */
  protected final void registerRelationDefinition(RelationDefinition<?, ?> d) {
    // Register the relation in this managed object definition.
    String relName = d.getName();
    relationDefinitions.put(relName, d);
    allRelationDefinitions.put(relName, d);
    // Now register the relation in the referenced managed object
    // definition for reverse lookups.
    registerReverseRelationDefinition(d);
  }
  /**
   * Register an option with this managed object definition.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param option
   *          The option to be registered.
   */
  protected final void registerOption(ManagedObjectOption option) {
    options.add(option);
  }
  /**
   * Register a tag with this managed object definition.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param tag
   *          The tag to be registered.
   */
  protected final void registerTag(Tag tag) {
    allTags.add(tag);
  }
  /**
   * Deregister a constraint from the managed object definition.
   * <p>
   * This method <b>must not</b> be called by applications and is
   * only intended for internal testing.
   *
   * @param constraint
   *          The constraint to be deregistered.
   */
  final void deregisterConstraint(Constraint constraint) {
    if (!constraints.remove(constraint)) {
      throw new RuntimeException("Failed to deregister a constraint");
    }
  }
  /**
   * Deregister a relation definition from the managed object
   * definition.
   * <p>
   * This method <b>must not</b> be called by applications and is
   * only intended for internal testing.
   *
   * @param d
   *          The relation definition to be deregistered.
   */
  final void deregisterRelationDefinition(
      RelationDefinition<?, ?> d) {
   // Deregister the relation from this managed object definition.
    String relName = d.getName();
    relationDefinitions.remove(relName);
    allRelationDefinitions.remove(relName);
    // Now deregister the relation from the referenced managed object
    // definition for reverse lookups.
    d.getChildDefinition().reverseRelationDefinitions.remove(d);
  }
  /**
   * Register this managed object definition in its parent.
   * <p>
   * This method <b>must not</b> be called by applications and is
   * only intended for internal testing.
   */
  final void registerInParent() {
    if (parent != null) {
      parent.children.put(name, this);
    }
  }
  // Register a relation definition in the referenced managed object
  // definition's reverse lookup table.
  private <CC extends ConfigurationClient, SS extends Configuration>
  void registerReverseRelationDefinition(RelationDefinition<CC, SS> rd) {
    rd.getChildDefinition().reverseRelationDefinitions.add(rd);
  }
  // Register a aggregation property definition in the referenced managed object
  // definition's reverse lookup table.
  private void registerReverseAggregationPropertyDefinition(
    AggregationPropertyDefinition<?, ?> apd) {
    apd.getRelationDefinition().getChildDefinition().
      reverseAggregationPropertyDefinitions.add(apd);
  }
  // Recursively descend definition hierarchy to find the best match definition.
  private AbstractManagedObjectDefinition<? extends C, ? extends S>
      resolveManagedObjectDefinitionAux(
      AbstractManagedObjectDefinition<? extends C, ? extends S> d,
      DefinitionResolver r) {
    if (!r.matches(d)) {
      return null;
    /**
     * Get the constraints defined by this managed object definition. The
     * returned collection will not contain inherited constraints.
     *
     * @return Returns an unmodifiable collection containing the constraints
     *         defined by this managed object definition.
     */
    public final Collection<Constraint> getConstraints() {
        return Collections.unmodifiableCollection(constraints);
    }
    for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : d
        .getChildren()) {
      AbstractManagedObjectDefinition<? extends C, ? extends S> rd =
        resolveManagedObjectDefinitionAux(child, r);
      if (rd != null) {
        return rd;
      }
    /**
     * Gets the optional description of this managed object definition in the
     * default locale.
     *
     * @return Returns the description of this managed object definition in the
     *         default locale, or <code>null</code> if there is no description.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getDescription() throws UnsupportedOperationException {
        return getDescription(Locale.getDefault());
    }
    return d;
  }
    /**
     * Gets the optional description of this managed object definition in the
     * specified locale.
     *
     * @param locale
     *            The locale.
     * @return Returns the description of this managed object definition in the
     *         specified locale, or <code>null</code> if there is no
     *         description.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getDescription(Locale locale) throws UnsupportedOperationException {
        try {
            return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, "description", locale);
        } catch (MissingResourceException e) {
            return null;
        }
    }
    /**
     * Get the name of the definition.
     *
     * @return Returns the name of the definition.
     */
    public final String getName() {
        return name;
    }
    /**
     * Get the parent managed object definition, if applicable.
     *
     * @return Returns the parent of this managed object definition, or
     *         <code>null</code> if this definition is the {@link TopCfgDefn}.
     */
    public final AbstractManagedObjectDefinition<? super C, ? super S> getParent() {
        return parent;
    }
    /**
     * Get the specified property definition associated with this type of
     * managed object. The search will include any inherited property
     * definitions.
     *
     * @param name
     *            The name of the property definition to be retrieved.
     * @return Returns the specified property definition associated with this
     *         type of managed object.
     * @throws IllegalArgumentException
     *             If the specified property name was null or empty or if the
     *             requested property definition was not found.
     */
    public final PropertyDefinition<?> getPropertyDefinition(String name) throws IllegalArgumentException {
        if ((name == null) || (name.length() == 0)) {
            throw new IllegalArgumentException("null or empty property name");
        }
        PropertyDefinition<?> d = allPropertyDefinitions.get(name);
        if (d == null) {
            throw new IllegalArgumentException("property definition \"" + name + "\" not found");
        }
        return d;
    }
    /**
     * Get the property definitions defined by this managed object definition.
     * The returned collection will not contain inherited property definitions.
     *
     * @return Returns an unmodifiable collection containing the property
     *         definitions defined by this managed object definition.
     */
    public final Collection<PropertyDefinition<?>> getPropertyDefinitions() {
        return Collections.unmodifiableCollection(propertyDefinitions.values());
    }
    /**
     * Get the specified relation definition associated with this type of
     * managed object.The search will include any inherited relation
     * definitions.
     *
     * @param name
     *            The name of the relation definition to be retrieved.
     * @return Returns the specified relation definition associated with this
     *         type of managed object.
     * @throws IllegalArgumentException
     *             If the specified relation name was null or empty or if the
     *             requested relation definition was not found.
     */
    public final RelationDefinition<?, ?> getRelationDefinition(String name) throws IllegalArgumentException {
        if ((name == null) || (name.length() == 0)) {
            throw new IllegalArgumentException("null or empty relation name");
        }
        RelationDefinition<?, ?> d = allRelationDefinitions.get(name);
        if (d == null) {
            throw new IllegalArgumentException("relation definition \"" + name + "\" not found");
        }
        return d;
    }
    /**
     * Get the relation definitions defined by this managed object definition.
     * The returned collection will not contain inherited relation definitions.
     *
     * @return Returns an unmodifiable collection containing the relation
     *         definitions defined by this managed object definition.
     */
    public final Collection<RelationDefinition<?, ?>> getRelationDefinitions() {
        return Collections.unmodifiableCollection(relationDefinitions.values());
    }
    /**
     * Get the relation definitions which refer directly to this managed object
     * definition. The returned collection will not contain relation definitions
     * which refer to parents of this managed object definition.
     *
     * @return Returns an unmodifiable collection containing the relation
     *         definitions which refer directly to this managed object
     *         definition.
     */
    public final Collection<RelationDefinition<C, S>> getReverseRelationDefinitions() {
        return Collections.unmodifiableCollection(reverseRelationDefinitions);
    }
    /**
     * Get the specified aggregation property definition associated with this
     * type of managed object.The search will include any inherited aggregation
     * property definitions.
     *
     * @param name
     *            The name of the aggregation property definition to be
     *            retrieved.
     * @return Returns the specified aggregation property definition associated
     *         with this type of managed object.
     * @throws IllegalArgumentException
     *             If the specified aggregation property name was null or empty
     *             or if the requested aggregation property definition was not
     *             found.
     */
    public final AggregationPropertyDefinition<?, ?> getAggregationPropertyDefinition(String name)
            throws IllegalArgumentException {
        if ((name == null) || (name.length() == 0)) {
            throw new IllegalArgumentException("null or empty aggregation property name");
        }
        AggregationPropertyDefinition<?, ?> d = allAggregationPropertyDefinitions.get(name);
        if (d == null) {
            throw new IllegalArgumentException("aggregation property definition \"" + name + "\" not found");
        }
        return d;
    }
    /**
     * Get the aggregation property definitions defined by this managed object
     * definition. The returned collection will not contain inherited
     * aggregation property definitions.
     *
     * @return Returns an unmodifiable collection containing the aggregation
     *         property definitions defined by this managed object definition.
     */
    public final Collection<AggregationPropertyDefinition<?, ?>> getAggregationPropertyDefinitions() {
        return Collections.unmodifiableCollection(aggregationPropertyDefinitions.values());
    }
    /**
     * Get the aggregation property definitions which refer directly to this
     * managed object definition. The returned collection will not contain
     * aggregation property definitions which refer to parents of this managed
     * object definition.
     *
     * @return Returns an unmodifiable collection containing the aggregation
     *         property definitions which refer directly to this managed object
     *         definition.
     */
    public final Collection<AggregationPropertyDefinition<?, ?>> getReverseAggregationPropertyDefinitions() {
        return Collections.unmodifiableCollection(reverseAggregationPropertyDefinitions);
    }
    /**
     * Gets the synopsis of this managed object definition in the default
     * locale.
     *
     * @return Returns the synopsis of this managed object definition in the
     *         default locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getSynopsis() throws UnsupportedOperationException {
        return getSynopsis(Locale.getDefault());
    }
    /**
     * Gets the synopsis of this managed object definition in the specified
     * locale.
     *
     * @param locale
     *            The locale.
     * @return Returns the synopsis of this managed object definition in the
     *         specified locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getSynopsis(Locale locale) throws UnsupportedOperationException {
        return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, "synopsis", locale);
    }
    /**
     * Gets the user friendly name of this managed object definition in the
     * default locale.
     *
     * @return Returns the user friendly name of this managed object definition
     *         in the default locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getUserFriendlyName() throws UnsupportedOperationException {
        return getUserFriendlyName(Locale.getDefault());
    }
    /**
     * Gets the user friendly name of this managed object definition in the
     * specified locale.
     *
     * @param locale
     *            The locale.
     * @return Returns the user friendly name of this managed object definition
     *         in the specified locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getUserFriendlyName(Locale locale) throws UnsupportedOperationException {
        return LocalizableMessage.raw(ManagedObjectDefinitionI18NResource.getInstance().getMessage(this,
                "user-friendly-name", locale));
    }
    /**
     * Gets the user friendly plural name of this managed object definition in
     * the default locale.
     *
     * @return Returns the user friendly plural name of this managed object
     *         definition in the default locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getUserFriendlyPluralName() throws UnsupportedOperationException {
        return getUserFriendlyPluralName(Locale.getDefault());
    }
    /**
     * Gets the user friendly plural name of this managed object definition in
     * the specified locale.
     *
     * @param locale
     *            The locale.
     * @return Returns the user friendly plural name of this managed object
     *         definition in the specified locale.
     * @throws UnsupportedOperationException
     *             If this managed object definition is the {@link TopCfgDefn}.
     */
    public final LocalizableMessage getUserFriendlyPluralName(Locale locale) throws UnsupportedOperationException {
        return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this,
                "user-friendly-plural-name", locale);
    }
    /**
     * Determine whether there are any child managed object definitions which
     * inherit from this managed object definition.
     *
     * @return Returns <code>true</code> if this type of managed object has any
     *         child managed object definitions, <code>false</code> otherwise.
     */
    public final boolean hasChildren() {
        return !children.isEmpty();
    }
    /**
     * Determines whether or not this managed object definition has the
     * specified option.
     *
     * @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(ManagedObjectOption option) {
        return options.contains(option);
    }
    /**
     * Determines whether or not this managed object definition has the
     * specified tag.
     *
     * @param t
     *            The tag definition.
     * @return Returns <code>true</code> if this managed object definition has
     *         the specified tag.
     */
    public final boolean hasTag(Tag t) {
        return allTags.contains(t);
    }
    /**
     * Determines whether or not this managed object definition is a sub-type of
     * the provided managed object definition. This managed object definition is
     * a sub-type of the provided managed object definition if they are both the
     * same or if the provided managed object definition can be obtained by
     * recursive invocations of the {@link #getParent()} method.
     *
     * @param d
     *            The managed object definition to be checked.
     * @return Returns <code>true</code> if this managed object definition is a
     *         sub-type of the provided managed object definition.
     */
    public final boolean isChildOf(AbstractManagedObjectDefinition<?, ?> d) {
        AbstractManagedObjectDefinition<?, ?> i;
        for (i = this; i != null; i = i.parent) {
            if (i == d) {
                return true;
            }
        }
        return false;
    }
    /**
     * Determines whether or not this managed object definition is a super-type
     * of the provided managed object definition. This managed object definition
     * is a super-type of the provided managed object definition if they are
     * both the same or if the provided managed object definition is a member of
     * the set of children returned from {@link #getAllChildren()}.
     *
     * @param d
     *            The managed object definition to be checked.
     * @return Returns <code>true</code> if this managed object definition is a
     *         super-type of the provided managed object definition.
     */
    public final boolean isParentOf(AbstractManagedObjectDefinition<?, ?> d) {
        return d.isChildOf(this);
    }
    /**
     * Determines whether or not this managed object definition is the
     * {@link TopCfgDefn}.
     *
     * @return Returns <code>true</code> if this managed object definition is
     *         the {@link TopCfgDefn}.
     */
    public final boolean isTop() {
        return (this instanceof TopCfgDefn);
    }
    /**
     * Finds a sub-type of this managed object definition which most closely
     * corresponds to the matching criteria of the provided definition resolver.
     *
     * @param r
     *            The definition resolver.
     * @return Returns the sub-type of this managed object definition which most
     *         closely corresponds to the matching criteria of the provided
     *         definition resolver.
     * @throws DefinitionDecodingException
     *             If no matching sub-type could be found or if the resolved
     *             definition was abstract.
     * @see DefinitionResolver
     */
    @SuppressWarnings("unchecked")
    public final ManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinition(DefinitionResolver r)
            throws DefinitionDecodingException {
        AbstractManagedObjectDefinition<? extends C, ? extends S> rd;
        rd = resolveManagedObjectDefinitionAux(this, r);
        if (rd == null) {
            // Unable to resolve the definition.
            throw new DefinitionDecodingException(this, Reason.WRONG_TYPE_INFORMATION);
        } else if (rd instanceof ManagedObjectDefinition) {
            return (ManagedObjectDefinition<? extends C, ? extends S>) rd;
        } else {
            // Resolved definition was abstract.
            throw new DefinitionDecodingException(this, Reason.ABSTRACT_TYPE_INFORMATION);
        }
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public final String toString() {
        StringBuilder builder = new StringBuilder();
        toString(builder);
        return builder.toString();
    }
    /**
     * Append a string representation of the managed object definition to the
     * provided string builder.
     *
     * @param builder
     *            The string builder where the string representation should be
     *            appended.
     */
    public final void toString(StringBuilder builder) {
        builder.append(getName());
    }
    /**
     * Initializes all of the components associated with this managed object
     * definition.
     *
     * @throws Exception
     *             If this managed object definition could not be initialized.
     */
    protected final void initialize() throws Exception {
        for (PropertyDefinition<?> pd : getAllPropertyDefinitions()) {
            pd.initialize();
            pd.getDefaultBehaviorProvider().initialize();
        }
        for (RelationDefinition<?, ?> rd : getAllRelationDefinitions()) {
            rd.initialize();
        }
        for (AggregationPropertyDefinition<?, ?> apd : getAllAggregationPropertyDefinitions()) {
            apd.initialize();
            // Now register the aggregation property in the referenced managed
            // object
            // definition for reverse lookups.
            registerReverseAggregationPropertyDefinition(apd);
        }
        for (Constraint constraint : getAllConstraints()) {
            constraint.initialize();
        }
    }
    /**
     * Register a constraint with this managed object definition.
     * <p>
     * This method <b>must not</b> be called by applications.
     *
     * @param constraint
     *            The constraint to be registered.
     */
    protected final void registerConstraint(Constraint constraint) {
        constraints.add(constraint);
    }
    /**
     * Register a property definition with this managed object definition,
     * overriding any existing property definition with the same name.
     * <p>
     * This method <b>must not</b> be called by applications.
     *
     * @param d
     *            The property definition to be registered.
     */
    protected final void registerPropertyDefinition(PropertyDefinition<?> d) {
        String propName = d.getName();
        propertyDefinitions.put(propName, d);
        allPropertyDefinitions.put(propName, d);
        if (d instanceof AggregationPropertyDefinition<?, ?>) {
            AggregationPropertyDefinition<?, ?> apd = (AggregationPropertyDefinition<?, ?>) d;
            aggregationPropertyDefinitions.put(propName, apd);
            // The key must also contain the managed object name, since several
            // MOs
            // in an inheritance tree may aggregate the same aggregation
            // property name
            allAggregationPropertyDefinitions.put(apd.getManagedObjectDefinition().getName() + ":" + propName, apd);
        }
    }
    /**
     * Register a relation definition with this managed object definition,
     * overriding any existing relation definition with the same name.
     * <p>
     * This method <b>must not</b> be called by applications.
     *
     * @param d
     *            The relation definition to be registered.
     */
    protected final void registerRelationDefinition(RelationDefinition<?, ?> d) {
        // Register the relation in this managed object definition.
        String relName = d.getName();
        relationDefinitions.put(relName, d);
        allRelationDefinitions.put(relName, d);
        // Now register the relation in the referenced managed object
        // definition for reverse lookups.
        registerReverseRelationDefinition(d);
    }
    /**
     * Register an option with this managed object definition.
     * <p>
     * This method <b>must not</b> be called by applications.
     *
     * @param option
     *            The option to be registered.
     */
    protected final void registerOption(ManagedObjectOption option) {
        options.add(option);
    }
    /**
     * Register a tag with this managed object definition.
     * <p>
     * This method <b>must not</b> be called by applications.
     *
     * @param tag
     *            The tag to be registered.
     */
    protected final void registerTag(Tag tag) {
        allTags.add(tag);
    }
    /**
     * Deregister a constraint from the managed object definition.
     * <p>
     * This method <b>must not</b> be called by applications and is only
     * intended for internal testing.
     *
     * @param constraint
     *            The constraint to be deregistered.
     */
    final void deregisterConstraint(Constraint constraint) {
        if (!constraints.remove(constraint)) {
            throw new RuntimeException("Failed to deregister a constraint");
        }
    }
    /**
     * Deregister a relation definition from the managed object definition.
     * <p>
     * This method <b>must not</b> be called by applications and is only
     * intended for internal testing.
     *
     * @param d
     *            The relation definition to be deregistered.
     */
    final void deregisterRelationDefinition(RelationDefinition<?, ?> d) {
        // Deregister the relation from this managed object definition.
        String relName = d.getName();
        relationDefinitions.remove(relName);
        allRelationDefinitions.remove(relName);
        // Now deregister the relation from the referenced managed object
        // definition for reverse lookups.
        d.getChildDefinition().reverseRelationDefinitions.remove(d);
    }
    /**
     * Register this managed object definition in its parent.
     * <p>
     * This method <b>must not</b> be called by applications and is only
     * intended for internal testing.
     */
    final void registerInParent() {
        if (parent != null) {
            parent.children.put(name, this);
        }
    }
    // Register a relation definition in the referenced managed object
    // definition's reverse lookup table.
    private <CC extends ConfigurationClient, SS extends Configuration> void registerReverseRelationDefinition(
            RelationDefinition<CC, SS> rd) {
        rd.getChildDefinition().reverseRelationDefinitions.add(rd);
    }
    // Register a aggregation property definition in the referenced managed
    // object
    // definition's reverse lookup table.
    private void registerReverseAggregationPropertyDefinition(AggregationPropertyDefinition<?, ?> apd) {
        apd.getRelationDefinition().getChildDefinition().reverseAggregationPropertyDefinitions.add(apd);
    }
    // Recursively descend definition hierarchy to find the best match
    // definition.
    private AbstractManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinitionAux(
            AbstractManagedObjectDefinition<? extends C, ? extends S> d, DefinitionResolver r) {
        if (!r.matches(d)) {
            return null;
        }
        for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : d.getChildren()) {
            AbstractManagedObjectDefinition<? extends C, ? extends S> rd = resolveManagedObjectDefinitionAux(child, r);
            if (rd != null) {
                return rd;
            }
        }
        return d;
    }
}