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