Skip to content

Commit

Permalink
Added converters/tests for Color, Dimension, InetAddress, Locale, Pat…
Browse files Browse the repository at this point in the history
…tern, and Point.
  • Loading branch information
SethFalco committed Dec 30, 2020
1 parent c9bde93 commit 36d836a
Show file tree
Hide file tree
Showing 13 changed files with 1,092 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@

package org.apache.commons.beanutils2;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.io.File;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
Expand All @@ -40,7 +44,9 @@
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Collection;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;

import org.apache.commons.beanutils2.converters.ArrayConverter;
import org.apache.commons.beanutils2.converters.BigDecimalConverter;
Expand All @@ -50,23 +56,29 @@
import org.apache.commons.beanutils2.converters.CalendarConverter;
import org.apache.commons.beanutils2.converters.CharacterConverter;
import org.apache.commons.beanutils2.converters.ClassConverter;
import org.apache.commons.beanutils2.converters.ColorConverter;
import org.apache.commons.beanutils2.converters.ConverterFacade;
import org.apache.commons.beanutils2.converters.DateConverter;
import org.apache.commons.beanutils2.converters.DimensionConverter;
import org.apache.commons.beanutils2.converters.DoubleConverter;
import org.apache.commons.beanutils2.converters.EnumConverter;
import org.apache.commons.beanutils2.converters.DurationConverter;
import org.apache.commons.beanutils2.converters.EnumConverter;
import org.apache.commons.beanutils2.converters.FileConverter;
import org.apache.commons.beanutils2.converters.FloatConverter;
import org.apache.commons.beanutils2.converters.InetAddressConverter;
import org.apache.commons.beanutils2.converters.IntegerConverter;
import org.apache.commons.beanutils2.converters.LocalDateConverter;
import org.apache.commons.beanutils2.converters.LocalDateTimeConverter;
import org.apache.commons.beanutils2.converters.LocalTimeConverter;
import org.apache.commons.beanutils2.converters.LocaleConverter;
import org.apache.commons.beanutils2.converters.LongConverter;
import org.apache.commons.beanutils2.converters.MonthDayConverter;
import org.apache.commons.beanutils2.converters.OffsetDateTimeConverter;
import org.apache.commons.beanutils2.converters.OffsetTimeConverter;
import org.apache.commons.beanutils2.converters.PathConverter;
import org.apache.commons.beanutils2.converters.PatternConverter;
import org.apache.commons.beanutils2.converters.PeriodConverter;
import org.apache.commons.beanutils2.converters.PointConverter;
import org.apache.commons.beanutils2.converters.ShortConverter;
import org.apache.commons.beanutils2.converters.SqlDateConverter;
import org.apache.commons.beanutils2.converters.SqlTimeConverter;
Expand Down Expand Up @@ -484,10 +496,13 @@ private void registerStandard(final boolean throwException, final boolean defaul
* This method registers the following converters:
* <ul>
* <li>{@code Class.class} - {@link ClassConverter}</li>
* <li>{@code Color.class} - {@link ColorConverter}</li>
* <li>{@code Enum.class} - {@link EnumConverter}</li>
* <li>{@code java.util.Date.class} - {@link DateConverter}</li>
* <li>{@code java.util.Calendar.class} - {@link CalendarConverter}</li>
* <li>{@code Dimension.class} - {@link DimensionConverter}</li>
* <li>{@code File.class} - {@link FileConverter}</li>
* <li>{@code InetAddress.class} - {@link InetAddressConverter}</li>
* <li>{@code Path.class} - {@link PathConverter}</li>
* <li>{@code java.sql.Date.class} - {@link SqlDateConverter}</li>
* <li>{@code java.sql.Time.class} - {@link SqlTimeConverter}</li>
Expand All @@ -498,12 +513,15 @@ private void registerStandard(final boolean throwException, final boolean defaul
* <li>{@code LocalDate.class} - {@link LocalDateConverter}</li>
* <li>{@code LocalDateTime.class} - {@link LocalDateTimeConverter}</li>
* <li>{@code LocalTime.class} - {@link LocalTimeConverter}</li>
* <li>{@code Locale.class} - {@link LocaleConverter}</li>
* <li>{@code OffsetDateTime.class} - {@link OffsetDateTimeConverter}</li>
* <li>{@code OffsetTime.class} - {@link OffsetTimeConverter}</li>
* <li>{@code ZonedDateTime.class} - {@link ZonedDateTimeConverter}</li>
* <li>{@code Duration.class} - {@link DurationConverter}</li>
* <li>{@code MonthDay.class} - {@link MonthDayConverter}</li>
* <li>{@code Pattern.class} - {@link PatternConverter}</li>
* <li>{@code Period.class} - {@link PeriodConverter}</li>
* <li>{@code Point.class} - {@link PointConverter}</li>
* <li>{@code Year.class} - {@link YearConverter}</li>
* <li>{@code YearMonth.class} - {@link YearMonthConverter}</li>
* <li>{@code ZoneId.class} - {@link ZoneIdConverter}</li>
Expand All @@ -516,10 +534,13 @@ private void registerStandard(final boolean throwException, final boolean defaul
private void registerOther(final boolean throwException) {
// @formatter:off
register(Class.class, throwException ? new ClassConverter() : new ClassConverter(null));
register(ColorConverter.class, throwException ? new ColorConverter() : new ColorConverter(null));
register(Enum.class, throwException ? new EnumConverter() : new EnumConverter(null));
register(java.util.Date.class, throwException ? new DateConverter() : new DateConverter(null));
register(Calendar.class, throwException ? new CalendarConverter() : new CalendarConverter(null));
register(Dimension.class, throwException ? new DimensionConverter() : new DimensionConverter(null));
register(File.class, throwException ? new FileConverter() : new FileConverter(null));
register(InetAddress.class, throwException ? new InetAddressConverter() : new InetAddressConverter(null));
register(Path.class, throwException ? new PathConverter() : new PathConverter(null));
register(java.sql.Date.class, throwException ? new SqlDateConverter() : new SqlDateConverter(null));
register(java.sql.Time.class, throwException ? new SqlTimeConverter() : new SqlTimeConverter(null));
Expand All @@ -530,12 +551,15 @@ private void registerOther(final boolean throwException) {
register(LocalDate.class, throwException ? new LocalDateConverter() : new LocalDateConverter(null));
register(LocalDateTime.class, throwException ? new LocalDateTimeConverter() : new LocalDateTimeConverter(null));
register(LocalTime.class, throwException ? new LocalTimeConverter() : new LocalTimeConverter(null));
register(Locale.class, throwException ? new LocaleConverter() : new LocaleConverter(null));
register(OffsetDateTime.class,throwException ? new OffsetDateTimeConverter():new OffsetDateTimeConverter(null));
register(OffsetTime.class, throwException ? new OffsetTimeConverter() : new OffsetTimeConverter(null));
register(ZonedDateTime.class, throwException ? new ZonedDateTimeConverter() : new ZonedDateTimeConverter(null));
register(Duration.class, throwException ? new DurationConverter() : new DurationConverter(null));
register(MonthDay.class, throwException ? new MonthDayConverter() : new MonthDayConverter(null));
register(Pattern.class, throwException ? new PatternConverter() : new PatternConverter(null));
register(Period.class, throwException ? new PeriodConverter() : new PeriodConverter(null));
register(Point.class, throwException ? new PointConverter() : new PointConverter(null));
register(Year.class, throwException ? new YearConverter() : new YearConverter(null));
register(YearMonth.class, throwException ? new YearMonthConverter() : new YearMonthConverter(null));
register(ZoneId.class, throwException ? new ZoneIdConverter() : new ZoneIdConverter(null));
Expand Down Expand Up @@ -582,10 +606,14 @@ private void registerArrays(final boolean throwException, final int defaultArray

// Other
registerArrayConverter(Class.class, new ClassConverter(), throwException, defaultArraySize);
registerArrayConverter(Color.class, new ColorConverter(), throwException, defaultArraySize);
registerArrayConverter(Enum.class, new EnumConverter(), throwException, defaultArraySize);
registerArrayConverter(java.util.Date.class, new DateConverter(), throwException, defaultArraySize);
registerArrayConverter(Calendar.class, new DateConverter(), throwException, defaultArraySize);
registerArrayConverter(Dimension.class, new DimensionConverter(), throwException, defaultArraySize);
registerArrayConverter(File.class, new FileConverter(), throwException, defaultArraySize);
registerArrayConverter(Color.class, new ColorConverter(), throwException, defaultArraySize);
registerArrayConverter(InetAddress.class, new InetAddressConverter(), throwException, defaultArraySize);
registerArrayConverter(Path.class, new PathConverter(), throwException, defaultArraySize);
registerArrayConverter(java.sql.Date.class, new SqlDateConverter(), throwException, defaultArraySize);
registerArrayConverter(java.sql.Time.class, new SqlTimeConverter(), throwException, defaultArraySize);
Expand All @@ -596,12 +624,15 @@ private void registerArrays(final boolean throwException, final int defaultArray
registerArrayConverter(LocalDate.class, new LocalDateConverter(), throwException, defaultArraySize);
registerArrayConverter(LocalDateTime.class, new LocalDateTimeConverter(), throwException, defaultArraySize);
registerArrayConverter(LocalTime.class, new LocalTimeConverter(), throwException, defaultArraySize);
registerArrayConverter(Locale.class, new LocaleConverter(), throwException, defaultArraySize);
registerArrayConverter(OffsetDateTime.class, new OffsetDateTimeConverter(),throwException, defaultArraySize);
registerArrayConverter(OffsetTime.class, new OffsetTimeConverter(), throwException, defaultArraySize);
registerArrayConverter(ZonedDateTime.class, new ZonedDateTimeConverter(), throwException, defaultArraySize);
registerArrayConverter(Duration.class, new DurationConverter(), throwException, defaultArraySize);
registerArrayConverter(MonthDay.class, new MonthDayConverter(), throwException, defaultArraySize);
registerArrayConverter(Pattern.class, new PatternConverter(), throwException, defaultArraySize);
registerArrayConverter(Period.class, new PeriodConverter(), throwException, defaultArraySize);
registerArrayConverter(Point.class, new PointConverter(), throwException, defaultArraySize);
registerArrayConverter(Year.class, new YearConverter(), throwException, defaultArraySize);
registerArrayConverter(YearMonth.class, new YearMonthConverter(), throwException, defaultArraySize);
registerArrayConverter(ZoneId.class, new ZoneIdConverter(), throwException, defaultArraySize);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/*
* 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.beanutils2.converters;

import java.awt.Color;
import java.util.Objects;

/**
* <p>Converts a configuration property into a Java {@link Color} object.</p>
*
* <p>
* This converter aims to be compatible with some some of the web color
* formats supported by browsers with CSS, rather than only support
* literal interpretations of numbers, such as:
* </p>
*
* <ul>
* <li>#RGB</li>
* <li>#RGBA</li>
* <li>#RRGGBBAA</li>
* </ul>
*
* <p>
* This converter will use the web based hexadecimal interpretations if
* the value is prefixed with {@link #HEX_COLOR_PREFIX}.
*
* If using a literal number, or {@link Color#decode(String)} is desired, you must
* prefix your value with <code>0x</code> instead of {@link #HEX_COLOR_PREFIX}.
* </p>
*
* @since 2.0.0
*/
public class ColorConverter extends AbstractConverter {

/** To be a web based hexadecimal color, it must be prefixed with this. */
private static final String HEX_COLOR_PREFIX = "#";

/**
* Construct a <b>{@link Color}</b> <i>Converter</i> that throws
* a {@code ConversionException} if an error occurs.
*/
public ColorConverter() {
super();
}

/**
* @param defaultValue The default value to be returned
* if the value to be converted is missing or an error
* occurs converting the value.
*/
public ColorConverter(final Object defaultValue) {
super(defaultValue);
}

@Override
protected Class<?> getDefaultType() {
return Color.class;
}

/**
* <p>
* Convert the configuration value to a Java {@link Color} object,
* by reading the hexadecimal {@link String} and converting each component.
* </p>
*
* <p>
* This can also interpret raw color names based on the standard colors
* defined in Java, such as the following:
* </p>
*
* <ul>
* <li>{@link Color#WHITE}</li>
* <li>{@link Color#LIGHT_GRAY}</li>
* <li>{@link Color#GRAY}</li>
* <li>{@link Color#DARK_GRAY}</li>
* <li>{@link Color#BLACK}</li>
* <li>{@link Color#RED}</li>
* <li>{@link Color#PINK}</li>
* <li>{@link Color#ORANGE}</li>
* <li>{@link Color#YELLOW}</li>
* <li>{@link Color#GREEN}</li>
* <li>{@link Color#MAGENTA}</li>
* <li>{@link Color#CYAN}</li>
* <li>{@link Color#BLUE}</li>
* </ul>
*
* <small>
* Implementation Notes: We specifically avoid the use of {@link Color#decode(String)}
* for hexadecimal {@link String}s starting with {@link #HEX_COLOR_PREFIX}
* as it does not provide the desired result.
* The {@link Color#decode(String)} method uses {@link Integer#decode(String)}
* under the hood to convert the input to a number, which means input like
* <code>#FFF</code> gets interpreted incorrectly as it's literally converted
* to the number <code>0xFFF</code>, rather than the color, <code>#FFFFFF</code> which
* it is short hand for. It also doesn't work for <code>#FFFFFFFF</code> due to it
* being unable to parse as an {@link Integer}.
* If this is desired, then this method falls back to using {@link Color#decode(String)},
* so for literal hexadecimal values you prefix it with <code>0x</code> instead of
* {@link #HEX_COLOR_PREFIX}.
* </small>
*
* @param value The String property value to convert.
* @return A {@link Color} which represents the compiled configuration property.
* @throws NullPointerException If the value is null.
* @throws NumberFormatException If an invalid number is provided.
*/
@Override
protected <T> T convertToType(Class<T> type, Object value) throws Throwable {
Objects.requireNonNull(value, "Value can't be null.");
final String stringValue = value.toString();

switch (stringValue.toLowerCase()) {
case "white":
return type.cast(Color.WHITE);
case "lightgray":
return type.cast(Color.LIGHT_GRAY);
case "gray":
return type.cast(Color.GRAY);
case "darkgray":
return type.cast(Color.DARK_GRAY);
case "black":
return type.cast(Color.BLACK);
case "red":
return type.cast(Color.RED);
case "pink":
return type.cast(Color.PINK);
case "orange":
return type.cast(Color.ORANGE);
case "yellow":
return type.cast(Color.YELLOW);
case "green":
return type.cast(Color.GREEN);
case "magenta":
return type.cast(Color.MAGENTA);
case "cyan":
return type.cast(Color.CYAN);
case "blue":
return type.cast(Color.BLUE);
default:
// Do nothing.
}

if (stringValue.startsWith(HEX_COLOR_PREFIX)) {
return type.cast(parseWebColor(stringValue));
}

return type.cast(Color.decode(stringValue));
}

/**
* <small>
* Implementation Notes: This must return a {@link Color}; not a {@link Number}
* or {@link String} for {@link Color#decode(String)} as it is not capable of supporting
* a color alpha channel due to the limited range of an {@link Integer}.
* </small>
*
* @param value The web friendly hexadecimal {@link String}.
* @return The Java friendly {@link Color} this color represents.
* @throws NumberFormatException If the hexadecimal input contains non parsable characters.
*/
private Color parseWebColor(final String value) {
Objects.requireNonNull(value);

switch (value.length()) {
case 4:
return new Color(
Integer.parseInt(value.substring(1, 2), 16) * 17,
Integer.parseInt(value.substring(2, 3), 16) * 17,
Integer.parseInt(value.substring(3, 4), 16) * 17
);
case 5:
return new Color(
Integer.parseInt(value.substring(1, 2), 16) * 17,
Integer.parseInt(value.substring(2, 3), 16) * 17,
Integer.parseInt(value.substring(3, 4), 16) * 17,
Integer.parseInt(value.substring(4, 5), 16) * 17
);
case 7:
return new Color(
Integer.parseInt(value.substring(1, 3), 16),
Integer.parseInt(value.substring(3, 5), 16),
Integer.parseInt(value.substring(5, 7), 16)
);
case 9:
return new Color(
Integer.parseInt(value.substring(1, 3), 16),
Integer.parseInt(value.substring(3, 5), 16),
Integer.parseInt(value.substring(5, 7), 16),
Integer.parseInt(value.substring(7, 9), 16)
);
default:
throw new IllegalArgumentException("Invalid hexadecimal color provided, if literal value decoding " +
"is required, specify 0x instead of #, otherwise expecting 3, 4, 6, or 8 characters only.");
}
}
}
Loading

0 comments on commit 36d836a

Please sign in to comment.