EMMA Coverage Report (generated Tue Oct 28 00:01:11 GMT 2008)
[all classes][org.joda.time.base]

COVERAGE SUMMARY FOR SOURCE FILE [BaseSingleFieldPeriod.java]

nameclass, %method, %block, %line, %
BaseSingleFieldPeriod.java100% (1/1)100% (16/16)100% (307/307)100% (69/69)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BaseSingleFieldPeriod100% (1/1)100% (16/16)100% (307/307)100% (69/69)
BaseSingleFieldPeriod (int): void 100% (1/1)100% (6/6)100% (3/3)
between (ReadableInstant, ReadableInstant, DurationFieldType): int 100% (1/1)100% (23/23)100% (5/5)
between (ReadablePartial, ReadablePartial, ReadablePeriod): int 100% (1/1)100% (70/70)100% (12/12)
compareTo (Object): int 100% (1/1)100% (40/40)100% (9/9)
equals (Object): boolean 100% (1/1)100% (28/28)100% (6/6)
get (DurationFieldType): int 100% (1/1)100% (9/9)100% (3/3)
getFieldType (int): DurationFieldType 100% (1/1)100% (11/11)100% (3/3)
getValue (): int 100% (1/1)100% (3/3)100% (1/1)
getValue (int): int 100% (1/1)100% (11/11)100% (3/3)
hashCode (): int 100% (1/1)100% (19/19)100% (4/4)
isSupported (DurationFieldType): boolean 100% (1/1)100% (8/8)100% (1/1)
setValue (int): void 100% (1/1)100% (4/4)100% (2/2)
size (): int 100% (1/1)100% (2/2)100% (1/1)
standardPeriodIn (ReadablePeriod, long): int 100% (1/1)100% (60/60)100% (12/12)
toMutablePeriod (): MutablePeriod 100% (1/1)100% (9/9)100% (3/3)
toPeriod (): Period 100% (1/1)100% (4/4)100% (1/1)

