/* * 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 2006-2009 Sun Microsystems, Inc. * Portions Copyright 2011-2013 ForgeRock AS */ package org.opends.server.types; import java.util.Collection; import java.util.List; import java.util.Map; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.api.AttributeSyntax; import org.opends.server.api.EqualityMatchingRule; import org.opends.server.api.OrderingMatchingRule; import org.opends.server.api.SubstringMatchingRule; import org.opends.server.core.DirectoryServer; import org.opends.server.schema.AttributeTypeSyntax; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.Validator.*; /** * This class defines a data structure for storing and interacting * with an attribute type, which contains information about the format * of an attribute and the syntax and matching rules that should be * used when interacting with it. *

* Any methods which accesses the set of names associated with this * attribute type, will retrieve the primary name as the first name, * regardless of whether or not it was contained in the original set * of names passed to the constructor. *

* Where ordered sets of names, or extra properties are provided, the * ordering will be preserved when the associated fields are accessed * via their getters or via the {@link #toString()} methods. */ @org.opends.server.types.PublicAPI( stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, mayInstantiate=false, mayExtend=false, mayInvoke=true) public final class AttributeType extends CommonSchemaElements implements SchemaFileElement, Comparable { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); // The approximate matching rule for this attribute type. private final ApproximateMatchingRule approximateMatchingRule; // The syntax for this attribute type. private final AttributeSyntax syntax; // The superior attribute type from which this attribute type // inherits. private final AttributeType superiorType; // The attribute usage for this attribute type. private final AttributeUsage attributeUsage; // Indicates whether this attribute type is declared "collective". private final boolean isCollective; // Indicates whether this attribute type is declared // "no-user-modification". private final boolean isNoUserModification; // Indicates whether this attribute type is the objectclass type. private final boolean isObjectClassType; // Indicates whether this attribute type is operational. private final boolean isOperational; // Indicates whether this attribute type is declared "single-value". private final boolean isSingleValue; // Indicates whether there is a possibility that this attribute type // may have one or more subtypes that list this type or one of its // subtypes as a superior. Note that this variable is intentional // not declared "final", but if it ever gets set to "true", then it // should never be unset back to "false". private boolean mayHaveSubordinateTypes; // The equality matching rule for this attribute type. private final EqualityMatchingRule equalityMatchingRule; // The ordering matching rule for this attribute type. private final OrderingMatchingRule orderingMatchingRule; // The definition string used to create this attribute type. private final String definition; // The OID for the associated syntax. private final String syntaxOID; // The substring matching rule for this attribute type. private final SubstringMatchingRule substringMatchingRule; // True once this attribute type has been removed from the schema. private volatile boolean isDirty = false; /** * Creates a new attribute type with the provided information. *

