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

matthew_swift
14.21.2007 25c232dabcfbaebb8295916bed92a56d9a18966f
Add support for tagging managed object definitions so that similar types of managed object can be grouped together. Tagging will enable us to automatically generate more user-friendly documentation and administration tools as a result of them being easier to navigate and search. For example, an administration CLI will be able to split the available set of sub-commands into categories, thus making it easier for administrators to find the sub-command that they need.

This change is implemented as follows:

* provide an extensible way in which tags can be defined: the XML root configuration definition element now supports an "adm:tag-definition" element, which can be used as follows:

<adm:tag-definition name="logging">
<adm:synopsis>Logging</adm:synopsis>
</adm:tag-definition>

* provide a means for tagging managed object definitions with zero or more tags using an "adm:tag" element, which can be used as follows:

<adm:tag name="logging"/>

* add support to the admin framework APIs for querying a managed object definition's tags

* define an initial set of tags and tag managed object definitions appropriately (this is just an initial guess and is likely to change):

* logging
* replication (incl. mmr)
* database (incl. caching)
* security (authn and authz)
* identity (user account management, pwp, etc)
* core (connection handlers, virtual attributes, etc)
1 files added
30 files modified
592 ■■■■■ changed files
opends/resource/admin/admin.xsd 84 ●●●●● patch | view | raw | blame | history
opends/resource/admin/messagesMO.xsl 10 ●●●●● patch | view | raw | blame | history
opends/resource/admin/metaMO.xsl 36 ●●●●● patch | view | raw | blame | history
opends/resource/admin/preprocessor.xsl 81 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/AccessControlHandlerConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/CertificateMapperConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/ConnectionHandlerConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/DebugTargetConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/ExtendedOperationHandlerConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/IdentityMapperConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/LogRetentionPolicyConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/LogRotationPolicyConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordGeneratorConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordValidatorConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PluginConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/ReplicationServerConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml 18 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/RootDSEBackendConfiguration.xml 2 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/SASLMechanismHandlerConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/VirtualAttributeConfiguration.xml 1 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java 122 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/Tag.java 211 ●●●●● patch | view | raw | blame | history
opends/resource/admin/admin.xsd
@@ -75,6 +75,31 @@
          </xsd:documentation>
        </xsd:annotation>
      </xsd:element>
      <xsd:element name="tag" minOccurs="0" maxOccurs="unbounded">
        <xsd:annotation>
          <xsd:documentation>
            The name of a tag defined in the root configuration
            definition. Tags can be used to group related managed object
            definitions together. For example, all managed objects that
            are associated with password management might be tagged with
            "password" (assuming that there is a "password" tag defined
            in the root configuration). Tags are inherited by derived
            managed object definitions.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:attribute name="name" type="tns:name-type"
            use="required">
            <xsd:annotation>
              <xsd:documentation>
                The name of the referenced tag. There must be an
                accompanying tag definition in the root configuration
                definition.
              </xsd:documentation>
            </xsd:annotation>
          </xsd:attribute>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="profile" type="tns:profile-type" minOccurs="0"
        maxOccurs="unbounded">
        <xsd:annotation>
