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.forgerock.opendj.config;
028
029import org.forgerock.util.Reject;
030
031import java.util.EnumSet;
032import java.util.HashMap;
033import java.util.Locale;
034import java.util.Map;
035import java.util.MissingResourceException;
036
037import org.forgerock.i18n.LocalizableMessage;
038
039/**
040 * Enumeration property definition.
041 *
042 * @param <E>
043 *            The enumeration that should be used for values of this property
044 *            definition.
045 */
046public final class EnumPropertyDefinition<E extends Enum<E>> extends PropertyDefinition<E> {
047
048    /**
049     * An interface for incrementally constructing enumeration property
050     * definitions.
051     *
052     * @param <E>
053     *            The enumeration that should be used for values of this
054     *            property definition.
055     */
056    public static final class Builder<E extends Enum<E>> extends AbstractBuilder<E, EnumPropertyDefinition<E>> {
057
058        /** The enumeration class. */
059        private Class<E> enumClass;
060
061        /** Private constructor. */
062        private Builder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
063            super(d, propertyName);
064            this.enumClass = null;
065        }
066
067        /**
068         * Set the enumeration class which should be used for values of this
069         * property definition.
070         *
071         * @param enumClass
072         *            The enumeration class which should be used for values of
073         *            this property definition.
074         */
075        public final void setEnumClass(Class<E> enumClass) {
076            this.enumClass = enumClass;
077        }
078
079        /** {@inheritDoc} */
080        @Override
081        protected EnumPropertyDefinition<E> buildInstance(AbstractManagedObjectDefinition<?, ?> d,
082            String propertyName, EnumSet<PropertyOption> options, AdministratorAction adminAction,
083            DefaultBehaviorProvider<E> defaultBehavior) {
084            // Make sure that the enumeration class has been defined.
085            if (enumClass == null) {
086                throw new IllegalStateException("Enumeration class undefined");
087            }
088
089            return new EnumPropertyDefinition<>(d, propertyName, options, adminAction, defaultBehavior, enumClass);
090        }
091    }
092
093    /**
094     * Create an enumeration property definition builder.
095     *
096     * @param <E>
097     *            The enumeration that should be used for values of this
098     *            property definition.
099     * @param d
100     *            The managed object definition associated with this property
101     *            definition.
102     * @param propertyName
103     *            The property name.
104     * @return Returns the new enumeration property definition builder.
105     */
106    public static <E extends Enum<E>> Builder<E> createBuilder(AbstractManagedObjectDefinition<?, ?> d,
107        String propertyName) {
108        return new Builder<>(d, propertyName);
109    }
110
111    /** The enumeration class. */
112    private final Class<E> enumClass;
113
114    /** Map used for decoding values. */
115    private final Map<String, E> decodeMap;
116
117    /** Private constructor. */
118    private EnumPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, String propertyName,
119        EnumSet<PropertyOption> options, AdministratorAction adminAction, DefaultBehaviorProvider<E> defaultBehavior,
120        Class<E> enumClass) {
121        super(d, enumClass, propertyName, options, adminAction, defaultBehavior);
122        this.enumClass = enumClass;
123
124        // Initialize the decoding map.
125        this.decodeMap = new HashMap<>();
126        for (E value : EnumSet.<E> allOf(enumClass)) {
127            String s = value.toString().trim().toLowerCase();
128            this.decodeMap.put(s, value);
129        }
130    }
131
132    /** {@inheritDoc} */
133    @Override
134    public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) {
135        return v.visitEnum(this, p);
136    }
137
138    /** {@inheritDoc} */
139    @Override
140    public <R, P> R accept(PropertyValueVisitor<R, P> v, E value, P p) {
141        return v.visitEnum(this, value, p);
142    }
143
144    /** {@inheritDoc} */
145    @Override
146    public E decodeValue(String value) {
147        Reject.ifNull(value);
148
149        String nvalue = value.trim().toLowerCase();
150        E eValue = decodeMap.get(nvalue);
151        if (eValue != null) {
152            return eValue;
153        }
154        throw PropertyException.illegalPropertyValueException(this, value);
155    }
156
157    /**
158     * Get the enumeration class used for values of this property.
159     *
160     * @return Returns the enumeration class used for values of this property.
161     */
162    public Class<E> getEnumClass() {
163        return enumClass;
164    }
165
166    /**
167     * Gets the synopsis of the specified enumeration value of this enumeration
168     * property definition in the default locale.
169     *
170     * @param value
171     *            The enumeration value.
172     * @return Returns the synopsis of the specified enumeration value of this
173     *         enumeration property definition in the default locale.
174     */
175    public final LocalizableMessage getValueSynopsis(E value) {
176        return getValueSynopsis(Locale.getDefault(), value);
177    }
178
179    /**
180     * Gets the synopsis of the specified enumeration value of this enumeration
181     * property definition in the specified locale.
182     *
183     * @param value
184     *            The enumeration value.
185     * @param locale
186     *            The locale.
187     * @return Returns the synopsis of the specified enumeration value of this
188     *         enumeration property definition in the specified locale.
189     */
190    public final LocalizableMessage getValueSynopsis(Locale locale, E value) {
191        ManagedObjectDefinitionI18NResource resource = ManagedObjectDefinitionI18NResource.getInstance();
192        String property = "property." + getName() + ".syntax.enumeration.value." + value + ".synopsis";
193        try {
194            return resource.getMessage(getManagedObjectDefinition(), property, locale);
195        } catch (MissingResourceException e) {
196            return null;
197        }
198    }
199
200    /** {@inheritDoc} */
201    @Override
202    public String normalizeValue(E value) {
203        Reject.ifNull(value);
204
205        return value.toString().trim().toLowerCase();
206    }
207
208    /** {@inheritDoc} */
209    @Override
210    public void validateValue(E value) {
211        Reject.ifNull(value);
212
213        // No additional validation required.
214    }
215}