alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (PeriodType.java)

This example Java source code file (PeriodType.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

durationfieldtype, illegalargumentexception, map, months, nomillis, nominutes, object, periodtype, seconds, serializable, string, types, unsupportedoperationexception, util, yearday

The PeriodType.java Java example source code

/*
 *  Copyright 2001-2009 Stephen Colebourne
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.joda.time;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.joda.time.field.FieldUtils;

/**
 * Controls a period implementation by specifying which duration fields are to be used.
 * <p>
 * The following implementations are provided:
 * <ul>
 * <li>Standard - years, months, weeks, days, hours, minutes, seconds, millis
 * <li>YearMonthDayTime - years, months, days, hours, minutes, seconds, millis
 * <li>YearMonthDay - years, months, days
 * <li>YearWeekDayTime - years, weeks, days, hours, minutes, seconds, millis
 * <li>YearWeekDay - years, weeks, days
 * <li>YearDayTime - years, days, hours, minutes, seconds, millis
 * <li>YearDay - years, days, hours
 * <li>DayTime - days, hours, minutes, seconds, millis
 * <li>Time - hours, minutes, seconds, millis
 * <li>plus one for each single type
 * </ul>
 *
 * <p>
 * PeriodType is thread-safe and immutable, and all subclasses must be as well.
 *
 * @author Brian S O'Neill
 * @author Stephen Colebourne
 * @since 1.0
 */
public class PeriodType implements Serializable {
    /** Serialization version */
    private static final long serialVersionUID = 2274324892792009998L;

    /** Cache of all the known types. */
    private static final Map<PeriodType, Object> cTypes = new HashMap(32);

    static int YEAR_INDEX = 0;
    static int MONTH_INDEX = 1;
    static int WEEK_INDEX = 2;
    static int DAY_INDEX = 3;
    static int HOUR_INDEX = 4;
    static int MINUTE_INDEX = 5;
    static int SECOND_INDEX = 6;
    static int MILLI_INDEX = 7;
    
    private static PeriodType cStandard;
    private static PeriodType cYMDTime;
    private static PeriodType cYMD;
    private static PeriodType cYWDTime;
    private static PeriodType cYWD;
    private static PeriodType cYDTime;
    private static PeriodType cYD;
    private static PeriodType cDTime;
    private static PeriodType cTime;
    
    private static PeriodType cYears;
    private static PeriodType cMonths;
    private static PeriodType cWeeks;
    private static PeriodType cDays;
    private static PeriodType cHours;
    private static PeriodType cMinutes;
    private static PeriodType cSeconds;
    private static PeriodType cMillis;

    /**
     * Gets a type that defines all standard fields.
     * <ul>
     * <li>years
     * <li>months
     * <li>weeks
     * <li>days
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType standard() {
        PeriodType type = cStandard;
        if (type == null) {
            type = new PeriodType(
                "Standard",
                new DurationFieldType[] {
                    DurationFieldType.years(), DurationFieldType.months(),
                    DurationFieldType.weeks(), DurationFieldType.days(),
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { 0, 1, 2, 3, 4, 5, 6, 7, }
            );
            cStandard = type;
        }
        return type;
    }

    /**
     * Gets a type that defines all standard fields except weeks.
     * <ul>
     * <li>years
     * <li>months
     * <li>days
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType yearMonthDayTime() {
        PeriodType type = cYMDTime;
        if (type == null) {
            type = new PeriodType(
                "YearMonthDayTime",
                new DurationFieldType[] {
                    DurationFieldType.years(), DurationFieldType.months(),
                    DurationFieldType.days(),
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { 0, 1, -1, 2, 3, 4, 5, 6, }
            );
            cYMDTime = type;
        }
        return type;
    }

    /**
     * Gets a type that defines the year, month and day fields.
     * <ul>
     * <li>years
     * <li>months
     * <li>days
     * </ul>
     *
     * @return the period type
     * @since 1.1
     */
    public static PeriodType yearMonthDay() {
        PeriodType type = cYMD;
        if (type == null) {
            type = new PeriodType(
                "YearMonthDay",
                new DurationFieldType[] {
                    DurationFieldType.years(), DurationFieldType.months(),
                    DurationFieldType.days(),
                },
                new int[] { 0, 1, -1, 2, -1, -1, -1, -1, }
            );
            cYMD = type;
        }
        return type;
    }

    /**
     * Gets a type that defines all standard fields except months.
     * <ul>
     * <li>years
     * <li>weeks
     * <li>days
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType yearWeekDayTime() {
        PeriodType type = cYWDTime;
        if (type == null) {
            type = new PeriodType(
                "YearWeekDayTime",
                new DurationFieldType[] {
                    DurationFieldType.years(),
                    DurationFieldType.weeks(), DurationFieldType.days(),
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { 0, -1, 1, 2, 3, 4, 5, 6, }
            );
            cYWDTime = type;
        }
        return type;
    }

    /**
     * Gets a type that defines year, week and day fields.
     * <ul>
     * <li>years
     * <li>weeks
     * <li>days
     * </ul>
     *
     * @return the period type
     * @since 1.1
     */
    public static PeriodType yearWeekDay() {
        PeriodType type = cYWD;
        if (type == null) {
            type = new PeriodType(
                "YearWeekDay",
                new DurationFieldType[] {
                    DurationFieldType.years(),
                    DurationFieldType.weeks(), DurationFieldType.days(),
                },
                new int[] { 0, -1, 1, 2, -1, -1, -1, -1, }
            );
            cYWD = type;
        }
        return type;
    }

    /**
     * Gets a type that defines all standard fields except months and weeks.
     * <ul>
     * <li>years
     * <li>days
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType yearDayTime() {
        PeriodType type = cYDTime;
        if (type == null) {
            type = new PeriodType(
                "YearDayTime",
                new DurationFieldType[] {
                    DurationFieldType.years(), DurationFieldType.days(),
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { 0, -1, -1, 1, 2, 3, 4, 5, }
            );
            cYDTime = type;
        }
        return type;
    }

    /**
     * Gets a type that defines the year and day fields.
     * <ul>
     * <li>years
     * <li>days
     * </ul>
     *
     * @return the period type
     * @since 1.1
     */
    public static PeriodType yearDay() {
        PeriodType type = cYD;
        if (type == null) {
            type = new PeriodType(
                "YearDay",
                new DurationFieldType[] {
                    DurationFieldType.years(), DurationFieldType.days(),
                },
                new int[] { 0, -1, -1, 1, -1, -1, -1, -1, }
            );
            cYD = type;
        }
        return type;
    }

    /**
     * Gets a type that defines all standard fields from days downwards.
     * <ul>
     * <li>days
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType dayTime() {
        PeriodType type = cDTime;
        if (type == null) {
            type = new PeriodType(
                "DayTime",
                new DurationFieldType[] {
                    DurationFieldType.days(),
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { -1, -1, -1, 0, 1, 2, 3, 4, }
            );
            cDTime = type;
        }
        return type;
    }

    /**
     * Gets a type that defines all standard time fields.
     * <ul>
     * <li>hours
     * <li>minutes
     * <li>seconds
     * <li>milliseconds
     * </ul>
     *
     * @return the period type
     */
    public static PeriodType time() {
        PeriodType type = cTime;
        if (type == null) {
            type = new PeriodType(
                "Time",
                new DurationFieldType[] {
                    DurationFieldType.hours(), DurationFieldType.minutes(),
                    DurationFieldType.seconds(), DurationFieldType.millis(),
                },
                new int[] { -1, -1, -1, -1, 0, 1, 2, 3, }
            );
            cTime = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the years field.
     *
     * @return the period type
     */
    public static PeriodType years() {
        PeriodType type = cYears;
        if (type == null) {
            type = new PeriodType(
                "Years",
                new DurationFieldType[] { DurationFieldType.years() },
                new int[] { 0, -1, -1, -1, -1, -1, -1, -1, }
            );
            cYears = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the months field.
     *
     * @return the period type
     */
    public static PeriodType months() {
        PeriodType type = cMonths;
        if (type == null) {
            type = new PeriodType(
                "Months",
                new DurationFieldType[] { DurationFieldType.months() },
                new int[] { -1, 0, -1, -1, -1, -1, -1, -1, }
            );
            cMonths = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the weeks field.
     *
     * @return the period type
     */
    public static PeriodType weeks() {
        PeriodType type = cWeeks;
        if (type == null) {
            type = new PeriodType(
                "Weeks",
                new DurationFieldType[] { DurationFieldType.weeks() },
                new int[] { -1, -1, 0, -1, -1, -1, -1, -1, }
            );
            cWeeks = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the days field.
     *
     * @return the period type
     */
    public static PeriodType days() {
        PeriodType type = cDays;
        if (type == null) {
            type = new PeriodType(
                "Days",
                new DurationFieldType[] { DurationFieldType.days() },
                new int[] { -1, -1, -1, 0, -1, -1, -1, -1, }
            );
            cDays = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the hours field.
     *
     * @return the period type
     */
    public static PeriodType hours() {
        PeriodType type = cHours;
        if (type == null) {
            type = new PeriodType(
                "Hours",
                new DurationFieldType[] { DurationFieldType.hours() },
                new int[] { -1, -1, -1, -1, 0, -1, -1, -1, }
            );
            cHours = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the minutes field.
     *
     * @return the period type
     */
    public static PeriodType minutes() {
        PeriodType type = cMinutes;
        if (type == null) {
            type = new PeriodType(
                "Minutes",
                new DurationFieldType[] { DurationFieldType.minutes() },
                new int[] { -1, -1, -1, -1, -1, 0, -1, -1, }
            );
            cMinutes = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the seconds field.
     *
     * @return the period type
     */
    public static PeriodType seconds() {
        PeriodType type = cSeconds;
        if (type == null) {
            type = new PeriodType(
                "Seconds",
                new DurationFieldType[] { DurationFieldType.seconds() },
                new int[] { -1, -1, -1, -1, -1, -1, 0, -1, }
            );
            cSeconds = type;
        }
        return type;
    }

    /**
     * Gets a type that defines just the millis field.
     *
     * @return the period type
     */
    public static PeriodType millis() {
        PeriodType type = cMillis;
        if (type == null) {
            type = new PeriodType(
                "Millis",
                new DurationFieldType[] { DurationFieldType.millis() },
                new int[] { -1, -1, -1, -1, -1, -1, -1, 0, }
            );
            cMillis = type;
        }
        return type;
    }

    /**
     * Gets a period type that contains the duration types of the array.
     * <p>
     * Only the 8 standard duration field types are supported.
     *
     * @param types  the types to include in the array.
     * @return the period type
     * @since 1.1
     */
    public static synchronized PeriodType forFields(DurationFieldType[] types) {
        if (types == null || types.length == 0) {
            throw new IllegalArgumentException("Types array must not be null or empty");
        }
        for (int i = 0; i < types.length; i++) {
            if (types[i] == null) {
                throw new IllegalArgumentException("Types array must not contain null");
            }
        }
        Map<PeriodType, Object> cache = cTypes;
        if (cache.isEmpty()) {
            cache.put(standard(), standard());
            cache.put(yearMonthDayTime(), yearMonthDayTime());
            cache.put(yearMonthDay(), yearMonthDay());
            cache.put(yearWeekDayTime(), yearWeekDayTime());
            cache.put(yearWeekDay(), yearWeekDay());
            cache.put(yearDayTime(), yearDayTime());
            cache.put(yearDay(), yearDay());
            cache.put(dayTime(), dayTime());
            cache.put(time(), time());
            cache.put(years(), years());
            cache.put(months(), months());
            cache.put(weeks(), weeks());
            cache.put(days(), days());
            cache.put(hours(), hours());
            cache.put(minutes(), minutes());
            cache.put(seconds(), seconds());
            cache.put(millis(), millis());
        }
        PeriodType inPartType = new PeriodType(null, types, null);
        Object cached = cache.get(inPartType);
        if (cached instanceof PeriodType) {
            return (PeriodType) cached;
        }
        if (cached != null) {
            throw new IllegalArgumentException("PeriodType does not support fields: " + cached);
        }
        PeriodType type = standard();
        List<DurationFieldType> list = new ArrayList(Arrays.asList(types));
        if (list.remove(DurationFieldType.years()) == false) {
            type = type.withYearsRemoved();
        }
        if (list.remove(DurationFieldType.months()) == false) {
            type = type.withMonthsRemoved();
        }
        if (list.remove(DurationFieldType.weeks()) == false) {
            type = type.withWeeksRemoved();
        }
        if (list.remove(DurationFieldType.days()) == false) {
            type = type.withDaysRemoved();
        }
        if (list.remove(DurationFieldType.hours()) == false) {
            type = type.withHoursRemoved();
        }
        if (list.remove(DurationFieldType.minutes()) == false) {
            type = type.withMinutesRemoved();
        }
        if (list.remove(DurationFieldType.seconds()) == false) {
            type = type.withSecondsRemoved();
        }
        if (list.remove(DurationFieldType.millis()) == false) {
            type = type.withMillisRemoved();
        }
        if (list.size() > 0) {
            cache.put(inPartType, list);
            throw new IllegalArgumentException("PeriodType does not support fields: " + list);
        }
        // recheck cache in case initial array order was wrong
        PeriodType checkPartType = new PeriodType(null, type.iTypes, null);
        PeriodType checkedType = (PeriodType) cache.get(checkPartType);
        if (checkedType != null) {
            cache.put(checkPartType, checkedType);
            return checkedType;
        }
        cache.put(checkPartType, type);
        return type;
    }

    //-----------------------------------------------------------------------    
    /** The name of the type */
    private final String iName;
    /** The array of types */
    private final DurationFieldType[] iTypes;
    /** The array of indices */
    private final int[] iIndices;

    /**
     * Constructor.
     *
     * @param name  the name
     * @param types  the types
     * @param indices  the indices
     */
    protected PeriodType(String name, DurationFieldType[] types, int[] indices) {
        super();
        iName = name;
        iTypes = types;
        iIndices = indices;
    }

    //-----------------------------------------------------------------------
    /**
     * Gets the name of the period type.
     * 
     * @return the name
     */
    public String getName() {
        return iName;
    }

    /**
     * Gets the number of fields in the period type.
     * 
     * @return the number of fields
     */
    public int size() {
        return iTypes.length;
    }

    /**
     * Gets the field type by index.
     * 
     * @param index  the index to retrieve
     * @return the field type
     * @throws IndexOutOfBoundsException if the index is invalid
     */
    public DurationFieldType getFieldType(int index) {
        return iTypes[index];
    }

    /**
     * Checks whether the field specified is supported by this period.
     *
     * @param type  the type to check, may be null which returns false
     * @return true if the field is supported
     */
    public boolean isSupported(DurationFieldType type) {
        return (indexOf(type) >= 0);
    }

    /**
     * Gets the index of the field in this period.
     *
     * @param type  the type to check, may be null which returns -1
     * @return the index of -1 if not supported
     */
    public int indexOf(DurationFieldType type) {
        for (int i = 0, isize = size(); i < isize; i++) {
            if (iTypes[i] == type) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Gets a debugging to string.
     * 
     * @return a string
     */
    public String toString() {
        return "PeriodType[" + getName() + "]";
    }

    //-----------------------------------------------------------------------
    /**
     * Gets the indexed field part of the period.
     * 
     * @param period  the period to query
     * @param index  the index to use
     * @return the value of the field, zero if unsupported
     */
    int getIndexedField(ReadablePeriod period, int index) {
        int realIndex = iIndices[index];
        return (realIndex == -1 ? 0 : period.getValue(realIndex));
    }

    /**
     * Sets the indexed field part of the period.
     * 
     * @param period  the period to query
     * @param index  the index to use
     * @param values  the array to populate
     * @param newValue  the value to set
     * @throws UnsupportedOperationException if not supported
     */
    boolean setIndexedField(ReadablePeriod period, int index, int[] values, int newValue) {
        int realIndex = iIndices[index];
        if (realIndex == -1) {
            throw new UnsupportedOperationException("Field is not supported");
        }
        values[realIndex] = newValue;
        return true;
    }

    /**
     * Adds to the indexed field part of the period.
     * 
     * @param period  the period to query
     * @param index  the index to use
     * @param values  the array to populate
     * @param valueToAdd  the value to add
     * @return true if the array is updated
     * @throws UnsupportedOperationException if not supported
     */
    boolean addIndexedField(ReadablePeriod period, int index, int[] values, int valueToAdd) {
        if (valueToAdd == 0) {
            return false;
        }
        int realIndex = iIndices[index];
        if (realIndex == -1) {
            throw new UnsupportedOperationException("Field is not supported");
        }
        values[realIndex] = FieldUtils.safeAdd(values[realIndex], valueToAdd);
        return true;
    }

    //-----------------------------------------------------------------------
    /**
     * Returns a version of this PeriodType instance that does not support years.
     * 
     * @return a new period type that supports the original set of fields except years
     */
    public PeriodType withYearsRemoved() {
        return withFieldRemoved(0, "NoYears");
    }

    /**
     * Returns a version of this PeriodType instance that does not support months.
     * 
     * @return a new period type that supports the original set of fields except months
     */
    public PeriodType withMonthsRemoved() {
        return withFieldRemoved(1, "NoMonths");
    }

    /**
     * Returns a version of this PeriodType instance that does not support weeks.
     * 
     * @return a new period type that supports the original set of fields except weeks
     */
    public PeriodType withWeeksRemoved() {
        return withFieldRemoved(2, "NoWeeks");
    }

    /**
     * Returns a version of this PeriodType instance that does not support days.
     * 
     * @return a new period type that supports the original set of fields except days
     */
    public PeriodType withDaysRemoved() {
        return withFieldRemoved(3, "NoDays");
    }

    /**
     * Returns a version of this PeriodType instance that does not support hours.
     * 
     * @return a new period type that supports the original set of fields except hours
     */
    public PeriodType withHoursRemoved() {
        return withFieldRemoved(4, "NoHours");
    }

    /**
     * Returns a version of this PeriodType instance that does not support minutes.
     * 
     * @return a new period type that supports the original set of fields except minutes
     */
    public PeriodType withMinutesRemoved() {
        return withFieldRemoved(5, "NoMinutes");
    }

    /**
     * Returns a version of this PeriodType instance that does not support seconds.
     * 
     * @return a new period type that supports the original set of fields except seconds
     */
    public PeriodType withSecondsRemoved() {
        return withFieldRemoved(6, "NoSeconds");
    }

    /**
     * Returns a version of this PeriodType instance that does not support milliseconds.
     * 
     * @return a new period type that supports the original set of fields except milliseconds
     */
    public PeriodType withMillisRemoved() {
        return withFieldRemoved(7, "NoMillis");
    }

    /**
     * Removes the field specified by indices index.
     * 
     * @param indicesIndex  the index to remove
     * @param name  the name addition
     * @return the new type
     */
    private PeriodType withFieldRemoved(int indicesIndex, String name) {
        int fieldIndex = iIndices[indicesIndex];
        if (fieldIndex == -1) {
            return this;
        }
        
        DurationFieldType[] types = new DurationFieldType[size() - 1];
        for (int i = 0; i < iTypes.length; i++) {
            if (i < fieldIndex) {
                types[i] = iTypes[i];
            } else if (i > fieldIndex) {
                types[i - 1] = iTypes[i];
            }
        }
        
        int[] indices = new int[8];
        for (int i = 0; i < indices.length; i++) {
            if (i < indicesIndex) {
                indices[i] = iIndices[i];
            } else if (i > indicesIndex) {
                indices[i] = (iIndices[i] == -1 ? -1 : iIndices[i] - 1);
            } else {
                indices[i] = -1;
            }
        }
        return new PeriodType(getName() + name, types, indices);
    }

    //-----------------------------------------------------------------------
    /**
     * Compares this type to another object.
     * To be equal, the object must be a PeriodType with the same set of fields.
     * 
     * @param obj  the object to compare to
     * @return true if equal
     */
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof PeriodType == false) {
            return false;
        }
        PeriodType other = (PeriodType) obj;
        return (Arrays.equals(iTypes, other.iTypes));
    }

    /**
     * Returns a hashcode based on the field types.
     * 
     * @return a suitable hashcode
     */
    public int hashCode() {
        int hash = 0;
        for (int i = 0; i < iTypes.length; i++) {
            hash += iTypes[i].hashCode();
        }
        return hash;
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java PeriodType.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.