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 Sun Microsystems, Inc.
025 *      Portions Copyright 2015 ForgeRock AS.
026 */
027package org.opends.server.admin;
028
029
030
031import java.util.Arrays;
032import java.util.HashMap;
033import java.util.List;
034import java.util.Map;
035import java.util.SortedSet;
036import java.util.TreeSet;
037
038
039
040/**
041 * A default managed object which should be created when a parent
042 * managed object is created. Default managed objects are associated
043 * with a {@link RelationDefinition}.
044 *
045 * @param <C>
046 *          The type of client default managed object configuration.
047 * @param <S>
048 *          The type of server default managed object configuration.
049 */
050public final class DefaultManagedObject
051    <C extends ConfigurationClient, S extends Configuration>
052    implements PropertyProvider {
053
054  /**
055   * An interface for incrementally constructing default managed
056   * objects.
057   *
058   * @param <C>
059   *          The type of client default managed object configuration.
060   * @param <S>
061   *          The type of server default managed object configuration.
062   */
063  public static final class Builder
064      <C extends ConfigurationClient, S extends Configuration> {
065
066    /** The default managed object's definition. */
067    private final ManagedObjectDefinition<C, S> definition;
068
069    /** The string encoded default managed object's properties. */
070    private final Map<String, List<String>> propertyStringValues = new HashMap<>();
071
072    /**
073     * Creates a new default managed object builder.
074     *
075     * @param definition
076     *          The default managed object's definition.
077     */
078    public Builder(ManagedObjectDefinition<C, S> definition) {
079      this.definition = definition;
080    }
081
082
083
084    /**
085     * Construct a default managed object based on the properties of
086     * this builder.
087     *
088     * @return Returns the new default managed object.
089     */
090    public DefaultManagedObject<C, S> getInstance() {
091      return new DefaultManagedObject<>(definition, propertyStringValues);
092    }
093
094
095
096    /**
097     * Defines a property's values for the default managed object.
098     *
099     * @param name
100     *          The name of the property.
101     * @param values
102     *          One or more property values in the string
103     *          representation.
104     */
105    public void setPropertyValues(String name, String... values) {
106      if (values == null || values.length == 0) {
107        throw new IllegalArgumentException(
108            "null or empty values specified for property " + name);
109      }
110
111      propertyStringValues.put(name, Arrays.asList(values));
112    }
113  }
114
115  /** The default managed object's definition. */
116  private final ManagedObjectDefinition<C, S> definition;
117
118  /** The string encoded default managed object's properties. */
119  private final Map<String, List<String>> propertyStringValues;
120
121
122
123  /** Private constructor. */
124  private DefaultManagedObject(ManagedObjectDefinition<C, S> definition,
125      Map<String, List<String>> propertyStringValues) {
126    this.definition = definition;
127    this.propertyStringValues = propertyStringValues;
128  }
129
130
131
132  /**
133   * Gets the managed object definition associated with this default
134   * managed object.
135   *
136   * @return Returns the managed object definition associated with
137   *         this default managed object.
138   */
139  public ManagedObjectDefinition<C, S> getManagedObjectDefinition() {
140    return definition;
141  }
142
143
144
145  /**
146   * Gets a mutable copy of the set of property values for the
147   * specified property.
148   *
149   * @param <T>
150   *          The type of the property to be retrieved.
151   * @param pd
152   *          The property to be retrieved.
153   * @return Returns a newly allocated set containing a copy of the
154   *         property's values. An empty set indicates that the
155   *         property has no values defined and any default behavior
156   *         is applicable.
157   * @throws IllegalArgumentException
158   *           If the property definition is not associated with this
159   *           managed object's definition.
160   */
161  public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> pd)
162      throws IllegalArgumentException {
163    // Validate the property definition.
164    definition.getPropertyDefinition(pd.getName());
165
166    // Do a defensive copy.
167    SortedSet<T> values = new TreeSet<>(pd);
168    List<String> stringValues = propertyStringValues.get(pd.getName());
169    if (stringValues != null) {
170      for (String stringValue : stringValues) {
171        values.add(pd.decodeValue(stringValue));
172      }
173    }
174    return values;
175  }
176
177
178
179  /**
180   * Performs run-time initialization of properties.
181   *
182   * @throws Exception
183   *           If this default managed object could not be
184   *           initialized.
185   */
186  void initialize() throws Exception {
187    // FIXME: it would be nice if we could decode all property values
188    // at this point. However this is not possible on the server side
189    // since some properties will be determined to be invalid since
190    // the schema is not loaded.
191
192    // Validate provided property names.
193    for (String name : propertyStringValues.keySet()) {
194      definition.getPropertyDefinition(name);
195    }
196  }
197}