View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.beanutils2.converters;
18  
19  /**
20   * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion to and from <strong>Boolean</strong> objects.
21   * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion to and from {@link Boolean} objects.
22   * <p>
23   * Can be configured to either return a <em>default value</em> or throw a {@code ConversionException} if a conversion error occurs.
24   * </p>
25   * <p>
26   * By default any object whose string representation is one of the values {"yes", "y", "true", "on", "1"} is converted to Boolean.TRUE, and string
27   * representations {"no", "n", "false", "off", "0"} are converted to Boolean.FALSE. The recognized true/false strings can be changed by:
28   * </p>
29   *
30   * <pre>
31   * String[] trueStrings = { "oui", "o", "1" };
32   * String[] falseStrings = { "non", "n", "0" };
33   * Converter bc = new BooleanConverter(trueStrings, falseStrings);
34   * ConvertUtils.register(bc, Boolean.class);
35   * ConvertUtils.register(bc, Boolean.TYPE);
36   * </pre>
37   *
38   * <p>
39   * Case is ignored when converting values to true or false.
40   * </p>
41   *
42   * @since 1.3
43   */
44  public final class BooleanConverter extends AbstractConverter<Boolean> {
45  
46      /**
47       * Copies the provided array, and ensures that all the strings in the newly created array contain only lower-case letters.
48       * <p>
49       * Using this method to copy string arrays means that changes to the src array do not modify the dst array.
50       * </p>
51       */
52      private static String[] copyStrings(final String[] src) {
53          final String[] dst = new String[src.length];
54          for (int i = 0; i < src.length; ++i) {
55              dst[i] = toLowerCase(src[i]);
56          }
57          return dst;
58      }
59  
60      /**
61       * The set of strings that are known to map to Boolean.TRUE.
62       */
63      private String[] trueStrings = { "true", "yes", "y", "on", "1" };
64  
65      /**
66       * The set of strings that are known to map to Boolean.FALSE.
67       */
68      private String[] falseStrings = { "false", "no", "n", "off", "0" };
69  
70      /**
71       * Constructs a {@link org.apache.commons.beanutils2.Converter} that will throw a {@link org.apache.commons.beanutils2.ConversionException} if a conversion
72       * error occurs, that is, if the string value being converted is not one of the known true strings, nor one of the known false strings.
73       */
74      public BooleanConverter() {
75      }
76  
77      /**
78       * Constructs a {@link org.apache.commons.beanutils2.Converter} that will return the specified default value if a conversion error occurs, that is, the
79       * string value being converted is not one of the known true strings, nor one of the known false strings.
80       *
81       * @param defaultValue The default value to be returned if the value being converted is not recognized. This value may be null, in which case null will be
82       *                     returned on conversion failure. When non-null, it is expected that this value will be either Boolean.TRUE or Boolean.FALSE. The
83       *                     special value BooleanConverter.NO_DEFAULT can also be passed here, in which case this constructor acts like the no-argument one.
84       */
85      public BooleanConverter(final Boolean defaultValue) {
86          super(defaultValue);
87      }
88  
89      /**
90       * Constructs a {@link org.apache.commons.beanutils2.Converter} that will throw a {@link org.apache.commons.beanutils2.ConversionException} if a conversion
91       * error occurs, that is, the string value being converted is not one of the known true strings, nor one of the known false strings.
92       * <p>
93       * 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.
94       *
95       * @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.
96       * @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.
97       * @since 1.8.0
98       */
99      public BooleanConverter(final String[] trueStrings, final String[] falseStrings) {
100         this.trueStrings = copyStrings(trueStrings);
101         this.falseStrings = copyStrings(falseStrings);
102     }
103 
104     /**
105      * Constructs a {@link org.apache.commons.beanutils2.Converter} that will return the specified default value if a conversion error occurs.
106      * <p>
107      * 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.
108      *
109      * @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.
110      * @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.
111      * @param defaultValue The default value to be returned if the value being converted is not recognized. This value may be null, in which case null will be
112      *                     returned on conversion failure. When non-null, it is expected that this value will be either Boolean.TRUE or Boolean.FALSE. The
113      *                     special value BooleanConverter.NO_DEFAULT can also be passed here, in which case an exception will be thrown on conversion failure.
114      * @since 1.8.0
115      */
116     public BooleanConverter(final String[] trueStrings, final String[] falseStrings, final Boolean defaultValue) {
117         super(defaultValue);
118         this.trueStrings = copyStrings(trueStrings);
119         this.falseStrings = copyStrings(falseStrings);
120     }
121 
122     /**
123      * Converts the specified input object into an output object of the specified type.
124      *
125      * @param <T>   Target type of the conversion.
126      * @param type  is the type to which this value should be converted. In the case of this BooleanConverter class, this value is ignored.
127      * @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
128      *              known "true" and "false" string values.
129      *
130      * @return Boolean.TRUE if the value was a recognized "true" value, Boolean.FALSE if the value was a recognized "false" value, or the default value if the
131      *         value was not recognized and the constructor was provided with a default value.
132      *
133      * @throws Throwable if an error occurs converting to the specified type
134      * @since 1.8.0
135      */
136     @Override
137     protected <T> T convertToType(final Class<T> type, final Object value) throws Throwable {
138         if (Boolean.class.equals(type) || Boolean.TYPE.equals(type)) {
139             // All the values in the trueStrings and falseStrings arrays are
140             // guaranteed to be lower-case. By converting the input value
141             // to lowercase too, we can use the efficient String.equals method
142             // instead of the less-efficient String.equalsIgnoreCase method.
143             final String stringValue = toLowerCase(value);
144 
145             for (final String trueString : trueStrings) {
146                 if (trueString.equals(stringValue)) {
147                     return type.cast(Boolean.TRUE);
148                 }
149             }
150 
151             for (final String falseString : falseStrings) {
152                 if (falseString.equals(stringValue)) {
153                     return type.cast(Boolean.FALSE);
154                 }
155             }
156         }
157 
158         throw conversionException(type, value);
159     }
160 
161     /**
162      * Gets the default type this {@code Converter} handles.
163      *
164      * @return The default type this {@code Converter} handles.
165      * @since 1.8.0
166      */
167     @Override
168     protected Class<Boolean> getDefaultType() {
169         return Boolean.class;
170     }
171 }