@@ -1419,6 +1444,65 @@
                </xsd:restriction>
              </xsd:simpleType>
            </xsd:element>
            <xsd:element name="tag-definition" minOccurs="0"
              maxOccurs="unbounded">
              <xsd:annotation>
                <xsd:documentation>
                  Defines a tag which can be used to group related types
                  of managed object. Administration tools can take
                  advantage of managed object tags to make it easier for
                  users to discover related components.
                </xsd:documentation>
              </xsd:annotation>
              <xsd:complexType>
                <xsd:sequence>
                  <xsd:element name="synopsis">
                    <xsd:annotation>
                      <xsd:documentation>
                        A brief description of this tag. The description
                        should describe, preferably in one sentence, the
                        types of managed object that this tag applies
                        to. The synopsis should be suitable for use in
                        applications such as tool-tips, CLI help, and
                        the summary description in Javadoc. It is
                        possible to embed rich content including XHTML
                        markup (this will only be used where supported).
                      </xsd:documentation>
                    </xsd:annotation>
                    <xsd:complexType mixed="true">
                      <xsd:choice minOccurs="0" maxOccurs="unbounded">
                        <xsd:any
                          namespace="http://www.w3.org/1999/xhtml"
                          processContents="lax" />
                        <xsd:element name="product-name">
                          <xsd:annotation>
                            <xsd:documentation>
                              The name of the product associated with
                              this definition.
                            </xsd:documentation>
                          </xsd:annotation>
                          <xsd:complexType />
                        </xsd:element>
                      </xsd:choice>
                    </xsd:complexType>
                  </xsd:element>
                </xsd:sequence>
                <xsd:attribute name="name" type="tns:name-type"
                  use="required">
                  <xsd:annotation>
                    <xsd:documentation>
                      The name of this tag. The name should describe as
                      concisely as possible the purpose of this tag and
                      should be suitable for use in Java method names
                      (e.g. getters and setters). The property name
                      should be a string comprising of short lower-case
                      words joined with hyphens "-". For example,
                      "security".
                    </xsd:documentation>
                  </xsd:annotation>
                </xsd:attribute>
              </xsd:complexType>
            </xsd:element>
          </xsd:sequence>
          <xsd:attribute name="name" type="tns:name-type"
            fixed="root">
opends/resource/admin/messagesMO.xsl
@@ -62,6 +62,16 @@
        select="concat('description=', normalize-space($this/adm:description), '&#xa;')" />
    </xsl:if>
    <!--
      Process tag definitions if this is the root configuration.
    -->
    <xsl:if test="$this-is-root">
      <xsl:for-each select="$this/adm:tag-definition">
        <xsl:sort select="@name" />
        <xsl:value-of
          select="concat('tag.', @name, '.synopsis=', normalize-space(adm:synopsis), '&#xa;')" />
      </xsl:for-each>
    </xsl:if>
    <!--
      Process each property definition.
    -->
    <xsl:for-each select="$this-all-properties">
opends/resource/admin/metaMO.xsl
@@ -92,6 +92,21 @@
      <xsl:call-template name="generate-enumeration" />
    </xsl:for-each>
    <!--
      Define application tags if this is the root configuration.
    -->
    <xsl:if test="$this-is-root">
      <xsl:text>&#xa;</xsl:text>
      <xsl:text>&#xa;</xsl:text>
      <xsl:text>&#xa;</xsl:text>
      <xsl:value-of select="'  // Define managed object tags.&#xa;'"/>
      <xsl:value-of select="'  static {&#xa;'"/>
      <xsl:for-each select="$this/adm:tag-definition">
        <xsl:sort select="@name" />
        <xsl:value-of select="concat('    Tag.define(&quot;', @name, '&quot;);&#xa;')"/>
      </xsl:for-each>
      <xsl:value-of select="'  }&#xa;'"/>
    </xsl:if>
    <!--
      Generate declarations for properties defined or
      overridden by this managed object.
    -->
@@ -134,6 +149,21 @@
      <xsl:call-template name="generate-relation-constructor" />
    </xsl:for-each>
    <!--
      Register any tags associated with this managed object definition.
    -->
    <xsl:if test="$this/adm:tag">
      <xsl:text>&#xa;</xsl:text>
      <xsl:text>&#xa;</xsl:text>
      <xsl:text>&#xa;</xsl:text>
      <xsl:value-of select="'  // Register the tags associated with this managed object definition.&#xa;'"/>
      <xsl:value-of select="'  static {&#xa;'"/>
      <xsl:for-each select="$this/adm:tag">
        <xsl:sort select="@name" />
        <xsl:value-of select="concat('    INSTANCE.registerTag(Tag.valueOf(&quot;', @name, '&quot;));&#xa;')"/>
      </xsl:for-each>
      <xsl:value-of select="'  }&#xa;'"/>
    </xsl:if>
    <!--
      Configuration definition singleton getter.
    -->
    <xsl:text>&#xa;</xsl:text>
