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.Chronology;
019    import org.joda.time.DateTimeField;
020    
021    /**
022     * Wraps another field such that a certain value is added back into
023     * the sequence of numbers.
024     * <p>
025     * This reverses the effect of SkipDateTimeField. This isn't very
026     * elegant.
027     * <p>
028     * SkipUndoDateTimeField is thread-safe and immutable.
029     *
030     * @author Brian S O'Neill
031     * @author Stephen Colebourne
032     * @since 1.0
033     */
034    public final class SkipUndoDateTimeField extends DelegatedDateTimeField {
035    
036        /** Serialization version. */
037        private static final long serialVersionUID = -5875876968979L;
038    
039        /** The chronology to wrap. */
040        private final Chronology iChronology;
041        /** The value to skip. */
042        private final int iSkip;
043        /** The calculated minimum value. */
044        private transient int iMinValue;
045    
046        /**
047         * Constructor that reinserts zero.
048         * 
049         * @param chronology  the chronoogy to use
050         * @param field  the field to skip zero on
051         */
052        public SkipUndoDateTimeField(Chronology chronology, DateTimeField field) {
053            this(chronology, field, 0);
054        }
055    
056        /**
057         * Constructor.
058         * 
059         * @param chronology  the chronoogy to use
060         * @param field  the field to skip zero on
061         * @param skip  the value to skip
062         */
063        public SkipUndoDateTimeField(Chronology chronology, DateTimeField field, int skip) {
064            super(field);
065            iChronology = chronology;
066            int min = super.getMinimumValue();
067            if (min < skip) {
068                iMinValue = min + 1;
069            } else if (min == skip + 1) {
070                iMinValue = skip;
071            } else {
072                iMinValue = min;
073            }
074            iSkip = skip;
075        }
076    
077        //-----------------------------------------------------------------------
078        public int get(long millis) {
079            int value = super.get(millis);
080            if (value < iSkip) {
081                value++;
082            }
083            return value;
084        }
085    
086        public long set(long millis, int value) {
087            FieldUtils.verifyValueBounds(this, value, iMinValue, getMaximumValue());
088            if (value <= iSkip) {
089                value--;
090            }
091            return super.set(millis, value);
092        }
093    
094        public int getMinimumValue() {
095            return iMinValue;
096        }
097    
098        private Object readResolve() {
099            return getType().getField(iChronology);
100        }
101    
102    }