Open Source Repository

Home /commons-beanutils/commons-beanutils-1.8.3 | Repository Home


org/apache/commons/beanutils/converters/BooleanConverter.java
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.beanutils.converters;

import org.apache.commons.beanutils.ConversionException;

/**
 {@link org.apache.commons.beanutils.Converter} implementaion that handles conversion
 * to and from <b>Boolean</b> objects.
 {@link org.apache.commons.beanutils.Converter} implementaion that
 * handles conversion to and from <b>java.lang.Boolean</b> objects.
 <p>
 * Can be configured to either return a <i>default value</i> or throw a
 <code>ConversionException</code> if a conversion error occurs.
 <p>
 * By default any object whose string representation is one of the values
 * {"yes", "y", "true", "on", "1"} is converted to Boolean.TRUE, and 
 * string representations {"no", "n", "false", "off", "0"} are converted
 * to Boolean.FALSE. The recognised true/false strings can be changed by:
 <pre>
 *  String[] trueStrings = {"oui", "o", "1"};
 *  String[] falseStrings = {"non", "n", "0"};
 *  Converter bc = new BooleanConverter(trueStrings, falseStrings);
 *  ConvertUtils.register(bc, Boolean.class);
 *  ConvertUtils.register(bc, Boolean.TYPE);
 </pre>
 * In addition, it is recommended that the BooleanArrayConverter also be
 * modified to recognise the same set of values:
 <pre>
 *   Converter bac = new BooleanArrayConverter(bc, BooleanArrayConverter.NO_DEFAULT);
 *   ConvertUtils.register(bac, bac.MODEL);
 </pre>
 </p>
 
 <p>Case is ignored when converting values to true or false.</p>
 *
 @author Craig R. McClanahan
 @version $Revision: 801644 $ $Date: 2009-08-06 14:38:56 +0100 (Thu, 06 Aug 2009) $
 @since 1.3
 */
public final class BooleanConverter extends AbstractConverter {


    // ----------------------------------------------------------- Constructors


    /**
     * Create a {@link org.apache.commons.beanutils.Converter} that will throw a {@link ConversionException}
     * if a conversion error occurs, ie the string value being converted is
     * not one of the known true strings, nor one of the known false strings.
     */
    public BooleanConverter() {
        super();
    }


    /**
     * Create a {@link org.apache.commons.beanutils.Converter} that will return the specified default value
     * if a conversion error occurs, ie the string value being converted is
     * not one of the known true strings, nor one of the known false strings.
     *
     @param defaultValue The default value to be returned if the value
     *  being converted is not recognised. This value may be null, in which
     *  case null will be returned on conversion failure. When non-null, it is
     *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
     *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
     *  in which case this constructor acts like the no-argument one.
     */
    public BooleanConverter(Object defaultValue) {
        super();
        if (defaultValue != NO_DEFAULT) {
            setDefaultValue(defaultValue);
        }
    }

    /**
     * Create a {@link org.apache.commons.beanutils.Converter} that will throw a {@link ConversionException}
     * if a conversion error occurs, ie the string value being converted is
     * not one of the known true strings, nor one of the known false strings.
     <p>
     * The provided string arrays are copied, so that changes to the elements
     * of the array after this call is made do not affect this object.
     *
     @param trueStrings is the set of strings which should convert to the
     *  value Boolean.TRUE. The value null must not be present. Case is
     *  ignored.
     *
     @param falseStrings is the set of strings which should convert to the
     *  value Boolean.TRUE. The value null must not be present. Case is
     *  ignored.
     @since 1.8.0
     */
    public BooleanConverter(String[] trueStrings, String[] falseStrings) {
        super();
        this.trueStrings = copyStrings(trueStrings);
        this.falseStrings = copyStrings(falseStrings);
    }

