/*
* DateParser.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST 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
* of the License, or (at your option) any later version.
*
* BEAST 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 BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.evoxml;
import dr.evolution.util.Date;
import dr.evolution.util.Units;
import dr.evoxml.util.DateUnitsType;
import dr.evoxml.util.XMLUnits;
import dr.xml.*;
/**
* @author Alexei Drummond
* @author Andrew Rambaut
* @version $Id: DateParser.java,v 1.2 2005/05/24 20:25:59 rambaut Exp $
*/
public class DateParser extends AbstractXMLObjectParser {
public static final String VALUE = "value";
public static final String UNITS = "units";
public static final String ORIGIN = "origin";
public static final String DIRECTION = "direction";
public static final String FORWARDS = DateUnitsType.FORWARDS.getAttribute(); //"forwards";
public static final String BACKWARDS = DateUnitsType.BACKWARDS.getAttribute(); //"backwards";
public static final String YEARS = DateUnitsType.YEARS.getAttribute(); //"units";
public static final String MONTHS = DateUnitsType.MONTHS.getAttribute(); //"units";
public static final String DAYS = DateUnitsType.DAYS.getAttribute(); //"days";
public static final String PRECISION = "precision";
public String getParserName() {
return Date.DATE;
}
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
java.text.DateFormat dateFormat = java.text.DateFormat.getDateInstance(java.text.DateFormat.SHORT, java.util.Locale.UK);
dateFormat.setLenient(true);
if (xo.getChildCount() > 0) {
throw new XMLParseException("No child elements allowed in date element.");
}
double value = 0.0;
java.util.Date dateValue = null;
if (xo.hasAttribute(VALUE)) {
try {
value = xo.getDoubleAttribute(VALUE);
} catch (XMLParseException e) {
String dateString = xo.getStringAttribute(VALUE);
try {
dateValue = dateFormat.parse(dateString);
} catch (Exception ex) {
throw new XMLParseException("value=" + dateString + " not recognised as a date, use DD/MM/YYYY");
}
}
} else {
throw new XMLParseException("Value attribute missing from date element.");
}
boolean backwards = false;
if (xo.hasAttribute(DIRECTION)) {
String direction = (String) xo.getAttribute(DIRECTION);
if (direction.equals(BACKWARDS)) {
backwards = true;
}
}
Units.Type units = XMLUnits.Utils.getUnitsAttr(xo);
Date date;
if (xo.hasAttribute(ORIGIN)) {
String originString = (String) xo.getAttribute(ORIGIN);
java.util.Date origin;
try {
origin = dateFormat.parse(originString);
} catch (Exception e) {
throw new XMLParseException("origin=" + originString + " not recognised as a date, use DD/MM/YYYY");
}
if (dateValue != null) {
date = new Date(dateValue, units, origin);
} else {
date = new Date(value, units, backwards, origin);
}
} else {
// No origin specified so use default (1st Jan 1970)
if (dateValue != null) {
date = new Date(dateValue, units);
} else {
date = new Date(value, units, backwards);
}
}
if (xo.hasAttribute(PRECISION)) {
double precision = (Double)xo.getDoubleAttribute(PRECISION);
date.setPrecision(precision);
}
return date;
}
public String getParserDescription() {
return "Specifies a date on a given timescale";
}
public String getExample() {
return
"<!-- a date representing 10 years in the past -->\n" +
"<date value=\"10.0\" units=\"years\" direction=\"backwards\"/>\n" +
"\n" +
"<!-- a date representing 300 days after Jan 1st 1989 -->\n" +
"<date value=\"300.0\" origin=\"01/01/89\" units=\"days\" direction=\"forwards\"/>\n";
}
public XMLSyntaxRule[] getSyntaxRules() {
return rules;
}
private XMLSyntaxRule[] rules = new XMLSyntaxRule[]{
new StringAttributeRule(VALUE,
"The value of this date"),
new StringAttributeRule(ORIGIN,
"The origin of this time scale, which must be a valid calendar date", "01/01/01", true),
new StringAttributeRule(UNITS, "The units of the timescale", new String[]{YEARS, MONTHS, DAYS}, true),
new StringAttributeRule(DIRECTION, "The direction of the timescale", new String[]{FORWARDS, BACKWARDS}, true),
AttributeRule.newDoubleRule(PRECISION, true, "The precision to which the date is specified"),
};
public Class getReturnType() {
return dr.evolution.util.Date.class;
}
}