/* * Copyright 2013 Guidewire Software, Inc. */ package gw.xml.date; import java.math.BigDecimal; import java.util.StringTokenizer; import java.util.NoSuchElementException; import java.lang.RuntimeException; import java.lang.StringBuilder; import java.math.BigInteger; public class XmlDuration { public static final XmlDuration ZERO = new XmlDuration( "PT0S" ); private boolean _negative = false; private BigInteger _years = BigInteger.ZERO; private BigInteger _months = BigInteger.ZERO; private BigInteger _days = BigInteger.ZERO; private BigInteger _hours = BigInteger.ZERO; private BigInteger _minutes = BigInteger.ZERO; private BigDecimal _seconds = new BigDecimal( "0" ); public XmlDuration() { } public XmlDuration( String s ) { boolean gotField = false; boolean properlyTerminated = false; RuntimeException ex = new RuntimeException(); try { StringTokenizer st = new StringTokenizer( s, "PTZ-YMDHS", true ); String token = st.nextToken(); if ( token.equals( "-" ) ) { _negative = true; token = st.nextToken(); } if ( ! token.equals( "P" ) ) { throw ex; } properlyTerminated = true; token = st.nextToken(); while ( ! token.equals( "T" ) ) { properlyTerminated = false; String tmp = token; token = st.nextToken(); properlyTerminated = true; gotField = true; if ( token.length() != 1 ) { throw ex; } switch ( token.charAt( 0 ) ) { case 'Y': _years = new BigInteger(tmp); break; case 'M': _months = new BigInteger(tmp); break; case 'D': _days = new BigInteger(tmp); break; default: throw ex; } token = st.nextToken(); } properlyTerminated = true; token = st.nextToken(); //noinspection InfiniteLoopStatement while ( true ) { properlyTerminated = false; String tmp = token; token = st.nextToken(); properlyTerminated = true; gotField = true; if ( token.length() != 1 ) { throw ex; } switch ( token.charAt( 0 ) ) { case 'H': _hours = new BigInteger(tmp); break; case 'M': _minutes = new BigInteger(tmp); break; case 'S': _seconds = new BigDecimal( tmp ); break; default: throw ex; } token = st.nextToken(); } } catch ( NoSuchElementException e ) { if ( ! properlyTerminated || ! gotField ) { throw new RuntimeException( "Could not parse duration: " + s ); } } catch ( Exception e ) { //noinspection ObjectEquality throw new RuntimeException( "Could not parse duration: " + s, e == ex ? null : e ); } } public BigInteger getDays() { return _days; } public void setDays( BigInteger days ) { _days = days; } public BigInteger getHours() { return _hours; } public void setHours( BigInteger hours ) { _hours = hours; } public BigInteger getMinutes() { return _minutes; } public void setMinutes( BigInteger minutes ) { _minutes = minutes; } public BigInteger getMonths() { return _months; } public void setMonths( BigInteger months ) { _months = months; } public boolean isNegative() { return _negative; } public void setNegative( boolean negative ) { _negative = negative; } public BigDecimal getSeconds() { return _seconds; } public void setSeconds( BigDecimal seconds ) { _seconds = seconds; } public BigInteger getYears() { return _years; } public void setYears( BigInteger years ) { _years = years; } @Override public String toString() { if ( isZero() ) { // at least one field is required - we'll use "zero seconds" if ( _negative ) { return "-PT0S"; } else { return "PT0S"; } } StringBuilder sb = new StringBuilder(); if ( _negative ) { sb.append( "-" ); } sb.append( "P" ); if ( ! _years.equals( BigInteger.ZERO ) ) { sb.append( getYears() ); sb.append( "Y" ); } if ( ! _months.equals( BigInteger.ZERO ) ) { sb.append( getMonths() ); sb.append( "M" ); } if ( ! _days.equals( BigInteger.ZERO ) ) { sb.append( getDays() ); sb.append( "D" ); } if ( ! ( _hours.equals( BigInteger.ZERO ) && _minutes.equals( BigInteger.ZERO ) && _seconds.equals( BigDecimal.ZERO ) ) ) { sb.append( "T" ); if ( ! _hours.equals( BigInteger.ZERO ) ) { sb.append( getHours() ); sb.append( "H" ); } if ( ! _minutes.equals( BigInteger.ZERO ) ) { sb.append( getMinutes() ); sb.append( "M" ); } if ( ! _seconds.equals( BigDecimal.ZERO ) ) { sb.append( getSeconds() ); sb.append( "S" ); } } return sb.toString(); } public boolean isZero() { return _years.equals( BigInteger.ZERO ) && _months.equals( BigInteger.ZERO ) && _days.equals( BigInteger.ZERO ) && _hours.equals( BigInteger.ZERO ) && _minutes.equals( BigInteger.ZERO ) && _seconds.equals( BigDecimal.ZERO ); } }