    /**
     * Create a {@link org.apache.commons.beanutils.Converter} that will return
     * the specified default value if a conversion error occurs.
     <p>
     * The provided string arrays are copied, so that changes to the elements
     * of the array after this call is made do not affect this object.
     *
     @param trueStrings is the set of strings which should convert to the
     *  value Boolean.TRUE. The value null must not be present. Case is
     *  ignored.
     *
     @param falseStrings is the set of strings which should convert to the
     *  value Boolean.TRUE. The value null must not be present. Case is
     *  ignored.
     *
     @param defaultValue The default value to be returned if the value
     *  being converted is not recognised. This value may be null, in which
     *  case null will be returned on conversion failure. When non-null, it is
     *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
     *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
     *  in which case an exception will be thrown on conversion failure.
     @since 1.8.0
     */
    public BooleanConverter(String[] trueStrings, String[] falseStrings, 
                Object defaultValue) {
        super();
        this.trueStrings = copyStrings(trueStrings);
        this.falseStrings = copyStrings(falseStrings);
        if (defaultValue != NO_DEFAULT) {
            setDefaultValue(defaultValue);
        }
    }


    // ----------------------------------------------------- Static Variables


    /**
     * This is a special reference that can be passed as the "default object"
     * to the constructor to indicate that no default is desired. Note that
     * the value 'null' cannot be used for this purpose, as the caller may
     * want a null to be returned as the default.
     @deprecated Use constructors without default value.
     */
    public static final Object NO_DEFAULT = new Object();


    // ----------------------------------------------------- Instance Variables

    /**
     * The set of strings that are known to map to Boolean.TRUE.
     */
    private String[] trueStrings = {"true""yes""y""on""1"};

    /**
     * The set of strings that are known to map to Boolean.FALSE.
     */
    private String[] falseStrings = {"false""no""n""off""0"};

    // --------------------------------------------------------- Protected Methods

    /**
     * Return the default type this <code>Converter</code> handles.
     *
     @return The default type this <code>Converter</code> handles.
     @since 1.8.0
     */
    protected Class getDefaultType() {
        return Boolean.class;
    }

    /**
     * Convert the specified input object into an output object of the
     * specified type.
     *
     @param type is the type to which this value should be converted. In the
     *  case of this BooleanConverter class, this value is ignored.
     *
     @param value is the input value to be converted. The toString method
     *  shall be invoked on this object, and the result compared (ignoring
     *  case) against the known "true" and "false" string values.
     *
     @return Boolean.TRUE if the value was a recognised "true" value, 
     *  Boolean.FALSE if the value was a recognised "false" value, or
     *  the default value if the value was not recognised and the constructor
     *  was provided with a default value.
     *
     @throws Throwable if an error occurs converting to the specified type
     @since 1.8.0
     */
    protected Object convertToType(Class type, Object valuethrows Throwable {

        // All the values in the trueStrings and falseStrings arrays are
        // guaranteed to be lower-case. By converting the input value
        // to lowercase too, we can use the efficient String.equals method
        // instead of the less-efficient String.equalsIgnoreCase method.
        String stringValue = value.toString().toLowerCase();

        for(int i=0; i<trueStrings.length; ++i) {
            if (trueStrings[i].equals(stringValue)) {
                return Boolean.TRUE;
            }
        }

        for(int i=0; i<falseStrings.length; ++i) {
            if (falseStrings[i].equals(stringValue)) {
                return Boolean.FALSE;
            }
        }
        
        throw new ConversionException("Can't convert value '" + value + "' to a Boolean");
    }

    /**
     * This method creates a copy of the provided array, and ensures that
     * all the strings in the newly created array contain only lower-case
     * letters.
     <p>
     * Using this method to copy string arrays means that changes to the
     * src array do not modify the dst array.
     */
    private static String[] copyStrings(String[] src) {
        String[] dst = new String[src.length];
        for(int i=0; i<src.length; ++i) {
            dst[i= src[i].toLowerCase();
        }
        return dst;
    }
}