| | |
| | | |
| | | package org.opends.server.admin.client.spi; |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.HashMap; |
| | |
| | | import org.opends.server.admin.PropertyIsSingleValuedException; |
| | | import org.opends.server.admin.PropertyOption; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of properties. Instances of this class can be used as the |
| | | * core of a managed object implementation. |
| | | * A set of properties. Instances of this class can be used as the core of a |
| | | * managed object implementation. |
| | | */ |
| | | public final class PropertySet { |
| | | |
| | | /** |
| | | * Internal property implementation. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | */ |
| | | private static final class MyProperty<T> implements Property<T> { |
| | | /** |
| | | * Internal property implementation. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | */ |
| | | private static final class MyProperty<T> implements Property<T> { |
| | | |
| | | // The active set of values. |
| | | private final SortedSet<T> activeValues; |
| | | // The active set of values. |
| | | private final SortedSet<T> activeValues; |
| | | |
| | | // The definition associated with this property. |
| | | private final PropertyDefinition<T> d; |
| | | // The definition associated with this property. |
| | | private final PropertyDefinition<T> d; |
| | | |
| | | // The default set of values (read-only). |
| | | private final SortedSet<T> defaultValues; |
| | | // The default set of values (read-only). |
| | | private final SortedSet<T> defaultValues; |
| | | |
| | | // The pending set of values. |
| | | private final SortedSet<T> pendingValues; |
| | | // The pending set of values. |
| | | private final SortedSet<T> pendingValues; |
| | | |
| | | /** |
| | | * Create a property with the provided sets of pre-validated default and |
| | | * active values. |
| | | * |
| | | * @param pd |
| | | * The property definition. |
| | | * @param defaultValues |
| | | * The set of default values for the property. |
| | | * @param activeValues |
| | | * The set of active values for the property. |
| | | */ |
| | | public MyProperty(PropertyDefinition<T> pd, Collection<T> defaultValues, Collection<T> activeValues) { |
| | | this.d = pd; |
| | | |
| | | SortedSet<T> sortedDefaultValues = new TreeSet<T>(pd); |
| | | sortedDefaultValues.addAll(defaultValues); |
| | | this.defaultValues = Collections.unmodifiableSortedSet(sortedDefaultValues); |
| | | |
| | | this.activeValues = new TreeSet<T>(pd); |
| | | this.activeValues.addAll(activeValues); |
| | | |
| | | // Initially the pending values is the same as the active |
| | | // values. |
| | | this.pendingValues = new TreeSet<T>(this.activeValues); |
| | | } |
| | | |
| | | /** |
| | | * Makes the pending values active. |
| | | */ |
| | | public void commit() { |
| | | activeValues.clear(); |
| | | activeValues.addAll(pendingValues); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SortedSet<T> getActiveValues() { |
| | | return Collections.unmodifiableSortedSet(activeValues); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SortedSet<T> getDefaultValues() { |
| | | return defaultValues; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SortedSet<T> getEffectiveValues() { |
| | | SortedSet<T> values = getPendingValues(); |
| | | |
| | | if (values.isEmpty()) { |
| | | values = getDefaultValues(); |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SortedSet<T> getPendingValues() { |
| | | return Collections.unmodifiableSortedSet(pendingValues); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public PropertyDefinition<T> getPropertyDefinition() { |
| | | return d; |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isEmpty() { |
| | | return pendingValues.isEmpty(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean isModified() { |
| | | if (activeValues.size() == pendingValues.size() && activeValues.containsAll(pendingValues)) { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * Replace all pending values of this property with the provided values. |
| | | * |
| | | * @param c |
| | | * The new set of pending property values. |
| | | */ |
| | | public void setPendingValues(Collection<T> c) { |
| | | pendingValues.clear(); |
| | | pendingValues.addAll(c); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return getEffectiveValues().toString(); |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public boolean wasEmpty() { |
| | | return activeValues.isEmpty(); |
| | | } |
| | | } |
| | | |
| | | // The properties. |
| | | private final Map<PropertyDefinition<?>, MyProperty<?>> properties; |
| | | |
| | | /** |
| | | * Create a property with the provided sets of pre-validated |
| | | * default and active values. |
| | | * Creates a new empty property set. |
| | | */ |
| | | public PropertySet() { |
| | | this.properties = new HashMap<PropertyDefinition<?>, MyProperty<?>>(); |
| | | } |
| | | |
| | | /** |
| | | * Creates a property with the provided sets of pre-validated default and |
| | | * active values. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | * @param pd |
| | | * The property definition. |
| | | * The property definition. |
| | | * @param defaultValues |
| | | * The set of default values for the property. |
| | | * The set of default values for the property. |
| | | * @param activeValues |
| | | * The set of active values for the property. |
| | | * The set of active values for the property. |
| | | */ |
| | | public MyProperty(PropertyDefinition<T> pd, Collection<T> defaultValues, |
| | | Collection<T> activeValues) { |
| | | this.d = pd; |
| | | |
| | | SortedSet<T> sortedDefaultValues = new TreeSet<T>(pd); |
| | | sortedDefaultValues.addAll(defaultValues); |
| | | this.defaultValues = Collections |
| | | .unmodifiableSortedSet(sortedDefaultValues); |
| | | |
| | | this.activeValues = new TreeSet<T>(pd); |
| | | this.activeValues.addAll(activeValues); |
| | | |
| | | // Initially the pending values is the same as the active |
| | | // values. |
| | | this.pendingValues = new TreeSet<T>(this.activeValues); |
| | | public <T> void addProperty(PropertyDefinition<T> pd, Collection<T> defaultValues, Collection<T> activeValues) { |
| | | MyProperty<T> p = new MyProperty<T>(pd, defaultValues, activeValues); |
| | | properties.put(pd, p); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes the pending values active. |
| | | */ |
| | | public void commit() { |
| | | activeValues.clear(); |
| | | activeValues.addAll(pendingValues); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public SortedSet<T> getActiveValues() { |
| | | return Collections.unmodifiableSortedSet(activeValues); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public SortedSet<T> getDefaultValues() { |
| | | return defaultValues; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public SortedSet<T> getEffectiveValues() { |
| | | SortedSet<T> values = getPendingValues(); |
| | | |
| | | if (values.isEmpty()) { |
| | | values = getDefaultValues(); |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public SortedSet<T> getPendingValues() { |
| | | return Collections.unmodifiableSortedSet(pendingValues); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public PropertyDefinition<T> getPropertyDefinition() { |
| | | return d; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isEmpty() { |
| | | return pendingValues.isEmpty(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isModified() { |
| | | if (activeValues.size() == pendingValues.size() |
| | | && activeValues.containsAll(pendingValues)) { |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Replace all pending values of this property with the provided |
| | | * values. |
| | | * Get the property associated with the specified property definition. |
| | | * |
| | | * @param c |
| | | * The new set of pending property values. |
| | | * @param <T> |
| | | * The underlying type of the property. |
| | | * @param d |
| | | * The Property definition. |
| | | * @return Returns the property associated with the specified property |
| | | * definition. |
| | | * @throws IllegalArgumentException |
| | | * If this property provider does not recognise the requested |
| | | * property definition. |
| | | */ |
| | | public void setPendingValues(Collection<T> c) { |
| | | pendingValues.clear(); |
| | | pendingValues.addAll(c); |
| | | @SuppressWarnings("unchecked") |
| | | public <T> Property<T> getProperty(PropertyDefinition<T> d) { |
| | | if (!properties.containsKey(d)) { |
| | | throw new IllegalArgumentException("Unknown property " + d.getName()); |
| | | } |
| | | |
| | | return (Property<T>) properties.get(d); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return getEffectiveValues().toString(); |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append('{'); |
| | | for (Map.Entry<PropertyDefinition<?>, MyProperty<?>> entry : properties.entrySet()) { |
| | | builder.append(entry.getKey().getName()); |
| | | builder.append('='); |
| | | builder.append(entry.getValue().toString()); |
| | | builder.append(' '); |
| | | } |
| | | builder.append('}'); |
| | | return builder.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | * Makes all pending values active. |
| | | */ |
| | | public boolean wasEmpty() { |
| | | return activeValues.isEmpty(); |
| | | } |
| | | } |
| | | |
| | | // The properties. |
| | | private final Map<PropertyDefinition<?>, MyProperty<?>> properties; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new empty property set. |
| | | */ |
| | | public PropertySet() { |
| | | this.properties = new HashMap<PropertyDefinition<?>, MyProperty<?>>(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a property with the provided sets of pre-validated |
| | | * default and active values. |
| | | * |
| | | * @param <T> |
| | | * The type of the property. |
| | | * @param pd |
| | | * The property definition. |
| | | * @param defaultValues |
| | | * The set of default values for the property. |
| | | * @param activeValues |
| | | * The set of active values for the property. |
| | | */ |
| | | public <T> void addProperty(PropertyDefinition<T> pd, |
| | | Collection<T> defaultValues, Collection<T> activeValues) { |
| | | MyProperty<T> p = new MyProperty<T>(pd, defaultValues, activeValues); |
| | | properties.put(pd, p); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Get the property associated with the specified property |
| | | * definition. |
| | | * |
| | | * @param <T> |
| | | * The underlying type of the property. |
| | | * @param d |
| | | * The Property definition. |
| | | * @return Returns the property associated with the specified |
| | | * property definition. |
| | | * @throws IllegalArgumentException |
| | | * If this property provider does not recognise the |
| | | * requested property definition. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public <T> Property<T> getProperty(PropertyDefinition<T> d) |
| | | throws IllegalArgumentException { |
| | | if (!properties.containsKey(d)) { |
| | | throw new IllegalArgumentException("Unknown property " + d.getName()); |
| | | void commit() { |
| | | for (MyProperty<?> p : properties.values()) { |
| | | p.commit(); |
| | | } |
| | | } |
| | | |
| | | return (Property<T>) properties.get(d); |
| | | } |
| | | /** |
| | | * Set a new pending values for the specified property. |
| | | * <p> |
| | | * See the class description for more information regarding pending values. |
| | | * |
| | | * @param <T> |
| | | * The type of the property to be modified. |
| | | * @param d |
| | | * The property to be modified. |
| | | * @param values |
| | | * A non-<code>null</code> set of new pending values for the |
| | | * property (an empty set indicates that the property should be |
| | | * reset to its default behavior). The set will not be referenced |
| | | * by this managed object. |
| | | * @throws IllegalPropertyValueException |
| | | * If a new pending value is deemed to be invalid according to |
| | | * the property definition. |
| | | * @throws PropertyIsSingleValuedException |
| | | * If an attempt was made to add multiple pending values to a |
| | | * single-valued property. |
| | | * @throws PropertyIsMandatoryException |
| | | * If an attempt was made to remove a mandatory property. |
| | | * @throws IllegalArgumentException |
| | | * If the specified property definition is not associated with |
| | | * this managed object. |
| | | */ |
| | | <T> void setPropertyValues(PropertyDefinition<T> d, Collection<T> values) { |
| | | MyProperty<T> property = (MyProperty<T>) getProperty(d); |
| | | |
| | | if (values.size() > 1 && !d.hasOption(PropertyOption.MULTI_VALUED)) { |
| | | throw new PropertyIsSingleValuedException(d); |
| | | } |
| | | |
| | | if (values.isEmpty() && d.hasOption(PropertyOption.MANDATORY)) { |
| | | // But only if there are no default values. |
| | | if (property.getDefaultValues().isEmpty()) { |
| | | throw new PropertyIsMandatoryException(d); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append('{'); |
| | | for (Map.Entry<PropertyDefinition<?>, MyProperty<?>> entry : properties |
| | | .entrySet()) { |
| | | builder.append(entry.getKey().getName()); |
| | | builder.append('='); |
| | | builder.append(entry.getValue().toString()); |
| | | builder.append(' '); |
| | | // Validate each value. |
| | | for (T e : values) { |
| | | if (e == null) { |
| | | throw new NullPointerException(); |
| | | } |
| | | |
| | | d.validateValue(e); |
| | | } |
| | | |
| | | // Update the property. |
| | | property.setPendingValues(values); |
| | | } |
| | | builder.append('}'); |
| | | return builder.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Makes all pending values active. |
| | | */ |
| | | void commit() { |
| | | for (MyProperty<?> p : properties.values()) { |
| | | p.commit(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Set a new pending values for the specified property. |
| | | * <p> |
| | | * See the class description for more information regarding pending |
| | | * values. |
| | | * |
| | | * @param <T> |
| | | * The type of the property to be modified. |
| | | * @param d |
| | | * The property to be modified. |
| | | * @param values |
| | | * A non-<code>null</code> set of new pending values for |
| | | * the property (an empty set indicates that the property |
| | | * should be reset to its default behavior). The set will |
| | | * not be referenced by this managed object. |
| | | * @throws IllegalPropertyValueException |
| | | * If a new pending value is deemed to be invalid |
| | | * according to the property definition. |
| | | * @throws PropertyIsSingleValuedException |
| | | * If an attempt was made to add multiple pending values |
| | | * to a single-valued property. |
| | | * @throws PropertyIsMandatoryException |
| | | * If an attempt was made to remove a mandatory property. |
| | | * @throws IllegalArgumentException |
| | | * If the specified property definition is not associated |
| | | * with this managed object. |
| | | */ |
| | | <T> void setPropertyValues(PropertyDefinition<T> d, |
| | | Collection<T> values) throws IllegalPropertyValueException, |
| | | PropertyIsSingleValuedException, PropertyIsMandatoryException, |
| | | IllegalArgumentException { |
| | | MyProperty<T> property = (MyProperty<T>) getProperty(d); |
| | | |
| | | if (values.size() > 1 && !d.hasOption(PropertyOption.MULTI_VALUED)) { |
| | | throw new PropertyIsSingleValuedException(d); |
| | | } |
| | | |
| | | if (values.isEmpty() && d.hasOption(PropertyOption.MANDATORY)) { |
| | | // But only if there are no default values. |
| | | if (property.getDefaultValues().isEmpty()) { |
| | | throw new PropertyIsMandatoryException(d); |
| | | } |
| | | } |
| | | |
| | | // Validate each value. |
| | | for (T e : values) { |
| | | if (e == null) { |
| | | throw new NullPointerException(); |
| | | } |
| | | |
| | | d.validateValue(e); |
| | | } |
| | | |
| | | // Update the property. |
| | | property.setPendingValues(values); |
| | | } |
| | | } |