001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.admin;
028
029
030
031 import org.opends.server.types.AttributeValue;
032 import org.opends.server.types.DN;
033 import org.opends.server.types.DirectoryException;
034 import org.opends.server.types.RDN;
035 import org.opends.server.util.StaticUtils;
036
037
038
039 /**
040 * A reference to another managed object.
041 *
042 * @param <C>
043 * The type of client managed object configuration that this
044 * reference refers to.
045 * @param <S>
046 * The type of server managed object configuration that this
047 * reference refers to.
048 */
049 public final class Reference<C extends ConfigurationClient,
050 S extends Configuration> {
051
052 /**
053 * Parses a DN string value as a reference using the provided
054 * managed object path and relation definition.
055 *
056 * @param <C>
057 * The type of client managed object configuration that
058 * this reference refers to.
059 * @param <S>
060 * The type of server managed object configuration that
061 * this reference refers to.
062 * @param p
063 * The path of the referenced managed object's parent.
064 * @param rd
065 * The instantiable relation in the parent which contains
066 * the referenced managed object.
067 * @param s
068 * The DN string value.
069 * @return Returns the new reference based on the provided DN string
070 * value.
071 * @throws IllegalArgumentException
072 * If the DN string value could not be decoded as a DN or
073 * if the provided DN did not correspond to the provided
074 * path and relation.
075 */
076 public static <C extends ConfigurationClient, S extends Configuration>
077 Reference<C, S> parseDN(
078 ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd,
079 String s) throws IllegalArgumentException {
080 AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition();
081 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
082 if (tmp != rd) {
083 throw new IllegalArgumentException("The relation \"" + rd.getName()
084 + "\" is not associated with the definition \"" + d.getName() + "\"");
085 }
086
087 DN dn;
088 try {
089 dn = DN.decode(s);
090 } catch (DirectoryException e) {
091 throw new IllegalArgumentException("Unabled to decode the DN string: \""
092 + s + "\"");
093 }
094
095 RDN rdn = dn.getRDN();
096 if (rdn == null) {
097 throw new IllegalArgumentException("Unabled to decode the DN string: \""
098 + s + "\"");
099 }
100
101 AttributeValue av = rdn.getAttributeValue(0);
102 if (av == null) {
103 throw new IllegalArgumentException("Unabled to decode the DN string: \""
104 + s + "\"");
105 }
106
107 String name = av.getStringValue();
108
109 // Check that the DN was valid.
110 DN expected = p.child(rd, name).toDN();
111 if (!dn.equals(expected)) {
112 throw new IllegalArgumentException("Unabled to decode the DN string: \""
113 + s + "\"");
114 }
115
116 return new Reference<C, S>(p, rd, name);
117 }
118
119
120
121 /**
122 * Parses a name as a reference using the provided managed object
123 * path and relation definition.
124 *
125 * @param <C>
126 * The type of client managed object configuration that
127 * this reference refers to.
128 * @param <S>
129 * The type of server managed object configuration that
130 * this reference refers to.
131 * @param p
132 * The path of the referenced managed object's parent.
133 * @param rd
134 * The instantiable relation in the parent which contains
135 * the referenced managed object.
136 * @param s
137 * The name of the referenced managed object.
138 * @return Returns the new reference based on the provided name.
139 * @throws IllegalArgumentException
140 * If the relation is not associated with the provided
141 * parent's definition, or if the provided name is empty.
142 */
143 public static <C extends ConfigurationClient, S extends Configuration>
144 Reference<C, S> parseName(
145 ManagedObjectPath<?, ?> p, InstantiableRelationDefinition<C, S> rd,
146 String s) throws IllegalArgumentException {
147 // Sanity checks.
148 AbstractManagedObjectDefinition<?, ?> d = p.getManagedObjectDefinition();
149 RelationDefinition<?, ?> tmp = d.getRelationDefinition(rd.getName());
150 if (tmp != rd) {
151 throw new IllegalArgumentException("The relation \"" + rd.getName()
152 + "\" is not associated with the definition \"" + d.getName() + "\"");
153 }
154
155 if (s.trim().length() == 0) {
156 throw new IllegalArgumentException("Empty names are not allowed");
157 }
158
159 return new Reference<C, S>(p, rd, s);
160 }
161
162 // The name of the referenced managed object.
163 private final String name;
164
165 // The path of the referenced managed object.
166 private final ManagedObjectPath<C, S> path;
167
168 // The instantiable relation in the parent which contains the
169 // referenced managed object.
170 private final InstantiableRelationDefinition<C, S> relation;
171
172
173
174 // Private constructor.
175 private Reference(ManagedObjectPath<?, ?> parent,
176 InstantiableRelationDefinition<C, S> relation, String name)
177 throws IllegalArgumentException {
178 this.relation = relation;
179 this.name = name;
180 this.path = parent.child(relation, name);
181 }
182
183
184
185 /**
186 * Gets the name of the referenced managed object.
187 *
188 * @return Returns the name of the referenced managed object.
189 */
190 public String getName() {
191 return name;
192 }
193
194
195
196 /**
197 * Gets the normalized name of the referenced managed object.
198 *
199 * @return Returns the normalized name of the referenced managed
200 * object.
201 */
202 public String getNormalizedName() {
203 PropertyDefinition<?> pd = relation.getNamingPropertyDefinition();
204 return normalizeName(pd);
205 }
206
207
208
209 /**
210 * Gets the DN of the referenced managed object.
211 *
212 * @return Returns the DN of the referenced managed object.
213 */
214 public DN toDN() {
215 return path.toDN();
216 }
217
218
219
220 /**
221 * {@inheritDoc}
222 */
223 public String toString() {
224 return name;
225 }
226
227
228
229 // Normalize a value using the specified naming property definition
230 // if defined.
231 private <T> String normalizeName(PropertyDefinition<T> pd) {
232 if (pd != null) {
233 try {
234 T tvalue = pd.decodeValue(name);
235 return pd.normalizeValue(tvalue);
236 } catch (IllegalPropertyValueStringException e) {
237 // Fall through to default normalization.
238 }
239 }
240
241 // FIXME: should really use directory string normalizer.
242 String s = name.trim().replaceAll(" +", " ");
243 return StaticUtils.toLowerCase(s);
244 }
245 }