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     */
016    package org.joda.time.field;
017    
018    import java.io.Serializable;
019    import java.util.HashMap;
020    import java.util.Locale;
021    import org.joda.time.DateTimeField;
022    import org.joda.time.DateTimeFieldType;
023    import org.joda.time.DurationField;
024    import 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     */
034    public 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    }