/*
* 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;
}
}