@@ -603,7 +633,8 @@
      </xsl:message>
    </xsl:if>
    <xsl:choose>
      <xsl:when test="not(adm:default-behavior) or adm:default-behavior/adm:undefined">
      <xsl:when
        test="not(adm:default-behavior) or adm:default-behavior/adm:undefined">
        <xsl:value-of
          select="concat('      builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider&lt;', $value-type,'&gt;());&#xa;')" />
      </xsl:when>
@@ -1591,6 +1622,9 @@
                                       @mandatory='true']">
          <import>org.opends.server.admin.PropertyOption</import>
        </xsl:if>
        <xsl:if test="$this/adm:tag-definition or $this/adm:tag">
          <import>org.opends.server.admin.Tag</import>
        </xsl:if>
        <xsl:if
          test="$this-local-properties[adm:default-behavior/adm:undefined or not(adm:default-behavior)]">
          <import>
opends/resource/admin/preprocessor.xsl
@@ -166,12 +166,29 @@
        Pre-process this managed object's elements.
      -->
      <xsl:apply-templates
        select="adm:TODO|adm:synopsis|adm:description|adm:profile"
        select="adm:TODO|adm:synopsis|adm:description"
        mode="pre-process">
        <xsl:with-param name="moname" select="@name" />
        <xsl:with-param name="mopackage" select="@package" />
        <xsl:with-param name="hierarchy" select="$hierarchy" />
      </xsl:apply-templates>
      <!--
        Copy all inherited tags plus locally defined tags.
      -->
      <xsl:copy-of select="$hierarchy/adm:managed-object/adm:tag" />
      <xsl:apply-templates select="adm:tag" mode="pre-process">
        <xsl:with-param name="moname" select="@name" />
        <xsl:with-param name="mopackage" select="@package" />
        <xsl:with-param name="hierarchy" select="$hierarchy" />
      </xsl:apply-templates>
      <!--
        Copy profile elements.
      -->
      <xsl:apply-templates select="adm:profile" mode="pre-process">
        <xsl:with-param name="moname" select="@name" />
        <xsl:with-param name="mopackage" select="@package" />
        <xsl:with-param name="hierarchy" select="$hierarchy" />
      </xsl:apply-templates>
      <!-- 
        Add a pre-processor element defining this managed object's uppermost
        definition.
@@ -249,6 +266,68 @@
    </xsl:copy>
  </xsl:template>
  <!--
    Pre-process a tag and validate it and by adding a "preprocessor"
    profile which contains information about where the tag was defined.
  -->
  <xsl:template match="adm:tag" mode="pre-process">
    <xsl:param name="mopackage" select="/.." />
    <xsl:param name="moname" select="/.." />
    <xsl:param name="hierarchy" />
    <!--
      Make sure that this tag is not duplicated.
    -->
    <xsl:variable name="name" select="@name" />
    <xsl:if test="../adm:tag[@name=$name][2]">
      <xsl:message terminate="yes">
        <xsl:value-of
          select="concat('Tag ', @name, ' is already defined in this managed object')" />
      </xsl:message>
    </xsl:if>
    <!--
      Make sure that this tag does not override an existing tag.
    -->
    <xsl:if test="$hierarchy/adm:managed-object/adm:tag[@name=$name]">
      <xsl:message terminate="yes">
        <xsl:value-of
          select="concat('Tag ', @name, ' is already defined in a parent managed object')" />
      </xsl:message>
    </xsl:if>
    <!--
      Get the referenced package.
    -->
    <xsl:variable name="uri">
      <xsl:call-template name="get-managed-object-uri">
        <xsl:with-param name="package"
          select="'org.opends.server.admin.std'" />
        <xsl:with-param name="name" select="'root'" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:if test="not(document($uri)/adm:root-managed-object)">
      <xsl:message terminate="yes">
        <xsl:value-of
          select="concat('Root managed object definition not found in ', $uri, '.')" />
      </xsl:message>
    </xsl:if>
    <xsl:if
      test="not(document($uri)/adm:root-managed-object/adm:tag-definition[@name=$name])">
      <xsl:message terminate="yes">
        <xsl:value-of
          select="concat('Tag &quot;', $name,
                           '&quot; not defined in root managed object definition.')" />
      </xsl:message>
    </xsl:if>
    <!--
      Copy the tag.
    -->
    <xsl:element name="adm:tag">
      <xsl:copy-of select="@*" />
      <xsl:apply-templates mode="pre-process">
        <xsl:with-param name="moname" select="$moname" />
        <xsl:with-param name="mopackage" select="$mopackage" />
      </xsl:apply-templates>
    </xsl:element>
  </xsl:template>
  <!--
    Pre-process a property definition by adding a "preprocessor" profile
    which contains information about where the property was defined.
  -->
