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.DurationField;
019    import org.joda.time.DurationFieldType;
020    
021    /**
022     * Scales a DurationField such that it's unit millis becomes larger in
023     * magnitude.
024     * <p>
025     * ScaledDurationField is thread-safe and immutable.
026     *
027     * @see PreciseDurationField
028     *
029     * @author Brian S O'Neill
030     * @since 1.0
031     */
032    public class ScaledDurationField extends DecoratedDurationField {
033    
034        private static final long serialVersionUID = -3205227092378684157L;
035    
036        private final int iScalar;
037    
038        /**
039         * Constructor
040         * 
041         * @param field  the field to wrap, like "year()".
042         * @param type  the type this field will actually use
043         * @param scalar  scalar, such as 100 years in a century
044         * @throws IllegalArgumentException if scalar is zero or one.
045         */
046        public ScaledDurationField(DurationField field, DurationFieldType type, int scalar) {
047            super(field, type);
048            if (scalar == 0 || scalar == 1) {
049                throw new IllegalArgumentException("The scalar must not be 0 or 1");
050            }
051            iScalar = scalar;
052        }
053    
054        public int getValue(long duration) {
055            return getWrappedField().getValue(duration) / iScalar;
056        }
057    
058        public long getValueAsLong(long duration) {
059            return getWrappedField().getValueAsLong(duration) / iScalar;
060        }
061    
062        public int getValue(long duration, long instant) {
063            return getWrappedField().getValue(duration, instant) / iScalar;
064        }
065    
066        public long getValueAsLong(long duration, long instant) {
067            return getWrappedField().getValueAsLong(duration, instant) / iScalar;
068        }
069    
070        public long getMillis(int value) {
071            long scaled = ((long) value) * ((long) iScalar);
072            return getWrappedField().getMillis(scaled);
073        }
074    
075        public long getMillis(long value) {
076            long scaled = FieldUtils.safeMultiply(value, iScalar);
077            return getWrappedField().getMillis(scaled);
078        }
079    
080        public long getMillis(int value, long instant) {
081            long scaled = ((long) value) * ((long) iScalar);
082            return getWrappedField().getMillis(scaled, instant);
083        }
084    
085        public long getMillis(long value, long instant) {
086            long scaled = FieldUtils.safeMultiply(value, iScalar);
087            return getWrappedField().getMillis(scaled, instant);
088        }
089    
090        public long add(long instant, int value) {
091            long scaled = ((long) value) * ((long) iScalar);
092            return getWrappedField().add(instant, scaled);
093        }
094    
095        public long add(long instant, long value) {
096            long scaled = FieldUtils.safeMultiply(value, iScalar);
097            return getWrappedField().add(instant, scaled);
098        }
099    
100        public int getDifference(long minuendInstant, long subtrahendInstant) {
101            return getWrappedField().getDifference(minuendInstant, subtrahendInstant) / iScalar;
102        }
103    
104        public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
105            return getWrappedField().getDifferenceAsLong(minuendInstant, subtrahendInstant) / iScalar;
106        }
107    
108        public long getUnitMillis() {
109            return getWrappedField().getUnitMillis() * iScalar;
110        }
111    
112        //-----------------------------------------------------------------------
113        /**
114         * Returns the scalar applied, in the field's units.
115         * 
116         * @return the scalar
117         */
118        public int getScalar() {
119            return iScalar;
120        }
121    
122        /**
123         * Compares this duration field to another.
124         * Two fields are equal if of the same type and duration.
125         * 
126         * @param obj  the object to compare to
127         * @return if equal
128         */
129        public boolean equals(Object obj) {
130            if (this == obj) {
131                return true;
132            } else if (obj instanceof ScaledDurationField) {
133                ScaledDurationField other = (ScaledDurationField) obj;
134                return (getWrappedField().equals(other.getWrappedField())) &&
135                       (getType() == other.getType()) &&
136                       (iScalar == other.iScalar);
137            }
138            return false;
139        }
140    
141        /**
142         * Gets a hash code for this instance.
143         * 
144         * @return a suitable hashcode
145         */
146        public int hashCode() {
147            long scalar = iScalar;
148            int hash = (int) (scalar ^ (scalar >>> 32));
149            hash += getType().hashCode();
150            hash += getWrappedField().hashCode();
151            return hash;
152        }
153    
154    }