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

COVERAGE SUMMARY FOR SOURCE FILE [PeriodType.java]

nameclass, %method, %block, %line, %
PeriodType.java100% (1/1)100% (40/40)100% (1642/1642)100% (215/215)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class PeriodType100% (1/1)100% (40/40)100% (1642/1642)100% (215/215)
<static initializer> 100% (1/1)100% (22/22)100% (9/9)
PeriodType (String, DurationFieldType [], int []): void 100% (1/1)100% (12/12)100% (5/5)
addIndexedField (ReadablePeriod, int, int [], int): boolean 100% (1/1)100% (27/27)100% (7/7)
dayTime (): PeriodType 100% (1/1)100% (69/69)100% (5/5)
days (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
equals (Object): boolean 100% (1/1)100% (19/19)100% (6/6)
forFields (DurationFieldType []): PeriodType 100% (1/1)100% (261/261)100% (58/58)
getFieldType (int): DurationFieldType 100% (1/1)100% (5/5)100% (1/1)
getIndexedField (ReadablePeriod, int): int 100% (1/1)100% (14/14)100% (2/2)
getName (): String 100% (1/1)100% (3/3)100% (1/1)
hashCode (): int 100% (1/1)100% (21/21)100% (4/4)
hours (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
indexOf (DurationFieldType): int 100% (1/1)100% (20/20)100% (4/4)
isSupported (DurationFieldType): boolean 100% (1/1)100% (8/8)100% (1/1)
millis (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
minutes (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
months (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
seconds (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
setIndexedField (ReadablePeriod, int, int [], int): boolean 100% (1/1)100% (19/19)100% (5/5)
size (): int 100% (1/1)100% (4/4)100% (1/1)
standard (): PeriodType 100% (1/1)100% (81/81)100% (5/5)
time (): PeriodType 100% (1/1)100% (65/65)100% (5/5)
toString (): String 100% (1/1)100% (12/12)100% (1/1)
weeks (): PeriodType 100% (1/1)100% (53/53)100% (5/5)
withDaysRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withFieldRemoved (int, String): PeriodType 100% (1/1)100% (110/110)100% (17/17)
withHoursRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withMillisRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withMinutesRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withMonthsRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withSecondsRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withWeeksRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
withYearsRemoved (): PeriodType 100% (1/1)100% (5/5)100% (1/1)
yearDay (): PeriodType 100% (1/1)100% (57/57)100% (5/5)
yearDayTime (): PeriodType 100% (1/1)100% (73/73)100% (5/5)
yearMonthDay (): PeriodType 100% (1/1)100% (61/61)100% (5/5)
yearMonthDayTime (): PeriodType 100% (1/1)100% (77/77)100% (5/5)
yearWeekDay (): PeriodType 100% (1/1)100% (61/61)100% (5/5)
yearWeekDayTime (): PeriodType 100% (1/1)100% (77/77)100% (5/5)
years (): PeriodType 100% (1/1)100% (53/53)100% (5/5)

1/*
2 *  Copyright 2001-2005 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;
17 
18import java.io.Serializable;
19import java.util.ArrayList;
20import java.util.Arrays;
21import java.util.HashMap;
22import java.util.List;
23import java.util.Map;
24 
25import org.joda.time.field.FieldUtils;
26 
27/**
28 * Controls a period implementation by specifying which duration fields are to be used.
29 * <p>
30 * The following implementations are provided:
31 * <ul>
32 * <li>Standard - years, months, weeks, days, hours, minutes, seconds, millis
33 * <li>YearMonthDayTime - years, months, days, hours, minutes, seconds, millis
34 * <li>YearMonthDay - years, months, days
35 * <li>YearWeekDayTime - years, weeks, days, hours, minutes, seconds, millis
36 * <li>YearWeekDay - years, weeks, days
37 * <li>YearDayTime - years, days, hours, minutes, seconds, millis
38 * <li>YearDay - years, days, hours
39 * <li>DayTime - days, hours, minutes, seconds, millis
40 * <li>Time - hours, minutes, seconds, millis
41 * <li>plus one for each single type
42 * </ul>
43 *
44 * <p>
45 * PeriodType is thread-safe and immutable, and all subclasses must be as well.
46 *
47 * @author Brian S O'Neill
48 * @author Stephen Colebourne
49 * @since 1.0
50 */
51public class PeriodType implements Serializable {
52    /** Serialization version */
53    private static final long serialVersionUID = 2274324892792009998L;
54 
55    /** Cache of all the known types. */
56    private static final Map cTypes = new HashMap(32);
57 
58    static int YEAR_INDEX = 0;
59    static int MONTH_INDEX = 1;
60    static int WEEK_INDEX = 2;
61    static int DAY_INDEX = 3;
62    static int HOUR_INDEX = 4;
63    static int MINUTE_INDEX = 5;
64    static int SECOND_INDEX = 6;
65    static int MILLI_INDEX = 7;
66    
67    private static PeriodType cStandard;
68    private static PeriodType cYMDTime;
69    private static PeriodType cYMD;
70    private static PeriodType cYWDTime;
71    private static PeriodType cYWD;
72    private static PeriodType cYDTime;
73    private static PeriodType cYD;
74    private static PeriodType cDTime;
75    private static PeriodType cTime;
76    
77    private static PeriodType cYears;
78    private static PeriodType cMonths;
79    private static PeriodType cWeeks;
80    private static PeriodType cDays;
81    private static PeriodType cHours;
82    private static PeriodType cMinutes;
83    private static PeriodType cSeconds;
84    private static PeriodType cMillis;
85 
86    /**
87     * Gets a type that defines all standard fields.
88     * <ul>
89     * <li>years
90     * <li>months
91     * <li>weeks
92     * <li>days
93     * <li>hours
94     * <li>minutes
95     * <li>seconds
96     * <li>milliseconds
97     * </ul>
98     *
99     * @return the period type
100     */
101    public static PeriodType standard() {
102        PeriodType type = cStandard;
103        if (type == null) {
104            type = new PeriodType(
105                "Standard",
106                new DurationFieldType[] {
107                    DurationFieldType.years(), DurationFieldType.months(),
108                    DurationFieldType.weeks(), DurationFieldType.days(),
109                    DurationFieldType.hours(), DurationFieldType.minutes(),
110                    DurationFieldType.seconds(), DurationFieldType.millis(),
111                },
112                new int[] { 0, 1, 2, 3, 4, 5, 6, 7, }
113            );
114            cStandard = type;
115        }
116        return type;
117    }
118 
119    /**
120     * Gets a type that defines all standard fields except weeks.
121     * <ul>
122     * <li>years
123     * <li>months
124     * <li>days
125     * <li>hours
126     * <li>minutes
127     * <li>seconds
128     * <li>milliseconds
129     * </ul>
130     *
131     * @return the period type
132     */
133    public static PeriodType yearMonthDayTime() {
134        PeriodType type = cYMDTime;
135        if (type == null) {
136            type = new PeriodType(
137                "YearMonthDayTime",
138                new DurationFieldType[] {
139                    DurationFieldType.years(), DurationFieldType.months(),
140                    DurationFieldType.days(),
141                    DurationFieldType.hours(), DurationFieldType.minutes(),
142                    DurationFieldType.seconds(), DurationFieldType.millis(),
143                },
144                new int[] { 0, 1, -1, 2, 3, 4, 5, 6, }
145            );
146            cYMDTime = type;
147        }
148        return type;
149    }
150 
151    /**
152     * Gets a type that defines the year, month and day fields.
153     * <ul>
154     * <li>years
155     * <li>months
156     * <li>days
157     * </ul>
158     *
159     * @return the period type
160     * @since 1.1
161     */
162    public static PeriodType yearMonthDay() {
163        PeriodType type = cYMD;
164        if (type == null) {
165            type = new PeriodType(
166                "YearMonthDay",
167                new DurationFieldType[] {
168                    DurationFieldType.years(), DurationFieldType.months(),
169                    DurationFieldType.days(),
170                },
171                new int[] { 0, 1, -1, 2, -1, -1, -1, -1, }
172            );
173            cYMD = type;
174        }
175        return type;
176    }
177 
178    /**
179     * Gets a type that defines all standard fields except months.
180     * <ul>
181     * <li>years
182     * <li>weeks
183     * <li>days
184     * <li>hours
185     * <li>minutes
186     * <li>seconds
187     * <li>milliseconds
188     * </ul>
189     *
190     * @return the period type
191     */
192    public static PeriodType yearWeekDayTime() {
193        PeriodType type = cYWDTime;
194        if (type == null) {
195            type = new PeriodType(
196                "YearWeekDayTime",
197                new DurationFieldType[] {
198                    DurationFieldType.years(),
199                    DurationFieldType.weeks(), DurationFieldType.days(),
200                    DurationFieldType.hours(), DurationFieldType.minutes(),
201                    DurationFieldType.seconds(), DurationFieldType.millis(),
202                },
203                new int[] { 0, -1, 1, 2, 3, 4, 5, 6, }
204            );
205            cYWDTime = type;
206        }
207        return type;
208    }
209 
210    /**
211     * Gets a type that defines year, week and day fields.
212     * <ul>
213     * <li>years
214     * <li>weeks
215     * <li>days
216     * </ul>
217     *
218     * @return the period type
219     * @since 1.1
220     */
221    public static PeriodType yearWeekDay() {
222        PeriodType type = cYWD;
223        if (type == null) {
224            type = new PeriodType(
225                "YearWeekDay",
226                new DurationFieldType[] {
227                    DurationFieldType.years(),
228                    DurationFieldType.weeks(), DurationFieldType.days(),
229                },
230                new int[] { 0, -1, 1, 2, -1, -1, -1, -1, }
231            );
232            cYWD = type;
233        }
234        return type;
235    }
236 
237    /**
238     * Gets a type that defines all standard fields except months and weeks.
239     * <ul>
240     * <li>years
241     * <li>days
242     * <li>hours
243     * <li>minutes
244     * <li>seconds
245     * <li>milliseconds
246     * </ul>
247     *
248     * @return the period type
249     */
250    public static PeriodType yearDayTime() {
251        PeriodType type = cYDTime;
252        if (type == null) {
253            type = new PeriodType(
254                "YearDayTime",
255                new DurationFieldType[] {
256                    DurationFieldType.years(), DurationFieldType.days(),
257                    DurationFieldType.hours(), DurationFieldType.minutes(),
258                    DurationFieldType.seconds(), DurationFieldType.millis(),
259                },
260                new int[] { 0, -1, -1, 1, 2, 3, 4, 5, }
261            );
262            cYDTime = type;
263        }
264        return type;
265    }
266 
267    /**
268     * Gets a type that defines the year and day fields.
269     * <ul>
270     * <li>years
271     * <li>days
272     * </ul>
273     *
274     * @return the period type
275     * @since 1.1
276     */
277    public static PeriodType yearDay() {
278        PeriodType type = cYD;
279        if (type == null) {
280            type = new PeriodType(
281                "YearDay",
282                new DurationFieldType[] {
283                    DurationFieldType.years(), DurationFieldType.days(),
284                },
285                new int[] { 0, -1, -1, 1, -1, -1, -1, -1, }
286            );
287            cYD = type;
288        }
289        return type;
290    }
291 
292    /**
293     * Gets a type that defines all standard fields from days downwards.
294     * <ul>
295     * <li>days
296     * <li>hours
297     * <li>minutes
298     * <li>seconds
299     * <li>milliseconds
300     * </ul>
301     *
302     * @return the period type
303     */
304    public static PeriodType dayTime() {
305        PeriodType type = cDTime;
306        if (type == null) {
307            type = new PeriodType(
308                "DayTime",
309                new DurationFieldType[] {
310                    DurationFieldType.days(),
311                    DurationFieldType.hours(), DurationFieldType.minutes(),
312                    DurationFieldType.seconds(), DurationFieldType.millis(),
313                },
314                new int[] { -1, -1, -1, 0, 1, 2, 3, 4, }
315            );
316            cDTime = type;
317        }
318        return type;
319    }
320 
321    /**
322     * Gets a type that defines all standard time fields.
323     * <ul>
324     * <li>hours
325     * <li>minutes
326     * <li>seconds
327     * <li>milliseconds
328     * </ul>
329     *
330     * @return the period type
331     */
332    public static PeriodType time() {
333        PeriodType type = cTime;
334        if (type == null) {
335            type = new PeriodType(
336                "Time",
337                new DurationFieldType[] {
338                    DurationFieldType.hours(), DurationFieldType.minutes(),
339                    DurationFieldType.seconds(), DurationFieldType.millis(),
340                },
341                new int[] { -1, -1, -1, -1, 0, 1, 2, 3, }
342            );
343            cTime = type;
344        }
345        return type;
346    }
347 
348    /**
349     * Gets a type that defines just the years field.
350     *
351     * @return the period type
352     */
353    public static PeriodType years() {
354        PeriodType type = cYears;
355        if (type == null) {
356            type = new PeriodType(
357                "Years",
358                new DurationFieldType[] { DurationFieldType.years() },
359                new int[] { 0, -1, -1, -1, -1, -1, -1, -1, }
360            );
361            cYears = type;
362        }
363        return type;
364    }
365 
366    /**
367     * Gets a type that defines just the months field.
368     *
369     * @return the period type
370     */
371    public static PeriodType months() {
372        PeriodType type = cMonths;
373        if (type == null) {
374            type = new PeriodType(
375                "Months",
376                new DurationFieldType[] { DurationFieldType.months() },
377                new int[] { -1, 0, -1, -1, -1, -1, -1, -1, }
378            );
379            cMonths = type;
380        }
381        return type;
382    }
383 
384    /**
385     * Gets a type that defines just the weeks field.
386     *
387     * @return the period type
388     */
389    public static PeriodType weeks() {
390        PeriodType type = cWeeks;
391        if (type == null) {
392            type = new PeriodType(
393                "Weeks",
394                new DurationFieldType[] { DurationFieldType.weeks() },
395                new int[] { -1, -1, 0, -1, -1, -1, -1, -1, }
396            );
397            cWeeks = type;
398        }
399        return type;
400    }
401 
402    /**
403     * Gets a type that defines just the days field.
404     *
405     * @return the period type
406     */
407    public static PeriodType days() {
408        PeriodType type = cDays;
409        if (type == null) {
410            type = new PeriodType(
411                "Days",
412                new DurationFieldType[] { DurationFieldType.days() },
413                new int[] { -1, -1, -1, 0, -1, -1, -1, -1, }
414            );
415            cDays = type;
416        }
417        return type;
418    }
419 
420    /**
421     * Gets a type that defines just the hours field.
422     *
423     * @return the period type
424     */
425    public static PeriodType hours() {
426        PeriodType type = cHours;
427        if (type == null) {
428            type = new PeriodType(
429                "Hours",
430                new DurationFieldType[] { DurationFieldType.hours() },
431                new int[] { -1, -1, -1, -1, 0, -1, -1, -1, }
432            );
433            cHours = type;
434        }
435        return type;
436    }
437 
438    /**
439     * Gets a type that defines just the minutes field.
440     *
441     * @return the period type
442     */
443    public static PeriodType minutes() {
444        PeriodType type = cMinutes;
445        if (type == null) {
446            type = new PeriodType(
447                "Minutes",
448                new DurationFieldType[] { DurationFieldType.minutes() },
449                new int[] { -1, -1, -1, -1, -1, 0, -1, -1, }
450            );
451            cMinutes = type;
452        }
453        return type;
454    }
455 
456    /**
457     * Gets a type that defines just the seconds field.
458     *
459     * @return the period type
460     */
461    public static PeriodType seconds() {
462        PeriodType type = cSeconds;
463        if (type == null) {
464            type = new PeriodType(
465                "Seconds",
466                new DurationFieldType[] { DurationFieldType.seconds() },
467                new int[] { -1, -1, -1, -1, -1, -1, 0, -1, }
468            );
469            cSeconds = type;
470        }
471        return type;
472    }
473 
474    /**
475     * Gets a type that defines just the millis field.
476     *
477     * @return the period type
478     */
479    public static PeriodType millis() {
480        PeriodType type = cMillis;
481        if (type == null) {
482            type = new PeriodType(
483                "Millis",
484                new DurationFieldType[] { DurationFieldType.millis() },
485                new int[] { -1, -1, -1, -1, -1, -1, -1, 0, }
486            );
487            cMillis = type;
488        }
489        return type;
490    }
491 
492    /**
493     * Gets a period type that contains the duration types of the array.
494     * <p>
495     * Only the 8 standard duration field types are supported.
496     *
497     * @param types  the types to include in the array.
498     * @return the period type
499     * @since 1.1
500     */
501    public static synchronized PeriodType forFields(DurationFieldType[] types) {
502        if (types == null || types.length == 0) {
503            throw new IllegalArgumentException("Types array must not be null or empty");
504        }
505        for (int i = 0; i < types.length; i++) {
506            if (types[i] == null) {
507                throw new IllegalArgumentException("Types array must not contain null");
508            }
509        }
510        Map cache = cTypes;
511        if (cTypes.isEmpty()) {
512            cache.put(standard(), standard());
513            cache.put(yearMonthDayTime(), yearMonthDayTime());
514            cache.put(yearMonthDay(), yearMonthDay());
515            cache.put(yearWeekDayTime(), yearWeekDayTime());
516            cache.put(yearWeekDay(), yearWeekDay());
517            cache.put(yearDayTime(), yearDayTime());
518            cache.put(yearDay(), yearDay());
519            cache.put(dayTime(), dayTime());
520            cache.put(time(), time());
521            cache.put(years(), years());
522            cache.put(months(), months());
523            cache.put(weeks(), weeks());
524            cache.put(days(), days());
525            cache.put(hours(), hours());
526            cache.put(minutes(), minutes());
527            cache.put(seconds(), seconds());
528            cache.put(millis(), millis());
529        }
530        PeriodType inPartType = new PeriodType(null, types, null);
531        Object cached = cache.get(inPartType);
532        if (cached instanceof PeriodType) {
533            return (PeriodType) cached;
534        }
535        if (cached != null) {
536            throw new IllegalArgumentException("PeriodType does not support fields: " + cached);
537        }
538        PeriodType type = standard();
539        List list = new ArrayList(Arrays.asList(types));
540        if (list.remove(DurationFieldType.years()) == false) {
541            type = type.withYearsRemoved();
542        }
543        if (list.remove(DurationFieldType.months()) == false) {
544            type = type.withMonthsRemoved();
545        }
546        if (list.remove(DurationFieldType.weeks()) == false) {
547            type = type.withWeeksRemoved();
548        }
549        if (list.remove(DurationFieldType.days()) == false) {
550            type = type.withDaysRemoved();
551        }
552        if (list.remove(DurationFieldType.hours()) == false) {
553            type = type.withHoursRemoved();
554        }
555        if (list.remove(DurationFieldType.minutes()) == false) {
556            type = type.withMinutesRemoved();
557        }
558        if (list.remove(DurationFieldType.seconds()) == false) {
559            type = type.withSecondsRemoved();
560        }
561        if (list.remove(DurationFieldType.millis()) == false) {
562            type = type.withMillisRemoved();
563        }
564        if (list.size() > 0) {
565            cache.put(inPartType, list);
566            throw new IllegalArgumentException("PeriodType does not support fields: " + list);
567        }
568        // recheck cache in case initial array order was wrong
569        PeriodType checkPartType = new PeriodType(null, type.iTypes, null);
570        PeriodType checkedType = (PeriodType) cache.get(checkPartType);
571        if (checkedType != null) {
572            cache.put(inPartType, checkedType);
573            return checkedType;
574        }
575        cache.put(inPartType, type);
576        return type;
577    }
578 
579    //-----------------------------------------------------------------------    
580    /** The name of the type */
581    private final String iName;
582    /** The array of types */
583    private final DurationFieldType[] iTypes;
584    /** The array of indices */
585    private final int[] iIndices;
586 
587    /**
588     * Constructor.
589     *
590     * @param name  the name
591     * @param types  the types
592     * @param indices  the indices
593     */
594    protected PeriodType(String name, DurationFieldType[] types, int[] indices) {
595        super();
596        iName = name;
597        iTypes = types;
598        iIndices = indices;
599    }
600 
601    //-----------------------------------------------------------------------
602    /**
603     * Gets the name of the period type.
604     * 
605     * @return the name
606     */
607    public String getName() {
608        return iName;
609    }
610 
611    /**
612     * Gets the number of fields in the period type.
613     * 
614     * @return the number of fields
615     */
616    public int size() {
617        return iTypes.length;
618    }
619 
620    /**
621     * Gets the field type by index.
622     * 
623     * @param index  the index to retrieve
624     * @return the field type
625     * @throws IndexOutOfBoundsException if the index is invalid
626     */
627    public DurationFieldType getFieldType(int index) {
628        return iTypes[index];
629    }
630 
631    /**
632     * Checks whether the field specified is supported by this period.
633     *
634     * @param type  the type to check, may be null which returns false
635     * @return true if the field is supported
636     */
637    public boolean isSupported(DurationFieldType type) {
638        return (indexOf(type) >= 0);
639    }
640 
641    /**
642     * Gets the index of the field in this period.
643     *
644     * @param type  the type to check, may be null which returns -1
645     * @return the index of -1 if not supported
646     */
647    public int indexOf(DurationFieldType type) {
648        for (int i = 0, isize = size(); i < isize; i++) {
649            if (iTypes[i] == type) {
650                return i;
651            }
652        }
653        return -1;
654    }
655 
656    /**
657     * Gets a debugging to string.
658     * 
659     * @return a string
660     */
661    public String toString() {
662        return "PeriodType[" + getName() + "]";
663    }
664 
665    //-----------------------------------------------------------------------
666    /**
667     * Gets the indexed field part of the period.
668     * 
669     * @param period  the period to query
670     * @param index  the index to use
671     * @return the value of the field, zero if unsupported
672     */
673    int getIndexedField(ReadablePeriod period, int index) {
674        int realIndex = iIndices[index];
675        return (realIndex == -1 ? 0 : period.getValue(realIndex));
676    }
677 
678    /**
679     * Sets the indexed field part of the period.
680     * 
681     * @param period  the period to query
682     * @param index  the index to use
683     * @param values  the array to populate
684     * @param newValue  the value to set
685     * @throws UnsupportedOperationException if not supported
686     */
687    boolean setIndexedField(ReadablePeriod period, int index, int[] values, int newValue) {
688        int realIndex = iIndices[index];
689        if (realIndex == -1) {
690            throw new UnsupportedOperationException("Field is not supported");
691        }
692        values[realIndex] = newValue;
693        return true;
694    }
695 
696    /**
697     * Adds to the indexed field part of the period.
698     * 
699     * @param period  the period to query
700     * @param index  the index to use
701     * @param values  the array to populate
702     * @param valueToAdd  the value to add
703     * @return true if the array is updated
704     * @throws UnsupportedOperationException if not supported
705     */
706    boolean addIndexedField(ReadablePeriod period, int index, int[] values, int valueToAdd) {
707        if (valueToAdd == 0) {
708            return false;
709        }
710        int realIndex = iIndices[index];
711        if (realIndex == -1) {
712            throw new UnsupportedOperationException("Field is not supported");
713        }
714        values[realIndex] = FieldUtils.safeAdd(values[realIndex], valueToAdd);
715        return true;
716    }
717 
718    //-----------------------------------------------------------------------
719    /**
720     * Returns a version of this PeriodType instance that does not support years.
721     * 
722     * @return a new period type that supports the original set of fields except years
723     */
724    public PeriodType withYearsRemoved() {
725        return withFieldRemoved(0, "NoYears");
726    }
727 
728    /**
729     * Returns a version of this PeriodType instance that does not support months.
730     * 
731     * @return a new period type that supports the original set of fields except months
732     */
733    public PeriodType withMonthsRemoved() {
734        return withFieldRemoved(1, "NoMonths");
735    }
736 
737    /**
738     * Returns a version of this PeriodType instance that does not support weeks.
739     * 
740     * @return a new period type that supports the original set of fields except weeks
741     */
742    public PeriodType withWeeksRemoved() {
743        return withFieldRemoved(2, "NoWeeks");
744    }
745 
746    /**
747     * Returns a version of this PeriodType instance that does not support days.
748     * 
749     * @return a new period type that supports the original set of fields except days
750     */
751    public PeriodType withDaysRemoved() {
752        return withFieldRemoved(3, "NoDays");
753    }
754 
755    /**
756     * Returns a version of this PeriodType instance that does not support hours.
757     * 
758     * @return a new period type that supports the original set of fields except hours
759     */
760    public PeriodType withHoursRemoved() {
761        return withFieldRemoved(4, "NoHours");
762    }
763 
764    /**
765     * Returns a version of this PeriodType instance that does not support minutes.
766     * 
767     * @return a new period type that supports the original set of fields except minutes
768     */
769    public PeriodType withMinutesRemoved() {
770        return withFieldRemoved(5, "NoMinutes");
771    }
772 
773    /**
774     * Returns a version of this PeriodType instance that does not support seconds.
775     * 
776     * @return a new period type that supports the original set of fields except seconds
777     */
778    public PeriodType withSecondsRemoved() {
779        return withFieldRemoved(6, "NoSeconds");
780    }
781 
782    /**
783     * Returns a version of this PeriodType instance that does not support milliseconds.
784     * 
785     * @return a new period type that supports the original set of fields except milliseconds
786     */
787    public PeriodType withMillisRemoved() {
788        return withFieldRemoved(7, "NoMillis");
789    }
790 
791    /**
792     * Removes the field specified by indices index.
793     * 
794     * @param indicesIndex  the index to remove
795     * @param name  the name addition
796     * @return the new type
797     */
798    private PeriodType withFieldRemoved(int indicesIndex, String name) {
799        int fieldIndex = iIndices[indicesIndex];
800        if (fieldIndex == -1) {
801            return this;
802        }
803        
804        DurationFieldType[] types = new DurationFieldType[size() - 1];
805        for (int i = 0; i < iTypes.length; i++) {
806            if (i < fieldIndex) {
807                types[i] = iTypes[i];
808            } else if (i > fieldIndex) {
809                types[i - 1] = iTypes[i];
810            }
811        }
812        
813        int[] indices = new int[8];
814        for (int i = 0; i < indices.length; i++) {
815            if (i < indicesIndex) {
816                indices[i] = iIndices[i];
817            } else if (i > indicesIndex) {
818                indices[i] = (iIndices[i] == -1 ? -1 : iIndices[i] - 1);
819            } else {
820                indices[i] = -1;
821            }
822        }
823        return new PeriodType(getName() + name, types, indices);
824    }
825 
826    //-----------------------------------------------------------------------
827    /**
828     * Compares this type to another object.
829     * To be equal, the object must be a PeriodType with the same set of fields.
830     * 
831     * @param obj  the object to compare to
832     * @return true if equal
833     */
834    public boolean equals(Object obj) {
835        if (this == obj) {
836            return true;
837        }
838        if (obj instanceof PeriodType == false) {
839            return false;
840        }
841        PeriodType other = (PeriodType) obj;
842        return (Arrays.equals(iTypes, other.iTypes));
843    }
844 
845    /**
846     * Returns a hashcode based on the field types.
847     * 
848     * @return a suitable hashcode
849     */
850    public int hashCode() {
851        int hash = 0;
852        for (int i = 0; i < iTypes.length; i++) {
853            hash += iTypes[i].hashCode();
854        }
855        return hash;
856    }
857 
858}

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