    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.beanutils.converters;
    018
    019    import org.apache.commons.beanutils.ConversionException;
    020
    021    /**
    022     * {@link org.apache.commons.beanutils.Converter} implementaion that handles conversion
    023     * to and from <b>Boolean</b> objects.
    024     * {@link org.apache.commons.beanutils.Converter} implementaion that
    025     * handles conversion to and from <b>java.lang.Boolean</b> objects.
    026     * <p>
    027     * Can be configured to either return a <i>default value</i> or throw a
    028     * <code>ConversionException</code> if a conversion error occurs.
    029     * <p>
    030     * By default any object whose string representation is one of the values
    031     * {"yes", "y", "true", "on", "1"} is converted to Boolean.TRUE, and
    032     * string representations {"no", "n", "false", "off", "0"} are converted
    033     * to Boolean.FALSE. The recognised true/false strings can be changed by:
    034     * <pre>
    035     *  String[] trueStrings = {"oui", "o", "1"};
    036     *  String[] falseStrings = {"non", "n", "0"};
    037     *  Converter bc = new BooleanConverter(trueStrings, falseStrings);
    038     *  ConvertUtils.register(bc, Boolean.class);
    039     *  ConvertUtils.register(bc, Boolean.TYPE);
    040     * </pre>
    041     * In addition, it is recommended that the BooleanArrayConverter also be
    042     * modified to recognise the same set of values:
    043     * <pre>
    044     *   Converter bac = new BooleanArrayConverter(bc, BooleanArrayConverter.NO_DEFAULT);
    045     *   ConvertUtils.register(bac, bac.MODEL);
    046     * </pre>
    047     * </p>
    048     *
    049     * <p>Case is ignored when converting values to true or false.</p>
    050     *
    051     * @author Craig R. McClanahan
    052     * @version $Revision: 801644 $ $Date: 2009-08-06 14:38:56 +0100 (Thu, 06 Aug 2009) $
    053     * @since 1.3
    054     */
    055    public final class BooleanConverter extends AbstractConverter {
    056
    057
    058        // ----------------------------------------------------------- Constructors
    059
    060
    061        /**
    062         * Create a {@link org.apache.commons.beanutils.Converter} that will throw a {@link ConversionException}
    063         * if a conversion error occurs, ie the string value being converted is
    064         * not one of the known true strings, nor one of the known false strings.
    065         */
    066        public BooleanConverter() {
    067            super();
    068        }
    069
    070
    071        /**
    072         * Create a {@link org.apache.commons.beanutils.Converter} that will return the specified default value
    073         * if a conversion error occurs, ie the string value being converted is
    074         * not one of the known true strings, nor one of the known false strings.
    075         *
    076         * @param defaultValue The default value to be returned if the value
    077         *  being converted is not recognised. This value may be null, in which
    078         *  case null will be returned on conversion failure. When non-null, it is
    079         *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
    080         *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
    081         *  in which case this constructor acts like the no-argument one.
    082         */
    083        public BooleanConverter(Object defaultValue) {
    084            super();
    085            if (defaultValue != NO_DEFAULT) {
    086                setDefaultValue(defaultValue);
    087            }
    088        }
    089
    090        /**
    091         * Create a {@link org.apache.commons.beanutils.Converter} that will throw a {@link ConversionException}
    092         * if a conversion error occurs, ie the string value being converted is
    093         * not one of the known true strings, nor one of the known false strings.
    094         * <p>
    095         * The provided string arrays are copied, so that changes to the elements
    096         * of the array after this call is made do not affect this object.
    097         *
    098         * @param trueStrings is the set of strings which should convert to the
    099         *  value Boolean.TRUE. The value null must not be present. Case is
    100         *  ignored.
    101         *
    102         * @param falseStrings is the set of strings which should convert to the
    103         *  value Boolean.TRUE. The value null must not be present. Case is
    104         *  ignored.
    105         * @since 1.8.0
    106         */
    107        public BooleanConverter(String[] trueStrings, String[] falseStrings) {
    108            super();
    109            this.trueStrings = copyStrings(trueStrings);
    110            this.falseStrings = copyStrings(falseStrings);
    111        }
    112
    113        /**
    114         * Create a {@link org.apache.commons.beanutils.Converter} that will return
    115         * the specified default value if a conversion error occurs.
    116         * <p>
    117         * The provided string arrays are copied, so that changes to the elements
    118         * of the array after this call is made do not affect this object.
    119         *
    120         * @param trueStrings is the set of strings which should convert to the
    121         *  value Boolean.TRUE. The value null must not be present. Case is
    122         *  ignored.
    123         *
    124         * @param falseStrings is the set of strings which should convert to the
    125         *  value Boolean.TRUE. The value null must not be present. Case is
    126         *  ignored.
    127         *
    128         * @param defaultValue The default value to be returned if the value
    129         *  being converted is not recognised. This value may be null, in which
    130         *  case null will be returned on conversion failure. When non-null, it is
    131         *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
    132         *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
    133         *  in which case an exception will be thrown on conversion failure.
    134         * @since 1.8.0
    135         */
    136        public BooleanConverter(String[] trueStrings, String[] falseStrings,
    137                    Object defaultValue) {
    138            super();
    139            this.trueStrings = copyStrings(trueStrings);
    140            this.falseStrings = copyStrings(falseStrings);
    141            if (defaultValue != NO_DEFAULT) {
    142                setDefaultValue(defaultValue);
    143            }
    144        }
    145
    146
    147        // ----------------------------------------------------- Static Variables
    148
    149
    150        /**
    151         * This is a special reference that can be passed as the "default object"
    152         * to the constructor to indicate that no default is desired. Note that
    153         * the value 'null' cannot be used for this purpose, as the caller may
    154         * want a null to be returned as the default.
    155         * @deprecated Use constructors without default value.
    156         */
    157        public static final Object NO_DEFAULT = new Object();
    158
    159
    160        // ----------------------------------------------------- Instance Variables
    161
    162        /**
    163         * The set of strings that are known to map to Boolean.TRUE.
    164         */
    165        private String[] trueStrings = {"true", "yes", "y", "on", "1"};
    166
    167        /**
    168         * The set of strings that are known to map to Boolean.FALSE.
    169         */
    170        private String[] falseStrings = {"false", "no", "n", "off", "0"};
    171
    172        // --------------------------------------------------------- Protected Methods
    173
    174        /**
    175         * Return the default type this <code>Converter</code> handles.
    176         *
    177         * @return The default type this <code>Converter</code> handles.
    178         * @since 1.8.0
    179         */
    180        protected Class getDefaultType() {
    181            return Boolean.class;
    182        }
    183
    184        /**
    185         * Convert the specified input object into an output object of the
    186         * specified type.
    187         *
    188         * @param type is the type to which this value should be converted. In the
    189         *  case of this BooleanConverter class, this value is ignored.
    190         *
    191         * @param value is the input value to be converted. The toString method
    192         *  shall be invoked on this object, and the result compared (ignoring
    193         *  case) against the known "true" and "false" string values.
    194         *
    195         * @return Boolean.TRUE if the value was a recognised "true" value,
    196         *  Boolean.FALSE if the value was a recognised "false" value, or
    197         *  the default value if the value was not recognised and the constructor
    198         *  was provided with a default value.
    199         *
    200         * @throws Throwable if an error occurs converting to the specified type
    201         * @since 1.8.0
    202         */
    203        protected Object convertToType(Class type, Object value) throws Throwable {
    204
    205            // All the values in the trueStrings and falseStrings arrays are
    206            // guaranteed to be lower-case. By converting the input value
    207            // to lowercase too, we can use the efficient String.equals method
    208            // instead of the less-efficient String.equalsIgnoreCase method.
    209            String stringValue = value.toString().toLowerCase();
    210
    211            for(int i=0; i<trueStrings.length; ++i) {
    212                if (trueStrings[i].equals(stringValue)) {
    213                    return Boolean.TRUE;
    214                }
    215            }
    216
    217            for(int i=0; i<falseStrings.length; ++i) {
    218                if (falseStrings[i].equals(stringValue)) {
    219                    return Boolean.FALSE;
    220                }
    221            }
    222
    223            throw new ConversionException("Can't convert value '" + value + "' to a Boolean");
    224        }
    225
    226        /**
    227         * This method creates a copy of the provided array, and ensures that
    228         * all the strings in the newly created array contain only lower-case
    229         * letters.
    230         * <p>
    231         * Using this method to copy string arrays means that changes to the
    232         * src array do not modify the dst array.
    233         */
    234        private static String[] copyStrings(String[] src) {
    235            String[] dst = new String[src.length];
    236            for(int i=0; i<src.length; ++i) {
    237                dst[i] = src[i].toLowerCase();
    238            }
    239            return dst;
    240        }
    241    }