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
028 package org.opends.server.admin;
029 import org.opends.messages.Message;
030
031
032
033 import static org.opends.server.util.Validator.*;
034
035 import java.util.EnumSet;
036 import java.util.Locale;
037 import java.util.MissingResourceException;
038 import java.util.Set;
039
040
041
042 /**
043 * Relation definitions define relationships between types of managed
044 * objects. In addition they define the ownership model:
045 * <ul>
046 * <li>composition - referenced managed objects are owned by the
047 * parent managed object and are deleted when the parent is deleted
048 * <li>aggregation - referenced managed objects are not owned by the
049 * parent managed object. Instead they are shared by other managed
050 * objects.
051 * </ul>
052 * Relations define how clients interact with the configuration. For
053 * example, clients manage aggregated managed objects in a shared
054 * location and attach them to parent managed objects. Composed
055 * managed objects, on the other hand, would be created directly
056 * beneath the parent managed object and destroyed with it too.
057 * <p>
058 * Within the server, listeners can choose to request notification of
059 * managed objects being added or removed from relations.
060 * <p>
061 * In LDAP, compositions are represented as follows:
062 * <ul>
063 * <li>singleton relations (one to one): a referenced managed object
064 * is represented using a child entry directly beneath the parent
065 * <li>optional relations (one to zero or one): a referenced managed
066 * object is represented using a child entry directly beneath the
067 * parent
068 * <li>instantiable relations (one to many): the relation is
069 * represented using a child entry directly beneath the parent.
070 * Referenced managed objects are represented using child entries of
071 * this "relation entry".
072 * </ul>
073 * Whereas, aggregations are represented by storing the DNs of the
074 * referenced managed objects in an attribute of the aggregating
075 * managed object.
076 *
077 * @param <C>
078 * The type of client managed object configuration that this
079 * relation definition refers to.
080 * @param <S>
081 * The type of server managed object configuration that this
082 * relation definition refers to.
083 */
084 public abstract class RelationDefinition
085 <C extends ConfigurationClient, S extends Configuration> {
086
087 /**
088 * An interface for incrementally constructing relation definitions.
089 *
090 * @param <C>
091 * The type of client managed object configuration that
092 * this relation definition refers to.
093 * @param <S>
094 * The type of server managed object configuration that
095 * this relation definition refers to.
096 * @param <D>
097 * The type of relation definition constructed by this
098 * builder.
099 */
100 protected abstract static class AbstractBuilder
101 <C extends ConfigurationClient, S extends Configuration,
102 D extends RelationDefinition<C, S>> {
103
104 // Common fields.
105 private final Common<C, S> common;
106
107
108
109 /**
110 * Create a property definition builder.
111 *
112 * @param pd
113 * The parent managed object definition.
114 * @param name
115 * The name of the relation.
116 * @param cd
117 * The child managed object definition.
118 */
119 protected AbstractBuilder(AbstractManagedObjectDefinition<?, ?> pd,
120 String name, AbstractManagedObjectDefinition<C, S> cd) {
121 this.common = new Common<C, S>(pd, name, cd);
122 }
123
124
125
126 /**
127 * Construct a relation definition based on the properties of this
128 * builder.
129 *
130 * @return The new relation definition.
131 */
132 public final D getInstance() {
133 return buildInstance(common);
134 }
135
136
137
138 /**
139 * Add a relation definition option.
140 *
141 * @param option
142 * The relation option.
143 */
144 public final void setOption(RelationOption option) {
145 ensureNotNull(option);
146 common.options.add(option);
147 }
148
149
150
151 /**
152 * Build a relation definition based on the properties of this
153 * builder.
154 *
155 * @param common
156 * The common fields of the new relation definition.
157 * @return The new relation definition.
158 */
159 protected abstract D buildInstance(Common<C, S> common);
160 }
161
162
163
164 /**
165 * Opaque structure containing fields common to all relation
166 * definition types.
167 *
168 * @param <C>
169 * The type of client managed object configuration that
170 * this relation definition refers to.
171 * @param <S>
172 * The type of server managed object configuration that
173 * this relation definition refers to.
174 */
175 protected static final class Common
176 <C extends ConfigurationClient, S extends Configuration> {
177
178 // The definition of the child managed object.
179 private final AbstractManagedObjectDefinition<C, S> cd;
180
181 // The name of the relation.
182 private final String name;
183
184 // Options applicable to this definition.
185 private final Set<RelationOption> options;
186
187 // The definition of the parent managed object.
188 private final AbstractManagedObjectDefinition<?, ?> pd;
189
190
191
192 // Private constructor.
193 private Common(AbstractManagedObjectDefinition<?, ?> pd, String name,
194 AbstractManagedObjectDefinition<C, S> cd) {
195 this.name = name;
196 this.pd = pd;
197 this.cd = cd;
198 this.options = EnumSet.noneOf(RelationOption.class);
199 }
200 }
201
202 // Common fields.
203 private final Common<C, S> common;
204
205
206
207 /**
208 * Create a new managed object relation definition with the
209 * specified common fields.
210 *
211 * @param common
212 * The common fields of the new relation definition.
213 */
214 protected RelationDefinition(Common<C, S> common) {
215 this.common = common;
216 }
217
218
219
220 /**
221 * Apply a visitor to this relation definition.
222 *
223 * @param <R>
224 * The return type of the visitor's methods.
225 * @param <P>
226 * The type of the additional parameters to the visitor's
227 * methods.
228 * @param v
229 * The relation definition visitor.
230 * @param p
231 * Optional additional visitor parameter.
232 * @return Returns a result as specified by the visitor.
233 */
234 public abstract <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p);
235
236
237
238 /**
239 * Get the definition of the child managed object.
240 *
241 * @return Returns the definition of the child managed object.
242 */
243 public final AbstractManagedObjectDefinition<C, S> getChildDefinition() {
244 return common.cd;
245 }
246
247
248
249 /**
250 * Gets the optional description of this relation definition in the
251 * default locale.
252 *
253 * @return Returns the description of this relation definition in
254 * the default locale, or <code>null</code> if there is no
255 * description.
256 */
257 public final Message getDescription() {
258 return getDescription(Locale.getDefault());
259 }
260
261
262
263 /**
264 * Gets the optional description of this relation definition in the
265 * specified locale.
266 *
267 * @param locale
268 * The locale.
269 * @return Returns the description of this relation definition in
270 * the specified locale, or <code>null</code> if there is
271 * no description.
272 */
273 public final Message getDescription(Locale locale) {
274 try {
275 String property = "relation." + common.name + ".description";
276 return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
277 getParentDefinition(), property, locale);
278 } catch (MissingResourceException e) {
279 return null;
280 }
281 }
282
283
284
285 /**
286 * Get the name of the relation.
287 *
288 * @return Returns the name of the relation.
289 */
290 public final String getName() {
291 return common.name;
292 }
293
294
295
296 /**
297 * Get the definition of the parent managed object.
298 *
299 * @return Returns the definition of the parent managed object.
300 */
301 public final AbstractManagedObjectDefinition<?, ?> getParentDefinition() {
302 return common.pd;
303 }
304
305
306
307 /**
308 * Gets the synopsis of this relation definition in the default
309 * locale.
310 *
311 * @return Returns the synopsis of this relation definition in the
312 * default locale.
313 */
314 public final Message getSynopsis() {
315 return getSynopsis(Locale.getDefault());
316 }
317
318
319
320 /**
321 * Gets the synopsis of this relation definition in the specified
322 * locale.
323 *
324 * @param locale
325 * The locale.
326 * @return Returns the synopsis of this relation definition in the
327 * specified locale.
328 */
329 public final Message getSynopsis(Locale locale) {
330 String property = "relation." + common.name + ".synopsis";
331 return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
332 getParentDefinition(), property, locale);
333 }
334
335
336
337 /**
338 * Gets the user friendly name of this relation definition in the
339 * default locale.
340 *
341 * @return Returns the user friendly name of this relation
342 * definition in the default locale.
343 */
344 public final Message getUserFriendlyName() {
345 return getUserFriendlyName(Locale.getDefault());
346 }
347
348
349
350 /**
351 * Gets the user friendly name of this relation definition in the
352 * specified locale.
353 *
354 * @param locale
355 * The locale.
356 * @return Returns the user friendly name of this relation
357 * definition in the specified locale.
358 */
359 public final Message getUserFriendlyName(Locale locale) {
360 String property = "relation." + common.name + ".user-friendly-name";
361 return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
362 getParentDefinition(), property, locale);
363 }
364
365
366
367 /**
368 * Check if the specified option is set for this relation
369 * definition.
370 *
371 * @param option
372 * The option to test.
373 * @return Returns <code>true</code> if the option is set, or
374 * <code>false</code> otherwise.
375 */
376 public final boolean hasOption(RelationOption option) {
377 return common.options.contains(option);
378 }
379
380
381
382 /**
383 * {@inheritDoc}
384 */
385 @Override
386 public final String toString() {
387 StringBuilder builder = new StringBuilder();
388 toString(builder);
389 return builder.toString();
390 }
391
392
393
394 /**
395 * Append a string representation of the managed object relation to
396 * the provided string builder.
397 *
398 * @param builder
399 * The string builder where the string representation
400 * should be appended.
401 */
402 public abstract void toString(StringBuilder builder);
403
404
405
406 /**
407 * Performs any run-time initialization required by this relation
408 * definition. This may include resolving managed object paths and
409 * property names.
410 *
411 * @throws Exception
412 * If this relation definition could not be initialized.
413 */
414 protected void initialize() throws Exception {
415 // No implementation required.
416 }
417 }