opends/src/admin/defn/org/opends/server/admin/std/AccessControlHandlerConfiguration.xml
@@ -35,6 +35,7 @@
    <adm:user-friendly-plural-name />
     manage the application-wide access-control.
  </adm:synopsis>
  <adm:tag name="security"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.1</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/AccountStatusNotificationHandlerConfiguration.xml
@@ -42,6 +42,8 @@
    may be used to notify the user and/or administrators of the change.
  </adm:synopsis>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.75</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml
@@ -39,6 +39,7 @@
    external system), or generated on the fly (e.g., calculated from other
    information that is available).
  </adm:synopsis>
  <adm:tag name="database"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.5</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/CertificateMapperConfiguration.xml
@@ -36,6 +36,8 @@
    certificate and the entry for the user that corresponds to that
    certificate.
  </adm:synopsis>
  <adm:tag name="security"/>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.12</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/ConnectionHandlerConfiguration.xml
@@ -37,6 +37,7 @@
    including accepting the connections, reading requests, and sending
    responses.
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.13</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/DebugTargetConfiguration.xml
@@ -8,6 +8,7 @@
    <adm:user-friendly-plural-name />
    define the types of messages logged by the debug logPublisher.
  </adm:synopsis>
  <adm:tag name="logging"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.101</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
@@ -38,6 +38,8 @@
    defines a Directory Server entry cache.
  </adm:synopsis>
  <adm:tag name="database"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.15</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/ExtendedOperationHandlerConfiguration.xml
@@ -38,6 +38,7 @@
    are responsible for all processing of different types of extended
    operations in the server.
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.18</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -36,6 +36,7 @@
    <adm:product-name />
    .
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.13</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/IdentityMapperConfiguration.xml
@@ -36,6 +36,8 @@
    are responsible for establishing a mapping between an identifier string and
    the entry for the user that corresponds to that identifier.
  </adm:synopsis>
  <adm:tag name="security"/>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.55</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/LogPublisherConfiguration.xml
@@ -9,6 +9,7 @@
    are reponsible for distributing log messages from different loggers to
    a destination.
  </adm:synopsis>
  <adm:tag name="logging"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.22</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/LogRetentionPolicyConfiguration.xml
@@ -10,6 +10,7 @@
    <adm:user-friendly-plural-name /> are used to specify when log files should
    be cleaned.
  </adm:synopsis>
  <adm:tag name="logging"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.102</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/LogRotationPolicyConfiguration.xml
@@ -10,6 +10,7 @@
    <adm:user-friendly-plural-name /> are used to specify when log files should
    be rotated.
  </adm:synopsis>
  <adm:tag name="logging"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.106</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
@@ -37,6 +37,7 @@
    is used to provide Multimaster Replication of several OpenDS copies
    of the same data
  </adm:synopsis>
  <adm:tag name="replication"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.58</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/PasswordGeneratorConfiguration.xml
@@ -35,6 +35,7 @@
    are used by the password modify extended operation to construct
    a new password for the user.
  </adm:synopsis>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.60</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
@@ -34,6 +34,7 @@
    Define a number of password management rules, as well as
    requirements for authentication processing.
  </adm:synopsis>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.62</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/PasswordStorageSchemeConfiguration.xml
@@ -39,6 +39,8 @@
    defines a module that implements a password storage scheme.
  </adm:synopsis>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.35</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/PasswordValidatorConfiguration.xml
