/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2007-2010 Sun Microsystems, Inc. * Portions Copyright 2015-2016 ForgeRock AS. */ package org.forgerock.opendj.config; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.Set; import java.util.TreeMap; import java.util.Vector; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.opendj.config.DefinitionDecodingException.Reason; /** * Defines the structure of an abstract managed object. Abstract managed objects * cannot be instantiated. *
* Applications can query a managed object definition in order to determine the
* overall configuration model of an application.
*
* @param
* This method must not be called by applications.
*
* @param constraint
* The constraint to be registered.
*/
protected final void registerConstraint(Constraint constraint) {
constraints.add(constraint);
}
/**
* Register a property definition with this managed object definition,
* overriding any existing property definition with the same name.
*
* This method must not be called by applications.
*
* @param d
* The property definition to be registered.
*/
protected final void registerPropertyDefinition(PropertyDefinition> d) {
String propName = d.getName();
propertyDefinitions.put(propName, d);
allPropertyDefinitions.put(propName, d);
if (d instanceof AggregationPropertyDefinition, ?>) {
AggregationPropertyDefinition, ?> apd = (AggregationPropertyDefinition, ?>) d;
aggregationPropertyDefinitions.put(propName, apd);
// The key must also contain the managed object name, since several
// MOs
// in an inheritance tree may aggregate the same aggregation
// property name
allAggregationPropertyDefinitions.put(apd.getManagedObjectDefinition().getName() + ":" + propName, apd);
}
}
/**
* Register a relation definition with this managed object definition,
* overriding any existing relation definition with the same name.
*
* This method must not be called by applications.
*
* @param d
* The relation definition to be registered.
*/
protected final void registerRelationDefinition(RelationDefinition, ?> d) {
// Register the relation in this managed object definition.
String relName = d.getName();
relationDefinitions.put(relName, d);
allRelationDefinitions.put(relName, d);
// Now register the relation in the referenced managed object
// definition for reverse lookups.
registerReverseRelationDefinition(d);
}
/**
* Register an option with this managed object definition.
*
* This method must not be called by applications.
*
* @param option
* The option to be registered.
*/
protected final void registerOption(ManagedObjectOption option) {
options.add(option);
}
/**
* Register a tag with this managed object definition.
*
* This method must not be called by applications.
*
* @param tag
* The tag to be registered.
*/
protected final void registerTag(Tag tag) {
allTags.add(tag);
}
/**
* Deregister a constraint from the managed object definition.
*
* This method must not be called by applications and is only
* intended for internal testing.
*
* @param constraint
* The constraint to be deregistered.
*/
final void deregisterConstraint(Constraint constraint) {
if (!constraints.remove(constraint)) {
throw new RuntimeException("Failed to deregister a constraint");
}
}
/**
* Deregister a relation definition from the managed object definition.
*
* This method must not be called by applications and is only
* intended for internal testing.
*
* @param d
* The relation definition to be deregistered.
*/
final void deregisterRelationDefinition(RelationDefinition, ?> d) {
// Deregister the relation from this managed object definition.
String relName = d.getName();
relationDefinitions.remove(relName);
allRelationDefinitions.remove(relName);
// Now deregister the relation from the referenced managed object
// definition for reverse lookups.
d.getChildDefinition().reverseRelationDefinitions.remove(d);
}
/**
* Register this managed object definition in its parent.
*
* This method must not be called by applications and is only
* intended for internal testing.
*/
final void registerInParent() {
if (parent != null) {
parent.children.put(name, this);
}
}
/**
* Register a relation definition in the referenced managed object
* definition's reverse lookup table.
*/
private
* The type of server managed object configuration that this
* definition represents.
*/
public abstract class AbstractManagedObjectDefinitionnull if there is no
* parent (only the {@link TopCfgDefn} should have a
* null parent, unless the definition is being used
* for testing).
*/
protected AbstractManagedObjectDefinition(String name,
AbstractManagedObjectDefinition super C, ? super S> parent) {
this.name = name;
this.parent = parent;
// If we have a parent definition then inherit its features.
if (parent != null) {
registerInParent();
for (PropertyDefinition> pd : parent.getAllPropertyDefinitions()) {
allPropertyDefinitions.put(pd.getName(), pd);
}
for (RelationDefinition, ?> rd : parent.getAllRelationDefinitions()) {
allRelationDefinitions.put(rd.getName(), rd);
}
for (AggregationPropertyDefinition, ?> apd : parent.getAllAggregationPropertyDefinitions()) {
allAggregationPropertyDefinitions.put(apd.getName(), apd);
}
// Tag inheritance is performed during preprocessing.
}
}
/**
* Get all the child managed object definitions which inherit from this
* managed object definition.
*
* @return Returns an unmodifiable collection containing all the subordinate
* managed object definitions which inherit from this managed object
* definition.
*/
public final Collectionnull if there is no description.
* @throws UnsupportedOperationException
* If this managed object definition is the {@link TopCfgDefn}.
*/
public final LocalizableMessage getDescription() {
return getDescription(Locale.getDefault());
}
/**
* Gets the optional description of this managed object definition in the
* specified locale.
*
* @param locale
* The locale.
* @return Returns the description of this managed object definition in the
* specified locale, or null if there is no
* description.
* @throws UnsupportedOperationException
* If this managed object definition is the {@link TopCfgDefn}.
*/
public final LocalizableMessage getDescription(Locale locale) {
try {
return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, "description", locale);
} catch (MissingResourceException e) {
return null;
}
}
/**
* Get the name of the definition.
*
* @return Returns the name of the definition.
*/
public final String getName() {
return name;
}
/**
* Get the parent managed object definition, if applicable.
*
* @return Returns the parent of this managed object definition, or
* null if this definition is the {@link TopCfgDefn}.
*/
public final AbstractManagedObjectDefinition super C, ? super S> getParent() {
return parent;
}
/**
* Get the specified property definition associated with this type of
* managed object. The search will include any inherited property
* definitions.
*
* @param name
* The name of the property definition to be retrieved.
* @return Returns the specified property definition associated with this
* type of managed object.
* @throws IllegalArgumentException
* If the specified property name was null or empty or if the
* requested property definition was not found.
*/
public final PropertyDefinition> getPropertyDefinition(String name) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("null or empty property name");
}
PropertyDefinition> d = allPropertyDefinitions.get(name);
if (d == null) {
throw new IllegalArgumentException("property definition \"" + name + "\" not found");
}
return d;
}
/**
* Get the property definitions defined by this managed object definition.
* The returned collection will not contain inherited property definitions.
*
* @return Returns an unmodifiable collection containing the property
* definitions defined by this managed object definition.
*/
public final Collectiontrue if this type of managed object has any
* child managed object definitions, false otherwise.
*/
public final boolean hasChildren() {
return !children.isEmpty();
}
/**
* Determines whether this managed object definition has the
* specified option.
*
* @param option
* The option to test.
* @return Returns true if the option is set, or
* false otherwise.
*/
public final boolean hasOption(ManagedObjectOption option) {
return options.contains(option);
}
/**
* Determines whether this managed object definition has the
* specified tag.
*
* @param t
* The tag definition.
* @return Returns true if this managed object definition has
* the specified tag.
*/
public final boolean hasTag(Tag t) {
return allTags.contains(t);
}
/**
* Determines whether this managed object definition is a sub-type of
* the provided managed object definition. This managed object definition is
* a sub-type of the provided managed object definition if they are both the
* same or if the provided managed object definition can be obtained by
* recursive invocations of the {@link #getParent()} method.
*
* @param d
* The managed object definition to be checked.
* @return Returns true if this managed object definition is a
* sub-type of the provided managed object definition.
*/
public final boolean isChildOf(AbstractManagedObjectDefinition, ?> d) {
AbstractManagedObjectDefinition, ?> i;
for (i = this; i != null; i = i.parent) {
if (i == d) {
return true;
}
}
return false;
}
/**
* Determines whether this managed object definition is a super-type
* of the provided managed object definition. This managed object definition
* is a super-type of the provided managed object definition if they are
* both the same or if the provided managed object definition is a member of
* the set of children returned from {@link #getAllChildren()}.
*
* @param d
* The managed object definition to be checked.
* @return Returns true if this managed object definition is a
* super-type of the provided managed object definition.
*/
public final boolean isParentOf(AbstractManagedObjectDefinition, ?> d) {
return d.isChildOf(this);
}
/**
* Determines whether this managed object definition is the {@link TopCfgDefn}.
*
* @return Returns true if this managed object definition is
* the {@link TopCfgDefn}.
*/
public final boolean isTop() {
return this instanceof TopCfgDefn;
}
/**
* Finds a sub-type of this managed object definition which most closely
* corresponds to the matching criteria of the provided definition resolver.
*
* @param r
* The definition resolver.
* @return Returns the sub-type of this managed object definition which most
* closely corresponds to the matching criteria of the provided
* definition resolver.
* @throws DefinitionDecodingException
* If no matching sub-type could be found or if the resolved
* definition was abstract.
* @see DefinitionResolver
*/
public final ManagedObjectDefinition extends C, ? extends S> resolveManagedObjectDefinition(DefinitionResolver r)
throws DefinitionDecodingException {
AbstractManagedObjectDefinition extends C, ? extends S> rd;
rd = resolveManagedObjectDefinitionAux(this, r);
if (rd == null) {
// Unable to resolve the definition.
throw new DefinitionDecodingException(this, Reason.WRONG_TYPE_INFORMATION);
} else if (rd instanceof ManagedObjectDefinition) {
return (ManagedObjectDefinition extends C, ? extends S>) rd;
} else {
// Resolved definition was abstract.
throw new DefinitionDecodingException(this, Reason.ABSTRACT_TYPE_INFORMATION);
}
}
@Override
public final String toString() {
StringBuilder builder = new StringBuilder();
toString(builder);
return builder.toString();
}
/**
* Append a string representation of the managed object definition to the
* provided string builder.
*
* @param builder
* The string builder where the string representation should be
* appended.
*/
public final void toString(StringBuilder builder) {
builder.append(getName());
}
/**
* Initializes all of the components associated with this managed object
* definition.
*
* @throws Exception
* If this managed object definition could not be initialized.
*/
protected final void initialize() throws Exception {
for (PropertyDefinition> pd : getAllPropertyDefinitions()) {
pd.initialize();
pd.getDefaultBehaviorProvider().initialize();
}
for (RelationDefinition, ?> rd : getAllRelationDefinitions()) {
rd.initialize();
}
for (AggregationPropertyDefinition, ?> apd : getAllAggregationPropertyDefinitions()) {
apd.initialize();
/*
* Now register the aggregation property in the referenced managed
* object definition for reverse lookups.
*/
registerReverseAggregationPropertyDefinition(apd);
}
for (Constraint constraint : getAllConstraints()) {
constraint.initialize();
}
}
/**
* Register a constraint with this managed object definition.
*