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.beanutils.converters;
18  
19  /**
20   * {@link org.apache.commons.beanutils.Converter} implementation that handles conversion
21   * to and from <b>Boolean</b> objects.
22   * {@link org.apache.commons.beanutils.Converter} implementation that
23   * handles conversion to and from <b>java.lang.Boolean</b> objects.
24   * <p>
25   * Can be configured to either return a <i>default value</i> or throw a
26   * <code>ConversionException</code> if a conversion error occurs.
27   * <p>
28   * By default any object whose string representation is one of the values
29   * {"yes", "y", "true", "on", "1"} is converted to Boolean.TRUE, and
30   * string representations {"no", "n", "false", "off", "0"} are converted
31   * to Boolean.FALSE. The recognized true/false strings can be changed by:
32   * <pre>
33   *  String[] trueStrings = {"oui", "o", "1"};
34   *  String[] falseStrings = {"non", "n", "0"};
35   *  Converter bc = new BooleanConverter(trueStrings, falseStrings);
36   *  ConvertUtils.register(bc, Boolean.class);
37   *  ConvertUtils.register(bc, Boolean.TYPE);
38   * </pre>
39   * In addition, it is recommended that the BooleanArrayConverter also be
40   * modified to recognise the same set of values:
41   * <pre>
42   *   Converter bac = new BooleanArrayConverter(bc, BooleanArrayConverter.NO_DEFAULT);
43   *   ConvertUtils.register(bac, bac.MODEL);
44   * </pre>
45   * </p>
46   *
47   * <p>Case is ignored when converting values to true or false.</p>
48   *
49   * @version $Id$
50   * @since 1.3
51   */
52  public final class BooleanConverter extends AbstractConverter {
53  
54  
55      // ----------------------------------------------------------- Constructors
56  
57  
58      /**
59       * Create a {@link org.apache.commons.beanutils.Converter} that will throw a
60       * {@link org.apache.commons.beanutils.ConversionException}
61       * if a conversion error occurs, ie the string value being converted is
62       * not one of the known true strings, nor one of the known false strings.
63       */
64      public BooleanConverter() {
65          super();
66      }
67  
68  
69      /**
70       * Create a {@link org.apache.commons.beanutils.Converter} that will return the specified default value
71       * if a conversion error occurs, ie the string value being converted is
72       * not one of the known true strings, nor one of the known false strings.
73       *
74       * @param defaultValue The default value to be returned if the value
75       *  being converted is not recognized. This value may be null, in which
76       *  case null will be returned on conversion failure. When non-null, it is
77       *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
78       *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
79       *  in which case this constructor acts like the no-argument one.
80       */
81      public BooleanConverter(final Object defaultValue) {
82          super();
83          if (defaultValue != NO_DEFAULT) {
84              setDefaultValue(defaultValue);
85          }
86      }
87  
88      /**
89       * Create a {@link org.apache.commons.beanutils.Converter} that will throw a
90       * {@link org.apache.commons.beanutils.ConversionException}
91       * if a conversion error occurs, ie the string value being converted is
92       * not one of the known true strings, nor one of the known false strings.
93       * <p>
94       * The provided string arrays are copied, so that changes to the elements
95       * of the array after this call is made do not affect this object.
96       *
97       * @param trueStrings is the set of strings which should convert to the
98       *  value Boolean.TRUE. The value null must not be present. Case is
99       *  ignored.
100      *
101      * @param falseStrings is the set of strings which should convert to the
102      *  value Boolean.TRUE. The value null must not be present. Case is
103      *  ignored.
104      * @since 1.8.0
105      */
106     public BooleanConverter(final String[] trueStrings, final String[] falseStrings) {
107         super();
108         this.trueStrings = copyStrings(trueStrings);
109         this.falseStrings = copyStrings(falseStrings);
110     }
111 
112     /**
113      * Create a {@link org.apache.commons.beanutils.Converter} that will return
114      * the specified default value if a conversion error occurs.
115      * <p>
116      * The provided string arrays are copied, so that changes to the elements
117      * of the array after this call is made do not affect this object.
118      *
119      * @param trueStrings is the set of strings which should convert to the
120      *  value Boolean.TRUE. The value null must not be present. Case is
121      *  ignored.
122      *
123      * @param falseStrings is the set of strings which should convert to the
124      *  value Boolean.TRUE. The value null must not be present. Case is
125      *  ignored.
126      *
127      * @param defaultValue The default value to be returned if the value
128      *  being converted is not recognized. This value may be null, in which
129      *  case null will be returned on conversion failure. When non-null, it is
130      *  expected that this value will be either Boolean.TRUE or Boolean.FALSE.
131      *  The special value BooleanConverter.NO_DEFAULT can also be passed here,
132      *  in which case an exception will be thrown on conversion failure.
133      * @since 1.8.0
134      */
135     public BooleanConverter(final String[] trueStrings, final String[] falseStrings,
136                 final Object defaultValue) {
137         super();
138         this.trueStrings = copyStrings(trueStrings);
139         this.falseStrings = copyStrings(falseStrings);
140         if (defaultValue != NO_DEFAULT) {
141             setDefaultValue(defaultValue);
142         }
143     }
144 
145 
146     // ----------------------------------------------------- Static Variables
147 
148 
149     /**
150      * This is a special reference that can be passed as the "default object"
151      * to the constructor to indicate that no default is desired. Note that
152      * the value 'null' cannot be used for this purpose, as the caller may
153      * want a null to be returned as the default.
154      * @deprecated Use constructors without default value.
155      */
156     @Deprecated
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     @Override
181     protected Class<Boolean> getDefaultType() {
182         return Boolean.class;
183     }
184 
185     /**
186      * Convert the specified input object into an output object of the
187      * specified type.
188      *
189      * @param <T> Target type of the conversion.
190      * @param type is the type to which this value should be converted. In the
191      *  case of this BooleanConverter class, this value is ignored.
192      *
193      * @param value is the input value to be converted. The toString method
194      *  shall be invoked on this object, and the result compared (ignoring
195      *  case) against the known "true" and "false" string values.
196      *
197      * @return Boolean.TRUE if the value was a recognized "true" value,
198      *  Boolean.FALSE if the value was a recognized "false" value, or
199      *  the default value if the value was not recognized and the constructor
200      *  was provided with a default value.
201      *
202      * @throws Throwable if an error occurs converting to the specified type
203      * @since 1.8.0
204      */
205     @Override
206     protected <T> T convertToType(final Class<T> type, final Object value) throws Throwable {
207 
208         if (Boolean.class.equals(type) || Boolean.TYPE.equals(type)) {
209             // All the values in the trueStrings and falseStrings arrays are
210             // guaranteed to be lower-case. By converting the input value
211             // to lowercase too, we can use the efficient String.equals method
212             // instead of the less-efficient String.equalsIgnoreCase method.
213             final String stringValue = value.toString().toLowerCase();
214 
215             for (String trueString : trueStrings) {
216                 if (trueString.equals(stringValue)) {
217                     return type.cast(Boolean.TRUE);
218                 }
219             }
220 
221             for (String falseString : falseStrings) {
222                 if (falseString.equals(stringValue)) {
223                     return type.cast(Boolean.FALSE);
224                 }
225             }
226         }
227 
228         throw conversionException(type, value);
229     }
230 
231     /**
232      * This method creates a copy of the provided array, and ensures that
233      * all the strings in the newly created array contain only lower-case
234      * letters.
235      * <p>
236      * Using this method to copy string arrays means that changes to the
237      * src array do not modify the dst array.
238      */
239     private static String[] copyStrings(final String[] src) {
240         final String[] dst = new String[src.length];
241         for(int i=0; i<src.length; ++i) {
242             dst[i] = src[i].toLowerCase();
243         }
244         return dst;
245     }
246 }