From 02d3bf611bd9d4c33d8ae74d320790cfb0495d8e Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 03 May 2007 09:37:28 +0000
Subject: [PATCH] Three introspection related changes required in order to support the CLI:
---
opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java | 67 ++
opends/src/server/org/opends/server/admin/server/ServerManagedObject.java | 7
opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java | 231 +++++++---
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java | 240 +++++++++++
opends/src/server/org/opends/server/admin/server/DNBuilder.java | 21
opends/src/server/org/opends/server/admin/client/PropertySet.java | 8
opends/src/server/org/opends/server/admin/client/ManagedObject.java | 6
opends/src/server/org/opends/server/admin/ManagedObjectPath.java | 618 +++++++++++++++++++++++-----
opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java | 21
opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java | 24 -
opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java | 11
opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java | 2
opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java | 2
13 files changed, 1,005 insertions(+), 253 deletions(-)
diff --git a/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java b/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
index 608e7d9..b1853a6 100644
--- a/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
+++ b/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -29,9 +29,11 @@
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
@@ -90,52 +92,15 @@
AbstractManagedObjectDefinition<? super C, ? super S> parent) {
this.name = name;
this.parent = parent;
+ this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
+ this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>();
+ this.children = new HashMap<String,
+ AbstractManagedObjectDefinition<? extends C, ? extends S>>();
// If we have a parent definition then inherit its features.
if (parent != null) {
- this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>(
- parent.propertyDefinitions);
- this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>(
- parent.relationDefinitions);
parent.children.put(name, this);
- } else {
- this.propertyDefinitions = new HashMap<String, PropertyDefinition<?>>();
- this.relationDefinitions = new HashMap<String, RelationDefinition<?,?>>();
}
-
- this.children = new HashMap<String,
- AbstractManagedObjectDefinition<? extends C, ? extends S>>();
- }
-
-
-
- /**
- * Get the named child managed object definition which inherits from this
- * managed object definition.
- *
- * @param name
- * The name of the managed object definition sub-type.
- * @return Returns the named child managed object definition which inherits
- * from this managed object definition.
- * @throws IllegalArgumentException
- * If the specified managed object definition name was null or empty
- * or if the requested subordinate managed object definition was not
- * found.
- */
- public final AbstractManagedObjectDefinition<? extends C, ? extends S>
- getChild(String name) throws IllegalArgumentException {
- if ((name == null) || (name.length() == 0)) {
- throw new IllegalArgumentException("null or empty managed object name");
- }
-
- AbstractManagedObjectDefinition<? extends C, ? extends S> d = children
- .get(name);
- if (d == null) {
- throw new IllegalArgumentException("managed object definition \"" + name
- + "\" not found");
- }
-
- return d;
}
@@ -149,6 +114,121 @@
* this managed object definition.
*/
public final Collection<AbstractManagedObjectDefinition
+ <? extends C, ? extends S>> getAllChildren() {
+ List<AbstractManagedObjectDefinition<? extends C, ? extends S>> list =
+ new ArrayList<AbstractManagedObjectDefinition<? extends C, ? extends S>>(
+ children.values());
+
+ for (AbstractManagedObjectDefinition<? extends C, ? extends S> child :
+ children.values()) {
+ list.addAll(child.getAllChildren());
+ }
+
+ return Collections.unmodifiableCollection(list);
+ }
+
+
+
+ /**
+ * Get all the property definitions associated with this type of
+ * managed object. The returned collection will contain inherited
+ * property definitions.
+ *
+ * @return Returns an unmodifiable collection containing all the
+ * property definitions associated with this type of managed
+ * object.
+ */
+ public final Collection<PropertyDefinition<?>> getAllPropertyDefinitions() {
+ if (parent == null) {
+ return getPropertyDefinitions();
+ } else {
+ List<PropertyDefinition<?>> list = new ArrayList<PropertyDefinition<?>>(
+ propertyDefinitions.values());
+ list.addAll(parent.getAllPropertyDefinitions());
+ return Collections.unmodifiableCollection(list);
+ }
+ }
+
+
+
+ /**
+ * Get all the relation definitions associated with this type of
+ * managed object. The returned collection will contain inherited
+ * relation definitions.
+ *
+ * @return Returns an unmodifiable collection containing all the
+ * relation definitions associated with this type of managed
+ * object.
+ */
+ public final Collection<RelationDefinition<?, ?>>
+ getAllRelationDefinitions() {
+ if (parent == null) {
+ return getRelationDefinitions();
+ } else {
+ List<RelationDefinition<?, ?>> list =
+ new ArrayList<RelationDefinition<?, ?>>(relationDefinitions.values());
+ list.addAll(parent.getAllRelationDefinitions());
+ return Collections.unmodifiableCollection(list);
+ }
+ }
+
+
+
+ /**
+ * Get the named child managed object definition which inherits from
+ * this managed object definition. This method will recursively
+ * search down through the inheritance hierarchy.
+ *
+ * @param name
+ * The name of the managed object definition sub-type.
+ * @return Returns the named child managed object definition which
+ * inherits from this managed object definition.
+ * @throws IllegalArgumentException
+ * If the specified managed object definition name was
+ * null or empty or if the requested subordinate managed
+ * object definition was not found.
+ */
+ public final AbstractManagedObjectDefinition<? extends C, ? extends S>
+ getChild(String name) throws IllegalArgumentException {
+ if ((name == null) || (name.length() == 0)) {
+ throw new IllegalArgumentException("null or empty managed object name");
+ }
+
+ AbstractManagedObjectDefinition<? extends C, ? extends S> d = children
+ .get(name);
+
+ if (d == null) {
+ // Recursively search.
+ for (AbstractManagedObjectDefinition<? extends C, ? extends S> child :
+ children.values()) {
+ try {
+ d = child.getChild(name);
+ break;
+ } catch (IllegalArgumentException e) {
+ // Try the next child.
+ }
+ }
+ }
+
+ if (d == null) {
+ throw new IllegalArgumentException("child managed object definition \""
+ + name + "\" not found");
+ }
+
+ return d;
+ }
+
+
+
+ /**
+ * Get the child managed object definitions which inherit directly
+ * from this managed object definition.
+ *
+ * @return Returns an unmodifiable collection containing the
+ * subordinate managed object definitions which inherit
+ * directly from this managed object definition.
+ */
+ public final Collection<AbstractManagedObjectDefinition
<? extends C, ? extends S>> getChildren() {
return Collections.unmodifiableCollection(children.values());
}
@@ -216,16 +296,17 @@
/**
- * Get the specified property definition associated with this type of managed
- * object.
+ * 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.
+ * @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.
+ * If the specified property name was null or empty or if
+ * the requested property definition was not found.
*/
public final PropertyDefinition getPropertyDefinition(String name)
throws IllegalArgumentException {
@@ -234,9 +315,14 @@
}
PropertyDefinition d = propertyDefinitions.get(name);
+
if (d == null) {
- throw new IllegalArgumentException("property definition \"" + name
- + "\" not found");
+ if (parent != null) {
+ return parent.getPropertyDefinition(name);
+ } else {
+ throw new IllegalArgumentException("property definition \"" + name
+ + "\" not found");
+ }
}
return d;
@@ -245,12 +331,13 @@
/**
- * Get all the property definitions associated with this type of
- * managed object.
+ * 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 all the
- * property definitions associated with this type of managed
- * object.
+ * @return Returns an unmodifiable collection containing the
+ * property definitions defined by this managed object
+ * definition.
*/
public final Collection<PropertyDefinition<?>> getPropertyDefinitions() {
return Collections.unmodifiableCollection(propertyDefinitions
@@ -260,16 +347,17 @@
/**
- * Get the specified relation definition associated with this type of managed
- * object.
+ * Get the specified relation definition associated with this type
+ * of managed object.The search will include any inherited relation
+ * definitions.
*
* @param name
* The name of the relation definition to be retrieved.
- * @return Returns the specified relation definition associated with this type
- * of managed object.
+ * @return Returns the specified relation definition associated with
+ * this type of managed object.
* @throws IllegalArgumentException
- * If the specified relation name was null or empty or if the
- * requested relation definition was not found.
+ * If the specified relation name was null or empty or if
+ * the requested relation definition was not found.
*/
public final RelationDefinition getRelationDefinition(String name)
throws IllegalArgumentException {
@@ -278,9 +366,14 @@
}
RelationDefinition d = relationDefinitions.get(name);
+
if (d == null) {
- throw new IllegalArgumentException("relation definition \"" + name
- + "\" not found");
+ if (parent != null) {
+ return parent.getRelationDefinition(name);
+ } else {
+ throw new IllegalArgumentException("relation definition \"" + name
+ + "\" not found");
+ }
}
return d;
@@ -289,16 +382,16 @@
/**
- * Get all the relation definitions associated with this type of
- * managed object.
+ * Get the relation definitions defined by this managed object
+ * definition. The returned collection will not contain inherited
+ * relation definitions.
*
- * @return Returns an unmodifiable collection containing all the
- * relation definitions associated with this type of managed
- * object.
+ * @return Returns an unmodifiable collection containing the
+ * relation definitions defined by this managed object
+ * definition.
*/
public final Collection<RelationDefinition<?,?>> getRelationDefinitions() {
- return Collections.unmodifiableCollection(relationDefinitions
- .values());
+ return Collections.unmodifiableCollection(relationDefinitions.values());
}
diff --git a/opends/src/server/org/opends/server/admin/ManagedObjectPath.java b/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
index 5e3639a..1571cbb 100644
--- a/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
+++ b/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
@@ -32,38 +32,62 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.opends.server.admin.std.client.RootCfgClient;
import org.opends.server.admin.std.meta.RootCfgDefn;
+import org.opends.server.admin.std.server.RootCfg;
/**
* A path which can be used to determine the location of a managed
* object instance.
+ *
+ * @param <C>
+ * The type of client managed object configuration that this
+ * path references.
+ * @param <S>
+ * The type of server managed object configuration that this
+ * path references.
*/
-public final class ManagedObjectPath {
+public final class ManagedObjectPath
+ <C extends ConfigurationClient, S extends Configuration> {
/**
* Abstract path element.
*/
- private static abstract class Element {
+ private static abstract class Element
+ <C extends ConfigurationClient, S extends Configuration> {
+
+ // The type of managed object referenced by this element.
+ private final AbstractManagedObjectDefinition<C, S> definition;
+
+
/**
* Protected constructor.
+ *
+ * @param definition
+ * The type of managed object referenced by this element.
*/
- protected Element() {
- // No implementation required.
+ protected Element(AbstractManagedObjectDefinition<C, S> definition) {
+ this.definition = definition;
}
/**
- * Get the relation definition associated with this element.
+ * Get the managed object definition associated with this element.
*
- * @return Returns the relation definition associated with this
- * element.
+ * @return Returns the managed object definition associated with
+ * this element.
*/
- public abstract RelationDefinition<?, ?> getRelation();
+ public final AbstractManagedObjectDefinition<C, S>
+ getManagedObjectDefinition() {
+ return definition;
+ }
@@ -74,8 +98,7 @@
* @param serializer
* The managed object path serialization strategy.
*/
- public abstract void serialize(
- ManagedObjectPathSerializer serializer);
+ public abstract void serialize(ManagedObjectPathSerializer serializer);
}
@@ -83,19 +106,32 @@
/**
* A path element representing an instantiable managed object.
*/
- private static final class InstantiableElement extends Element {
+ private static final class InstantiableElement
+ <C extends ConfigurationClient, S extends Configuration>
+ extends Element<C, S> {
- // The instantiable relation.
- private final InstantiableRelationDefinition<?, ?> r;
+ // Factory method.
+ private static final
+ <C extends ConfigurationClient, S extends Configuration>
+ InstantiableElement<C, S> create(
+ InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name) {
+ return new InstantiableElement<C, S>(r, d, name);
+ }
// The name of the managed object.
private final String name;
+ // The instantiable relation.
+ private final InstantiableRelationDefinition<? super C, ? super S> r;
+
// Private constructor.
private InstantiableElement(
- InstantiableRelationDefinition<?, ?> r, String name) {
+ InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name) {
+ super(d);
this.r = r;
this.name = name;
}
@@ -106,20 +142,10 @@
* {@inheritDoc}
*/
@Override
- public RelationDefinition<?, ?> getRelation() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
public void serialize(ManagedObjectPathSerializer serializer) {
- serializer.appendManagedObjectPathElement(r, name);
+ serializer.appendManagedObjectPathElement(r,
+ getManagedObjectDefinition(), name);
}
-
}
@@ -127,15 +153,28 @@
/**
* A path element representing an optional managed object.
*/
- private static final class OptionalElement extends Element {
+ private static final class OptionalElement
+ <C extends ConfigurationClient, S extends Configuration>
+ extends Element<C, S> {
+
+ // Factory method.
+ private static final
+ <C extends ConfigurationClient, S extends Configuration>
+ OptionalElement<C, S> create(
+ OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ return new OptionalElement<C, S>(r, d);
+ }
// The optional relation.
- private final OptionalRelationDefinition<?, ?> r;
+ private final OptionalRelationDefinition<? super C, ? super S> r;
// Private constructor.
- private OptionalElement(OptionalRelationDefinition<?, ?> r) {
+ private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ super(d);
this.r = r;
}
@@ -145,18 +184,9 @@
* {@inheritDoc}
*/
@Override
- public RelationDefinition<?, ?> getRelation() {
- return r;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
public void serialize(ManagedObjectPathSerializer serializer) {
- serializer.appendManagedObjectPathElement(r);
+ serializer
+ .appendManagedObjectPathElement(r, getManagedObjectDefinition());
}
}
@@ -165,15 +195,29 @@
/**
* A path element representing a singleton managed object.
*/
- private static final class SingletonElement extends Element {
+ private static final class SingletonElement
+ <C extends ConfigurationClient, S extends Configuration>
+ extends Element<C, S> {
+
+ // Factory method.
+ private static final
+ <C extends ConfigurationClient, S extends Configuration>
+ SingletonElement<C, S> create(
+ SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ return new SingletonElement<C, S>(r, d);
+ }
// The singleton relation.
- private final SingletonRelationDefinition<?, ?> r;
+ private final SingletonRelationDefinition<? super C, ? super S> r;
// Private constructor.
- private SingletonElement(SingletonRelationDefinition<?, ?> r) {
+ private SingletonElement(
+ SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
+ super(d);
this.r = r;
}
@@ -183,8 +227,29 @@
* {@inheritDoc}
*/
@Override
- public RelationDefinition<?, ?> getRelation() {
- return r;
+ public void serialize(ManagedObjectPathSerializer serializer) {
+ serializer
+ .appendManagedObjectPathElement(r, getManagedObjectDefinition());
+ }
+ }
+
+
+
+ /**
+ * A serialize which is used to generate the toString
+ * representation.
+ */
+ private static final class StringSerializer implements
+ ManagedObjectPathSerializer {
+
+ // Serialize to this string builder.
+ private final StringBuilder builder;
+
+
+
+ // Private constructor.
+ private StringSerializer(StringBuilder builder) {
+ this.builder = builder;
}
@@ -192,15 +257,69 @@
/**
* {@inheritDoc}
*/
- @Override
- public void serialize(ManagedObjectPathSerializer serializer) {
- serializer.appendManagedObjectPathElement(r);
+ public <M extends ConfigurationClient, N extends Configuration>
+ void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d, String name) {
+ serializeElement(r, d);
+
+ // Be careful to escape any forward slashes in the name.
+ builder.append("+name=");
+ builder.append(name.replace("/", "//"));
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration>
+ void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d) {
+ serializeElement(r, d);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public <M extends ConfigurationClient, N extends Configuration>
+ void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d) {
+ serializeElement(r, d);
+ }
+
+
+
+ // Common element serialization.
+ private <M, N> void serializeElement(RelationDefinition r,
+ AbstractManagedObjectDefinition d) {
+ // Always specify the relation name.
+ builder.append("/relation=");
+ builder.append(r.getName());
+
+ // Only specify the type if it is a sub-type of the relation's
+ // type.
+ if (r.getChildDefinition() != d) {
+ builder.append("+type=");
+ builder.append(d.getName());
+ }
}
}
// Single instance of a root path.
- private static final ManagedObjectPath EMPTY_PATH = new ManagedObjectPath(
- new LinkedList<Element>());
+ private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH =
+ new ManagedObjectPath<RootCfgClient, RootCfg>(
+ new LinkedList<Element<?, ?>>(), RootCfgDefn.getInstance());
+
+ // A regular expression used to parse path elements.
+ private static final Pattern PE_REGEXP = Pattern
+ .compile("^\\s*relation=\\s*([^+]+)\\s*"
+ + "(\\+\\s*type=\\s*([^+]+)\\s*)?"
+ + "(\\+\\s*name=\\s*([^+]+)\\s*)?$");
@@ -211,11 +330,12 @@
* @return Returns a new managed object path representing the
* configuration root.
*/
- public static ManagedObjectPath emptyPath() {
+ public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() {
return EMPTY_PATH;
}
+
/**
* Returns a managed object path holding the value of the specified
* string.
@@ -227,29 +347,226 @@
* @throws IllegalArgumentException
* If the string could not be parsed.
*/
- public static ManagedObjectPath valueOf(String s)
+ public static ManagedObjectPath<?, ?> valueOf(String s)
throws IllegalArgumentException {
- return null;
+ String ns = s.trim();
+
+ // Check for root special case.
+ if (ns.equals("/")) {
+ return EMPTY_PATH;
+ }
+
+ // Parse the elements.
+ LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
+ AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn
+ .getInstance();
+
+ if (!ns.startsWith("/")) {
+ throw new IllegalArgumentException("Invalid path \"" + ns
+ + "\": must begin with a \"/\"");
+ }
+
+ int start = 1;
+ while (true) {
+ // Get the next path element.
+ int end;
+ for (end = start; end < ns.length(); end++) {
+ char c = ns.charAt(end);
+ if (c == '/') {
+ if (end == (ns.length() - 1)) {
+ throw new IllegalArgumentException("Invalid path \"" + ns
+ + "\": must not end with a trailing \"/\"");
+ }
+
+ if (ns.charAt(end + 1) == '/') {
+ // Found an escaped forward slash.
+ end++;
+ } else {
+ // Found the end of this path element.
+ break;
+ }
+ }
+ }
+
+ // Get the next element.
+ String es = ns.substring(start, end);
+
+ Matcher m = PE_REGEXP.matcher(es);
+ if (!m.matches()) {
+ throw new IllegalArgumentException("Invalid path element \"" + es
+ + "\" in path \"" + ns + "\"");
+ }
+
+ String relation = m.group(1); // Mandatory.
+ String type = m.group(3); // Optional.
+ String name = m.group(5); // Mandatory if relation is
+ // instantiable.
+
+ // Get the relation definition.
+ RelationDefinition<?, ?> r;
+ try {
+ r = definition.getRelationDefinition(relation);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Invalid path element \"" + es
+ + "\" in path \"" + ns + "\": unknown relation \"" + relation
+ + "\"");
+ }
+
+ // Append the next element.
+ Element<?, ?> e = createElement(r, ns, es, type, name);
+ elements.add(e);
+ definition = e.getManagedObjectDefinition();
+
+ // Update start to point to the beginning of the next element.
+ if (end < ns.length()) {
+ // Skip to the beginning of the next element
+ start = end + 1;
+ } else {
+ // We reached the end of the string.
+ break;
+ }
+ }
+
+ // Construct the new path.
+ return create(elements, definition);
}
+ // Factory method required in order to allow generic wild-card
+ // construction of new paths.
+ private static <C extends ConfigurationClient, S extends Configuration>
+ ManagedObjectPath<C, S> create(
+ LinkedList<Element<?, ?>> elements,
+ AbstractManagedObjectDefinition<C, S> definition) {
+ return new ManagedObjectPath<C, S>(elements, definition);
+ }
+
+
+
+ // Decode an element.
+ private static <C extends ConfigurationClient, S extends Configuration>
+ Element<? extends C, ? extends S> createElement(
+ RelationDefinition<C, S> r, String path, String element, String type,
+ String name) {
+ // First determine the managed object definition.
+ AbstractManagedObjectDefinition<? extends C, ? extends S> d = null;
+
+ if (type != null) {
+ for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : r
+ .getChildDefinition().getAllChildren()) {
+ if (child.getName().equals(type)) {
+ d = child;
+ break;
+ }
+ }
+
+ if (d == null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element
+ + "\" in path \"" + path + "\": unknown sub-type \"" + type + "\"");
+ }
+ } else {
+ d = r.getChildDefinition();
+ }
+
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<C, S> ir =
+ (InstantiableRelationDefinition<C, S>) r;
+
+ if (name == null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element
+ + "\" in path \"" + path
+ + "\": no instance name for instantiable relation");
+ }
+
+ return InstantiableElement.create(ir, d, name);
+ } else if (r instanceof OptionalRelationDefinition) {
+ OptionalRelationDefinition<C, S> or =
+ (OptionalRelationDefinition<C, S>) r;
+
+ if (name != null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element
+ + "\" in path \"" + path
+ + "\": instance name specified for optional relation");
+ }
+
+ return OptionalElement.create(or, d);
+ } else if (r instanceof SingletonRelationDefinition) {
+ SingletonRelationDefinition<C, S> sr =
+ (SingletonRelationDefinition<C, S>) r;
+
+ if (name != null) {
+ throw new IllegalArgumentException("Invalid path element \"" + element
+ + "\" in path \"" + path
+ + "\": instance name specified for singleton relation");
+ }
+
+ return SingletonElement.create(sr, d);
+ } else {
+ throw new IllegalArgumentException("Invalid path element \"" + element
+ + "\" in path \"" + path + "\": unsupported relation type");
+ }
+ }
+
+ // The last element in this path.
+ private final AbstractManagedObjectDefinition<C, S> definition;
+
// The list of path elements in this path.
- private final List<Element> elements;
+ private final List<Element<?, ?>> elements;
// Private constructor.
- private ManagedObjectPath(LinkedList<Element> elements) {
+ private ManagedObjectPath(LinkedList<Element<?, ?>> elements,
+ AbstractManagedObjectDefinition<C, S> definition) {
this.elements = Collections.unmodifiableList(elements);
+ this.definition = definition;
}
/**
* Creates a new child managed object path beneath the provided
- * parent path.
+ * parent path having the specified managed object definition.
*
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
+ * @param r
+ * The instantiable relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child
+ * (must be a sub-type of the relation).
+ * @param name
+ * The relative name of the child managed object.
+ * @return Returns a new child managed object path beneath the
+ * provided parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ InstantiableRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d, String name) {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
+ elements);
+ celements.add(new InstantiableElement<M, N>(r, d, name));
+ return new ManagedObjectPath<M, N>(celements, d);
+ }
+
+
+
+ /**
+ * Creates a new child managed object path beneath the provided
+ * parent path using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
* @param r
* The instantiable relation referencing the child.
* @param name
@@ -257,45 +574,116 @@
* @return Returns a new child managed object path beneath the
* provided parent path.
*/
- public ManagedObjectPath child(
- InstantiableRelationDefinition<?, ?> r, String name) {
- LinkedList<Element> celements = new LinkedList<Element>(elements);
- celements.add(new InstantiableElement(r, name));
- return new ManagedObjectPath(celements);
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ InstantiableRelationDefinition<M, N> r, String name) {
+ return child(r, r.getChildDefinition(), name);
}
/**
* Creates a new child managed object path beneath the provided
- * parent path.
+ * parent path having the specified managed object definition.
*
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
+ * @param r
+ * The optional relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child
+ * (must be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the
+ * provided parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ OptionalRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d) {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
+ elements);
+ celements.add(new OptionalElement<M, N>(r, d));
+ return new ManagedObjectPath<M, N>(celements, d);
+ }
+
+
+
+ /**
+ * Creates a new child managed object path beneath the provided
+ * parent path using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
* @param r
* The optional relation referencing the child.
* @return Returns a new child managed object path beneath the
* provided parent path.
*/
- public ManagedObjectPath child(OptionalRelationDefinition<?, ?> r) {
- LinkedList<Element> celements = new LinkedList<Element>(elements);
- celements.add(new OptionalElement(r));
- return new ManagedObjectPath(celements);
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ OptionalRelationDefinition<M, N> r) {
+ return child(r, r.getChildDefinition());
}
/**
* Creates a new child managed object path beneath the provided
- * parent path.
+ * parent path having the specified managed object definition.
*
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
+ * @param r
+ * The singleton relation referencing the child.
+ * @param d
+ * The managed object definition associated with the child
+ * (must be a sub-type of the relation).
+ * @return Returns a new child managed object path beneath the
+ * provided parent path.
+ */
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ SingletonRelationDefinition<? super M, ? super N> r,
+ AbstractManagedObjectDefinition<M, N> d) {
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
+ elements);
+ celements.add(new SingletonElement<M, N>(r, d));
+ return new ManagedObjectPath<M, N>(celements, d);
+ }
+
+
+
+ /**
+ * Creates a new child managed object path beneath the provided
+ * parent path using the relation's child managed object definition.
+ *
+ * @param <M>
+ * The type of client managed object configuration that the
+ * child path references.
+ * @param <N>
+ * The type of server managed object configuration that the
+ * child path references.
* @param r
* The singleton relation referencing the child.
* @return Returns a new child managed object path beneath the
* provided parent path.
*/
- public ManagedObjectPath child(SingletonRelationDefinition<?, ?> r) {
- LinkedList<Element> celements = new LinkedList<Element>(elements);
- celements.add(new SingletonElement(r));
- return new ManagedObjectPath(celements);
+ public <M extends ConfigurationClient, N extends Configuration>
+ ManagedObjectPath<M, N> child(
+ SingletonRelationDefinition<M, N> r) {
+ return child(r, r.getChildDefinition());
}
@@ -321,20 +709,14 @@
* Get the definition of the managed object referred to by this
* path.
* <p>
- * When the path is empty, the {@link RootCfgDefn}
- * is returned.
+ * When the path is empty, the {@link RootCfgDefn} is returned.
*
* @return Returns the definition of the managed object referred to
- * by this path, or the {@link RootCfgDefn}
- * if the path is empty.
+ * by this path, or the {@link RootCfgDefn} if the path is
+ * empty.
*/
- public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() {
- if (elements.isEmpty()) {
- return RootCfgDefn.getInstance();
- } else {
- Element e = elements.get(elements.size() - 1);
- return e.getRelation().getChildDefinition();
- }
+ public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
+ return definition;
}
@@ -362,6 +744,23 @@
/**
+ * Creates a new parent managed object path representing the
+ * immediate parent of this path. This method is a short-hand
+ * for <code>parent(1)</code>.
+ *
+ * @return Returns a new parent managed object path representing the
+ * immediate parent of this path.
+ * @throws IllegalArgumentException
+ * If this path does not have a parent (i.e. it is the
+ * empty path).
+ */
+ public ManagedObjectPath<?, ?> parent() throws IllegalArgumentException {
+ return parent(1);
+ }
+
+
+
+ /**
* Creates a new parent managed object path the specified number of
* path elements above this path.
*
@@ -374,7 +773,7 @@
* If the offset is less than 0, or greater than the
* number of path elements in this path.
*/
- public ManagedObjectPath parent(int offset)
+ public ManagedObjectPath<?, ?> parent(int offset)
throws IllegalArgumentException {
if (offset < 0) {
throw new IllegalArgumentException("Negative offset");
@@ -390,9 +789,16 @@
return this;
}
- LinkedList<Element> celements = new LinkedList<Element>(elements
- .subList(0, elements.size() - offset));
- return new ManagedObjectPath(celements);
+ // Return the empty path if the parent has zero elements.
+ if (elements.size() == offset) {
+ return emptyPath();
+ }
+
+ LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
+ elements.subList(0, elements.size() - offset));
+ AbstractManagedObjectDefinition<?, ?> definition = celements.getLast()
+ .getManagedObjectDefinition();
+ return create(celements, definition);
}
@@ -409,7 +815,7 @@
* The managed object path serialization strategy.
*/
public void serialize(ManagedObjectPathSerializer serializer) {
- for (Element element : elements) {
+ for (Element<?, ?> element : elements) {
element.serialize(serializer);
}
}
@@ -449,36 +855,14 @@
* @see #toString()
*/
public void toString(final StringBuilder builder) {
- // Use a simple serializer to create the contents.
- ManagedObjectPathSerializer serializer = new ManagedObjectPathSerializer() {
-
- public void appendManagedObjectPathElement(
- InstantiableRelationDefinition<?, ?> r, String name) {
- builder.append('/');
- builder.append(r.getName());
- builder.append('/');
- builder.append(name);
- }
-
-
-
- public void appendManagedObjectPathElement(
- OptionalRelationDefinition<?, ?> r) {
- builder.append('/');
- builder.append(r.getName());
- }
-
-
-
- public void appendManagedObjectPathElement(
- SingletonRelationDefinition<?, ?> r) {
- builder.append('/');
- builder.append(r.getName());
- }
-
- };
-
- serialize(serializer);
+ if (isEmpty()) {
+ // Special treatment of root configuration paths.
+ builder.append('/');
+ } else {
+ // Use a simple serializer to create the contents.
+ ManagedObjectPathSerializer serializer = new StringSerializer(builder);
+ serialize(serializer);
+ }
}
}
diff --git a/opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java b/opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java
index 3c4cd55..df164c1 100644
--- a/opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java
+++ b/opends/src/server/org/opends/server/admin/ManagedObjectPathSerializer.java
@@ -31,48 +31,83 @@
/**
* A strategy for serializing managed object paths.
* <p>
- * This interface provides a generic means for serializing managed object paths
- * into application specific forms. For example, a JNDI client would use this
- * interface to construct <code>LdapName</code> objects from a path.
- * Similarly, on the server side, a serialization strategy is used to construct
- * <code>DN</code> instances from a path.
+ * This interface provides a generic means for serializing managed
+ * object paths into application specific forms. For example, a JNDI
+ * client would use this interface to construct <code>LdapName</code>
+ * objects from a path. Similarly, on the server side, a serialization
+ * strategy is used to construct <code>DN</code> instances from a
+ * path.
* <p>
- * During serialization the serializer is invoked for each element in the
- * managed object path in big-endian order, starting from the root and
- * proceeding down to the leaf element.
+ * During serialization the serializer is invoked for each element in
+ * the managed object path in big-endian order, starting from the root
+ * and proceeding down to the leaf element.
*/
public interface ManagedObjectPathSerializer {
/**
- * Append a managed object path element identified by an instantiable relation
- * and an instance name.
+ * Append a managed object path element identified by an
+ * instantiable relation and an instance name.
*
+ * @param <C>
+ * The type of client managed object configuration that
+ * this path element references.
+ * @param <S>
+ * The type of server managed object configuration that
+ * this path element references.
* @param r
* The instantiable relation.
+ * @param d
+ * The managed object definition.
* @param name
* The instance name.
*/
- void appendManagedObjectPathElement(InstantiableRelationDefinition<?, ?> r,
- String name);
+ <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name);
/**
- * Append a managed object path element identified by a optional relation.
+ * Append a managed object path element identified by an optional
+ * relation.
*
+ * @param <C>
+ * The type of client managed object configuration that
+ * this path element references.
+ * @param <S>
+ * The type of server managed object configuration that
+ * this path element references.
* @param r
* The optional relation.
+ * @param d
+ * The managed object definition.
*/
- void appendManagedObjectPathElement(OptionalRelationDefinition<?, ?> r);
+ <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d);
/**
- * Append a managed object path element identified by a singleton relation.
+ * Append a managed object path element identified by a singleton
+ * relation.
*
+ * @param <C>
+ * The type of client managed object configuration that
+ * this path element references.
+ * @param <S>
+ * The type of server managed object configuration that
+ * this path element references.
* @param r
* The singleton relation.
+ * @param d
+ * The managed object definition.
*/
- void appendManagedObjectPathElement(SingletonRelationDefinition<?, ?> r);
+ <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d);
}
diff --git a/opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java b/opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java
index a5f2276..cf22f7c 100644
--- a/opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java
+++ b/opends/src/server/org/opends/server/admin/client/ExampleIntrospection.java
@@ -32,17 +32,14 @@
import static org.opends.server.util.ServerConstants.PROPERTY_SERVER_ROOT;
import java.io.File;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import org.opends.server.admin.AbstractManagedObjectDefinition;
-import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.AggregationRelationDefinition;
import org.opends.server.admin.AttributeTypePropertyDefinition;
+import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.ManagedObjectDefinition;
@@ -136,7 +133,7 @@
RootCfgDefn d = RootCfgDefn.getInstance();
String operands = "";
- for (RelationDefinition<?, ?> r : d.getRelationDefinitions()) {
+ for (RelationDefinition<?, ?> r : d.getAllRelationDefinitions()) {
r.accept(this, operands);
}
}
@@ -316,22 +313,7 @@
private void processManagedObjectDefinition(
AbstractManagedObjectDefinition<?, ?> parent,
AbstractManagedObjectDefinition<?, ?> child, String operands) {
- Set<RelationDefinition<?, ?>> parentRelations;
- Set<RelationDefinition<?, ?>> childRelations;
-
- if (parent != null) {
- parentRelations = new HashSet<RelationDefinition<?, ?>>(parent
- .getRelationDefinitions());
- } else {
- parentRelations = Collections.emptySet();
- }
-
- // Only process relations not defined in parent.
- childRelations = new HashSet<RelationDefinition<?, ?>>(child
- .getRelationDefinitions());
- childRelations.removeAll(parentRelations);
-
- for (RelationDefinition<?, ?> r : childRelations) {
+ for (RelationDefinition<?, ?> r : child.getRelationDefinitions()) {
r.accept(this, operands);
}
diff --git a/opends/src/server/org/opends/server/admin/client/ManagedObject.java b/opends/src/server/org/opends/server/admin/client/ManagedObject.java
index c0ebde7..2fc4148 100644
--- a/opends/src/server/org/opends/server/admin/client/ManagedObject.java
+++ b/opends/src/server/org/opends/server/admin/client/ManagedObject.java
@@ -154,8 +154,7 @@
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
* If the specified property definition is not associated
- * with this managed object, or if the property is
- * read-only.
+ * with this managed object.
*/
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
throws IllegalPropertyValueException,
@@ -191,8 +190,7 @@
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
* If the specified property definition is not associated
- * with this managed object, or if the property is
- * read-only.
+ * with this managed object.
*/
public <T> void setPropertyValues(PropertyDefinition<T> d,
Collection<T> values) throws IllegalPropertyValueException,
diff --git a/opends/src/server/org/opends/server/admin/client/PropertySet.java b/opends/src/server/org/opends/server/admin/client/PropertySet.java
index 83272d4..155ad0b 100644
--- a/opends/src/server/org/opends/server/admin/client/PropertySet.java
+++ b/opends/src/server/org/opends/server/admin/client/PropertySet.java
@@ -434,7 +434,7 @@
new HashMap<PropertyDefinition, MyProperty>();
// Copy the properties from the provider.
- for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
createProperty(pd, p, i, properties, exceptions);
}
@@ -472,7 +472,7 @@
new HashMap<PropertyDefinition, MyProperty>();
// Copy the properties from the provider.
- for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
createProperty(pd, p, i, properties, exceptions);
}
@@ -692,7 +692,7 @@
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
* If the specified property definition is not associated with this
- * managed object, or if the property is read-only.
+ * managed object.
*/
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
throws IllegalPropertyValueException, PropertyIsReadOnlyException,
@@ -732,7 +732,7 @@
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
* If the specified property definition is not associated with this
- * managed object, or if the property is read-only.
+ * managed object.
*/
public <T> void setPropertyValues(PropertyDefinition<T> d,
Collection<T> values) throws IllegalPropertyValueException,
diff --git a/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index 8f8a8a3..d95a896 100644
--- a/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -128,7 +128,8 @@
public Collection<?> getDefaultPropertyValues(
ManagedObjectPath path, String propertyName)
throws OperationsException, PropertyNotFoundException {
- ManagedObject<?> mo = readEntry(dirContext, path, path
+ ManagedObjectPath<?, ?> tmp = path;
+ ManagedObject<?> mo = readEntry(dirContext, tmp, tmp
.getManagedObjectDefinition());
ManagedObjectDefinition<?, ?> mod = mo
.getManagedObjectDefinition();
@@ -202,7 +203,7 @@
ManagedObjectDefinition<?, ?> d) {
ArrayList<String> attrIds = new ArrayList<String>();
- for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
String attrId = LDAPProfile.getInstance().getAttributeName(d,
pd);
attrIds.add(attrId);
@@ -348,7 +349,7 @@
private final DirContext dirContext;
// The path associated with this managed object.
- private final ManagedObjectPath path;
+ private final ManagedObjectPath<?, ?> path;
// LDAP profile associated with this connection.
private final LDAPProfile profile;
@@ -382,7 +383,7 @@
ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition();
LDAPChangeBuilder builder = new LDAPChangeBuilder(dirContext,
path, d);
- for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
// FIXME: should throw an error when there are missing mandatory
// properties.
Property<?> p = properties.getProperty(pd);
@@ -696,7 +697,7 @@
attributes.put(rdn.getType(), rdn.getValue().toString());
// Create the remaining attributes.
- for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
String attrID = profile.getAttributeName(d, pd);
Attribute attribute = new BasicAttribute(attrID);
encodeProperty(attribute, pd, properties);
diff --git a/opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java b/opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
index 53c2f80..021b1ce 100644
--- a/opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
+++ b/opends/src/server/org/opends/server/admin/client/ldap/LDAPNameBuilder.java
@@ -35,6 +35,9 @@
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.Configuration;
+import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectPath;
@@ -106,8 +109,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- InstantiableRelationDefinition<?, ?> r, String name) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
@@ -146,8 +151,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- OptionalRelationDefinition<?, ?> r) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
}
@@ -157,8 +164,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- SingletonRelationDefinition<?, ?> r) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
}
diff --git a/opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java b/opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
index d921be2..8d55359 100644
--- a/opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
+++ b/opends/src/server/org/opends/server/admin/server/ConfigAddListenerAdaptor.java
@@ -58,7 +58,7 @@
AbstractConfigListenerAdaptor implements ConfigAddListener {
// The managed object path of the parent.
- private final ManagedObjectPath path;
+ private final ManagedObjectPath<?, ?> path;
// The instantiable relation.
private final InstantiableRelationDefinition<?, S> instantiableRelation;
diff --git a/opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java b/opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
index 8184d8e..8abd474 100644
--- a/opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
+++ b/opends/src/server/org/opends/server/admin/server/ConfigDeleteListenerAdaptor.java
@@ -60,7 +60,7 @@
ConfigDeleteListener {
// The managed object path of the parent.
- private final ManagedObjectPath path;
+ private final ManagedObjectPath<?, ?> path;
// The instantiable relation.
private final InstantiableRelationDefinition<?, S> instantiableRelation;
diff --git a/opends/src/server/org/opends/server/admin/server/DNBuilder.java b/opends/src/server/org/opends/server/admin/server/DNBuilder.java
index 4219b2e..3d89202 100644
--- a/opends/src/server/org/opends/server/admin/server/DNBuilder.java
+++ b/opends/src/server/org/opends/server/admin/server/DNBuilder.java
@@ -29,6 +29,9 @@
+import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.Configuration;
+import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectPath;
@@ -120,8 +123,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- InstantiableRelationDefinition<?, ?> r, String name) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ InstantiableRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d, String name) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
@@ -155,8 +160,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- OptionalRelationDefinition<?, ?> r) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ OptionalRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
}
@@ -166,8 +173,10 @@
/**
* {@inheritDoc}
*/
- public void appendManagedObjectPathElement(
- SingletonRelationDefinition<?, ?> r) {
+ public <C extends ConfigurationClient, S extends Configuration>
+ void appendManagedObjectPathElement(
+ SingletonRelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
// Add the RDN sequence representing the relation.
appendManagedObjectPathElement((RelationDefinition) r);
}
diff --git a/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java b/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
index 2347042..ddf788d 100644
--- a/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
+++ b/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -96,7 +96,7 @@
InheritedDefaultValueProvider {
// The base path.
- private final ManagedObjectPath path;
+ private final ManagedObjectPath<?, ?> path;
@@ -131,7 +131,8 @@
throw new ManagedObjectNotFoundException();
}
- ServerManagedObject<?> mo = decode(path, path
+ ManagedObjectPath<?, ?> tmp = path;
+ ServerManagedObject<?> mo = decode(tmp, tmp
.getManagedObjectDefinition(), configEntry);
ManagedObjectDefinition<?, ?> mod = mo
.getManagedObjectDefinition();
@@ -295,7 +296,7 @@
// The managed object path identifying this managed object's
// location.
- private final ManagedObjectPath path;
+ private final ManagedObjectPath<?, ?> path;
// The managed object's properties.
private final PropertySet properties;
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
new file mode 100644
index 0000000..6b65d80
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
@@ -0,0 +1,240 @@
+/*
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * 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
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.admin;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.client.ConnectionHandlerCfgClient;
+import org.opends.server.admin.std.client.GlobalCfgClient;
+import org.opends.server.admin.std.client.LDAPConnectionHandlerCfgClient;
+import org.opends.server.admin.std.meta.ConnectionHandlerCfgDefn;
+import org.opends.server.admin.std.meta.GlobalCfgDefn;
+import org.opends.server.admin.std.meta.LDAPConnectionHandlerCfgDefn;
+import org.opends.server.admin.std.meta.MultimasterDomainCfgDefn;
+import org.opends.server.admin.std.meta.MultimasterSynchronizationProviderCfgDefn;
+import org.opends.server.admin.std.meta.RootCfgDefn;
+import org.opends.server.admin.std.server.ConnectionHandlerCfg;
+import org.opends.server.admin.std.server.GlobalCfg;
+import org.opends.server.admin.std.server.LDAPConnectionHandlerCfg;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * ManagedObjectPath test cases.
+ */
+public class ManagedObjectPathTest {
+
+ /**
+ * Sets up tests
+ *
+ * @throws Exception
+ * If the server could not be initialized.
+ */
+ @BeforeClass
+ public void setUp() throws Exception {
+ // This test suite depends on having the schema available, so
+ // we'll start the server.
+ TestCaseUtils.startServer();
+ }
+
+
+
+ /**
+ * Tests that the empty path is empty.
+ */
+ @Test
+ public void testEmptyPathIsEmpty() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ assertTrue(path.isEmpty());
+ }
+
+
+
+ /**
+ * Tests that the empty path has a size of zero.
+ */
+ @Test
+ public void testEmptyPathHasZeroElements() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ assertEquals(path.size(), 0);
+ }
+
+
+
+ /**
+ * Tests that the empty path has no parent.
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testEmptyPathHasNoParent() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ path.parent();
+ }
+
+
+
+ /**
+ * Tests that the empty path represents the root configuration.
+ */
+ @Test
+ public void testEmptyPathIsRootConfiguration() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ assertEquals(path.getManagedObjectDefinition(), RootCfgDefn.getInstance());
+ }
+
+
+
+ /**
+ * Tests that the empty path has a string representation of "/".
+ */
+ @Test
+ public void testEmptyPathString() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ assertEquals(path.toString(), "/");
+ }
+
+
+
+ /**
+ * Tests that the empty path can be decoded.
+ */
+ @Test
+ public void testEmptyPathDecode() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.valueOf("/");
+ assertEquals(path, ManagedObjectPath.emptyPath());
+ }
+
+
+
+ /**
+ * Tests singleton child creation.
+ */
+ @Test
+ public void testSingletonChild() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ ManagedObjectPath<GlobalCfgClient, GlobalCfg> child = path
+ .child(RootCfgDefn.getInstance()
+ .getGlobalConfigurationRelationDefinition());
+
+ assertFalse(child.isEmpty());
+ assertEquals(child.size(), 1);
+ assertEquals(child.parent(), path);
+ assertEquals(child.getManagedObjectDefinition(), GlobalCfgDefn
+ .getInstance());
+ assertEquals(child.toString(), "/relation=global-configuration");
+ assertEquals(child, ManagedObjectPath
+ .valueOf("/relation=global-configuration"));
+ }
+
+
+
+ /**
+ * Tests instantiable child creation.
+ */
+ @Test
+ public void testInstantiableChild() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ ManagedObjectPath<ConnectionHandlerCfgClient, ConnectionHandlerCfg> child = path
+ .child(RootCfgDefn.getInstance()
+ .getConnectionHandlersRelationDefinition(),
+ "LDAP connection handler");
+
+ assertFalse(child.isEmpty());
+ assertEquals(child.size(), 1);
+ assertEquals(child.parent(), path);
+ assertEquals(child.getManagedObjectDefinition(), ConnectionHandlerCfgDefn
+ .getInstance());
+ assertEquals(child.toString(),
+ "/relation=connection-handler+name=LDAP connection handler");
+ assertEquals(child, ManagedObjectPath
+ .valueOf("/relation=connection-handler+name=LDAP connection handler"));
+ }
+
+
+
+ /**
+ * Tests instantiable child creation with specific sub-type.
+ */
+ @Test
+ public void testInstantiableChildWithSubtype() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ ManagedObjectPath<LDAPConnectionHandlerCfgClient, LDAPConnectionHandlerCfg> child = path
+ .child(RootCfgDefn.getInstance()
+ .getConnectionHandlersRelationDefinition(),
+ LDAPConnectionHandlerCfgDefn.getInstance(),
+ "LDAP connection handler");
+
+ assertFalse(child.isEmpty());
+ assertEquals(child.size(), 1);
+ assertEquals(child.parent(), path);
+ assertEquals(child.getManagedObjectDefinition(),
+ LDAPConnectionHandlerCfgDefn.getInstance());
+ assertEquals(
+ child.toString(),
+ "/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler");
+ assertEquals(
+ child,
+ ManagedObjectPath
+ .valueOf("/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler"));
+ }
+
+
+
+ /**
+ * Tests instantiable child creation with multiple levels.
+ */
+ @Test
+ public void testInstantiableMultipleLevels() {
+ ManagedObjectPath<?, ?> root = ManagedObjectPath.emptyPath();
+ ManagedObjectPath<?, ?> mmr = root.child(RootCfgDefn.getInstance()
+ .getSynchronizationProvidersRelationDefinition(),
+ MultimasterSynchronizationProviderCfgDefn.getInstance(), "MMR");
+ ManagedObjectPath<?, ?> domain = mmr.child(
+ MultimasterSynchronizationProviderCfgDefn.getInstance()
+ .getMultimasterDomainsRelationDefinition(), "Domain");
+ assertFalse(domain.isEmpty());
+ assertEquals(domain.size(), 2);
+ assertEquals(domain.parent(), mmr);
+ assertEquals(domain.parent(2), root);
+ assertEquals(domain.getManagedObjectDefinition(), MultimasterDomainCfgDefn
+ .getInstance());
+ assertEquals(
+ domain.toString(),
+ "/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain");
+ assertEquals(
+ domain,
+ ManagedObjectPath
+ .valueOf("/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain"));
+ }
+}
--
Gitblit v1.10.0