devdaily home | apple | java | perl | unix | directory | blog

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.apache.axis2.databinding.types;

import java.io.Serializable;
import java.util.Calendar;

/**
 * Implementation of the XML Schema type duration. Duration supports a minimum fractional second
 * precision of milliseconds.
 *
 * @see <a href="http://www.w3.org/TR/xmlschema-2/#duration">XML Schema 3.2.6
 */
public class Duration implements Serializable {

    private static final long serialVersionUID = -3736760992541369098L;

    boolean isNegative;
    int years;
    int months;
    int days;
    int hours;
    int minutes;
    double seconds;

    /** Default no-arg constructor */
    public Duration() {
    }

    /**
     * @param negative
     * @param aYears
     * @param aMonths
     * @param aDays
     * @param aHours
     * @param aMinutes
     * @param aSeconds
     */
    public Duration(boolean negative, int aYears, int aMonths, int aDays,
                    int aHours, int aMinutes, double aSeconds) {
        isNegative = negative;
        years = aYears;
        months = aMonths;
        days = aDays;
        hours = aHours;
        minutes = aMinutes;
        setSeconds(aSeconds);
    }

    /**
     * Constructs Duration from a String in an xsd:duration format - PnYnMnDTnHnMnS.
     *
     * @param duration String
     * @throws IllegalArgumentException if the string doesn't parse correctly.
     */
    public Duration(String duration) throws IllegalArgumentException {
        int position = 1;
        int timePosition = duration.indexOf("T");

        // P is required but P by itself is invalid
        if (duration.indexOf("P") == -1 || duration.equals("P")) {
            throw new IllegalArgumentException();
            // Messages.getMessage("badDuration"));
        }

        // if present, time cannot be empty
        if (duration.lastIndexOf("T") == duration.length() - 1) {
            throw new IllegalArgumentException();
//                    Messages.getMessage("badDuration"));
        }

        // check the sign
        if (duration.startsWith("-")) {
            isNegative = true;
            position++;
        }

        // parse time part
        if (timePosition != -1) {
            parseTime(duration.substring(timePosition + 1));
        } else {
            timePosition = duration.length();
        }

        // parse date part
        if (position != timePosition) {
            parseDate(duration.substring(position, timePosition));
        }
    }

    /**
     * Constructs Duration from a Calendar.
     *
     * @param calendar Calendar
     * @throws IllegalArgumentException if the calendar object does not represent any date nor
     *                                  time.
     */
    public Duration(boolean negative, Calendar calendar) throws
            IllegalArgumentException {
        this.isNegative = negative;
        this.years = calendar.get(Calendar.YEAR);
        this.months = calendar.get(Calendar.MONTH);
        this.days = calendar.get(Calendar.DATE);
        this.hours = calendar.get(Calendar.HOUR);
        this.minutes = calendar.get(Calendar.MINUTE);
        this.seconds = calendar.get(Calendar.SECOND);
        this.seconds += ((double)calendar.get(Calendar.MILLISECOND)) / 100;
        if (years == 0 && months == 0 && days == 0 && hours == 0 &&
                minutes == 0 && seconds == 0) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badCalendarForDuration"));
        }
    }

    /**
     * This method parses the time portion of a String that represents xsd:duration - nHnMnS.
     *
     * @param time
     * @throws IllegalArgumentException if time does not match pattern
     */
    public void parseTime(String time) throws IllegalArgumentException {
        if (time.length() == 0 || time.indexOf("-") != -1) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badTimeDuration"));
        }

        // check if time ends with either H, M, or S
        if (!time.endsWith("H") && !time.endsWith("M") && !time.endsWith("S")) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badTimeDuration"));
        }

        try {
            // parse string and extract hours, minutes, and seconds
            int start = 0;

            // Hours
            int end = time.indexOf("H");
            // if there is H in a string but there is no value for hours,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
                //Messages.getMessage("badTimeDuration"));
            }
            if (end != -1) {
                hours = Integer.parseInt(time.substring(0, end));
                start = end + 1;
            }

            // Minutes
            end = time.indexOf("M");
            // if there is M in a string but there is no value for hours,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
