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 * https://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 }