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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2008-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027
028package org.opends.server.admin;
029import org.forgerock.i18n.LocalizableMessage;
030
031
032
033import static org.forgerock.util.Reject.*;
034
035import java.util.EnumSet;
036import java.util.Locale;
037import java.util.MissingResourceException;
038import 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" and are named by the user
072 * <li>set relations (one to many): the relation is
073 * represented using a child entry directly beneath the parent.
074 * Referenced managed objects are represented using child entries of
075 * this "relation entry" whose name is the type of the managed object.
076 * </ul>
077 * Whereas, aggregations are represented by storing the DNs of the
078 * referenced managed objects in an attribute of the aggregating
079 * managed object.
080 *
081 * @param <C>
082 *          The type of client managed object configuration that this
083 *          relation definition refers to.
084 * @param <S>
085 *          The type of server managed object configuration that this
086 *          relation definition refers to.
087 */
088public abstract class RelationDefinition
089    <C extends ConfigurationClient, S extends Configuration> {
090
091  /**
092   * An interface for incrementally constructing relation definitions.
093   *
094   * @param <C>
095   *          The type of client managed object configuration that
096   *          this relation definition refers to.
097   * @param <S>
098   *          The type of server managed object configuration that
099   *          this relation definition refers to.
100   * @param <D>
101   *          The type of relation definition constructed by this
102   *          builder.
103   */
104  protected static abstract class AbstractBuilder
105      <C extends ConfigurationClient, S extends Configuration,
106       D extends RelationDefinition<C, S>> {
107
108    /** Common fields. */
109    private final Common<C, S> common;
110
111
112
113    /**
114     * Create a property definition builder.
115     *
116     * @param pd
117     *          The parent managed object definition.
118     * @param name
119     *          The name of the relation.
120     * @param cd
121     *          The child managed object definition.
122     */
123    protected AbstractBuilder(AbstractManagedObjectDefinition<?, ?> pd,
124        String name, AbstractManagedObjectDefinition<C, S> cd) {
125      this.common = new Common<>(pd, name, cd);
126    }
127
128
129
130    /**
131     * Construct a relation definition based on the properties of this
132     * builder.
133     *
134     * @return The new relation definition.
135     */
136    public final D getInstance() {
137      return buildInstance(common);
138    }
139
140
141
142    /**
143     * Add a relation definition option.
144     *
145     * @param option
146     *          The relation option.
147     */
148    public final void setOption(RelationOption option) {
149      ifNull(option);
150      common.options.add(option);
151    }
152
153
154
155    /**
156     * Build a relation definition based on the properties of this
157     * builder.
158     *
159     * @param common
160     *          The common fields of the new relation definition.
161     * @return The new relation definition.
162     */
163    protected abstract D buildInstance(Common<C, S> common);
164  }
165
166
167
168  /**
169   * Opaque structure containing fields common to all relation
170   * definition types.
171   *
172   * @param <C>
173   *          The type of client managed object configuration that
174   *          this relation definition refers to.
175   * @param <S>
176   *          The type of server managed object configuration that
177   *          this relation definition refers to.
178   */
179  protected static final class Common
180    <C extends ConfigurationClient, S extends Configuration> {
181
182    /** The definition of the child managed object. */
183    private final AbstractManagedObjectDefinition<C, S> cd;
184
185    /** The name of the relation. */
186    private final String name;
187
188    /** Options applicable to this definition. */
189    private final Set<RelationOption> options;
190
191    /** The definition of the parent managed object. */
192    private final AbstractManagedObjectDefinition<?, ?> pd;
193
194
195
196    /** Private constructor. */
197    private Common(AbstractManagedObjectDefinition<?, ?> pd, String name,
198        AbstractManagedObjectDefinition<C, S> cd) {
199      this.name = name;
200      this.pd = pd;
201      this.cd = cd;
202      this.options = EnumSet.noneOf(RelationOption.class);
203    }
204  }
205
206  /** Common fields. */
207  private final Common<C, S> common;
208
209
210
211  /**
212   * Create a new managed object relation definition with the
213   * specified common fields.
214   *
215   * @param common
216   *          The common fields of the new relation definition.
217   */
218  protected RelationDefinition(Common<C, S> common) {
219    this.common = common;
220  }
221
222
223
224  /**
225   * Apply a visitor to this relation definition.
226   *
227   * @param <R>
228   *          The return type of the visitor's methods.
229   * @param <P>
230   *          The type of the additional parameters to the visitor's
231   *          methods.
232   * @param v
233   *          The relation definition visitor.
234   * @param p
235   *          Optional additional visitor parameter.
236   * @return Returns a result as specified by the visitor.
237   */
238  public abstract <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p);
239
240
241
242  /**
243   * Get the definition of the child managed object.
244   *
245   * @return Returns the definition of the child managed object.
246   */
247  public final AbstractManagedObjectDefinition<C, S> getChildDefinition() {
248    return common.cd;
249  }
250
251
252
253  /**
254   * Gets the optional description of this relation definition in the
255   * default locale.
256   *
257   * @return Returns the description of this relation definition in
258   *         the default locale, or <code>null</code> if there is no
259   *         description.
260   */
261  public final LocalizableMessage getDescription() {
262    return getDescription(Locale.getDefault());
263  }
264
265
266
267  /**
268   * Gets the optional description of this relation definition in the
269   * specified locale.
270   *
271   * @param locale
272   *          The locale.
273   * @return Returns the description of this relation definition in
274   *         the specified locale, or <code>null</code> if there is
275   *         no description.
276   */
277  public final LocalizableMessage getDescription(Locale locale) {
278    try {
279      String property = "relation." + common.name + ".description";
280      return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
281          getParentDefinition(), property, locale);
282    } catch (MissingResourceException e) {
283      return null;
284    }
285  }
286
287
288
289  /**
290   * Get the name of the relation.
291   *
292   * @return Returns the name of the relation.
293   */
294  public final String getName() {
295    return common.name;
296  }
297
298
299
300  /**
301   * Get the definition of the parent managed object.
302   *
303   * @return Returns the definition of the parent managed object.
304   */
305  public final AbstractManagedObjectDefinition<?, ?> getParentDefinition() {
306    return common.pd;
307  }
308
309
310
311  /**
312   * Gets the synopsis of this relation definition in the default
313   * locale.
314   *
315   * @return Returns the synopsis of this relation definition in the
316   *         default locale.
317   */
318  public final LocalizableMessage getSynopsis() {
319    return getSynopsis(Locale.getDefault());
320  }
321
322
323
324  /**
325   * Gets the synopsis of this relation definition in the specified
326   * locale.
327   *
328   * @param locale
329   *          The locale.
330   * @return Returns the synopsis of this relation definition in the
331   *         specified locale.
332   */
333  public final LocalizableMessage getSynopsis(Locale locale) {
334    String property = "relation." + common.name + ".synopsis";
335    return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
336        getParentDefinition(), property, locale);
337  }
338
339
340
341  /**
342   * Gets the user friendly name of this relation definition in the
343   * default locale.
344   *
345   * @return Returns the user friendly name of this relation
346   *         definition in the default locale.
347   */
348  public final LocalizableMessage getUserFriendlyName() {
349    return getUserFriendlyName(Locale.getDefault());
350  }
351
352
353
354  /**
355   * Gets the user friendly name of this relation definition in the
356   * specified locale.
357   *
358   * @param locale
359   *          The locale.
360   * @return Returns the user friendly name of this relation
361   *         definition in the specified locale.
362   */
363  public final LocalizableMessage getUserFriendlyName(Locale locale) {
364    String property = "relation." + common.name + ".user-friendly-name";
365    return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
366        getParentDefinition(), property, locale);
367  }
368
369
370
371  /**
372   * Check if the specified option is set for this relation
373   * definition.
374   *
375   * @param option
376   *          The option to test.
377   * @return Returns <code>true</code> if the option is set, or
378   *         <code>false</code> otherwise.
379   */
380  public final boolean hasOption(RelationOption option) {
381    return common.options.contains(option);
382  }
383
384
385
386  /** {@inheritDoc} */
387  @Override
388  public final String toString() {
389    StringBuilder builder = new StringBuilder();
390    toString(builder);
391    return builder.toString();
392  }
393
394
395
396  /**
397   * Append a string representation of the managed object relation to
398   * the provided string builder.
399   *
400   * @param builder
401   *          The string builder where the string representation
402   *          should be appended.
403   */
404  public abstract void toString(StringBuilder builder);
405
406
407
408  /**
409   * Performs any run-time initialization required by this relation
410   * definition. This may include resolving managed object paths and
411   * property names.
412   *
413   * @throws Exception
414   *           If this relation definition could not be initialized.
415   */
416  protected void initialize() throws Exception {
417    // No implementation required.
418  }
419}