1/*
2 *  Copyright 2001-2006 Stephen Colebourne
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16package org.joda.time.base;
17 
18import java.io.Serializable;
19 
20import org.joda.time.Chronology;
21import org.joda.time.DateTimeUtils;
22import org.joda.time.DurationField;
23import org.joda.time.DurationFieldType;
24import org.joda.time.MutablePeriod;
25import org.joda.time.Period;
26import org.joda.time.PeriodType;
27import org.joda.time.ReadableInstant;
28import org.joda.time.ReadablePartial;
29import org.joda.time.ReadablePeriod;
30import org.joda.time.chrono.ISOChronology;
31import org.joda.time.field.FieldUtils;
32 
33/**
34 * BaseSingleFieldPeriod is an abstract implementation of ReadablePeriod that
35 * manages a single duration field, such as days or minutes.
36 * <p>
37 * This class should generally not be used directly by API users.
38 * The {@link ReadablePeriod} interface should be used when different 
39 * kinds of period objects are to be referenced.
40 * <p>
41 * BaseSingleFieldPeriod subclasses may be mutable and not thread-safe.
42 *
43 * @author Stephen Colebourne
44 * @since 1.4
45 */
46public abstract class BaseSingleFieldPeriod
47        implements ReadablePeriod, Comparable, Serializable {
48 
49    /** Serialization version. */
50    private static final long serialVersionUID = 9386874258972L;
51 
52    /** The period in the units of this period. */
53    private int iPeriod;
54 
55    //-----------------------------------------------------------------------
56    /**
57     * Calculates the number of whole units between the two specified datetimes.
58     *
59     * @param start  the start instant, validated to not be null
60     * @param end  the end instant, validated to not be null
61     * @param field  the field type to use, must not be null
62     * @return the period
63     * @throws IllegalArgumentException if the instants are null or invalid
64     */
65    protected static int between(ReadableInstant start, ReadableInstant end, DurationFieldType field) {
66        if (start == null || end == null) {
67            throw new IllegalArgumentException("ReadableInstant objects must not be null");
68        }
69        Chronology chrono = DateTimeUtils.getInstantChronology(start);
70        int amount = field.getField(chrono).getDifference(end.getMillis(), start.getMillis());
71        return amount;
72    }
73 
74    //-----------------------------------------------------------------------
75    /**
76     * Calculates the number of whole units between the two specified partial datetimes.
77     * <p>
78     * The two partials must contain the same fields, for example you can specify
79     * two <code>LocalDate</code> objects.
80     *
81     * @param start  the start partial date, validated to not be null
82     * @param end  the end partial date, validated to not be null
83     * @param zeroInstance  the zero instance constant, must not be null
84     * @return the period
85     * @throws IllegalArgumentException if the partials are null or invalid
86     */
87    protected static int between(ReadablePartial start, ReadablePartial end, ReadablePeriod zeroInstance) {
88        if (start == null || end == null) {
89            throw new IllegalArgumentException("ReadablePartial objects must not be null");
90        }
91        if (start.size() != end.size()) {
92            throw new IllegalArgumentException("ReadablePartial objects must have the same set of fields");
93        }
94        for (int i = 0, isize = start.size(); i < isize; i++) {
95            if (start.getFieldType(i) != end.getFieldType(i)) {
96                throw new IllegalArgumentException("ReadablePartial objects must have the same set of fields");
97            }
98        }
99        if (DateTimeUtils.isContiguous(start) == false) {
100            throw new IllegalArgumentException("ReadablePartial objects must be contiguous");
101        }
102        Chronology chrono = DateTimeUtils.getChronology(start.getChronology()).withUTC();
103        int[] values = chrono.get(zeroInstance, chrono.set(start, 0L), chrono.set(end, 0L));
104        return values[0];
105    }
106 
107    /**
108     * Creates a new instance representing the number of complete standard length units
109     * in the specified period.
110     * <p>
111     * This factory method converts all fields from the period to hours using standardised
112     * durations for each field. Only those fields which have a precise duration in
113     * the ISO UTC chronology can be converted.
114     * <ul>
115     * <li>One week consists of 7 days.
116     * <li>One day consists of 24 hours.
117     * <li>One hour consists of 60 minutes.
118     * <li>One minute consists of 60 seconds.
119     * <li>One second consists of 1000 milliseconds.
120     * </ul>
121     * Months and Years are imprecise and periods containing these values cannot be converted.
122     *
123     * @param period  the period to get the number of hours from, must not be null
124     * @param millisPerUnit  the number of milliseconds in one standard unit of this period
125     * @throws IllegalArgumentException if the period contains imprecise duration values
126     */
127    protected static int standardPeriodIn(ReadablePeriod period, long millisPerUnit) {
128        if (period == null) {
129            return 0;
130        }
131        Chronology iso = ISOChronology.getInstanceUTC();
132        long duration = 0L;
133        for (int i = 0; i < period.size(); i++) {
134            int value = period.getValue(i);
135            if (value != 0) {
136                DurationField field = period.getFieldType(i).getField(iso);
137                if (field.isPrecise() == false) {
138                    throw new IllegalArgumentException(
139                            "Cannot convert period to duration as " + field.getName() +
140                            " is not precise in the period " + period);
141                }
142                duration = FieldUtils.safeAdd(duration, FieldUtils.safeMultiply(field.getUnitMillis(), value));
143            }
144        }
145        return FieldUtils.safeToInt(duration / millisPerUnit);
146    }
147 
148    //-----------------------------------------------------------------------
149    /**
150     * Creates a new instance representing the specified period.
151     *
152     * @param period  the period to represent
153     */
154    protected BaseSingleFieldPeriod(int period) {
155        super();
156        iPeriod = period;
157    }
158 
159    //-----------------------------------------------------------------------
160    /**
161     * Gets the amount of this period.
162     *
163     * @return the period value
164     */
165    protected int getValue() {
166        return iPeriod;
167    }
168 
169    /**
170     * Sets the amount of this period.
171     * To make a subclass immutable you must declare it final, or block this method.
172     *
173     * @param value  the period value
174     */
175    protected void setValue(int value) {
176        iPeriod = value;
177    }
178 
179    //-----------------------------------------------------------------------
180    /**
181     * Gets the single duration field type.
182     *
183     * @return the duration field type, not null
184     */
185    public abstract DurationFieldType getFieldType();
186 
187    /**
188     * Gets the period type which matches the duration field type.
189     *
190     * @return the period type, not null
191     */
192    public abstract PeriodType getPeriodType();
193 
194    //-----------------------------------------------------------------------
195    /**
196     * Gets the number of fields that this period supports, which is one.
197     *
198     * @return the number of fields supported, which is one
199     */
200    public int size() {
201        return 1;
202    }
203 
204    /**
205     * Gets the field type at the specified index.
206     * <p>
207     * The only index supported by this period is zero which returns the
208     * field type of this class.
209     *
210     * @param index  the index to retrieve, which must be zero
211     * @return the field at the specified index
212     * @throws IndexOutOfBoundsException if the index is invalid
213     */
214    public DurationFieldType getFieldType(int index) {
215        if (index != 0) {
216            throw new IndexOutOfBoundsException(String.valueOf(index));
217        }
218        return getFieldType();
219    }
220 
221    /**
222     * Gets the value at the specified index.
223     * <p>
224     * The only index supported by this period is zero.
225     *
226     * @param index  the index to retrieve, which must be zero
227     * @return the value of the field at the specified index
228     * @throws IndexOutOfBoundsException if the index is invalid
229     */
230    public int getValue(int index) {
231        if (index != 0) {
232            throw new IndexOutOfBoundsException(String.valueOf(index));
233        }
234        return getValue();
235    }
236 
237    /**
238     * Gets the value of a duration field represented by this period.
239     * <p>
240     * If the field type specified does not match the type used by this class
241     * then zero is returned.
242     *
243     * @param type  the field type to query, null returns zero
244     * @return the value of that field, zero if field not supported
245     */
246    public int get(DurationFieldType type) {
247        if (type == getFieldType()) {
248            return getValue();
249        }
250        return 0;
251    }
252 
253    /**
254     * Checks whether the duration field specified is supported by this period.
255     *
256     * @param type  the type to check, may be null which returns false
257     * @return true if the field is supported
258     */
259    public boolean isSupported(DurationFieldType type) {
260        return (type == getFieldType());
261    }
262 
263    //-----------------------------------------------------------------------
264    /**
265     * Get this period as an immutable <code>Period</code> object.
266     * The period will use <code>PeriodType.standard()</code>.
267     *
268     * @return a <code>Period</code> representing the same number of days
269     */
270    public Period toPeriod() {
271        return Period.ZERO.withFields(this);
272    }
273 
274    /**
275     * Get this object as a <code>MutablePeriod</code>.
276     * <p>
277     * This will always return a new <code>MutablePeriod</code> with the same fields.
278     * The period will use <code>PeriodType.standard()</code>.
279     * 
280     * @return a MutablePeriod using the same field set and values
281     */
282    public MutablePeriod toMutablePeriod() {
283        MutablePeriod period = new MutablePeriod();
284        period.add(this);
285        return period;
286    }
287 
288    //-----------------------------------------------------------------------
289    /**
290     * Compares this object with the specified object for equality based on the
291     * value of each field. All ReadablePeriod instances are accepted, but only
292     * those with a matching <code>PeriodType</code> can return true.
293     *
294     * @param period  a readable period to check against
295     * @return true if all the field values are equal, false if
296     *  not or the period is null or of an incorrect type
297     */
298    public boolean equals(Object period) {
299        if (this == period) {
300            return true;
301        }
302        if (period instanceof ReadablePeriod == false) {
303            return false;
304        }
305        ReadablePeriod other = (ReadablePeriod) period;
306        return (other.getPeriodType() == getPeriodType() && other.getValue(0) == getValue());
307    }
308 
309    /**
310     * Gets a hash code for the period as defined by ReadablePeriod.
311     *
312     * @return a hash code
313     */
314    public int hashCode() {
315        int total = 17;
316        total = 27 * total + getValue();
317        total = 27 * total + getFieldType().hashCode();
318        return total;
319    }
320 
321    /**
322     * Compares this period to another object of the same class.
323     *
324     * @param other  the other period, must not be null
325     * @return zero if equal, positive if greater, negative if less
326     * @throws NullPointerException if the other period is null
327     * @throws ClassCastException if the other period is of a different type
328     */
329    public int compareTo(Object other) {
330        if (other.getClass() != getClass()) {
331            throw new ClassCastException(getClass() + " cannot be compared to " + other.getClass());
332        }
333        int otherValue = ((BaseSingleFieldPeriod) other).getValue();
334        int thisValue = getValue();
335        if (thisValue > otherValue) {
336            return 1;
337        }
338        if (thisValue < otherValue) {
339            return -1;
340        }
341        return 0;
342    }
343 
344}

[all classes][org.joda.time.base]
EMMA 2.0.5312 (C) Vladimir Roubtsov