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 */
016package org.joda.time.field;
017
018import org.joda.time.DurationField;
019import 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 */
032public 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}