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