View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.beanutils2.converters;
20  
21  import java.awt.Dimension;
22  import java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  
25  /**
26   * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion to and from {@link Dimension}.
27   *
28   * <p>
29   * Accepts a single {@link Integer} value, or two {@link Integer} values separated by the character {@code x}.
30   * </p>
31   *
32   * <p>
33   * The dimensions must consist of non-negative {@link Integer} values only.
34   * </p>
35   *
36   * @since 2.0.0
37   */
38  public class DimensionConverter extends AbstractConverter<Dimension> {
39  
40      /** Pattern used to validate and tokenizer the {@link String}. */
41      private static final Pattern DIMENSION_PATTERN = Pattern.compile("(\\d+)(?:x(\\d+))?");
42  
43      /**
44       * Construct a <strong>{@link Dimension}</strong> <em>Converter</em> that throws a {@code ConversionException} if an error occurs.
45       */
46      public DimensionConverter() {
47      }
48  
49      /**
50       * Constructs a {@link org.apache.commons.beanutils2.Converter} that will return the specified default value if a conversion error occurs.
51       *
52       * @param defaultValue The default value to be returned if the value to be converted is missing or an error occurs converting the value.
53       */
54      public DimensionConverter(final Dimension defaultValue) {
55          super(defaultValue);
56      }
57  
58      /**
59       * Converts the input object into an output object of the specified type.
60       *
61       * @param type  Data type to which this value should be converted.
62       * @param value String property value to convert.
63       * @return A {@link Dimension} which represents the configuration property value.
64       * @throws NullPointerException  If the value is null.
65       * @throws NumberFormatException If the {@link Dimension} width or height is bigger than {@link Integer#MAX_VALUE}.
66       */
67      @Override
68      protected <T> T convertToType(final Class<T> type, final Object value) throws Throwable {
69          if (Dimension.class.isAssignableFrom(type)) {
70              final String stringValue = toString(value);
71  
72              if (stringValue.isEmpty()) {
73                  throw new IllegalArgumentException("Dimensions cannot be empty.");
74              }
75  
76              final Matcher matcher = DIMENSION_PATTERN.matcher(stringValue);
77  
78              if (!matcher.matches()) {
79                  throw new IllegalArgumentException("Dimension doesn't match format: {width/height} or {width}x{height}");
80              }
81  
82              final String x = matcher.group(1);
83              final String y = matcher.group(2);
84  
85              final int xValue = Integer.parseInt(x);
86              final int yValue = y == null || x.equals(y) ? xValue : Integer.parseInt(y);
87  
88              return type.cast(new Dimension(xValue, yValue));
89          }
90  
91          throw conversionException(type, value);
92      }
93  
94      /**
95       * Gets the default type this {@code Converter} handles.
96       *
97       * @return The default type this {@code Converter} handles.
98       * @since 2.0.0
99       */
100     @Override
101     protected Class<Dimension> getDefaultType() {
102         return Dimension.class;
103     }
104 }