/* * 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 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 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 * * * Copyright 2009 Sun Microsystems, Inc. */ 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 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; // The set of user defined names for this definition. private final List names; // Indicates whether this definition is declared "obsolete". private final boolean isObsolete; // The name form for this DIT structure rule. private final String nameFormOID; // The set of superior DIT structure rules. private final Set superiorRuleIDs; // The definition string used to create this objectclass. private final String definition; private NameForm nameForm; private Set superiorRules = Collections.emptySet(); // Indicates whether or not validation has been performed. private boolean needsValidating = true; // The indicates whether or not validation failed. private boolean isValid = false; DITStructureRule(final Integer ruleID, final List names, final String description, final boolean obsolete, final String nameFormOID, final Set superiorRuleIDs, final Map> 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; } else { this.definition = buildDefinition(); } } /** * Returns {@code true} if the provided object is a DIT structure rule * having the same rule ID as this DIT structure rule. * * @param o * The object to be compared. * @return {@code true} if the provided object is a DIT structure rule * having the same rule ID as this DIT structure rule. */ @Override public boolean equals(final Object o) { if (this == o) { return true; } else if (o instanceof DITStructureRule) { final DITStructureRule other = (DITStructureRule) o; return ruleID.equals(other.ruleID); } else { return false; } } /** * 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(); } 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 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 getSuperiorRules() { return superiorRules; } /** * Returns the hash code for this DIT structure rule. It will be calculated * as the hash code of the rule ID. * * @return The hash code for this DIT structure rule. */ @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 true if the specified name is assigned to this * schema definition, or false 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 true if this schema definition is declared * "obsolete", or false 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; } DITStructureRule duplicate() { return new DITStructureRule(ruleID, names, description, isObsolete, nameFormOID, superiorRuleIDs, extraProperties, definition); } @Override void toStringContent(final StringBuilder buffer) { buffer.append(ruleID); if (!names.isEmpty()) { final Iterator 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("'"); } } 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 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); } } } boolean validate(final Schema schema, final List invalidSchemaElements, final List 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(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 invalidSchemaElements, final List warnings, final LocalizableMessage message) { invalidSchemaElements.add(this); warnings.add(ERR_DSR_VALIDATION_FAIL.get(toString(), message)); } }