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

Matthew Swift
25.33.2012 263d085885df024dca9250cc03c807912b0a7662
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java
@@ -6,17 +6,16 @@
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opendj3/legal-notices/CDDLv1_0.txt
 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
 * or http://forgerock.org/license/CDDLv1.0.html.
 * 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/opendj3/legal-notices/CDDLv1_0.txt.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying information:
 * file and include the License file at legal-notices/CDDLv1_0.txt.
 * 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
@@ -27,346 +26,278 @@
package org.forgerock.opendj.ldap.schema;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID;
import static org.forgerock.opendj.ldap.CoreMessages.ERR_DSR_VALIDATION_FAIL;
import static org.forgerock.opendj.ldap.CoreMessages.*;
import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.i18n.LocalizableMessage;
import com.forgerock.opendj.util.Validator;
/**
 * This class defines a DIT structure rule, which is used to indicate the types
 * of children that entries may have.
 */
public final class DITStructureRule extends SchemaElement
{
  // The rule ID for this DIT structure rule.
  private final Integer ruleID;
public final class DITStructureRule extends SchemaElement {
    // The rule ID for this DIT structure rule.
    private final Integer ruleID;
  // The set of user defined names for this definition.
  private final List<String> names;
    // The set of user defined names for this definition.
    private final List<String> names;
  // Indicates whether this definition is declared "obsolete".
  private final boolean isObsolete;
    // Indicates whether this definition is declared "obsolete".
    private final boolean isObsolete;
  // The name form for this DIT structure rule.
  private final String nameFormOID;
    // The name form for this DIT structure rule.
    private final String nameFormOID;
  // The set of superior DIT structure rules.
  private final Set<Integer> superiorRuleIDs;
    // The set of superior DIT structure rules.
    private final Set<Integer> superiorRuleIDs;
  // The definition string used to create this objectclass.
  private final String definition;
    // The definition string used to create this objectclass.
    private final String definition;
  private NameForm nameForm;
  private Set<DITStructureRule> superiorRules = Collections.emptySet();
    private NameForm nameForm;
    private Set<DITStructureRule> superiorRules = Collections.emptySet();
  // Indicates whether or not validation has been performed.
  private boolean needsValidating = true;
    // Indicates whether or not validation has been performed.
    private boolean needsValidating = true;
  // The indicates whether or not validation failed.
  private boolean isValid = false;
    // The indicates whether or not validation failed.
    private boolean isValid = false;
    DITStructureRule(final Integer ruleID, final List<String> names, final String description,
            final boolean obsolete, final String nameFormOID, final Set<Integer> superiorRuleIDs,
            final Map<String, List<String>> extraProperties, final String definition) {
        super(description, extraProperties);
        Validator.ensureNotNull(ruleID, nameFormOID, superiorRuleIDs);
        this.ruleID = ruleID;
        this.names = names;
        this.isObsolete = obsolete;
        this.nameFormOID = nameFormOID;
        this.superiorRuleIDs = superiorRuleIDs;
  DITStructureRule(final Integer ruleID, final List<String> names,
      final String description, final boolean obsolete,
      final String nameFormOID, final Set<Integer> superiorRuleIDs,
      final Map<String, List<String>> extraProperties, final String definition)
  {
    super(description, extraProperties);
    Validator.ensureNotNull(ruleID, nameFormOID, superiorRuleIDs);
    this.ruleID = ruleID;
    this.names = names;
    this.isObsolete = obsolete;
    this.nameFormOID = nameFormOID;
    this.superiorRuleIDs = superiorRuleIDs;
    if (definition != null)
    {
      this.definition = definition;
        if (definition != null) {
            this.definition = definition;
        } else {
            this.definition = buildDefinition();
        }
    }
    else
    {
      this.definition = buildDefinition();
    /**
     * Retrieves the name form for this DIT structure rule.
     *
     * @return The name form for this DIT structure rule.
     */
    public NameForm getNameForm() {
        return nameForm;
    }
  }
  /**
   * Retrieves the name form for this DIT structure rule.
   *
   * @return The name form for this DIT structure rule.
   */
  public NameForm getNameForm()
  {
    return nameForm;
  }
  /**
   * Retrieves the name or rule ID for this schema definition. If it has one or
   * more names, then the primary name will be returned. If it does not have any
   * names, then the OID will be returned.
   *
   * @return The name or OID for this schema definition.
   */
  public String getNameOrRuleID()
  {
    if (names.isEmpty())
    {
      return ruleID.toString();
    /**
     * Retrieves the name or rule ID for this schema definition. If it has one
     * or more names, then the primary name will be returned. If it does not
     * have any names, then the OID will be returned.
     *
     * @return The name or OID for this schema definition.
     */
    public String getNameOrRuleID() {
        if (names.isEmpty()) {
            return ruleID.toString();
        }
        return names.get(0);
    }
    return names.get(0);
  }
  /**
   * Returns an unmodifiable list containing the user-defined names that may be
   * used to reference this schema definition.
   *
   * @return Returns an unmodifiable list containing the user-defined names that
   *         may be used to reference this schema definition.
   */
  public List<String> getNames()
  {
    return names;
  }
  /**
   * Retrieves the rule ID for this DIT structure rule.
   *
   * @return The rule ID for this DIT structure rule.
   */
  public Integer getRuleID()
  {
    return ruleID;
  }
  /**
   * Returns an unmodifiable set containing the superior rules for this DIT
   * structure rule.
   *
   * @return An unmodifiable set containing the superior rules for this DIT
   *         structure rule.
   */
  public Set<DITStructureRule> getSuperiorRules()
  {
    return superiorRules;
  }
  @Override
  public int hashCode()
  {
    return ruleID.hashCode();
  }
  /**
   * Indicates whether this schema definition has the specified name.
   *
   * @param name
   *          The name for which to make the determination.
   * @return <code>true</code> if the specified name is assigned to this schema
   *         definition, or <code>false</code> if not.
   */
  public boolean hasName(final String name)
  {
    for (final String n : names)
    {
      if (n.equalsIgnoreCase(name))
      {
        return true;
      }
    /**
     * Returns an unmodifiable list containing the user-defined names that may
     * be used to reference this schema definition.
     *
     * @return Returns an unmodifiable list containing the user-defined names
     *         that may be used to reference this schema definition.
     */
    public List<String> getNames() {
        return names;
    }
    return false;
  }
    /**
     * Retrieves the rule ID for this DIT structure rule.
     *
     * @return The rule ID for this DIT structure rule.
     */
    public Integer getRuleID() {
        return ruleID;
    }
    /**
     * Returns an unmodifiable set containing the superior rules for this DIT
     * structure rule.
     *
     * @return An unmodifiable set containing the superior rules for this DIT
     *         structure rule.
     */
    public Set<DITStructureRule> getSuperiorRules() {
        return superiorRules;
    }
  /**
   * Indicates whether this schema definition is declared "obsolete".
   *
   * @return <code>true</code> if this schema definition is declared "obsolete",
   *         or <code>false</code> if not.
   */
  public boolean isObsolete()
  {
    return isObsolete;
  }
    @Override
    public int hashCode() {
        return ruleID.hashCode();
    }
    /**
     * Indicates whether this schema definition has the specified name.
     *
     * @param name
     *            The name for which to make the determination.
     * @return <code>true</code> if the specified name is assigned to this
     *         schema definition, or <code>false</code> if not.
     */
    public boolean hasName(final String name) {
        for (final String n : names) {
            if (n.equalsIgnoreCase(name)) {
                return true;
            }
        }
        return false;
    }
    /**
     * Indicates whether this schema definition is declared "obsolete".
     *
     * @return <code>true</code> if this schema definition is declared
     *         "obsolete", or <code>false</code> if not.
     */
    public boolean isObsolete() {
        return isObsolete;
    }
  /**
   * Retrieves the string representation of this schema definition in the form
   * specified in RFC 2252.
   *
   * @return The string representation of this schema definition in the form
   *         specified in RFC 2252.
   */
  @Override
  public String toString()
  {
    return definition;
  }
    /**
     * Retrieves the string representation of this schema definition in the form
     * specified in RFC 2252.
     *
     * @return The string representation of this schema definition in the form
     *         specified in RFC 2252.
     */
    @Override
    public String toString() {
        return definition;
    }
    DITStructureRule duplicate() {
        return new DITStructureRule(ruleID, names, description, isObsolete, nameFormOID,
                superiorRuleIDs, extraProperties, definition);
    }
    @Override
    void toStringContent(final StringBuilder buffer) {
        buffer.append(ruleID);
  DITStructureRule duplicate()
  {
    return new DITStructureRule(ruleID, names, description, isObsolete,
        nameFormOID, superiorRuleIDs, extraProperties, definition);
  }
        if (!names.isEmpty()) {
            final Iterator<String> iterator = names.iterator();
            final String firstName = iterator.next();
            if (iterator.hasNext()) {
                buffer.append(" NAME ( '");
                buffer.append(firstName);
                while (iterator.hasNext()) {
                    buffer.append("' '");
                    buffer.append(iterator.next());
                }
  @Override
  void toStringContent(final StringBuilder buffer)
  {
    buffer.append(ruleID);
    if (!names.isEmpty())
    {
      final Iterator<String> iterator = names.iterator();
      final String firstName = iterator.next();
      if (iterator.hasNext())
      {
        buffer.append(" NAME ( '");
        buffer.append(firstName);
        while (iterator.hasNext())
        {
          buffer.append("' '");
          buffer.append(iterator.next());
                buffer.append("' )");
            } else {
                buffer.append(" NAME '");
                buffer.append(firstName);
                buffer.append("'");
            }
        }
        buffer.append("' )");
      }
      else
      {
        buffer.append(" NAME '");
        buffer.append(firstName);
        buffer.append("'");
      }
    }
    if (description != null && description.length() > 0)
    {
      buffer.append(" DESC '");
      buffer.append(description);
      buffer.append("'");
    }
    if (isObsolete)
    {
      buffer.append(" OBSOLETE");
    }
    buffer.append(" FORM ");
    buffer.append(nameFormOID);
    if (superiorRuleIDs != null && !superiorRuleIDs.isEmpty())
    {
      final Iterator<Integer> iterator = superiorRuleIDs.iterator();
      final Integer firstRule = iterator.next();
      if (iterator.hasNext())
      {
        buffer.append(" SUP ( ");
        buffer.append(firstRule);
        while (iterator.hasNext())
        {
          buffer.append(" ");
          buffer.append(iterator.next());
        if (description != null && description.length() > 0) {
            buffer.append(" DESC '");
            buffer.append(description);
            buffer.append("'");
        }
        buffer.append(" )");
      }
      else
      {
        buffer.append(" SUP ");
        buffer.append(firstRule);
      }
    }
  }
  boolean validate(final Schema schema,
      final List<DITStructureRule> invalidSchemaElements,
      final List<LocalizableMessage> warnings)
  {
    // Avoid validating this schema element more than once. This may occur if
    // multiple rules specify the same superior.
    if (!needsValidating)
    {
      return isValid;
    }
    // Prevent re-validation.
    needsValidating = false;
    try
    {
      nameForm = schema.getNameForm(nameFormOID);
    }
    catch (final UnknownSchemaElementException e)
    {
      final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM
          .get(getNameOrRuleID(), nameFormOID);
      failValidation(invalidSchemaElements, warnings, message);
      return false;
    }
    if (!superiorRuleIDs.isEmpty())
    {
      superiorRules = new HashSet<DITStructureRule>(superiorRuleIDs.size());
      DITStructureRule rule;
      for (final Integer id : superiorRuleIDs)
      {
        try
        {
          rule = schema.getDITStructureRule(id);
        if (isObsolete) {
            buffer.append(" OBSOLETE");
        }
        catch (final UnknownSchemaElementException e)
        {
          final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID
              .get(getNameOrRuleID(), id);
          failValidation(invalidSchemaElements, warnings, message);
          return false;
        buffer.append(" FORM ");
        buffer.append(nameFormOID);
        if (superiorRuleIDs != null && !superiorRuleIDs.isEmpty()) {
            final Iterator<Integer> iterator = superiorRuleIDs.iterator();
            final Integer firstRule = iterator.next();
            if (iterator.hasNext()) {
                buffer.append(" SUP ( ");
                buffer.append(firstRule);
                while (iterator.hasNext()) {
                    buffer.append(" ");
                    buffer.append(iterator.next());
                }
                buffer.append(" )");
            } else {
                buffer.append(" SUP ");
                buffer.append(firstRule);
            }
        }
        superiorRules.add(rule);
      }
    }
    superiorRules = Collections.unmodifiableSet(superiorRules);
    return (isValid = true);
  }
    boolean validate(final Schema schema, final List<DITStructureRule> invalidSchemaElements,
            final List<LocalizableMessage> warnings) {
        // Avoid validating this schema element more than once. This may occur
        // if
        // multiple rules specify the same superior.
        if (!needsValidating) {
            return isValid;
        }
        // Prevent re-validation.
        needsValidating = false;
        try {
            nameForm = schema.getNameForm(nameFormOID);
        } catch (final UnknownSchemaElementException e) {
            final LocalizableMessage message =
                    ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM.get(getNameOrRuleID(), nameFormOID);
            failValidation(invalidSchemaElements, warnings, message);
            return false;
        }
  private void failValidation(final List<DITStructureRule> invalidSchemaElements,
      final List<LocalizableMessage> warnings, final LocalizableMessage message)
  {
    invalidSchemaElements.add(this);
    warnings.add(ERR_DSR_VALIDATION_FAIL.get(toString(), message));
  }
        if (!superiorRuleIDs.isEmpty()) {
            superiorRules = new HashSet<DITStructureRule>(superiorRuleIDs.size());
            DITStructureRule rule;
            for (final Integer id : superiorRuleIDs) {
                try {
                    rule = schema.getDITStructureRule(id);
                } catch (final UnknownSchemaElementException e) {
                    final LocalizableMessage message =
                            ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID.get(getNameOrRuleID(), id);
                    failValidation(invalidSchemaElements, warnings, message);
                    return false;
                }
                superiorRules.add(rule);
            }
        }
        superiorRules = Collections.unmodifiableSet(superiorRules);
        return (isValid = true);
    }
    private void failValidation(final List<DITStructureRule> invalidSchemaElements,
            final List<LocalizableMessage> warnings, final LocalizableMessage message) {
        invalidSchemaElements.add(this);
        warnings.add(ERR_DSR_VALIDATION_FAIL.get(toString(), message));
    }
}