001/*
002 *  Copyright 2001-2009 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.field;
017
018import java.io.Serializable;
019import java.util.HashMap;
020import java.util.Locale;
021import org.joda.time.DateTimeField;
022import org.joda.time.DateTimeFieldType;
023import org.joda.time.DurationField;
024import org.joda.time.ReadablePartial;
025
026/**
027 * A placeholder implementation to use when a datetime field is not supported.
028 * <p>
029 * UnsupportedDateTimeField is thread-safe and immutable.
030 *
031 * @author Brian S O'Neill
032 * @since 1.0
033 */
034public final class UnsupportedDateTimeField extends DateTimeField implements Serializable {
035
036    /** Serialilzation version */
037    private static final long serialVersionUID = -1934618396111902255L;
038
039    /** The cache of unsupported datetime field instances */
040    private static HashMap<DateTimeFieldType, UnsupportedDateTimeField> cCache;
041
042    /**
043     * Gets an instance of UnsupportedDateTimeField for a specific named field.
044     * Names should be of standard format, such as 'monthOfYear' or 'hourOfDay'.
045     * The returned instance is cached.
046     * 
047     * @param type  the type to obtain
048     * @return the instance
049     * @throws IllegalArgumentException if durationField is null
050     */
051    public static synchronized UnsupportedDateTimeField getInstance(
052            DateTimeFieldType type, DurationField durationField) {
053
054        UnsupportedDateTimeField field;
055        if (cCache == null) {
056            cCache = new HashMap<DateTimeFieldType, UnsupportedDateTimeField>(7);
057            field = null;
058        } else {
059            field = cCache.get(type);
060            if (field != null && field.getDurationField() != durationField) {
061                field = null;
062            }
063        }
064        if (field == null) {
065            field = new UnsupportedDateTimeField(type, durationField);
066            cCache.put(type, field);
067        }
068        return field;
069    }
070
071    /** The field type */
072    private final DateTimeFieldType iType;
073    /** The duration of the datetime field */
074    private final DurationField iDurationField;
075
076    /**
077     * Constructor.
078     * 
079     * @param type  the field type
080     * @param durationField  the duration to use
081     */
082    private UnsupportedDateTimeField(DateTimeFieldType type, DurationField durationField) {
083        if (type == null || durationField == null) {
084            throw new IllegalArgumentException();
085        }
086        iType = type;
087        iDurationField = durationField;
088    }
089
090    //-----------------------------------------------------------------------
091    // Design note: Simple accessors return a suitable value, but methods
092    // intended to perform calculations throw an UnsupportedOperationException.
093
094    public DateTimeFieldType getType() {
095        return iType;
096    }
097
098    public String getName() {
099        return iType.getName();
100    }
101
102    /**
103     * This field is not supported.
104     *
105     * @return false always
106     */
107    public boolean isSupported() {
108        return false;
109    }
110
111    /**
112     * This field is not lenient.
113     *
114     * @return false always
115     */
116    public boolean isLenient() {
117        return false;
118    }
119
120    /**
121     * Always throws UnsupportedOperationException
122     *
123     * @throws UnsupportedOperationException
124     */
125    public int get(long instant) {
126        throw unsupported();
127    }
128
129    /**
130     * Always throws UnsupportedOperationException
131     *
132     * @throws UnsupportedOperationException
133     */
134    public String getAsText(long instant, Locale locale) {
135        throw unsupported();
136    }
137
138    /**
139     * Always throws UnsupportedOperationException
140     *
141     * @throws UnsupportedOperationException
142     */
143    public String getAsText(long instant) {
144        throw unsupported();
145    }
146
147    /**
148     * Always throws UnsupportedOperationException
149     *
150     * @throws UnsupportedOperationException
151     */
152    public String getAsText(ReadablePartial partial, int fieldValue, Locale locale) {
153        throw unsupported();
154    }
155
156    /**
157     * Always throws UnsupportedOperationException
158     *
159     * @throws UnsupportedOperationException
160     */
161    public String getAsText(ReadablePartial partial, Locale locale) {
162        throw unsupported();
163    }
164
165    /**
166     * Always throws UnsupportedOperationException
167     *
168     * @throws UnsupportedOperationException
169     */
170    public String getAsText(int fieldValue, Locale locale) {
171        throw unsupported();
172    }
173
174    /**
175     * Always throws UnsupportedOperationException
176     *
177     * @throws UnsupportedOperationException
178     */
179    public String getAsShortText(long instant, Locale locale) {
180        throw unsupported();
181    }
182
183    /**
184     * Always throws UnsupportedOperationException
185     *
186     * @throws UnsupportedOperationException
187     */
188    public String getAsShortText(long instant) {
189        throw unsupported();
190    }
191
192    /**
193     * Always throws UnsupportedOperationException
194     *
195     * @throws UnsupportedOperationException
196     */
197    public String getAsShortText(ReadablePartial partial, int fieldValue, Locale locale) {
198        throw unsupported();
199    }
200
201    /**
202     * Always throws UnsupportedOperationException
203     *
204     * @throws UnsupportedOperationException
205     */
206    public String getAsShortText(ReadablePartial partial, Locale locale) {
207        throw unsupported();
208    }
209
210    /**
211     * Always throws UnsupportedOperationException
212     *
213     * @throws UnsupportedOperationException
214     */
215    public String getAsShortText(int fieldValue, Locale locale) {
216        throw unsupported();
217    }
218
219    /**
220     * Delegates to the duration field.
221     *
222     * @throws UnsupportedOperationException if the duration is unsupported
223     */
224    public long add(long instant, int value) {
225        return getDurationField().add(instant, value);
226    }
227
228    /**
229     * Delegates to the duration field.
230     *
231     * @throws UnsupportedOperationException if the duration is unsupported
232     */
233    public long add(long instant, long value) {
234        return getDurationField().add(instant, value);
235    }
236
237    /**
238     * Always throws UnsupportedOperationException
239     *
240     * @throws UnsupportedOperationException
241     */
242    public int[] add(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd) {
243        throw unsupported();
244    }
245
246    /**
247     * Always throws UnsupportedOperationException
248     *
249     * @throws UnsupportedOperationException
250     */
251    public int[] addWrapPartial(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd) {
252        throw unsupported();
253    }
254
255    /**
256     * Always throws UnsupportedOperationException
257     *
258     * @throws UnsupportedOperationException
259     */
260    public long addWrapField(long instant, int value) {
261        throw unsupported();
262    }
263
264    /**
265     * Always throws UnsupportedOperationException
266     *
267     * @throws UnsupportedOperationException
268     */
269    public int[] addWrapField(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd) {
270        throw unsupported();
271    }
272
273    /**
274     * Delegates to the duration field.
275     *
276     * @throws UnsupportedOperationException if the duration is unsupported
277     */
278    public int getDifference(long minuendInstant, long subtrahendInstant) {
279        return getDurationField().getDifference(minuendInstant, subtrahendInstant);
280    }
281
282    /**
283     * Delegates to the duration field.
284     *
285     * @throws UnsupportedOperationException if the duration is unsupported
286     */
287    public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
288        return getDurationField().getDifferenceAsLong(minuendInstant, subtrahendInstant);
289    }
290
291    /**
292     * Always throws UnsupportedOperationException
293     *
294     * @throws UnsupportedOperationException
295     */
296    public long set(long instant, int value) {
297        throw unsupported();
298    }
299
300    /**
301     * Always throws UnsupportedOperationException
302     *
303     * @throws UnsupportedOperationException
304     */
305    public int[] set(ReadablePartial instant, int fieldIndex, int[] values, int newValue) {
306        throw unsupported();
307    }
308
309    /**
310     * Always throws UnsupportedOperationException
311     *
312     * @throws UnsupportedOperationException
313     */
314    public long set(long instant, String text, Locale locale) {
315        throw unsupported();
316    }
317
318    /**
319     * Always throws UnsupportedOperationException
320     *
321     * @throws UnsupportedOperationException
322     */
323    public long set(long instant, String text) {
324        throw unsupported();
325    }
326
327    /**
328     * Always throws UnsupportedOperationException
329     *
330     * @throws UnsupportedOperationException
331     */
332    public int[] set(ReadablePartial instant, int fieldIndex, int[] values, String text, Locale locale) {
333        throw unsupported();
334    }
335
336    /**
337     * Even though this DateTimeField is unsupported, the duration field might
338     * be supported.
339     *
340     * @return a possibly supported DurationField
341     */
342    public DurationField getDurationField() {
343        return iDurationField;
344    }
345
346    /**
347     * Always returns null.
348     *
349     * @return null always
350     */
351    public DurationField getRangeDurationField() {
352        return null;
353    }
354
355    /**
356     * Always throws UnsupportedOperationException
357     *
358     * @throws UnsupportedOperationException
359     */
360    public boolean isLeap(long instant) {
361        throw unsupported();
362    }
363
364    /**
365     * Always throws UnsupportedOperationException
366     *
367     * @throws UnsupportedOperationException
368     */
369    public int getLeapAmount(long instant) {
370        throw unsupported();
371    }
372
373    /**
374     * Always returns null.
375     *
376     * @return null always
377     */
378    public DurationField getLeapDurationField() {
379        return null;
380    }
381
382    /**
383     * Always throws UnsupportedOperationException
384     *
385     * @throws UnsupportedOperationException
386     */
387    public int getMinimumValue() {
388        throw unsupported();
389    }
390
391    /**
392     * Always throws UnsupportedOperationException
393     *
394     * @throws UnsupportedOperationException
395     */
396    public int getMinimumValue(long instant) {
397        throw unsupported();
398    }
399
400    /**
401     * Always throws UnsupportedOperationException
402     *
403     * @throws UnsupportedOperationException
404     */
405    public int getMinimumValue(ReadablePartial instant) {
406        throw unsupported();
407    }
408
409    /**
410     * Always throws UnsupportedOperationException
411     *
412     * @throws UnsupportedOperationException
413     */
414    public int getMinimumValue(ReadablePartial instant, int[] values) {
415        throw unsupported();
416    }
417
418    /**
419     * Always throws UnsupportedOperationException
420     *
421     * @throws UnsupportedOperationException
422     */
423    public int getMaximumValue() {
424        throw unsupported();
425    }
426
427    /**
428     * Always throws UnsupportedOperationException
429     *
430     * @throws UnsupportedOperationException
431     */
432    public int getMaximumValue(long instant) {
433        throw unsupported();
434    }
435
436    /**
437     * Always throws UnsupportedOperationException
438     *
439     * @throws UnsupportedOperationException
440     */
441    public int getMaximumValue(ReadablePartial instant) {
442        throw unsupported();
443    }
444
445    /**
446     * Always throws UnsupportedOperationException
447     *
448     * @throws UnsupportedOperationException
449     */
450    public int getMaximumValue(ReadablePartial instant, int[] values) {
451        throw unsupported();
452    }
453
454    /**
455     * Always throws UnsupportedOperationException
456     *
457     * @throws UnsupportedOperationException
458     */
459    public int getMaximumTextLength(Locale locale) {
460        throw unsupported();
461    }
462
463    /**
464     * Always throws UnsupportedOperationException
465     *
466     * @throws UnsupportedOperationException
467     */
468    public int getMaximumShortTextLength(Locale locale) {
469        throw unsupported();
470    }
471
472    /**
473     * Always throws UnsupportedOperationException
474     *
475     * @throws UnsupportedOperationException
476     */
477    public long roundFloor(long instant) {
478        throw unsupported();
479    }
480
481    /**
482     * Always throws UnsupportedOperationException
483     *
484     * @throws UnsupportedOperationException
485     */
486    public long roundCeiling(long instant) {
487        throw unsupported();
488    }
489
490    /**
491     * Always throws UnsupportedOperationException
492     *
493     * @throws UnsupportedOperationException
494     */
495    public long roundHalfFloor(long instant) {
496        throw unsupported();
497    }
498
499    /**
500     * Always throws UnsupportedOperationException
501     *
502     * @throws UnsupportedOperationException
503     */
504    public long roundHalfCeiling(long instant) {
505        throw unsupported();
506    }
507
508    /**
509     * Always throws UnsupportedOperationException
510     *
511     * @throws UnsupportedOperationException
512     */
513    public long roundHalfEven(long instant) {
514        throw unsupported();
515    }
516
517    /**
518     * Always throws UnsupportedOperationException
519     *
520     * @throws UnsupportedOperationException
521     */
522    public long remainder(long instant) {
523        throw unsupported();
524    }
525
526    //------------------------------------------------------------------------
527    /**
528     * Get a suitable debug string.
529     * 
530     * @return debug string
531     */
532    public String toString() {
533        return "UnsupportedDateTimeField";
534    }
535
536    /**
537     * Ensure proper singleton serialization
538     */
539    private Object readResolve() {
540        return getInstance(iType, iDurationField);
541    }
542
543    private UnsupportedOperationException unsupported() {
544        return new UnsupportedOperationException(iType + " field is unsupported");
545    }
546
547}