| | |
| | | |
| | | package org.opends.server.admin; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | |
| | | import org.forgerock.opendj.ldap.RDN; |
| | | import org.forgerock.opendj.ldap.schema.AttributeType; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.DirectoryException; |
| | | |
| | | |
| | | /** |
| | | * A path which can be used to determine the location of a managed |
| | | * object instance. |
| | | * A path which can be used to determine the location of a managed object |
| | | * instance. |
| | | * <p> |
| | | * A path is made up of zero or more elements each of which represents |
| | | * a managed object. Managed objects are arranged hierarchically with |
| | | * the root configuration being the top-most managed object. Elements |
| | | * are ordered such that the root configuration managed object is the |
| | | * first element and subsequent elements representing managed objects |
| | | * further down the hierarchy. |
| | | * A path is made up of zero or more elements each of which represents a managed |
| | | * object. Managed objects are arranged hierarchically with the root |
| | | * configuration being the top-most managed object. Elements are ordered such |
| | | * that the root configuration managed object is the first element and |
| | | * subsequent elements representing managed objects further down the hierarchy. |
| | | * <p> |
| | | * A path can be encoded into a string representation using the |
| | | * {@link #toString()} and {@link #toString(StringBuilder)} methods. |
| | | * Conversely, this string representation can be parsed using the |
| | | * {@link #valueOf(String)} method. |
| | | * {@link #toString()} and {@link #toString(StringBuilder)} methods. Conversely, |
| | | * this string representation can be parsed using the {@link #valueOf(String)} |
| | | * method. |
| | | * <p> |
| | | * The string representation of a managed object path is similar in |
| | | * principle to a UNIX file-system path and is defined as follows: |
| | | * The string representation of a managed object path is similar in principle to |
| | | * a UNIX file-system path and is defined as follows: |
| | | * <ul> |
| | | * <li>the root element is represented by the string <code>/</code> |
| | | * <li>subordinate elements are arranged in big-endian order |
| | | * separated by a forward slash <code>/</code> character |
| | | * <li>an element representing a managed object associated with a |
| | | * one-to-one (singleton) or one-to-zero-or-one (optional) relation |
| | | * has the form <code>relation=</code><i>relation</i> |
| | | * <code>[+type=</code><i>definition</i><code>]</code>, where |
| | | * <i>relation</i> is the name of the relation and <i>definition</i> |
| | | * is the name of the referenced managed object's definition if |
| | | * required (usually this is implied by the relation itself) |
| | | * <li>an element representing a managed object associated with a |
| | | * one-to-many (instantiable) relation has the form |
| | | * <code>relation=</code><i>relation</i><code>[+type=</code> |
| | | * <i>definition</i><code>]</code><code>+name=</code><i>name</i>, |
| | | * where <i>relation</i> is the name of the relation and |
| | | * <i>definition</i> is the name of the referenced managed object's |
| | | * definition if required (usually this is implied by the relation |
| | | * itself), and <i>name</i> is the name of the managed object |
| | | * instance |
| | | * <li>an element representing a managed object associated with a |
| | | * one-to-many (set) relation has the form |
| | | * <code>relation=</code><i>relation</i><code>[+type=</code> |
| | | * <i>definition</i><code>]</code>, |
| | | * where <i>relation</i> is the name of the relation and |
| | | * <i>definition</i> is the name of the referenced managed object's |
| | | * definition. |
| | | * <li>subordinate elements are arranged in big-endian order separated by a |
| | | * forward slash <code>/</code> character |
| | | * <li>an element representing a managed object associated with a one-to-one |
| | | * (singleton) or one-to-zero-or-one (optional) relation has the form |
| | | * <code>relation=</code><i>relation</i> <code>[+type=</code><i>definition</i> |
| | | * <code>]</code>, where <i>relation</i> is the name of the relation and |
| | | * <i>definition</i> is the name of the referenced managed object's definition |
| | | * if required (usually this is implied by the relation itself) |
| | | * <li>an element representing a managed object associated with a one-to-many |
| | | * (instantiable) relation has the form <code>relation=</code><i>relation</i> |
| | | * <code>[+type=</code> <i>definition</i><code>]</code><code>+name=</code> |
| | | * <i>name</i>, where <i>relation</i> is the name of the relation and |
| | | * <i>definition</i> is the name of the referenced managed object's definition |
| | | * if required (usually this is implied by the relation itself), and <i>name</i> |
| | | * is the name of the managed object instance |
| | | * <li>an element representing a managed object associated with a one-to-many |
| | | * (set) relation has the form <code>relation=</code><i>relation</i> |
| | | * <code>[+type=</code> <i>definition</i><code>]</code>, where <i>relation</i> |
| | | * is the name of the relation and <i>definition</i> is the name of the |
| | | * referenced managed object's definition. |
| | | * </ul> |
| | | * The following path string representation identifies a connection |
| | | * handler instance (note that the <code>type</code> is not |
| | | * specified indicating that the path identifies a connection handler |
| | | * called <i>my handler</i> which can be any type of connection |
| | | * handler): |
| | | * The following path string representation identifies a connection handler |
| | | * instance (note that the <code>type</code> is not specified indicating that |
| | | * the path identifies a connection handler called <i>my handler</i> which can |
| | | * be any type of connection handler): |
| | | * |
| | | * <pre> |
| | | * /relation=connection-handler+name=my handler |
| | | * </pre> |
| | | * |
| | | * If the identified connection handler must be an LDAP connection |
| | | * handler then the above path should include the <code>type</code>: |
| | | * If the identified connection handler must be an LDAP connection handler then |
| | | * the above path should include the <code>type</code>: |
| | | * |
| | | * <pre> |
| | | * /relation=connection-handler+type=ldap-connection-handler+name=my handler |
| | |
| | | * </pre> |
| | | * |
| | | * @param <C> |
| | | * The type of client managed object configuration that this |
| | | * path references. |
| | | * The type of client managed object configuration that this path |
| | | * references. |
| | | * @param <S> |
| | | * The type of server managed object configuration that this |
| | | * path references. |
| | | * The type of server managed object configuration that this path |
| | | * references. |
| | | */ |
| | | public final class ManagedObjectPath<C extends ConfigurationClient, |
| | | S extends Configuration> { |
| | | |
| | | /** |
| | | * A serialize which is used to generate the toDN representation. |
| | | */ |
| | | private static final class DNSerializer implements |
| | | ManagedObjectPathSerializer { |
| | | |
| | | // The current DN. |
| | | private DN dn; |
| | | |
| | | // The LDAP profile. |
| | | private final LDAPProfile profile; |
| | | |
| | | |
| | | |
| | | // Create a new DN builder. |
| | | private DNSerializer() { |
| | | this.dn = DN.rootDN(); |
| | | this.profile = LDAPProfile.getInstance(); |
| | | } |
| | | |
| | | |
| | | public final class ManagedObjectPath<C extends ConfigurationClient, S extends Configuration> { |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * A serialize which is used to generate the toDN representation. |
| | | */ |
| | | 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(r); |
| | | private static final class DNSerializer implements ManagedObjectPathSerializer { |
| | | |
| | | // Now add the single RDN representing the named instance. |
| | | String type = profile.getRelationChildRDNType(r); |
| | | AttributeType atype = DirectoryServer.getAttributeType( |
| | | type.toLowerCase(), true); |
| | | AttributeValue avalue = AttributeValues.create(atype, name); |
| | | dn = dn.concat(RDN.create(atype, avalue)); |
| | | // The current DN. |
| | | private DN dn; |
| | | |
| | | // The LDAP profile. |
| | | private final LDAPProfile profile; |
| | | |
| | | // Create a new DN builder. |
| | | private DNSerializer() { |
| | | this.dn = DN.rootDN(); |
| | | this.profile = LDAPProfile.getInstance(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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(r); |
| | | |
| | | // Now add the single RDN representing the named instance. |
| | | String type = profile.getRelationChildRDNType(r); |
| | | AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true); |
| | | dn = dn.child(new RDN(attrType, name)); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public <C extends ConfigurationClient, S extends Configuration> void appendManagedObjectPathElement( |
| | | SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { |
| | | // Add the RDN sequence representing the relation. |
| | | appendManagedObjectPathElement(r); |
| | | |
| | | // Now add the single RDN representing the instance. |
| | | String type = profile.getRelationChildRDNType(r); |
| | | AttributeType attrType = DirectoryServer.getAttributeType(type.toLowerCase(), true); |
| | | dn = dn.child(new RDN(attrType, d.getName())); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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(r); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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(r); |
| | | } |
| | | |
| | | // Appends the RDN sequence representing the provided relation. |
| | | private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) { |
| | | DN localName = DN.valueOf(profile.getRelationRDNSequence(r)); |
| | | dn = dn.child(localName); |
| | | } |
| | | |
| | | // Gets the serialized DN value. |
| | | private DN toDN() { |
| | | return dn; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * Abstract path element. |
| | | */ |
| | | public <C extends ConfigurationClient, S extends Configuration> |
| | | void appendManagedObjectPathElement( |
| | | SetRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | // Add the RDN sequence representing the relation. |
| | | appendManagedObjectPathElement(r); |
| | | private static abstract class Element<C extends ConfigurationClient, S extends Configuration> { |
| | | |
| | | // Now add the single RDN representing the instance. |
| | | String type = profile.getRelationChildRDNType(r); |
| | | AttributeType atype = DirectoryServer.getAttributeType( |
| | | type.toLowerCase(), true); |
| | | AttributeValue avalue = AttributeValues.create(atype, d.getName()); |
| | | dn = dn.concat(RDN.create(atype, avalue)); |
| | | // 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(AbstractManagedObjectDefinition<C, S> definition) { |
| | | this.definition = definition; |
| | | } |
| | | |
| | | /** |
| | | * Get the managed object definition associated with this element. |
| | | * |
| | | * @return Returns the managed object definition associated with this |
| | | * element. |
| | | */ |
| | | public final AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() { |
| | | return definition; |
| | | } |
| | | |
| | | /** |
| | | * Get the name associated with this element if applicable. |
| | | * |
| | | * @return Returns the name associated with this element if applicable. |
| | | */ |
| | | public String getName() { |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Get the relation definition associated with this element. |
| | | * |
| | | * @return Returns the relation definition associated with this element. |
| | | */ |
| | | public abstract RelationDefinition<? super C, ? super S> getRelationDefinition(); |
| | | |
| | | /** |
| | | * Serialize this path element using the provided serialization |
| | | * strategy. |
| | | * |
| | | * @param serializer |
| | | * The managed object path serialization strategy. |
| | | */ |
| | | public abstract void serialize(ManagedObjectPathSerializer serializer); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * A path element representing an instantiable managed object. |
| | | */ |
| | | 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(r); |
| | | private static final class InstantiableElement<C extends ConfigurationClient, S extends Configuration> extends |
| | | Element<C, S> { |
| | | |
| | | // 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<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d, String name) { |
| | | super(d); |
| | | this.r = r; |
| | | this.name = name; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String getName() { |
| | | return name; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public InstantiableRelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition(), name); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * A path element representing an optional managed object. |
| | | */ |
| | | 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(r); |
| | | 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<? super C, ? super S> r; |
| | | |
| | | // Private constructor. |
| | | private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public OptionalRelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // Appends the RDN sequence representing the provided relation. |
| | | private void appendManagedObjectPathElement(RelationDefinition<?, ?> r) { |
| | | // Add the RDN sequence representing the relation. |
| | | try { |
| | | DN localName = DN.decode(profile.getRelationRDNSequence(r)); |
| | | dn = dn.concat(localName); |
| | | } catch (DirectoryException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // Gets the serialized DN value. |
| | | private DN toDN() { |
| | | return dn; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Abstract path 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. |
| | | * A path element representing an set managed object. |
| | | */ |
| | | private static final class SetElement<C extends ConfigurationClient, S extends Configuration> extends Element<C, S> { |
| | | |
| | | // Factory method. |
| | | private static final <C extends ConfigurationClient, S extends Configuration> SetElement<C, S> create( |
| | | SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { |
| | | return new SetElement<C, S>(r, d); |
| | | } |
| | | |
| | | // The set relation. |
| | | private final SetRelationDefinition<? super C, ? super S> r; |
| | | |
| | | // Private constructor. |
| | | private SetElement(SetRelationDefinition<? super C, ? super S> r, AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SetRelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, getManagedObjectDefinition()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * A path element representing a singleton managed object. |
| | | */ |
| | | 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<? super C, ? super S> r; |
| | | |
| | | // Private constructor. |
| | | private SingletonElement(SingletonRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SingletonRelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> void appendManagedObjectPathElement( |
| | | SetRelationDefinition<? 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<RootCfgClient, RootCfg> EMPTY_PATH = new ManagedObjectPath<RootCfgClient, RootCfg>( |
| | | new LinkedList<Element<?, ?>>(), null, 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*)?$"); |
| | | |
| | | /** |
| | | * Creates a new managed object path representing the configuration root. |
| | | * |
| | | * @param definition |
| | | * The type of managed object referenced by this element. |
| | | * @return Returns a new managed object path representing the configuration |
| | | * root. |
| | | */ |
| | | protected Element(AbstractManagedObjectDefinition<C, S> definition) { |
| | | this.definition = definition; |
| | | public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() { |
| | | return EMPTY_PATH; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the managed object definition associated with this element. |
| | | * Returns a managed object path holding the value of the specified string. |
| | | * |
| | | * @return Returns the managed object definition associated with |
| | | * this element. |
| | | * @param s |
| | | * The string to be parsed. |
| | | * @return Returns a managed object path holding the value of the specified |
| | | * string. |
| | | * @throws IllegalArgumentException |
| | | * If the string could not be parsed. |
| | | */ |
| | | public final AbstractManagedObjectDefinition<C, S> |
| | | getManagedObjectDefinition() { |
| | | return definition; |
| | | public static ManagedObjectPath<?, ?> valueOf(String s) throws IllegalArgumentException { |
| | | String ns = s.trim(); |
| | | |
| | | // Check for root special case. |
| | | if (ns.equals("/")) { |
| | | return EMPTY_PATH; |
| | | } |
| | | |
| | | // Parse the elements. |
| | | LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>(); |
| | | Element<?, ?> lastElement = null; |
| | | 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 + "\""); |
| | | } |
| | | |
| | | // Mandatory. |
| | | String relation = m.group(1); |
| | | |
| | | // Optional. |
| | | String type = m.group(3); |
| | | |
| | | // Mandatory if relation is instantiable. |
| | | String name = m.group(5); |
| | | |
| | | // 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. |
| | | lastElement = createElement(r, ns, es, type, name); |
| | | elements.add(lastElement); |
| | | definition = lastElement.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, lastElement); |
| | | } |
| | | |
| | | // 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, Element<C, S> lastElement) { |
| | | return new ManagedObjectPath<C, S>(elements, lastElement.getRelationDefinition(), |
| | | lastElement.getManagedObjectDefinition()); |
| | | } |
| | | |
| | | // 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 SetRelationDefinition) { |
| | | SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r; |
| | | |
| | | if (name != null) { |
| | | throw new IllegalArgumentException("Invalid path element \"" + element + "\" in path \"" + path |
| | | + "\": instance name specified for set relation"); |
| | | } |
| | | |
| | | return SetElement.create(ir, d); |
| | | } 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 managed object definition in this path. |
| | | private final AbstractManagedObjectDefinition<C, S> d; |
| | | |
| | | // The list of path elements in this path. |
| | | private final List<Element<?, ?>> elements; |
| | | |
| | | // The last relation definition in this path. |
| | | private final RelationDefinition<? super C, ? super S> r; |
| | | |
| | | // Private constructor. |
| | | private ManagedObjectPath(LinkedList<Element<?, ?>> elements, RelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | this.elements = Collections.unmodifiableList(elements); |
| | | this.r = r; |
| | | this.d = d; |
| | | } |
| | | |
| | | /** |
| | | * Get the name associated with this element if applicable. |
| | | * Creates a new managed object path which has the same structure as this |
| | | * path except that the final path element is associated with the specified |
| | | * managed object definition. |
| | | * |
| | | * @return Returns the name associated with this element if |
| | | * applicable. |
| | | * @param <CC> |
| | | * The type of client managed object configuration that this path |
| | | * will reference. |
| | | * @param <SS> |
| | | * The type of server managed object configuration that this path |
| | | * will reference. |
| | | * @param nd |
| | | * The new managed object definition. |
| | | * @return Returns a new managed object path which has the same structure as |
| | | * this path except that the final path element is associated with |
| | | * the specified managed object definition. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType(AbstractManagedObjectDefinition<CC, SS> nd) { |
| | | if (r instanceof InstantiableRelationDefinition) { |
| | | InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r; |
| | | if (elements.size() == 0) { |
| | | return parent().child(ir, nd, "null"); |
| | | } else { |
| | | return parent().child(ir, nd, elements.get(elements.size() - 1).getName()); |
| | | } |
| | | } else if (r instanceof SetRelationDefinition) { |
| | | SetRelationDefinition<? super C, ? super S> sr = (SetRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(sr, nd); |
| | | } else if (r instanceof OptionalRelationDefinition) { |
| | | OptionalRelationDefinition<? super C, ? super S> or = (OptionalRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(or, nd); |
| | | } else { |
| | | SingletonRelationDefinition<? super C, ? super S> sr = (SingletonRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(sr, nd); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( |
| | | InstantiableRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d, String name) |
| | | throws IllegalArgumentException { |
| | | if (name.trim().length() == 0) { |
| | | throw new IllegalArgumentException("Empty or blank managed object names are not allowed"); |
| | | } |
| | | LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements); |
| | | celements.add(new InstantiableElement<M, N>(r, d, name)); |
| | | return new ManagedObjectPath<M, N>(celements, r, 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 |
| | | * The relative name of the child managed object. |
| | | * @return Returns a new child managed object path beneath the provided |
| | | * parent path. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( |
| | | InstantiableRelationDefinition<M, N> r, String name) throws IllegalArgumentException { |
| | | return child(r, r.getChildDefinition(), name); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided 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, r, 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 <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 |
| | | * 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, r, 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 <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( |
| | | SingletonRelationDefinition<M, N> r) { |
| | | return child(r, r.getChildDefinition()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided 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 set 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( |
| | | SetRelationDefinition<? super M, ? super N> r, AbstractManagedObjectDefinition<M, N> d) |
| | | throws IllegalArgumentException { |
| | | LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(elements); |
| | | celements.add(new SetElement<M, N>(r, d)); |
| | | return new ManagedObjectPath<M, N>(celements, r, d); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided parent path |
| | | * having the managed object definition indicated by <code>name</code>. |
| | | * |
| | | * @param <M> |
| | | * The type of client managed object configuration that the path |
| | | * references. |
| | | * @param <N> |
| | | * The type of server managed object configuration that the path |
| | | * references. |
| | | * @param r |
| | | * The set relation referencing the child. |
| | | * @param name |
| | | * The name of 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank or specifies a managed |
| | | * object definition which is not a sub-type of the relation's |
| | | * child definition. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<? extends M, ? extends N> child( |
| | | SetRelationDefinition<M, N> r, String name) throws IllegalArgumentException { |
| | | AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition(); |
| | | return child(r, d.getChild(name)); |
| | | } |
| | | |
| | | /** |
| | | * 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 set relation referencing the child. |
| | | * @return Returns a new child managed object path beneath the provided |
| | | * parent path. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> ManagedObjectPath<M, N> child( |
| | | SetRelationDefinition<M, N> r) throws IllegalArgumentException { |
| | | return child(r, r.getChildDefinition()); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean equals(Object obj) { |
| | | if (obj == this) { |
| | | return true; |
| | | } else if (obj instanceof ManagedObjectPath) { |
| | | ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj; |
| | | return toString().equals(other.toString()); |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Get the definition of the managed object referred to by this path. |
| | | * <p> |
| | | * 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. |
| | | */ |
| | | public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() { |
| | | return d; |
| | | } |
| | | |
| | | /** |
| | | * Get the name of the managed object referred to by this path if |
| | | * applicable. |
| | | * <p> |
| | | * If there path does not refer to an instantiable managed object |
| | | * <code>null</code> is returned. |
| | | * |
| | | * @return Returns the name of the managed object referred to by this path, |
| | | * or <code>null</code> if the managed object does not have a name. |
| | | */ |
| | | public String getName() { |
| | | return null; |
| | | if (elements.isEmpty()) { |
| | | return null; |
| | | } else { |
| | | return elements.get(elements.size() - 1).getName(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the relation definition associated with this element. |
| | | * Get the relation definition of the managed object referred to by this |
| | | * path. |
| | | * <p> |
| | | * When the path is empty, the <code>null</code> is returned. |
| | | * |
| | | * @return Returns the relation definition associated with this |
| | | * element. |
| | | * @return Returns the relation definition of the managed object referred to |
| | | * by this path, or the <code>null</code> if the path is empty. |
| | | */ |
| | | public abstract RelationDefinition<? super C, ? super S> |
| | | getRelationDefinition(); |
| | | |
| | | |
| | | public RelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | /** |
| | | * Serialize this path element using the provided serialization |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public int hashCode() { |
| | | return toString().hashCode(); |
| | | } |
| | | |
| | | /** |
| | | * Determine whether or not this path contains any path elements. |
| | | * |
| | | * @return Returns <code>true</code> if this path does not contain any path |
| | | * elements. |
| | | */ |
| | | public boolean isEmpty() { |
| | | return elements.isEmpty(); |
| | | } |
| | | |
| | | /** |
| | | * Determines whether this managed object path references the same location |
| | | * as the provided managed object path. |
| | | * <p> |
| | | * This method differs from <code>equals</code> in that it ignores sub-type |
| | | * definitions. |
| | | * |
| | | * @param other |
| | | * The managed object path to be compared. |
| | | * @return Returns <code>true</code> if this managed object path references |
| | | * the same location as the provided managed object path. |
| | | */ |
| | | public boolean matches(ManagedObjectPath<?, ?> other) { |
| | | DN thisDN = toDN(); |
| | | DN otherDN = other.toDN(); |
| | | return thisDN.equals(otherDN); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | * |
| | | * @param offset |
| | | * The number of path elements (0 - means no offset, 1 means the |
| | | * parent, and 2 means the grand-parent). |
| | | * @return Returns a new parent managed object path the specified number of |
| | | * path elements above this path. |
| | | * @throws IllegalArgumentException |
| | | * If the offset is less than 0, or greater than the number of |
| | | * path elements in this path. |
| | | */ |
| | | public ManagedObjectPath<?, ?> parent(int offset) throws IllegalArgumentException { |
| | | if (offset < 0) { |
| | | throw new IllegalArgumentException("Negative offset"); |
| | | } |
| | | |
| | | if (offset > elements.size()) { |
| | | throw new IllegalArgumentException("Offset is greater than the number of path elements"); |
| | | } |
| | | |
| | | // An offset of 0 leaves the path unchanged. |
| | | if (offset == 0) { |
| | | return this; |
| | | } |
| | | |
| | | // 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)); |
| | | return create(celements, celements.getLast()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new managed object path which has the same structure as this |
| | | * path except that the final path element is renamed. The final path |
| | | * element must comprise of an instantiable relation. |
| | | * |
| | | * @param newName |
| | | * The new name of the final path element. |
| | | * @return Returns a new managed object path which has the same structure as |
| | | * this path except that the final path element is renamed. |
| | | * @throws IllegalStateException |
| | | * If this managed object path is empty or if its final path |
| | | * element does not comprise of an instantiable relation. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public ManagedObjectPath<C, S> rename(String newName) throws IllegalStateException { |
| | | if (elements.size() == 0) { |
| | | throw new IllegalStateException("Cannot rename an empty path"); |
| | | } |
| | | |
| | | if (r instanceof InstantiableRelationDefinition) { |
| | | InstantiableRelationDefinition<? super C, ? super S> ir = (InstantiableRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(ir, d, newName); |
| | | } else { |
| | | throw new IllegalStateException("Not an instantiable relation"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Serialize this managed object path using the provided serialization |
| | | * strategy. |
| | | * <p> |
| | | * The path elements will be passed to the serializer in big-endian order: |
| | | * starting from the root element and proceeding down to the leaf. |
| | | * |
| | | * @param serializer |
| | | * The managed object path serialization strategy. |
| | | * The managed object path serialization strategy. |
| | | */ |
| | | public abstract void serialize(ManagedObjectPathSerializer serializer); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A path element representing an instantiable managed object. |
| | | */ |
| | | private static final class InstantiableElement |
| | | <C extends ConfigurationClient, S extends Configuration> |
| | | extends Element<C, S> { |
| | | |
| | | // 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<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d, String name) { |
| | | super(d); |
| | | this.r = r; |
| | | this.name = name; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String getName() { |
| | | return name; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public InstantiableRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, |
| | | getManagedObjectDefinition(), name); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A path element representing an optional managed object. |
| | | */ |
| | | 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<? super C, ? super S> r; |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private OptionalElement(OptionalRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public OptionalRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer |
| | | .appendManagedObjectPathElement(r, getManagedObjectDefinition()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A path element representing an set managed object. |
| | | */ |
| | | private static final class SetElement |
| | | <C extends ConfigurationClient, S extends Configuration> |
| | | extends Element<C, S> { |
| | | |
| | | // Factory method. |
| | | private static final <C extends ConfigurationClient, |
| | | S extends Configuration> |
| | | SetElement<C, S> create( |
| | | SetRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | return new SetElement<C, S>(r, d); |
| | | } |
| | | |
| | | // The set relation. |
| | | private final SetRelationDefinition<? super C, ? super S> r; |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private SetElement( |
| | | SetRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SetRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, |
| | | getManagedObjectDefinition()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * A path element representing a singleton managed object. |
| | | */ |
| | | 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<? super C, ? super S> r; |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private SingletonElement( |
| | | SingletonRelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | super(d); |
| | | this.r = r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SingletonRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | void appendManagedObjectPathElement( |
| | | SetRelationDefinition<? 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<RootCfgClient, RootCfg> EMPTY_PATH = |
| | | new ManagedObjectPath<RootCfgClient, RootCfg>( |
| | | new LinkedList<Element<?, ?>>(), null, 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*)?$"); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new managed object path representing the configuration |
| | | * root. |
| | | * |
| | | * @return Returns a new managed object path representing the |
| | | * configuration root. |
| | | */ |
| | | public static ManagedObjectPath<RootCfgClient, RootCfg> emptyPath() { |
| | | return EMPTY_PATH; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns a managed object path holding the value of the specified |
| | | * string. |
| | | * |
| | | * @param s |
| | | * The string to be parsed. |
| | | * @return Returns a managed object path holding the value of the |
| | | * specified string. |
| | | * @throws IllegalArgumentException |
| | | * If the string could not be parsed. |
| | | */ |
| | | public static ManagedObjectPath<?, ?> valueOf(String s) |
| | | throws IllegalArgumentException { |
| | | String ns = s.trim(); |
| | | |
| | | // Check for root special case. |
| | | if (ns.equals("/")) { |
| | | return EMPTY_PATH; |
| | | } |
| | | |
| | | // Parse the elements. |
| | | LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>(); |
| | | Element<?, ?> lastElement = null; |
| | | 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; |
| | | } |
| | | for (Element<?, ?> element : elements) { |
| | | element.serialize(serializer); |
| | | } |
| | | } |
| | | |
| | | // 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 + "\""); |
| | | } |
| | | |
| | | // Mandatory. |
| | | String relation = m.group(1); |
| | | |
| | | // Optional. |
| | | String type = m.group(3); |
| | | |
| | | // Mandatory if relation is instantiable. |
| | | String name = m.group(5); |
| | | |
| | | // 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. |
| | | lastElement = createElement(r, ns, es, type, name); |
| | | elements.add(lastElement); |
| | | definition = lastElement.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, lastElement); |
| | | } |
| | | /** |
| | | * Get the number of path elements in this managed object path. |
| | | * |
| | | * @return Returns the number of path elements (0 - means no offset, 1 means |
| | | * the parent, and 2 means the grand-parent). |
| | | */ |
| | | public int size() { |
| | | return elements.size(); |
| | | } |
| | | |
| | | /** |
| | | * Creates a DN representation of this managed object path. |
| | | * |
| | | * @return Returns a DN representation of this managed object path. |
| | | */ |
| | | public DN toDN() { |
| | | // Use a simple serializer to create the contents. |
| | | DNSerializer serializer = new DNSerializer(); |
| | | serialize(serializer); |
| | | return serializer.toDN(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | StringBuilder builder = new StringBuilder(); |
| | | toString(builder); |
| | | return builder.toString(); |
| | | } |
| | | |
| | | // 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, Element<C, S> lastElement) { |
| | | return new ManagedObjectPath<C, S>(elements, lastElement |
| | | .getRelationDefinition(), lastElement.getManagedObjectDefinition()); |
| | | } |
| | | |
| | | |
| | | |
| | | // 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; |
| | | /** |
| | | * Appends a string representation of this managed object path to the |
| | | * provided string builder. |
| | | * |
| | | * @param builder |
| | | * Append the string representation to this builder. |
| | | * @see #toString() |
| | | */ |
| | | public void toString(final StringBuilder builder) { |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | 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 SetRelationDefinition) { |
| | | SetRelationDefinition<C, S> ir = (SetRelationDefinition<C, S>) r; |
| | | |
| | | if (name != null) { |
| | | throw new IllegalArgumentException("Invalid path element \"" + element |
| | | + "\" in path \"" + path |
| | | + "\": instance name specified for set relation"); |
| | | } |
| | | |
| | | return SetElement.create(ir, d); |
| | | } 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 managed object definition in this path. |
| | | private final AbstractManagedObjectDefinition<C, S> d; |
| | | |
| | | // The list of path elements in this path. |
| | | private final List<Element<?, ?>> elements; |
| | | |
| | | // The last relation definition in this path. |
| | | private final RelationDefinition<? super C, ? super S> r; |
| | | |
| | | |
| | | |
| | | // Private constructor. |
| | | private ManagedObjectPath(LinkedList<Element<?, ?>> elements, |
| | | RelationDefinition<? super C, ? super S> r, |
| | | AbstractManagedObjectDefinition<C, S> d) { |
| | | this.elements = Collections.unmodifiableList(elements); |
| | | this.r = r; |
| | | this.d = d; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new managed object path which has the same structure as |
| | | * this path except that the final path element is associated with |
| | | * the specified managed object definition. |
| | | * |
| | | * @param <CC> |
| | | * The type of client managed object configuration that |
| | | * this path will reference. |
| | | * @param <SS> |
| | | * The type of server managed object configuration that |
| | | * this path will reference. |
| | | * @param nd |
| | | * The new managed object definition. |
| | | * @return Returns a new managed object path which has the same |
| | | * structure as this path except that the final path element |
| | | * is associated with the specified managed object |
| | | * definition. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public <CC extends C, SS extends S> ManagedObjectPath<CC, SS> asSubType( |
| | | AbstractManagedObjectDefinition<CC, SS> nd) { |
| | | if (r instanceof InstantiableRelationDefinition) { |
| | | InstantiableRelationDefinition<? super C, ? super S> ir = |
| | | (InstantiableRelationDefinition<? super C, ? super S>) r; |
| | | if (elements.size() == 0) { |
| | | return parent().child(ir, nd, "null"); |
| | | } else { |
| | | return parent().child(ir, nd, |
| | | elements.get(elements.size() - 1).getName()); |
| | | } |
| | | } else if (r instanceof SetRelationDefinition) { |
| | | SetRelationDefinition<? super C, ? super S> sr = |
| | | (SetRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(sr, nd); |
| | | } else if (r instanceof OptionalRelationDefinition) { |
| | | OptionalRelationDefinition<? super C, ? super S> or = |
| | | (OptionalRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(or, nd); |
| | | } else { |
| | | SingletonRelationDefinition<? super C, ? super S> sr = |
| | | (SingletonRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(sr, nd); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided |
| | | * 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<M, N> child( |
| | | InstantiableRelationDefinition<? super M, ? super N> r, |
| | | AbstractManagedObjectDefinition<M, N> d, String name) |
| | | throws IllegalArgumentException { |
| | | if (name.trim().length() == 0) { |
| | | throw new IllegalArgumentException( |
| | | "Empty or blank managed object names are not allowed"); |
| | | } |
| | | LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( |
| | | elements); |
| | | celements.add(new InstantiableElement<M, N>(r, d, name)); |
| | | return new ManagedObjectPath<M, N>(celements, r, 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 |
| | | * The relative name of the child managed object. |
| | | * @return Returns a new child managed object path beneath the |
| | | * provided parent path. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<M, N> child( |
| | | InstantiableRelationDefinition<M, N> r, String name) |
| | | throws IllegalArgumentException { |
| | | return child(r, r.getChildDefinition(), name); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided |
| | | * 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, r, 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 <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 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, r, 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 <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<M, N> child(SingletonRelationDefinition<M, N> r) { |
| | | return child(r, r.getChildDefinition()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided |
| | | * 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 set 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<M, N> child( |
| | | SetRelationDefinition<? super M, ? super N> r, |
| | | AbstractManagedObjectDefinition<M, N> d) |
| | | throws IllegalArgumentException { |
| | | LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>( |
| | | elements); |
| | | celements.add(new SetElement<M, N>(r, d)); |
| | | return new ManagedObjectPath<M, N>(celements, r, d); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new child managed object path beneath the provided parent |
| | | * path having the managed object definition indicated by |
| | | * <code>name</code>. |
| | | * |
| | | * @param <M> |
| | | * The type of client managed object configuration that the |
| | | * path references. |
| | | * @param <N> |
| | | * The type of server managed object configuration that the |
| | | * path references. |
| | | * @param r |
| | | * The set relation referencing the child. |
| | | * @param name |
| | | * The name of 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. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank or specifies a |
| | | * managed object definition which is not a sub-type of the |
| | | * relation's child definition. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<? extends M, ? extends N> child( |
| | | SetRelationDefinition<M, N> r, |
| | | String name) |
| | | throws IllegalArgumentException { |
| | | AbstractManagedObjectDefinition<M, N> d = r.getChildDefinition(); |
| | | return child(r, d.getChild(name)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 set relation referencing the child. |
| | | * @return Returns a new child managed object path beneath the |
| | | * provided parent path. |
| | | * @throws IllegalArgumentException |
| | | * If the provided name is empty or blank. |
| | | */ |
| | | public <M extends ConfigurationClient, N extends Configuration> |
| | | ManagedObjectPath<M, N> child( |
| | | SetRelationDefinition<M, N> r) |
| | | throws IllegalArgumentException { |
| | | return child(r, r.getChildDefinition()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean equals(Object obj) { |
| | | if (obj == this) { |
| | | return true; |
| | | } else if (obj instanceof ManagedObjectPath) { |
| | | ManagedObjectPath<?, ?> other = (ManagedObjectPath<?, ?>) obj; |
| | | return toString().equals(other.toString()); |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the definition of the managed object referred to by this |
| | | * path. |
| | | * <p> |
| | | * 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. |
| | | */ |
| | | public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() { |
| | | return d; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the name of the managed object referred to by this path if |
| | | * applicable. |
| | | * <p> |
| | | * If there path does not refer to an instantiable managed object |
| | | * <code>null</code> is returned. |
| | | * |
| | | * @return Returns the name of the managed object referred to by |
| | | * this path, or <code>null</code> if the managed object |
| | | * does not have a name. |
| | | */ |
| | | public String getName() { |
| | | if (elements.isEmpty()) { |
| | | return null; |
| | | } else { |
| | | return elements.get(elements.size() - 1).getName(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the relation definition of the managed object referred to by |
| | | * this path. |
| | | * <p> |
| | | * When the path is empty, the <code>null</code> is returned. |
| | | * |
| | | * @return Returns the relation definition of the managed object |
| | | * referred to by this path, or the <code>null</code> if |
| | | * the path is empty. |
| | | */ |
| | | public RelationDefinition<? super C, ? super S> getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public int hashCode() { |
| | | return toString().hashCode(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Determine whether or not this path contains any path elements. |
| | | * |
| | | * @return Returns <code>true</code> if this path does not contain |
| | | * any path elements. |
| | | */ |
| | | public boolean isEmpty() { |
| | | return elements.isEmpty(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Determines whether this managed object path references the same |
| | | * location as the provided managed object path. |
| | | * <p> |
| | | * This method differs from <code>equals</code> in that it ignores |
| | | * sub-type definitions. |
| | | * |
| | | * @param other |
| | | * The managed object path to be compared. |
| | | * @return Returns <code>true</code> if this managed object path |
| | | * references the same location as the provided managed |
| | | * object path. |
| | | */ |
| | | public boolean matches(ManagedObjectPath<?, ?> other) { |
| | | DN thisDN = toDN(); |
| | | DN otherDN = other.toDN(); |
| | | return thisDN.equals(otherDN); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | | * |
| | | * @param offset |
| | | * The number of path elements (0 - means no offset, 1 |
| | | * means the parent, and 2 means the grand-parent). |
| | | * @return Returns a new parent managed object path the specified |
| | | * number of path elements above this path. |
| | | * @throws IllegalArgumentException |
| | | * If the offset is less than 0, or greater than the |
| | | * number of path elements in this path. |
| | | */ |
| | | public ManagedObjectPath<?, ?> parent(int offset) |
| | | throws IllegalArgumentException { |
| | | if (offset < 0) { |
| | | throw new IllegalArgumentException("Negative offset"); |
| | | } |
| | | |
| | | if (offset > elements.size()) { |
| | | throw new IllegalArgumentException( |
| | | "Offset is greater than the number of path elements"); |
| | | } |
| | | |
| | | // An offset of 0 leaves the path unchanged. |
| | | if (offset == 0) { |
| | | return this; |
| | | } |
| | | |
| | | // 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)); |
| | | return create(celements, celements.getLast()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new managed object path which has the same structure as |
| | | * this path except that the final path element is renamed. The |
| | | * final path element must comprise of an instantiable relation. |
| | | * |
| | | * @param newName |
| | | * The new name of the final path element. |
| | | * @return Returns a new managed object path which has the same |
| | | * structure as this path except that the final path element |
| | | * is renamed. |
| | | * @throws IllegalStateException |
| | | * If this managed object path is empty or if its final |
| | | * path element does not comprise of an instantiable |
| | | * relation. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public ManagedObjectPath<C, S> rename(String newName) |
| | | throws IllegalStateException { |
| | | if (elements.size() == 0) { |
| | | throw new IllegalStateException("Cannot rename an empty path"); |
| | | } |
| | | |
| | | if (r instanceof InstantiableRelationDefinition) { |
| | | InstantiableRelationDefinition<? super C, ? super S> ir = |
| | | (InstantiableRelationDefinition<? super C, ? super S>) r; |
| | | return parent().child(ir, d, newName); |
| | | } else { |
| | | throw new IllegalStateException("Not an instantiable relation"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Serialize this managed object path using the provided |
| | | * serialization strategy. |
| | | * <p> |
| | | * The path elements will be passed to the serializer in big-endian |
| | | * order: starting from the root element and proceeding down to the |
| | | * leaf. |
| | | * |
| | | * @param serializer |
| | | * The managed object path serialization strategy. |
| | | */ |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | for (Element<?, ?> element : elements) { |
| | | element.serialize(serializer); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the number of path elements in this managed object path. |
| | | * |
| | | * @return Returns the number of path elements (0 - means no offset, |
| | | * 1 means the parent, and 2 means the grand-parent). |
| | | */ |
| | | public int size() { |
| | | return elements.size(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a DN representation of this managed object path. |
| | | * |
| | | * @return Returns a DN representation of this managed object path. |
| | | */ |
| | | public DN toDN() { |
| | | // Use a simple serializer to create the contents. |
| | | DNSerializer serializer = new DNSerializer(); |
| | | serialize(serializer); |
| | | return serializer.toDN(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | StringBuilder builder = new StringBuilder(); |
| | | toString(builder); |
| | | return builder.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Appends a string representation of this managed object path to |
| | | * the provided string builder. |
| | | * |
| | | * @param builder |
| | | * Append the string representation to this builder. |
| | | * @see #toString() |
| | | */ |
| | | public void toString(final StringBuilder builder) { |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | } |