001/*
002 *  Copyright 2001-2006 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.time;
017
018/**
019 * Exception thrown when attempting to set a field outside its supported range.
020 *
021 * @author Brian S O'Neill
022 * @since 1.1
023 */
024public class IllegalFieldValueException extends IllegalArgumentException {
025    
026    /** Serialization lock. */
027    private static final long serialVersionUID = 6305711765985447737L;
028
029    /**
030     * Creates a message for the exception.
031     *
032     * @param fieldName  the field name
033     * @param value  the value rejected
034     * @param lowerBound  the lower bound allowed
035     * @param upperBound  the uppe bound allowed
036     * @param explain  an explanation
037     * @return the message
038     */
039    private static String createMessage(String fieldName, Number value,
040                                        Number lowerBound, Number upperBound, String explain) {
041        StringBuilder buf = new StringBuilder()
042            .append("Value ").append(value).append(" for ").append(fieldName).append(' ');
043
044        if (lowerBound == null) {
045            if (upperBound == null) {
046                buf.append("is not supported");
047            } else {
048                buf.append("must not be larger than ").append(upperBound);
049            }
050        } else if (upperBound == null) {
051            buf.append("must not be smaller than ").append(lowerBound);
052        } else {
053            buf.append("must be in the range [")
054                .append(lowerBound)
055                .append(',')
056                .append(upperBound)
057                .append(']');
058        }
059        if (explain != null) {
060            buf.append(": ").append(explain);
061        }
062
063        return buf.toString();
064    }
065
066    /**
067     * Creates a message for the exception.
068     *
069     * @param fieldName  the field name
070     * @param value  the value rejected
071     * @return the message
072     */
073    private static String createMessage(String fieldName, String value) {
074        StringBuffer buf = new StringBuffer().append("Value ");
075
076        if (value == null) {
077            buf.append("null");
078        } else {
079            buf.append('"');
080            buf.append(value);
081            buf.append('"');
082        }
083
084        buf.append(" for ").append(fieldName).append(' ').append("is not supported");
085        
086        return buf.toString();
087    }
088
089    private final DateTimeFieldType iDateTimeFieldType;
090    private final DurationFieldType iDurationFieldType;
091    private final String iFieldName;
092    private final Number iNumberValue;
093    private final String iStringValue;
094    private final Number iLowerBound;
095    private final Number iUpperBound;
096    private String iMessage;
097
098    /**
099     * Constructor.
100     * 
101     * @param fieldType  type of field being set
102     * @param value  illegal value being set
103     * @param lowerBound  lower legal field value, or null if not applicable
104     * @param upperBound  upper legal field value, or null if not applicable
105     */
106    public IllegalFieldValueException(DateTimeFieldType fieldType,
107                                      Number value, Number lowerBound, Number upperBound) {
108        super(createMessage(fieldType.getName(), value, lowerBound, upperBound, null));
109        iDateTimeFieldType = fieldType;
110        iDurationFieldType = null;
111        iFieldName = fieldType.getName();
112        iNumberValue = value;
113        iStringValue = null;
114        iLowerBound = lowerBound;
115        iUpperBound = upperBound;
116        iMessage = super.getMessage();
117    }
118
119    /**
120     * Constructor.
121     * 
122     * @param fieldType  type of field being set
123     * @param value  illegal value being set
124     * @param explain  an explanation
125     * @since 1.5
126     */
127    public IllegalFieldValueException(DateTimeFieldType fieldType,
128                                      Number value, String explain) {
129        super(createMessage(fieldType.getName(), value, null, null, explain));
130        iDateTimeFieldType = fieldType;
131        iDurationFieldType = null;
132        iFieldName = fieldType.getName();
133        iNumberValue = value;
134        iStringValue = null;
135        iLowerBound = null;
136        iUpperBound = null;
137        iMessage = super.getMessage();
138    }
139
140    /**
141     * Constructor.
142     * 
143     * @param fieldType  type of field being set
144     * @param value  illegal value being set
145     * @param lowerBound  lower legal field value, or null if not applicable
146     * @param upperBound  upper legal field value, or null if not applicable
147     */
148    public IllegalFieldValueException(DurationFieldType fieldType,
149                                      Number value, Number lowerBound, Number upperBound) {
150        super(createMessage(fieldType.getName(), value, lowerBound, upperBound, null));
151        iDateTimeFieldType = null;
152        iDurationFieldType = fieldType;
153        iFieldName = fieldType.getName();
154        iNumberValue = value;
155        iStringValue = null;
156        iLowerBound = lowerBound;
157        iUpperBound = upperBound;
158        iMessage = super.getMessage();
159    }
160
161    /**
162     * Constructor.
163     * 
164     * @param fieldName  name of field being set
165     * @param value  illegal value being set
166     * @param lowerBound  lower legal field value, or null if not applicable
167     * @param upperBound  upper legal field value, or null if not applicable
168     */
169    public IllegalFieldValueException(String fieldName,
170                                      Number value, Number lowerBound, Number upperBound) {
171        super(createMessage(fieldName, value, lowerBound, upperBound, null));
172        iDateTimeFieldType = null;
173        iDurationFieldType = null;
174        iFieldName = fieldName;
175        iNumberValue = value;
176        iStringValue = null;
177        iLowerBound = lowerBound;
178        iUpperBound = upperBound;
179        iMessage = super.getMessage();
180    }
181
182    /**
183     * Constructor.
184     * 
185     * @param fieldType  type of field being set
186     * @param value  illegal value being set
187     */
188    public IllegalFieldValueException(DateTimeFieldType fieldType, String value) {
189        super(createMessage(fieldType.getName(), value));
190        iDateTimeFieldType = fieldType;
191        iDurationFieldType = null;
192        iFieldName = fieldType.getName();
193        iStringValue = value;
194        iNumberValue = null;
195        iLowerBound = null;
196        iUpperBound = null;
197        iMessage = super.getMessage();
198    }
199
200    /**
201     * Constructor.
202     * 
203     * @param fieldType  type of field being set
204     * @param value  illegal value being set
205     */
206    public IllegalFieldValueException(DurationFieldType fieldType, String value) {
207        super(createMessage(fieldType.getName(), value));
208        iDateTimeFieldType = null;
209        iDurationFieldType = fieldType;
210        iFieldName = fieldType.getName();
211        iStringValue = value;
212        iNumberValue = null;
213        iLowerBound = null;
214        iUpperBound = null;
215        iMessage = super.getMessage();
216    }
217
218    /**
219     * Constructor.
220     * 
221     * @param fieldName  name of field being set
222     * @param value  illegal value being set
223     */
224    public IllegalFieldValueException(String fieldName, String value) {
225        super(createMessage(fieldName, value));
226        iDateTimeFieldType = null;
227        iDurationFieldType = null;
228        iFieldName = fieldName;
229        iStringValue = value;
230        iNumberValue = null;
231        iLowerBound = null;
232        iUpperBound = null;
233        iMessage = super.getMessage();
234    }
235
236    //-----------------------------------------------------------------------
237    /**
238     * Returns the DateTimeFieldType whose value was invalid, or null if not applicable.
239     * 
240     * @return the datetime field type
241     */
242    public DateTimeFieldType getDateTimeFieldType() {
243        return iDateTimeFieldType;
244    }
245
246    /**
247     * Returns the DurationFieldType whose value was invalid, or null if not applicable.
248     * 
249     * @return the duration field type
250     */
251    public DurationFieldType getDurationFieldType() {
252        return iDurationFieldType;
253    }
254
255    /**
256     * Returns the name of the field whose value was invalid.
257     * 
258     * @return the field name
259     */
260    public String getFieldName() {
261        return iFieldName;
262    }
263
264    /**
265     * Returns the illegal integer value assigned to the field, or null if not applicable.
266     * 
267     * @return the value
268     */
269    public Number getIllegalNumberValue() {
270        return iNumberValue;
271    }
272
273    /**
274     * Returns the illegal string value assigned to the field, or null if not applicable.
275     * 
276     * @return the value
277     */
278    public String getIllegalStringValue() {
279        return iStringValue;
280    }
281
282    /**
283     * Returns the illegal value assigned to the field as a non-null string.
284     * 
285     * @return the value
286     */
287    public String getIllegalValueAsString() {
288        String value = iStringValue;
289        if (value == null) {
290            value = String.valueOf(iNumberValue);
291        }
292        return value;
293    }
294
295    /**
296     * Returns the lower bound of the legal value range, or null if not applicable.
297     * 
298     * @return the lower bound
299     */
300    public Number getLowerBound() {
301        return iLowerBound;
302    }
303
304    /**
305     * Returns the upper bound of the legal value range, or null if not applicable.
306     * 
307     * @return the upper bound
308     */
309    public Number getUpperBound() {
310        return iUpperBound;
311    }
312
313    public String getMessage() {
314        return iMessage;
315    }
316
317    /**
318     * Provide additional detail by prepending a message to the existing message.
319     * A colon is separator is automatically inserted between the messages.
320     * @since 1.3
321     */
322    public void prependMessage(String message) {
323        if (iMessage == null) {
324            iMessage = message;
325        } else if (message != null) {
326            iMessage = message + ": " + iMessage;
327        }
328    }
329}