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