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-2016 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        /** The optional default managed objects associated with this instantiable relation definition. */
065        private final Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects =
066            new HashMap<>();
067
068        /**
069         * Creates a new builder which can be used to incrementally build an
070         * instantiable relation definition.
071         *
072         * @param pd
073         *            The parent managed object definition.
074         * @param name
075         *            The name of the relation.
076         * @param pluralName
077         *            The plural name of the relation.
078         * @param cd
079         *            The child managed object definition.
080         */
081        public Builder(AbstractManagedObjectDefinition<?, ?> pd, String name, String pluralName,
082            AbstractManagedObjectDefinition<C, S> cd) {
083            super(pd, name, cd);
084            this.pluralName = pluralName;
085        }
086
087        /**
088         * Adds the named default managed object to this instantiable relation
089         * definition.
090         *
091         * @param name
092         *            The name of the default managed object.
093         * @param defaultManagedObject
094         *            The default managed object.
095         */
096        public void setDefaultManagedObject(String name,
097            DefaultManagedObject<? extends C, ? extends S> defaultManagedObject) {
098            this.defaultManagedObjects.put(name, defaultManagedObject);
099        }
100
101        /**
102         * Sets the naming property for the instantiable relation definition.
103         *
104         * @param namingPropertyDefinition
105         *            The property of the child managed object definition which
106         *            should be used for naming, or <code>null</code> if this
107         *            relation does not use a property for naming.
108         */
109        public void setNamingProperty(PropertyDefinition<?> namingPropertyDefinition) {
110            Reject.ifNull(namingPropertyDefinition);
111            this.namingPropertyDefinition = namingPropertyDefinition;
112        }
113
114        @Override
115        protected InstantiableRelationDefinition<C, S> buildInstance(Common<C, S> common) {
116            return new InstantiableRelationDefinition<>(common, pluralName, namingPropertyDefinition,
117                defaultManagedObjects);
118        }
119
120    }
121
122    /** The optional naming property definition. */
123    private final PropertyDefinition<?> namingPropertyDefinition;
124
125    /** The plural name of the relation. */
126    private final String pluralName;
127
128    /** The optional default managed objects associated with this instantiable relation definition. */
129    private final Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects;
130
131    /** Private constructor. */
132    private InstantiableRelationDefinition(Common<C, S> common, String pluralName,
133        PropertyDefinition<?> namingPropertyDefinition,
134        Map<String, DefaultManagedObject<? extends C, ? extends S>> defaultManagedObjects) {
135        super(common);
136        this.pluralName = pluralName;
137        this.namingPropertyDefinition = namingPropertyDefinition;
138        this.defaultManagedObjects = defaultManagedObjects;
139    }
140
141    @Override
142    public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
143        return v.visitInstantiable(this, p);
144    }
145
146    /**
147     * Gets the named default managed object associated with this instantiable
148     * relation definition.
149     *
150     * @param name
151     *            The name of the default managed object.
152     * @return Returns the named default managed object.
153     * @throws IllegalArgumentException
154     *             If there is no default managed object associated with the
155     *             provided name.
156     */
157    public DefaultManagedObject<? extends C, ? extends S> getDefaultManagedObject(String name) {
158        if (!defaultManagedObjects.containsKey(name)) {
159            throw new IllegalArgumentException("unrecognized default managed object \"" + name + "\"");
160        }
161        return defaultManagedObjects.get(name);
162    }
163
164    /**
165     * Gets the names of the default managed objects associated with this
166     * instantiable relation definition.
167     *
168     * @return Returns an unmodifiable set containing the names of the default
169     *         managed object.
170     */
171    public Set<String> getDefaultManagedObjectNames() {
172        return Collections.unmodifiableSet(defaultManagedObjects.keySet());
173    }
174
175    /**
176     * Get the property of the child managed object definition which should be
177     * used for naming children.
178     *
179     * @return Returns the property of the child managed object definition which
180     *         should be used for naming, or <code>null</code> if this relation
181     *         does not use a property for naming.
182     */
183    public PropertyDefinition<?> getNamingPropertyDefinition() {
184        return namingPropertyDefinition;
185    }
186
187    /**
188     * Get the plural name of the relation.
189     *
190     * @return Returns the plural name of the relation.
191     */
192    public String getPluralName() {
193        return pluralName;
194    }
195
196    /**
197     * Gets the user friendly plural name of this relation definition in the
198     * default locale.
199     *
200     * @return Returns the user friendly plural name of this relation definition
201     *         in the default locale.
202     */
203    public LocalizableMessage getUserFriendlyPluralName() {
204        return getUserFriendlyPluralName(Locale.getDefault());
205    }
206
207    /**
208     * Gets the user friendly plural name of this relation definition in the
209     * specified locale.
210     *
211     * @param locale
212     *            The locale.
213     * @return Returns the user friendly plural name of this relation definition
214     *         in the specified locale.
215     */
216    public LocalizableMessage getUserFriendlyPluralName(Locale locale) {
217        String property = "relation." + getName() + ".user-friendly-plural-name";
218        return ManagedObjectDefinitionI18NResource.getInstance().getMessage(getParentDefinition(), property, locale);
219    }
220
221    @Override
222    public void toString(StringBuilder builder) {
223        builder.append("name=");
224        builder.append(getName());
225        builder.append(" type=collection parent=");
226        builder.append(getParentDefinition().getName());
227        builder.append(" child=");
228        builder.append(getChildDefinition().getName());
229    }
230
231    @Override
232    protected void initialize() throws Exception {
233        for (DefaultManagedObject<?, ?> dmo : defaultManagedObjects.values()) {
234            dmo.initialize();
235        }
236    }
237}