View Javadoc
1   /**
2    *  Copyright (C) 2016 Gary Gregory. All rights reserved.
3    *
4    *  See the NOTICE.txt file distributed with this work for additional
5    *  information regarding copyright ownership.
6    *  
7    *  Licensed under the Apache License, Version 2.0 (the "License");
8    *  you may not use this file except in compliance with the License.
9    *  You may obtain a copy of the License at
10   *  
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *  
13   *  Unless required by applicable law or agreed to in writing, software
14   *  distributed under the License is distributed on an "AS IS" BASIS,
15   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   *  See the License for the specific language governing permissions and
17   *  limitations under the License.
18   */
19  package com.garygregory.jcommander.converters;
20  
21  import java.net.URI;
22  import java.util.Objects;
23  
24  import com.beust.jcommander.ParameterException;
25  import com.beust.jcommander.converters.BaseConverter;
26  import com.beust.jcommander.converters.IntegerConverter;
27  import com.garygregory.jcommander.converters.net.URIConverter;
28  
29  /**
30   * Provides common services for converters in this package
31   * 
32   * @param <T>
33   *            the target type of the conversion.
34   * @since 1.0.0
35   * @author <a href="mailto:ggregory@garygregory.com">Gary Gregory</a>
36   */
37  public abstract class AbstractBaseConverter<T> extends BaseConverter<T> {
38  
39      /**
40       * The target class to convert strings.
41       */
42      protected final Class<T> targetClass;
43  
44      /**
45       * Whether or not a null conversion failure throws a ParameterException.
46       */
47      protected final boolean failOnNull;
48  
49      /**
50       * Constructs a new instance for the given option and target class.
51       * 
52       * @param optionName
53       *            The option name, may be null.
54       * @param targetClass
55       *            must not be null
56       */
57      public AbstractBaseConverter(final String optionName, final Class<T> targetClass) {
58          this(optionName, targetClass, true);
59      }
60  
61      /**
62       * Constructs a new instance for the given option, target class and fail-on-null.
63       * 
64       * @param optionName
65       *            may be null
66       * @param targetClass
67       *            must not be null
68       * @param failOnNull
69       *            if true, the converter fails when the conversion results in a null value
70       */
71      public AbstractBaseConverter(final String optionName, final Class<T> targetClass, final boolean failOnNull) {
72          super(optionName);
73          this.failOnNull = failOnNull;
74          this.targetClass = Objects.requireNonNull(targetClass, "targetClass for " + getClass());
75      }
76  
77      /**
78       * Converts the given value or throws a {@link ParameterException}. Delegates the actual conversion to subclasses with
79       * {@link #convertImpl(String)}.
80       * 
81       * @param value
82       *            the value to convert.
83       * @throws ParameterException
84       *             for a conversion problem
85       */
86      @Override
87      public T convert(final String value) {
88          try {
89              final T result = convertImpl(value);
90              if (result == null && failOnNull) {
91                  throw newParameterException(value);
92              }
93              return result;
94          } catch (final Exception e) {
95              throw newParameterException(value, e);
96          }
97      }
98  
99      /**
100      * Converts a value.
101      * 
102      * @param value
103      *            the value to convert
104      * @return the converted value
105      * @throws Exception
106      *             subclasses can throw any Exception
107      */
108     protected abstract T convertImpl(String value) throws Exception;
109 
110     /**
111      * Builds an error message for the given value in error
112      * 
113      * @param value
114      *            the value that cause the error
115      * @return an error message
116      */
117     protected String getErrorString(final String value) {
118         return getClass().getName() + " could not convert \"" + value + "\" to an instance of " + targetClass + " for option "
119                 + getOptionName();
120     }
121 
122     /**
123      * Returns true if the array is of size 1, false otherwise.
124      * 
125      * @param split
126      *            an array
127      * @return true if the array is of size 1, false otherwise.
128      */
129     protected boolean isSingle(final String[] split) {
130         return split.length == 1;
131     }
132 
133     /**
134      * Creates a new {@link ParameterException} for the given value.
135      * 
136      * @param value
137      *            the value in error
138      * @return a new ParameterException
139      */
140     protected ParameterException newParameterException(final String value) {
141         return new ParameterException(getErrorString(value));
142     }
143 
144     /**
145      * Creates a new {@link ParameterException} for the given value and throwable
146      * 
147      * @param value
148      *            the value in error
149      * @param t
150      *            the throwable
151      * @return a new ParameterException
152      */
153     protected ParameterException newParameterException(final String value, final Throwable t) {
154         return new ParameterException(getErrorString(value), t);
155     }
156 
157     /**
158      * Splits the given string using {@link ConverterConstants#VALUE_SEPARATOR} as the boundary.
159      * 
160      * @param value
161      *            the string to split
162      * @return the split array result
163      */
164     protected String[] split(final String value) {
165         return value.split(ConverterConstants.VALUE_SEPARATOR);
166     }
167 
168     /**
169      * Converts the given value to an int for the given option.
170      * 
171      * @param optionName
172      *            the option name
173      * @param value
174      *            the value to parse
175      * @return the int result
176      */
177     protected int toInt(final String optionName, final String value) {
178         return new IntegerConverter(optionName).convert(value).intValue();
179     }
180 
181     /**
182      * Converts the given string into a URI
183      * 
184      * @param optionName
185      *            the option name
186      * @param value
187      *            a string
188      * 
189      * @return a new URI
190      * @see java.net.URI
191      */
192     protected URI toURI(final String optionName, final String value) {
193         return new URIConverter(null).convert(value);
194     }
195 
196 }