//                        Messages.getMessage("badTimeDuration"));
            }

            if (end != -1) {
                minutes = Integer.parseInt(time.substring(start, end));
                start = end + 1;
            }

            // Seconds
            end = time.indexOf("S");
            // if there is S in a string but there is no value for hours,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
                //Messages.getMessage("badTimeDuration"));
            }

            if (end != -1) {
                setSeconds(Double.parseDouble(time.substring(start, end)));
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badTimeDuration"));
        }
    }

    /**
     * This method parses the date portion of a String that represents xsd:duration - nYnMnD.
     *
     * @param date
     * @throws IllegalArgumentException if date does not match pattern
     */
    public void parseDate(String date) throws IllegalArgumentException {
        if (date.length() == 0 || date.indexOf("-") != -1) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badDateDuration"));
        }

        // check if date string ends with either Y, M, or D
        if (!date.endsWith("Y") && !date.endsWith("M") && !date.endsWith("D")) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badDateDuration"));
        }

        // catch any parsing exception
        try {
            // parse string and extract years, months, days
            int start = 0;
            int end = date.indexOf("Y");

            // if there is Y in a string but there is no value for years,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
                // Messages.getMessage("badDateDuration"));
            }
            if (end != -1) {
                years = Integer.parseInt(date.substring(0, end));
                start = end + 1;
            }

            // months
            end = date.indexOf("M");
            // if there is M in a string but there is no value for months,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
                //Messages.getMessage("badDateDuration"));
            }
            if (end != -1) {
                months = Integer.parseInt(date.substring(start, end));
                start = end + 1;
            }

            end = date.indexOf("D");
            // if there is D in a string but there is no value for days,
            // throw an exception
            if (start == end) {
                throw new IllegalArgumentException();
                // Messages.getMessage("badDateDuration"));
            }
            if (end != -1) {
                days = Integer.parseInt(date.substring(start, end));
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException();
            //Messages.getMessage("badDateDuration"));
        }
    }

    /**
     *
     */
    public boolean isNegative() {
        return isNegative;
    }

    /**
     *
     */
    public int getYears() {
        return years;
    }

    /**
     *
     */
    public int getMonths() {
        return months;
    }

    /**
     *
     */
    public int getDays() {
        return days;
    }

    /**
     *
     */
    public int getHours() {
        return hours;
    }

    /**
     *
     */
    public int getMinutes() {
        return minutes;
    }

    /**
     *
     */
    public double getSeconds() {
        return seconds;
    }

    /** @param negative  */
    public void setNegative(boolean negative) {
        isNegative = negative;
    }

    /** @param years  */
    public void setYears(int years) {
        this.years = years;
    }

    /** @param months  */
    public void setMonths(int months) {
        this.months = months;
    }

    /** @param days  */
    public void setDays(int days) {
        this.days = days;
    }

    /** @param hours  */
    public void setHours(int hours) {
        this.hours = hours;
    }

    /** @param minutes  */
    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    /**
     * @param seconds
     * @deprecated use {@link #setSeconds(double) setSeconds(double)} instead
     */
    public void setSeconds(int seconds) {
        this.seconds = seconds;
    }

    /**
     * Sets the seconds. NOTE: The fractional value of seconds is rounded up to milliseconds.
     *
     * @param seconds double
     */
    public void setSeconds(double seconds) {
        this.seconds = ((double)(Math.round(seconds * 100))) / 100;
    }

    /** This returns the xml representation of an xsd:duration object. */
    public String toString() {
        StringBuffer duration = new StringBuffer();

        duration.append("P");

        if (years != 0) {
            duration.append(years).append("Y");
        }
        if (months != 0) {
            duration.append(months).append("M");
        }
        if (days != 0) {
            duration.append(days).append("D");
        }
        if (hours != 0 || minutes != 0 || seconds != 0.0) {
            duration.append("T");

            if (hours != 0) {
                duration.append(hours).append("H");

            }
            if (minutes != 0) {
                duration.append(minutes).append("M");

            }
            if (seconds != 0) {
                if (seconds == (int)seconds) {
                    duration.append((int)seconds).append("S");
                } else {
                    duration.append(seconds).append("S");
                }
            }
        }

        if (duration.length() == 1) {
            duration.append("T0S");
        }

        if (isNegative) {
            duration.insert(0, "-");
        }

        return duration.toString();
    }

    /**
     * The equals method compares the time represented by duration object, not its string
     * representation. Hence, a duration object representing 65 minutes is considered equal to a
     * duration object representing 1 hour and 5 minutes.
     *
     * @param object
     */
    public boolean equals(Object object) {
        if (!(object instanceof Duration)) {
            return false;
        }

        Duration duration = (Duration)object;

        return this.isNegative == duration.isNegative &&
                this.getAsCalendar().equals(duration.getAsCalendar());
    }

    public long compare(Duration duration) {
        return this.getAsCalendar().getTimeInMillis() - duration.getAsCalendar().getTimeInMillis();
    }

    public int hashCode() {
        int hashCode = 0;

        if (isNegative) {
            hashCode++;
        }
        hashCode += years;
        hashCode += months;
        hashCode += days;
        hashCode += hours;
        hashCode += minutes;
        hashCode += seconds;
        // milliseconds
        hashCode += (seconds * 100) % 100;

        return hashCode;
    }

    /**
     * Returns duration as a calendar.  Due to the way a Calendar class works, the values for
     * particular fields may not be the same as obtained through getter methods.  For example, if a
     * duration's object getMonths returns 20, a similar call on a calendar object will return 1
     * year and 8 months.
     *
     * @return Calendar
     */
    public Calendar getAsCalendar() {
        return getAsCalendar(Calendar.getInstance());
    }

    /**
     * Returns duration as a calendar.  Due to the way a Calendar class works, the values for
     * particular fields may not be the same as obtained through getter methods.  For example, if a
     * Duration's object getMonths returns 20, a similar call on a Calendar object will return 1
     * year and 8 months.
     *
     * @param startTime Calendar
     * @return Calendar
     */
    public Calendar getAsCalendar(Calendar startTime) {
        Calendar ret = (Calendar)startTime.clone();
        ret.set(Calendar.YEAR, years);
        ret.set(Calendar.MONTH, months);
        ret.set(Calendar.DATE, days);
        ret.set(Calendar.HOUR, hours);
        ret.set(Calendar.MINUTE, minutes);
        ret.set(Calendar.SECOND, (int)seconds);
        ret.set(Calendar.MILLISECOND,
                (int)(seconds * 100 - Math.round(seconds) * 100));
        return ret;
    }
}




Copyright 1998-2008 Alvin Alexander
All Rights Reserved.
 
devdaily.com is based in louisville, kentucky, and this web site is hosted by godaddy.com