View Javadoc
1   /*
2    * Copyright 2007 Kasper B. Graversen
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.supercsv.cellprocessor.constraint;
17  
18  import org.supercsv.cellprocessor.CellProcessorAdaptor;
19  import org.supercsv.cellprocessor.ift.DoubleCellProcessor;
20  import org.supercsv.cellprocessor.ift.StringCellProcessor;
21  import org.supercsv.exception.SuperCsvCellProcessorException;
22  import org.supercsv.exception.SuperCsvConstraintViolationException;
23  import org.supercsv.util.CsvContext;
24  
25  /**
26   * Converts the input data to a Double and ensures that number is within a specified numeric range (inclusive). If the
27   * data has no upper bound (or lower bound), you should use either of <code>MIN</code> or <code>MAX</code> constants
28   * provided in the class.
29   * 
30   * @author Kasper B. Graversen
31   * @author James Bassett
32   */
33  public class DMinMax extends CellProcessorAdaptor implements StringCellProcessor {
34  	
35  	/** Maximum value for a Double */
36  	public static final double MAX_DOUBLE = Double.MAX_VALUE;
37  	
38  	/** Minimum value for a Double */
39  	public static final double MIN_DOUBLE = Double.MIN_VALUE;
40  	
41  	/** Maximum value for a Short */
42  	public static final double MAX_SHORT = Short.MAX_VALUE;
43  	
44  	/** Minimum value for a Short */
45  	public static final double MIN_SHORT = Short.MIN_VALUE;
46  	
47  	/** Maximum value for a Character */
48  	public static final double MAX_CHAR = Character.MAX_VALUE;
49  	
50  	/** Minimum value for a Character */
51  	public static final double MIN_CHAR = Character.MIN_VALUE;
52  	
53  	/** Maximum value for 8 bits (unsigned) */
54  	public static final int MAX_8_BIT_UNSIGNED = 255;
55  	
56  	/** Minimum value for 8 bits (unsigned) */
57  	public static final int MIN_8_BIT_UNSIGNED = 0;
58  	
59  	/** Maximum value for 8 bits (signed) */
60  	public static final int MAX_8_BIT_SIGNED = Byte.MAX_VALUE;
61  	
62  	/** Minimum value for 8 bits (signed) */
63  	public static final int MIN_8_BIT_SIGNED = Byte.MIN_VALUE;
64  	
65  	private final double min;
66  	
67  	private final double max;
68  	
69  	/**
70  	 * Constructs a new <tt>DMinMax</tt> processor, which converts the input to a Double and ensures the value is
71  	 * between the supplied min and max values.
72  	 * 
73  	 * @param min
74  	 *            the minimum value (inclusive)
75  	 * @param max
76  	 *            the maximum value (inclusive)
77  	 * @throws IllegalArgumentException
78  	 *             if {@code max < min}
79  	 */
80  	public DMinMax(final double min, final double max) {
81  		super();
82  		checkPreconditions(min, max);
83  		this.min = min;
84  		this.max = max;
85  	}
86  	
87  	/**
88  	 * Constructs a new <tt>DMinMax</tt> processor, which converts the input to a Double, ensures the value is between
89  	 * the supplied min and max values, then calls the next processor in the chain.
90  	 * 
91  	 * @param min
92  	 *            the minimum value (inclusive)
93  	 * @param max
94  	 *            the maximum value (inclusive)
95  	 * @param next
96  	 *            the next processor in the chain
97  	 * @throws IllegalArgumentException
98  	 *             if {@code max < min}
99  	 * @throws NullPointerException
100 	 *             if next is null
101 	 */
102 	public DMinMax(final double min, final double max, final DoubleCellProcessor next) {
103 		super(next);
104 		checkPreconditions(min, max);
105 		this.min = min;
106 		this.max = max;
107 	}
108 	
109 	/**
110 	 * Checks the preconditions for creating a new DMinMax processor.
111 	 * 
112 	 * @param min
113 	 *            the minimum value (inclusive)
114 	 * @param max
115 	 *            the maximum value (inclusive)
116 	 * @throws IllegalArgumentException
117 	 *             if {@code max < min}
118 	 */
119 	private static void checkPreconditions(final double min, final double max) {
120 		if( max < min ) {
121 			throw new IllegalArgumentException(String.format("max (%f) should not be < min (%f)", max, min));
122 		}
123 	}
124 	
125 	/**
126 	 * {@inheritDoc}
127 	 * 
128 	 * @throws SuperCsvCellProcessorException
129 	 *             if value is null or can't be parsed as a Double
130 	 * @throws SuperCsvConstraintViolationException
131 	 *             if value doesn't lie between min and max (inclusive)
132 	 */
133 	public Object execute(final Object value, final CsvContext context) {
134 		validateInputNotNull(value, context);
135 		
136 		final Double result;
137 		if( value instanceof Double ) {
138 			result = (Double) value;
139 		} else {
140 			try {
141 				result = Double.parseDouble(value.toString());
142 			}
143 			catch(final NumberFormatException e) {
144 				throw new SuperCsvCellProcessorException(String.format("'%s' could not be parsed as a Double", value),
145 					context, this, e);
146 			}
147 		}
148 		
149 		if( result < min || result > max ) {
150 			throw new SuperCsvConstraintViolationException(String.format(
151 				"%f does not lie between the min (%f) and max (%f) values (inclusive)", result, min, max), context,
152 				this);
153 		}
154 		
155 		return next.execute(result, context);
156 	}
157 	
158 }