| /* |
| * 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</a> |
| */ |
| 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; |
| } |
| } |