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    }