001    /*
002     *  Copyright 2001-2005 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 org.joda.time.DateTimeField;
019    import org.joda.time.DateTimeFieldType;
020    import org.joda.time.DurationField;
021    import org.joda.time.ReadablePartial;
022    
023    /**
024     * Wraps another field such that zero values are replaced with one more than
025     * it's maximum. This is particularly useful for implementing an clockhourOfDay
026     * field, where the midnight value of 0 is replaced with 24.
027     * <p>
028     * ZeroIsMaxDateTimeField is thread-safe and immutable.
029     *
030     * @author Brian S O'Neill
031     * @since 1.0
032     */
033    public final class ZeroIsMaxDateTimeField extends DecoratedDateTimeField {
034    
035        private static final long serialVersionUID = 961749798233026866L;
036    
037        /**
038         * Constructor.
039         * 
040         * @param field  the base field
041         * @param type  the field type this field will actually use
042         * @throws IllegalArgumentException if wrapped field's minimum value is not zero
043         */
044        public ZeroIsMaxDateTimeField(DateTimeField field, DateTimeFieldType type) {
045            super(field, type);
046            if (field.getMinimumValue() != 0) {
047                throw new IllegalArgumentException("Wrapped field's minumum value must be zero");
048            }
049        }
050    
051        public int get(long instant) {
052            int value = getWrappedField().get(instant);
053            if (value == 0) {
054                value = getMaximumValue();
055            }
056            return value;
057        }
058    
059        public long add(long instant, int value) {
060            return getWrappedField().add(instant, value);
061        }
062    
063        public long add(long instant, long value) {
064            return getWrappedField().add(instant, value);
065        }
066    
067        public long addWrapField(long instant, int value) {
068            return getWrappedField().addWrapField(instant, value);
069        }
070    
071        public int[] addWrapField(ReadablePartial instant, int fieldIndex, int[] values, int valueToAdd) {
072            return getWrappedField().addWrapField(instant, fieldIndex, values, valueToAdd);
073        }
074    
075        public int getDifference(long minuendInstant, long subtrahendInstant) {
076            return getWrappedField().getDifference(minuendInstant, subtrahendInstant);
077        }
078    
079        public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
080            return getWrappedField().getDifferenceAsLong(minuendInstant, subtrahendInstant);
081        }
082    
083        public long set(long instant, int value) {
084            int max = getMaximumValue();
085            FieldUtils.verifyValueBounds(this, value, 1, max);
086            if (value == max) {
087                value = 0;
088            }
089            return getWrappedField().set(instant, value);
090        }
091    
092        public boolean isLeap(long instant) {
093            return getWrappedField().isLeap(instant);
094        }
095    
096        public int getLeapAmount(long instant) {
097            return getWrappedField().getLeapAmount(instant);
098        }
099    
100        public DurationField getLeapDurationField() {
101            return getWrappedField().getLeapDurationField();
102        }
103    
104        /**
105         * Always returns 1.
106         * 
107         * @return the minimum value of 1
108         */
109        public int getMinimumValue() {
110            return 1;
111        }
112    
113        /**
114         * Always returns 1.
115         * 
116         * @return the minimum value of 1
117         */
118        public int getMinimumValue(long instant) {
119            return 1;
120        }
121    
122        /**
123         * Always returns 1.
124         * 
125         * @return the minimum value of 1
126         */
127        public int getMinimumValue(ReadablePartial instant) {
128            return 1;
129        }
130    
131        /**
132         * Always returns 1.
133         * 
134         * @return the minimum value of 1
135         */
136        public int getMinimumValue(ReadablePartial instant, int[] values) {
137            return 1;
138        }
139    
140        /**
141         * Get the maximum value for the field, which is one more than the wrapped
142         * field's maximum value.
143         * 
144         * @return the maximum value
145         */
146        public int getMaximumValue() {
147            return getWrappedField().getMaximumValue() + 1;
148        }
149    
150        /**
151         * Get the maximum value for the field, which is one more than the wrapped
152         * field's maximum value.
153         * 
154         * @return the maximum value
155         */
156        public int getMaximumValue(long instant) {
157            return getWrappedField().getMaximumValue(instant) + 1;
158        }
159    
160        /**
161         * Get the maximum value for the field, which is one more than the wrapped
162         * field's maximum value.
163         * 
164         * @return the maximum value
165         */
166        public int getMaximumValue(ReadablePartial instant) {
167            return getWrappedField().getMaximumValue(instant) + 1;
168        }
169    
170        /**
171         * Get the maximum value for the field, which is one more than the wrapped
172         * field's maximum value.
173         * 
174         * @return the maximum value
175         */
176        public int getMaximumValue(ReadablePartial instant, int[] values) {
177            return getWrappedField().getMaximumValue(instant, values) + 1;
178        }
179    
180        public long roundFloor(long instant) {
181            return getWrappedField().roundFloor(instant);
182        }
183    
184        public long roundCeiling(long instant) {
185            return getWrappedField().roundCeiling(instant);
186        }
187    
188        public long roundHalfFloor(long instant) {
189            return getWrappedField().roundHalfFloor(instant);
190        }
191    
192        public long roundHalfCeiling(long instant) {
193            return getWrappedField().roundHalfCeiling(instant);
194        }
195    
196        public long roundHalfEven(long instant) {
197            return getWrappedField().roundHalfEven(instant);
198        }
199    
200        public long remainder(long instant) {
201            return getWrappedField().remainder(instant);
202        }
203    
204    }