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 2015 ForgeRock AS.
026 */
027
028package org.forgerock.opendj.config;
029
030import org.forgerock.util.Reject;
031
032import java.util.Collections;
033import java.util.HashMap;
034import java.util.Locale;
035import java.util.Map;
036import java.util.Set;
037
038import org.forgerock.i18n.LocalizableMessage;
039
040/**
041 * A managed object composite relationship definition which represents a
042 * composition of zero or more managed objects.
043 *
044 * @param <C>
045 *            The type of client managed object configuration that this relation
046 *            definition refers to.
047 * @param <S>
048 *            The type of server managed object configuration that this relation
049 *            definition refers to.
050 */
051public final class InstantiableRelationDefinition<C extends ConfigurationClient, S extends Configuration> extends
052    RelationDefinition<C, S> {
053
054    /**
055     * An interface for incrementally constructing instantiable relation
056     * definitions.
057     *
058     * @param <C>
059     *            The type of client managed object configuration that this
060     *            relation definition refers to.
061     * @param <S>
062     *            The type of server managed object configuration that this
063     *            relation definition refers to.
064     */
065    public static final class Builder<C extends ConfigurationClient, S extends Configuration> extends
066        AbstractBuilder<C, S, InstantiableRelationDefinition<C, S>> {
067
068        /** The optional naming property definition. */
069        private PropertyDefinition<?> namingPropertyDefinition;
070
071        /** The plural name of the relation. */
072        private final String pluralName;
073
074        /**
075         * The optional default managed objects associated with this
076         * instantiable relation definition.
077         */
078        private final Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects =
079            new HashMap<>();
080
081        /**
082         * Creates a new builder which can be used to incrementally build an
083         * instantiable relation definition.
084         *
085         * @param pd
086         *            The parent managed object definition.
087         * @param name
088         *            The name of the relation.
089         * @param pluralName
090         *            The plural name of the relation.
091         * @param cd
092         *            The child managed object definition.
093         */
094        public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name, String pluralName,
095            AbstractManagedObjectDefinition<C, S> cd) {
096            super(pd, name, cd);
097            this.pluralName = pluralName;
098        }
099
100        /**
101         * Adds the named default managed object to this instantiable relation
102         * definition.
103         *
104         * @param name
105         *            The name of the default managed object.
106         * @param defaultManagedObject
107         *            The default managed object.
108         */
109        public void setDefaultManagedObject(String name,
110            DefaultManagedObject<? extends C, ? extends S> defaultManagedObject) {
111            this.defaultManagedObjects.put(name, defaultManagedObject);
112        }
113
114        /**
115         * Sets the naming property for the instantiable relation definition.
116         *
117         * @param namingPropertyDefinition
118         *            The property of the child managed object definition which
119         *            should be used for naming, or <code>null</code> if this
120         *            relation does not use a property for naming.
121         */
122        public void setNamingProperty(PropertyDefinition<?> namingPropertyDefinition) {
123            Reject.ifNull(namingPropertyDefinition);
124            this.namingPropertyDefinition = namingPropertyDefinition;
125        }
126
127        /** {@inheritDoc} */
128        @Override
129        protected InstantiableRelationDefinition<C, S> buildInstance(Common<C, S> common) {
130            return new InstantiableRelationDefinition<>(common, pluralName, namingPropertyDefinition,
131                defaultManagedObjects);
132        }
133
134    }
135
136    /** The optional naming property definition. */
137    private final PropertyDefinition<?> namingPropertyDefinition;
138
139    /** The plural name of the relation. */
140    private final String pluralName;
141
142    /**
143     * The optional default managed objects associated with this
144     * instantiable relation definition.
145     */
146    private final Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects;
147
148    /** Private constructor. */
149    private InstantiableRelationDefinition(Common<C, S> common, String pluralName,
150        PropertyDefinition<?> namingPropertyDefinition,
151        Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects) {
152        super(common);
153        this.pluralName = pluralName;
154        this.namingPropertyDefinition = namingPropertyDefinition;
155        this.defaultManagedObjects = defaultManagedObjects;
156    }
157
158    /** {@inheritDoc} */
159    @Override
160    public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
161        return v.visitInstantiable(this, p);
162    }
163
164    /**
165     * Gets the named default managed object associated with this instantiable
166     * relation definition.
167     *
168     * @param name
169     *            The name of the default managed object.
170     * @return Returns the named default managed object.
171     * @throws IllegalArgumentException
172     *             If there is no default managed object associated with the
173     *             provided name.
174     */
175    public DefaultManagedObject<? extends C, ? extends S> getDefaultManagedObject(String name) {
176        if (!defaultManagedObjects.containsKey(name)) {
177            throw new IllegalArgumentException("unrecognized default managed object \"" + name + "\"");
178        }
179        return defaultManagedObjects.get(name);
180    }
181
182    /**
183     * Gets the names of the default managed objects associated with this
184     * instantiable relation definition.
185     *
186     * @return Returns an unmodifiable set containing the names of the default
187     *         managed object.
188     */
189    public Set<String> getDefaultManagedObjectNames() {
190        return Collections.unmodifiableSet(defaultManagedObjects.keySet());
191    }
192
193    /**
194     * Get the property of the child managed object definition which should be
195     * used for naming children.
196     *
197     * @return Returns the property of the child managed object definition which
198     *         should be used for naming, or <code>null</code> if this relation
199     *         does not use a property for naming.
200     */
201    public PropertyDefinition<?> getNamingPropertyDefinition() {
202        return namingPropertyDefinition;
203    }
204
205    /**
206     * Get the plural name of the relation.
207     *
208     * @return Returns the plural name of the relation.
209     */
210    public String getPluralName() {
211        return pluralName;
212    }
213
214    /**
215     * Gets the user friendly plural name of this relation definition in the
216     * default locale.
217     *
218     * @return Returns the user friendly plural name of this relation definition
219     *         in the default locale.
220     */
221    public LocalizableMessage getUserFriendlyPluralName() {
222        return getUserFriendlyPluralName(Locale.getDefault());
223    }
224
225    /**
226     * Gets the user friendly plural name of this relation definition in the
227     * specified locale.
228     *
229     * @param locale
230     *            The locale.
231     * @return Returns the user friendly plural name of this relation definition
232     *         in the specified locale.
233     */
234    public LocalizableMessage getUserFriendlyPluralName(Locale locale) {
235        String property = "relation." + getName() + ".user-friendly-plural-name";
236        return ManagedObjectDefinitionI18NResource.getInstance().getMessage(getParentDefinition(), property, locale);
237    }
238
239    /** {@inheritDoc} */
240    @Override
241    public void toString(StringBuilder builder) {
242        builder.append("name=");
243        builder.append(getName());
244        builder.append(" type=collection parent=");
245        builder.append(getParentDefinition().getName());
246        builder.append(" child=");
247        builder.append(getChildDefinition().getName());
248    }
249
250    /** {@inheritDoc} */
251    @Override
252    protected void initialize() throws Exception {
253        for (DefaultManagedObject<?, ?> dmo : defaultManagedObjects.values()) {
254            dmo.initialize();
255        }
256    }
257}