/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.convention.calendar;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.lang.Validate;
import org.threeten.bp.LocalDate;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.opengamma.OpenGammaRuntimeException;
/**
* Populates an {@code ExceptionCalendar} with working and non-working days from
* an XML data source.
*/
public class XMLCalendarLoader {
private static final String TAG_WORKING_DAYS = "WorkingDays";
private static final String TAG_NON_WORKING_DAYS = "NonWorkingDays";
private static final String TAG_DATE = "Date";
/**
* The state of the parser.
*/
private static enum ParserState {
WORKING_DAYS, NON_WORKING_DAYS, OTHER;
}
/**
* The source URI.
*/
private final String _sourceDataURI;
/**
* Creates an instance using the URI of the XML file.
* @param sourceDataUri the source URI, not null
*/
public XMLCalendarLoader(final String sourceDataUri) {
Validate.notNull(sourceDataUri, "URI");
_sourceDataURI = sourceDataUri;
}
// -------------------------------------------------------------------------
/**
* Gets the source data URI.
* @return the URI, not null
*/
protected String getSourceDataURI() {
return _sourceDataURI;
}
/**
* Throws a suitable exception.
* @param th the error, not null
* @return the exception to throw, not null
*/
private OpenGammaRuntimeException wrap(final Throwable th) {
return new OpenGammaRuntimeException("Unable to populate calendar from XML", th);
}
/**
* Populate the specified working day calendar from the XML file.
* @param calendar the calendar to populate, not null
*/
public void populateCalendar(final ExceptionCalendar calendar) {
final SAXParserFactory factory = SAXParserFactory.newInstance();
try {
final SAXParser parser = factory.newSAXParser();
parser.parse(getSourceDataURI(), new DefaultHandler() {
private ParserState _state = ParserState.OTHER;
private String _innerText;
@Override
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
switch (_state) {
case OTHER:
if (qName.equalsIgnoreCase(TAG_WORKING_DAYS)) {
_state = ParserState.WORKING_DAYS;
} else if (qName.equalsIgnoreCase(TAG_NON_WORKING_DAYS)) {
_state = ParserState.NON_WORKING_DAYS;
}
break;
}
}
@Override
public void characters(final char[] ch, final int start, final int length) {
_innerText = new String(ch, start, length);
}
@Override
public void endElement(final String uri, final String localName, final String qName) {
switch (_state) {
case WORKING_DAYS:
if (qName.equalsIgnoreCase(TAG_DATE)) {
calendar.addWorkingDay(LocalDate.parse(_innerText));
} else if (qName.equalsIgnoreCase(TAG_WORKING_DAYS)) {
_state = ParserState.OTHER;
}
break;
case NON_WORKING_DAYS:
if (qName.equalsIgnoreCase(TAG_DATE)) {
calendar.addNonWorkingDay(LocalDate.parse(_innerText));
} else if (qName.equalsIgnoreCase(TAG_NON_WORKING_DAYS)) {
_state = ParserState.OTHER;
}
break;
}
}
});
} catch (final ParserConfigurationException ex) {
throw wrap(ex);
} catch (final SAXException ex) {
throw wrap(ex);
} catch (final IOException ex) {
throw wrap(ex);
}
}
}