* If no primaryName is specified, but a set of * names is specified, then the first name retrieved * from the set of names will be used as the primary * name. * * @param definition * The definition string used to create this attribute * type. It must not be {@code null}. * @param primaryName * The primary name for this attribute type, or * null if there is no primary name. * @param typeNames * The full set of names for this attribute type, or * null if there are no names. * @param oid * The OID for this attribute type. It must not be * {@code null}. * @param description * The description for the attribute type, or * null if there is no description. * @param superiorType * The reference to the superior type for this attribute * type, or null if there is no superior * type. * @param syntax * The syntax for this attribute type, or null * if there is no syntax. * @param attributeUsage * The attribute usage for this attribute type, or * null to default to user applications. * @param isCollective * Indicates whether this attribute type is declared * "collective". * @param isNoUserModification * Indicates whether this attribute type is declared * "no-user-modification". * @param isObsolete * Indicates whether this attribute type is declared * "obsolete". * @param isSingleValue * Indicates whether this attribute type is declared * "single-value". */ public AttributeType(String definition, String primaryName, Collection typeNames, String oid, String description, AttributeType superiorType, AttributeSyntax syntax, AttributeUsage attributeUsage, boolean isCollective, boolean isNoUserModification, boolean isObsolete, boolean isSingleValue) { this(definition, primaryName, typeNames, oid, description, superiorType, syntax, null, null, null, null, attributeUsage, isCollective, isNoUserModification, isObsolete, isSingleValue, null); } /** * Creates a new attribute type with the provided information. *

* If no primaryName is specified, but a set of * names is specified, then the first name retrieved * from the set of names will be used as the primary * name. * * @param definition * The definition string used to create this attribute * type. It must not be {@code null}. * @param primaryName * The primary name for this attribute type, or * null if there is no primary name. * @param typeNames * The full set of names for this attribute type, or * null if there are no names. * @param oid * The OID for this attribute type. It must not be * {@code null}. * @param description * The description for the attribute type, or * null if there is no description. * @param superiorType * The reference to the superior type for this attribute * type, or null if there is no superior * type. * @param syntax * The syntax for this attribute type, or null * if there is no syntax. * @param approximateMatchingRule * The approximate matching rule for this attribute type, * or null if there is no rule. * @param equalityMatchingRule * The equality matching rule for this attribute type, or * null if there is no rule. * @param orderingMatchingRule * The ordering matching rule for this attribute type, or * null if there is no rule. * @param substringMatchingRule * The substring matching rule for this attribute type, or * null if there is no rule. * @param attributeUsage * The attribute usage for this attribute type, or * null to default to user applications. * @param isCollective * Indicates whether this attribute type is declared * "collective". * @param isNoUserModification * Indicates whether this attribute type is declared * "no-user-modification". * @param isObsolete * Indicates whether this attribute type is declared * "obsolete". * @param isSingleValue * Indicates whether this attribute type is declared * "single-value". * @param extraProperties * A set of extra properties for this attribute type, or * null if there are no extra properties. */ public AttributeType(String definition, String primaryName, Collection typeNames, String oid, String description, AttributeType superiorType, AttributeSyntax syntax, ApproximateMatchingRule approximateMatchingRule, EqualityMatchingRule equalityMatchingRule, OrderingMatchingRule orderingMatchingRule, SubstringMatchingRule substringMatchingRule, AttributeUsage attributeUsage, boolean isCollective, boolean isNoUserModification, boolean isObsolete, boolean isSingleValue, Map> extraProperties) { super(primaryName, typeNames, oid, description, isObsolete, extraProperties); ensureNotNull(definition, oid); this.superiorType = superiorType; this.isCollective = isCollective; this.isNoUserModification = isNoUserModification; this.isSingleValue = isSingleValue; mayHaveSubordinateTypes = false; int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME); if (schemaFilePos > 0) { String defStr; try { int firstQuotePos = definition.indexOf('\'', schemaFilePos); int secondQuotePos = definition.indexOf('\'', firstQuotePos+1); defStr = definition.substring(0, schemaFilePos).trim() + " " + definition.substring(secondQuotePos+1).trim(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } defStr = definition; } this.definition = defStr; } else { this.definition = definition; } if (syntax == null) { if (superiorType != null) { this.syntax = superiorType.getSyntax(); } else { this.syntax = DirectoryServer.getDefaultAttributeSyntax(); } } else { this.syntax = syntax; } syntaxOID = this.syntax.getOID(); if (approximateMatchingRule == null) { this.approximateMatchingRule = this.syntax.getApproximateMatchingRule(); } else { this.approximateMatchingRule = approximateMatchingRule; } if (equalityMatchingRule == null) { this.equalityMatchingRule = this.syntax.getEqualityMatchingRule(); } else { this.equalityMatchingRule = equalityMatchingRule; } if (orderingMatchingRule == null) { this.orderingMatchingRule = this.syntax.getOrderingMatchingRule(); } else { this.orderingMatchingRule = orderingMatchingRule; } if (substringMatchingRule == null) { this.substringMatchingRule = this.syntax.getSubstringMatchingRule(); } else { this.substringMatchingRule = substringMatchingRule; } if (attributeUsage != null) { this.attributeUsage = attributeUsage; } else { this.attributeUsage = AttributeUsage.USER_APPLICATIONS; } if (oid.equals(OBJECTCLASS_ATTRIBUTE_TYPE_OID)) { isObjectClassType = true; } else { isObjectClassType = hasName(OBJECTCLASS_ATTRIBUTE_TYPE_NAME); } isOperational = this.attributeUsage.isOperational(); } /** * Retrieves the definition string used to create this attribute * type. * * @return The definition string used to create this attribute * type. */ public String getDefinition() { return definition; } /** * Retrieves the definition string used to create this attribute * type and including the X-SCHEMA-FILE extension. * * @return The definition string used to create this attribute * type including the X-SCHEMA-FILE extension. */ public String getDefinitionWithFileName() { if (getSchemaFile() != null) { int pos = definition.lastIndexOf(')'); String defStr = definition.substring(0, pos).trim() + " " + SCHEMA_PROPERTY_FILENAME + " '" + getSchemaFile() + "' )"; return defStr; } else return definition; } /** * {@inheritDoc} */ public AttributeType recreateFromDefinition(Schema schema) throws DirectoryException { ByteString value = ByteString.valueOf(definition); AttributeType at = AttributeTypeSyntax.decodeAttributeType(value, schema, false); at.setSchemaFile(getSchemaFile()); at.mayHaveSubordinateTypes = mayHaveSubordinateTypes; return at; } /** * Retrieves the superior type for this attribute type. * * @return The superior type for this attribute type, or * null if it does not have one. */ public AttributeType getSuperiorType() { return superiorType; } /** * Indicates whether there is a possibility that this attribute type * may have one or more subordinate attribute types defined in the * server schema. This is only intended for use by the * {@code org.opends.server.types.Entry} class for the purpose of * determining whether to check for subtypes when retrieving * attributes. Note that it is possible for this method to report * false positives (if an attribute type that previously had one or * more subordinate types no longer has any), but not false * negatives. * * @return {@code true} if the {@code hasSubordinateTypes} flag has * been set for this attribute type at any time since * startup, or {@code false} if not. */ boolean mayHaveSubordinateTypes() { return mayHaveSubordinateTypes; } /** * Sets a flag indicating that this attribute type may have one or * more subordinate attribute types defined in the server schema. * This is only intended for use by the * {@code org.opends.server.types.Schema} class. */ void setMayHaveSubordinateTypes() { mayHaveSubordinateTypes = true; } /** * Retrieves the syntax for this attribute type. * * @return The syntax for this attribute type. */ public AttributeSyntax getSyntax() { return syntax; } /** * Indicates whether this attribute syntax requires BER encoding. * * @return {@code true} if this syntax required BER encoding. */ public boolean isBinary() { return syntax.isBinary(); } /** * Indicates whether this attribute syntax is human readable. * * @return {@code true} if this syntax is human readable. */ public boolean isHumanReadable() { return syntax.isHumanReadable(); } /** * Retrieves the OID for this syntax associated with this attribute * type. * * @return The OID for this syntax associated with this attribute * type. */ public String getSyntaxOID() { return syntaxOID; } /** * Retrieves the matching rule that should be used for approximate * matching with this attribute type. * * @return The matching rule that should be used for approximate * matching with this attribute type. */ public ApproximateMatchingRule getApproximateMatchingRule() { return approximateMatchingRule; } /** * Retrieves the matching rule that should be used for equality * matching with this attribute type. * * @return The matching rule that should be used for equality * matching with this attribute type. */ public EqualityMatchingRule getEqualityMatchingRule() { return equalityMatchingRule; } /** * Retrieves the matching rule that should be used for ordering with * this attribute type. * * @return The matching rule that should be used for ordering with * this attribute type. */ public OrderingMatchingRule getOrderingMatchingRule() { return orderingMatchingRule; } /** * Retrieves the matching rule that should be used for substring * matching with this attribute type. * * @return The matching rule that should be used for substring * matching with this attribute type. */ public SubstringMatchingRule getSubstringMatchingRule() { return substringMatchingRule; } /** * Retrieves the usage indicator for this attribute type. * * @return The usage indicator for this attribute type. */ public AttributeUsage getUsage() { return attributeUsage; } /** * Indicates whether this is an operational attribute. An * operational attribute is one with a usage of * "directoryOperation", "distributedOperation", or "dSAOperation" * (i.e., only userApplications is not operational). * * @return true if this is an operational attribute, * or false if not. */ public boolean isOperational() { return isOperational; } /** * Indicates whether this attribute type is declared "collective". * * @return true if this attribute type is declared * "collective", or false if not. */ public boolean isCollective() { return isCollective; } /** * Indicates whether this attribute type is declared * "no-user-modification". * * @return true if this attribute type is declared * "no-user-modification", or false if not. */ public boolean isNoUserModification() { return isNoUserModification; } /** * Indicates whether this attribute type is declared "single-value". * * @return true if this attribute type is declared * "single-value", or false if not. */ public boolean isSingleValue() { return isSingleValue; } /** * Indicates whether this attribute type represents the * "objectclass" attribute. The determination will be made based on * the name and/or OID. * * @return true if this attribute type is the * objectclass type, or false if not. */ public boolean isObjectClassType() { return isObjectClassType; } /** * Appends a string representation of this schema definition's * non-generic properties to the provided buffer. * * @param buffer The buffer to which the information should be * appended. */ protected void toStringContent(StringBuilder buffer) { if (superiorType != null) { buffer.append(" SUP "); buffer.append(superiorType.getNameOrOID()); } if (equalityMatchingRule != null) { buffer.append(" EQUALITY "); buffer.append(equalityMatchingRule.getNameOrOID()); } if (orderingMatchingRule != null) { buffer.append(" ORDERING "); buffer.append(orderingMatchingRule.getNameOrOID()); } if (substringMatchingRule != null) { buffer.append(" SUBSTR "); buffer.append(substringMatchingRule.getNameOrOID()); } // NOTE -- We will not include any approximate matching rule // information here because it would break the standard and // anything that depends on it. // FIXME -- Should we encode this into one of the "extra" // properties? if (syntax != null) { buffer.append(" SYNTAX "); buffer.append(syntax.getOID()); } if (isSingleValue) { buffer.append(" SINGLE-VALUE"); } if (isCollective) { buffer.append(" COLLECTIVE"); } if (isNoUserModification) { buffer.append(" NO-USER-MODIFICATION"); } if (attributeUsage != null) { buffer.append(" USAGE "); buffer.append(attributeUsage.toString()); } } /** * {@inheritDoc} */ public int compareTo(AttributeType o) { return getNormalizedPrimaryNameOrOID().compareTo( o.getNormalizedPrimaryNameOrOID()); } /** * Marks this attribute type as dirty, indicating that it has been removed or * replaced in the schema. * * @return A reference to this attribute type. */ public AttributeType setDirty() { isDirty = true; return this; } /** * Returns {@code true} if this attribute type has been removed or replaced in * the schema. * * @return {@code true} if this attribute type has been removed or replaced in * the schema. */ public boolean isDirty() { return isDirty; } }