@@ -35,6 +35,7 @@
    are responsible for determining whether proposed passwords are acceptable
    for use.
  </adm:synopsis>
  <adm:tag name="identity"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.36</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/PluginConfiguration.xml
@@ -38,6 +38,7 @@
    establishment and termination, server startup and shutdown, and LDIF import
    and export.
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.37</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/ReplicationServerConfiguration.xml
@@ -36,6 +36,7 @@
    is the server to which Multimaster Domain connects to publish and
    receive changes to or from other Multimaster Domains.
  </adm:synopsis>
  <adm:tag name="replication"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.65</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -304,4 +304,22 @@
    </adm:profile>
  </adm:relation>
  <adm:product-name>OpenDS Directory Server</adm:product-name>
  <adm:tag-definition name="logging">
    <adm:synopsis>Logging</adm:synopsis>
  </adm:tag-definition>
  <adm:tag-definition name="identity">
    <adm:synopsis>User management</adm:synopsis>
  </adm:tag-definition>
  <adm:tag-definition name="replication">
    <adm:synopsis>Replication</adm:synopsis>
  </adm:tag-definition>
  <adm:tag-definition name="database">
    <adm:synopsis>Caching and back-ends</adm:synopsis>
  </adm:tag-definition>
  <adm:tag-definition name="security">
    <adm:synopsis>Authentication and authorization</adm:synopsis>
  </adm:tag-definition>
  <adm:tag-definition name="core">
    <adm:synopsis>Core server</adm:synopsis>
  </adm:tag-definition>
</adm:root-managed-object>
opends/src/admin/defn/org/opends/server/admin/std/RootDSEBackendConfiguration.xml
@@ -38,6 +38,8 @@
    entry for base-level searches, and will simply redirect to other backends
    for operations in other scopes.
  </adm:description>
  <adm:tag name="core"/>
  <adm:tag name="database"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.42</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/SASLMechanismHandlerConfiguration.xml
@@ -35,6 +35,7 @@
    <adm:user-friendly-plural-name />
    are responsible for the processing associated with SASL bind operations.
  </adm:synopsis>
  <adm:tag name="security"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.43</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml
@@ -36,6 +36,7 @@
    are responsible for handling Synchronization of the Directory Server
    datas with other OpenDS instances or other data repositories.
  </adm:synopsis>
  <adm:tag name="replication"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.57</ldap:oid>
opends/src/admin/defn/org/opends/server/admin/std/VirtualAttributeConfiguration.xml
@@ -36,6 +36,7 @@
    are responsible for dynamically generating attribute values that appear in
    entries but are not persistently stored in the backend.
  </adm:synopsis>
  <adm:tag name="core"/>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid>
opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -33,10 +33,12 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import org.opends.server.admin.DefinitionDecodingException.Reason;
@@ -81,6 +83,9 @@
  // object definition including inherited relation definitions.
  private final Map<String, RelationDefinition<?, ?>> allRelationDefinitions;
  // The set of tags associated with this managed object.
  private final Set<Tag> allTags;
  // The set of managed object definitions which inherit from this definition.
  private final Map<String,
    AbstractManagedObjectDefinition<? extends C, ? extends S>> children;
@@ -105,6 +110,7 @@
    this.allPropertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
    this.allRelationDefinitions =
      new HashMap<String, RelationDefinition<?, ?>>();
    this.allTags = new HashSet<Tag>();
    this.children = new HashMap<String,
        AbstractManagedObjectDefinition<? extends C, ? extends S>>();
@@ -119,6 +125,8 @@
      for (RelationDefinition<?, ?> rd : parent.getAllRelationDefinitions()) {
        allRelationDefinitions.put(rd.getName(), rd);
      }
      // Tag inheritance is performed during preprocessing.
    }
  }
