/* * file: XsdDuration.java * author: Jon Iles * copyright: (c) Packwood Software 2002-2003 * date: 20/02/2003 */ /* * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package net.sf.mpxj.mspdi; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import net.sf.mpxj.Duration; /** * This class parses and represents an xsd:duration value. */ final class XsdDuration { /** * Constructor. Parses the xsd:duration value and extracts the * duration data from it. * * @param duration value formatted as an xsd:duration */ XsdDuration(String duration) { if (duration != null) { int length = duration.length(); if (length > 0) { if (duration.charAt(0) != 'P') { if (length < 2 || (duration.charAt(0) != '-' && duration.charAt(1) != 'P')) { throw new IllegalArgumentException(duration); } } int index; boolean negative; if (duration.charAt(0) == '-') { index = 2; negative = true; } else { index = 1; negative = false; } while (index < length) { index = readComponent(duration, index, length); } if (negative == true) { m_years = -m_years; m_months = -m_months; m_days = -m_days; m_hours = -m_hours; m_minutes = -m_minutes; m_seconds = -m_seconds; } } } } /** * This constructor allows an xsd:duration to be created from * an MPX duration. * * @param duration An MPX duration. */ XsdDuration(Duration duration) { if (duration != null) { double amount = duration.getDuration(); if (amount != 0) { switch (duration.getUnits()) { case MINUTES: case ELAPSED_MINUTES: { m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case HOURS: case ELAPSED_HOURS: { m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case DAYS: case ELAPSED_DAYS: { m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case WEEKS: case ELAPSED_WEEKS: { amount *= 7; m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case MONTHS: case ELAPSED_MONTHS: { m_months = (int) amount; amount = (amount * 28) - (m_months * 28); m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case YEARS: case ELAPSED_YEARS: { m_years = (int) amount; amount = (amount * 12) - (m_years * 12); m_months = (int) amount; amount = (amount * 28) - (m_months * 28); m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } default: { break; } } } } } /** * This method is called repeatedly to parse each duration component * from sorting data in xsd:duration format. Each component consists * of a number, followed by a letter representing the type. * * @param duration xsd:duration formatted string * @param index current position in the string * @param length length of string * @return current position in the string */ private int readComponent(String duration, int index, int length) { char c = 0; StringBuilder number = new StringBuilder(); while (index < length) { c = duration.charAt(index); if (Character.isDigit(c) == true || c == '.') { number.append(c); } else { break; } ++index; } switch (c) { case 'Y': { m_years = Integer.parseInt(number.toString()); break; } case 'M': { if (m_hasTime == false) { m_months = Integer.parseInt(number.toString()); } else { m_minutes = Integer.parseInt(number.toString()); } break; } case 'D': { m_days = Integer.parseInt(number.toString()); break; } case 'T': { m_hasTime = true; break; } case 'H': { m_hours = Integer.parseInt(number.toString()); break; } case 'S': { m_seconds = Double.parseDouble(number.toString()); break; } default: { throw new IllegalArgumentException(duration); } } ++index; return (index); } /** * Retrieves the number of days. * * @return int */ public int getDays() { return (m_days); } /** * Retrieves the number of hours. * * @return int */ public int getHours() { return (m_hours); } /** * Retrieves the number of minutes. * * @return int */ public int getMinutes() { return (m_minutes); } /** * Retrieves the number of months. * * @return int */ public int getMonths() { return (m_months); } /** * Retrieves the number of seconds. * * @return double */ public double getSeconds() { return (m_seconds); } /** * Retrieves the number of years. * * @return int */ public int getYears() { return (m_years); } /** * This method generates the string representation of an xsd:duration value. * * @return xsd:duration value */ @Override public String toString() { StringBuilder buffer = new StringBuilder("P"); boolean negative = false; if (m_years != 0 || m_months != 0 || m_days != 0) { if (m_years < 0) { negative = true; buffer.append(-m_years); } else { buffer.append(m_years); } buffer.append("Y"); if (m_months < 0) { negative = true; buffer.append(-m_months); } else { buffer.append(m_months); } buffer.append("M"); if (m_days < 0) { negative = true; buffer.append(-m_days); } else { buffer.append(m_days); } buffer.append("D"); } buffer.append("T"); if (m_hours < 0) { negative = true; buffer.append(-m_hours); } else { buffer.append(m_hours); } buffer.append("H"); if (m_minutes < 0) { negative = true; buffer.append(-m_minutes); } else { buffer.append(m_minutes); } buffer.append("M"); if (m_seconds < 0) { negative = true; buffer.append(FORMAT.format(-m_seconds)); } else { buffer.append(FORMAT.format(m_seconds)); } buffer.append("S"); if (negative == true) { buffer.insert(0, '-'); } return (buffer.toString()); } private boolean m_hasTime; private int m_years; private int m_months; private int m_days; private int m_hours; private int m_minutes; private double m_seconds; /** * Configure the decimal separator to be independent of the * one used by the default locale. */ private static final DecimalFormatSymbols SYMBOLS = new DecimalFormatSymbols(); static { SYMBOLS.setDecimalSeparator('.'); } private static final DecimalFormat FORMAT = new DecimalFormat("#", SYMBOLS); }