/* * 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-2015 ForgeRock AS */ package org.opends.server.types; import java.util.Collection; import java.util.List; import java.util.Map; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.ldap.schema.AttributeUsage; import org.forgerock.opendj.ldap.schema.Syntax; import org.forgerock.opendj.ldap.schema.MatchingRule; import org.opends.server.core.DirectoryServer; import static org.forgerock.util.Reject.*; import static org.opends.server.util.ServerConstants.*; /** * 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. * <p> * 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 <code>names</code> passed to the constructor. * <p> * 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 Comparable<AttributeType> { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** The approximate matching rule for this attribute type. */ private final MatchingRule approximateMatchingRule; /** The syntax for this attribute type. */ private final Syntax 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 definition string used to create this attribute type. */ private final String definition; /** The equality matching rule for this attribute type. */ private final MatchingRule equalityMatchingRule; /** The ordering matching rule for this attribute type. */ private final MatchingRule orderingMatchingRule; /** The substring matching rule for this attribute type. */ private final MatchingRule substringMatchingRule; /** True once this attribute type has been removed from the schema. */ private volatile boolean isDirty; /** * Creates a new attribute type with the provided information. * <p> * If no <code>primaryName</code> is specified, but a set of * <code>names</code> is specified, then the first name retrieved * from the set of <code>names</code> 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 * <code>null</code> if there is no primary name. * @param typeNames * The full set of names for this attribute type, or * <code>null</code> 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 * <code>null</code> if there is no description. * @param superiorType * The reference to the superior type for this attribute * type, or <code>null</code> if there is no superior * type. * @param syntax * The syntax for this attribute type, or <code>null</code> * if there is no syntax. * @param attributeUsage * The attribute usage for this attribute type, or * <code>null</code> 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<String> typeNames, String oid, String description, AttributeType superiorType, Syntax 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. * <p> * If no <code>primaryName</code> is specified, but a set of * <code>names</code> is specified, then the first name retrieved * from the set of <code>names</code> 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 * <code>null</code> if there is no primary name. * @param typeNames * The full set of names for this attribute type, or * <code>null</code> 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 * <code>null</code> if there is no description. * @param superiorType * The reference to the superior type for this attribute * type, or <code>null</code> if there is no superior * type. * @param syntax * The syntax for this attribute type, or <code>null</code> * if there is no syntax. * @param approximateMatchingRule * The approximate matching rule for this attribute type, * or <code>null</code> if there is no rule. * @param equalityMatchingRule * The equality matching rule for this attribute type, or * <code>null</code> if there is no rule. * @param orderingMatchingRule * The ordering matching rule for this attribute type, or * <code>null</code> if there is no rule. * @param substringMatchingRule * The substring matching rule for this attribute type, or * <code>null</code> if there is no rule. * @param attributeUsage * The attribute usage for this attribute type, or * <code>null</code> 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 * <code>null</code> if there are no extra properties. */ public AttributeType(String definition, String primaryName, Collection<String> typeNames, String oid, String description, AttributeType superiorType, Syntax syntax, MatchingRule approximateMatchingRule, MatchingRule equalityMatchingRule, MatchingRule orderingMatchingRule, MatchingRule substringMatchingRule, AttributeUsage attributeUsage, boolean isCollective, boolean isNoUserModification, boolean isObsolete, boolean isSingleValue, Map<String,List<String>> extraProperties) { super(primaryName, typeNames, oid, description, isObsolete, extraProperties); ifNull(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) { logger.traceException(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; } 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 superior type for this attribute type. * * @return The superior type for this attribute type, or * <CODE>null</CODE> 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 Syntax getSyntax() { return syntax; } /** * 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 MatchingRule 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 MatchingRule 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 MatchingRule 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 MatchingRule 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 <CODE>true</CODE> if this is an operational attribute, * or <CODE>false</CODE> if not. */ public boolean isOperational() { return isOperational; } /** * Indicates whether this attribute type is declared "collective". * * @return <CODE>true</CODE> if this attribute type is declared * "collective", or <CODE>false</CODE> if not. */ public boolean isCollective() { return isCollective; } /** * Indicates whether this attribute type is declared * "no-user-modification". * * @return <CODE>true</CODE> if this attribute type is declared * "no-user-modification", or <CODE>false</CODE> if not. */ public boolean isNoUserModification() { return isNoUserModification; } /** * Indicates whether this attribute type is declared "single-value". * * @return <CODE>true</CODE> if this attribute type is declared * "single-value", or <CODE>false</CODE> 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 <CODE>true</CODE> if this attribute type is the * objectclass type, or <CODE>false</CODE> if not. */ public boolean isObjectClass() { return isObjectClassType; } /** {@inheritDoc} */ @Override public String toString() { return definition; } /** {@inheritDoc} */ @Override 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; } }