@@ -180,6 +188,19 @@
  /**
   * 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.
@@ -492,6 +513,21 @@
  /**
   * 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
@@ -538,42 +574,6 @@
  /**
   * Register a property definition with the 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 name = d.getName();
    propertyDefinitions.put(name, d);
    allPropertyDefinitions.put(name, d);
  }
  /**
   * Register a relation definition with the 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) {
    String name = d.getName();
    relationDefinitions.put(name, d);
    allRelationDefinitions.put(name, d);
  }
  /**
   * Finds a sub-type of this managed object definition which most closely
   * corresponds to the matching criteria of the provided definition resolver.
   *
@@ -632,6 +632,56 @@
  /**
   * Register a property definition with the 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 name = d.getName();
    propertyDefinitions.put(name, d);
    allPropertyDefinitions.put(name, d);
  }
  /**
   * Register a relation definition with the 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) {
    String name = d.getName();
    relationDefinitions.put(name, d);
    allRelationDefinitions.put(name, d);
  }
  /**
   * Register a tag with the managed object definition.
   * <p>
   * This method <b>must not</b> be called by applications.
   *
   * @param t
   *          The tag to be registered.
   */
  protected final void registerTag(Tag t) {
    allTags.add(t);
  }
  // Recursively descend definition hierarchy to find the best match definition.
  private AbstractManagedObjectDefinition<? extends C, ? extends S>
      resolveManagedObjectDefinitionAux(
opends/src/server/org/opends/server/admin/Tag.java
New file
@@ -0,0 +1,211 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.util.Validator;
/**
 * An interface for querying the properties of a tag.
 * <p>
 * Tags are used to group related managed objects together into
 * categories.
 */
public final class Tag implements Comparable<Tag> {
  // All the tags.
  private static final Map<String, Tag> tags = new HashMap<String, Tag>();
  /**
   * Defines a new tag with the specified name.
   *
   * @param name
   *          The name of the new tag.
   */
  public static void define(String name) {
    Tag tag = new Tag(name);
    // Register the tag.
    tags.put(name, tag);
  }
  /**
   * Returns the tag associated with the specified name.
   *
   * @param name
   *          The name of the tag.
   * @return Returns the tag associated with the specified name.
   * @throws IllegalArgumentException
   *           If the tag name was not recognized.
   */
  public static Tag valueOf(String name) throws IllegalArgumentException {
    Validator.ensureNotNull(name);
    // Hack to force initialization of the tag definitions.
    RootCfgDefn.getInstance();
    Tag tag = tags.get(name.toLowerCase());
    if (tag == null) {
      throw new IllegalArgumentException("Unknown tag \"" + name + "\"");
    }
    return tag;
  }
  /**
   * Returns an unmodifiable collection view of the set of registered
   * tags.
   *
   * @return Returns an unmodifiable collection view of the set of
   *         registered tags.
   */
  public static Collection<Tag> values() {
    // Hack to force initialization of the tag definitions.
    RootCfgDefn.getInstance();
    return Collections.unmodifiableCollection(tags.values());
  }
  // The name of the tag.
  private final String name;
  // Private constructor.
  private Tag(String name) {
    this.name = name;
  }
  /**
   * {@inheritDoc}
   */
  public final int compareTo(Tag o) {
    return name.compareTo(o.name);
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public final boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj instanceof Tag) {
      Tag other = (Tag) obj;
      return other.name.equals(this.name);
    }
    return false;
  }
  /**
   * Gets the name of this tag.
   *
   * @return Returns the name of this tag.
   */
  public final String getName() {
    return name;
  }
  /**
   * Gets the synopsis of this tag in the default locale.
   *
   * @return Returns the synopsis of this tag in the default locale.
   */
  public final String getSynopsis() {
    return getSynopsis(Locale.getDefault());
  }
  /**
   * Gets the synopsis of this tag in the specified locale.
   *
   * @param locale
   *          The locale.
   * @return Returns the synopsis of this tag in the specified locale.
   */
  public final String getSynopsis(Locale locale) {
    ManagedObjectDefinitionI18NResource resource =
      ManagedObjectDefinitionI18NResource.getInstance();
    String property = "tag." + name + ".synopsis";
    try {
      return resource.getMessage(RootCfgDefn.getInstance(), property, locale);
    } catch (MissingResourceException e) {
      return null;
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public final int hashCode() {
    return name.hashCode();
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public final String toString() {
    return name;
  }
}