You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

package nl.wldelft.timeseriesparsers;

import nl.wldelft.util.TextUtils;
import nl.wldelft.util.TimeZoneUtils;
import nl.wldelft.util.io.XmlParser;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: pelgrim
 * Date: 8/9/13
 * Time: 9:35 AM
 * To change this template use File | Settings | File Templates.
 */
public class AifsMLTimeSeriesParser implements XmlParser<TimeSeriesContentHandler> {
    private TimeSeriesContentHandler contentHandler = null;
    private String virtualFileName = null;
    private XMLStreamReader reader = null;
    private DefaultTimeSeriesHeader header = null;

    //Use for all
    private String externalForecastTime = null;
    private String productId = null;
    private String sequenceNumber = null;

    @Override
    public void parse(XMLStreamReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
        this.reader = reader;
        this.virtualFileName = virtualFileName;
        this.contentHandler = contentHandler;

        header = new DefaultTimeSeriesHeader();

        reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
        reader.nextTag();
        reader.require(XMLStreamConstants.START_ELEMENT, null, "aifsml");
        reader.nextTag();
        reader.require(XMLStreamConstants.START_ELEMENT, null, "metadata");

        parseMetadata();

        parseForeCasts();
    }

    /**
     * Retrieve the productId, externalForecastTime and sequenceNumber from the elements within the metadata element
     *
     * @throws javax.xml.stream.XMLStreamException;
     */
    private void parseMetadata() throws XMLStreamException {
        reader.nextTag();
        if (TextUtils.equals(reader.getLocalName(), "product-id")) {
            productId = reader.getElementText();
        }
        goTo("issue-time-utc");
        externalForecastTime = reader.getElementText();
        goTo("sequence-number");
        sequenceNumber = reader.getElementText();
    }

    /**
     * Retrieve the locationId from the forecast element(s) and call separate method to parse forecast data
     *
     * @throws javax.xml.stream.XMLStreamException;
     */
    private void parseForeCasts() throws XMLStreamException {
        do {
            if (!goTo("forecast")) return;
            String locationId = reader.getAttributeValue(null, "locationId");
            parseForecastData(locationId);
        } while (reader.hasNext());
    }

    /**
     * Retrieve the variable, value, unit and time from the forecast data element(s)
     * Retrieve comment text from forecast text element
     * @throws javax.xml.stream.XMLStreamException;
     */
    private void parseForecastData(String locationId) throws XMLStreamException {
        goTo("forecast_data");
        //Read in variable, value, unit and time-local for all forecast data elements
        //Store them in an array of strings for each data element for later use by the contentHandler
        List<String[]> forecastDataList = new ArrayList<String[]>();
        while (TextUtils.equals(reader.getLocalName(), "forecast_data")) {
            String[] forecastData = new String[4];
            forecastData[0] = reader.getAttributeValue(null, "variable");
            forecastData[1] = reader.getAttributeValue(null, "value");
            forecastData[2] = reader.getAttributeValue(null, "unit");
            forecastData[3] = reader.getAttributeValue(null, "time-local");
            forecastDataList.add(forecastData);
            while(XMLStreamReader.START_ELEMENT != reader.nextTag());
        }
        String text = null;
        if (TextUtils.equals(reader.getLocalName(), "forecast_text")){
            text = reader.getElementText();
        }

        //After the forecast text is read, info is ready to be applied
        //ForecastTime, productId, sequenceNumber is the same for the entire import
        //locationId and "text" for the comment is the same for the coming list of forecastData
        //The forecastDataList contains ParameterId, Value, Unit and Time which can differ every time

        header.setForecastTime(TimeZoneUtils.GMT, "yyyy-MM-dd'T'HH:mm:ss'Z'", externalForecastTime);
        header.setLocationId(locationId);
        contentHandler.setComment(productId + " " + sequenceNumber + " " + text);
        for (int i = 0; i < forecastDataList.size(); i++){
            String[] fcd = forecastDataList.get(i);
            header.setParameterId(fcd[0]);
            contentHandler.setValue('.', fcd[1]);
            header.setUnit(fcd[2]);
            long rawTimeZoneOffset = TimeZoneUtils.parseRawTimeZoneOffset(fcd[3].substring(fcd[3].length()-6));
            contentHandler.setTime(TimeZoneUtils.getTimeZone(rawTimeZoneOffset), "yyyy-MM-dd'T'HH:mm:ss", fcd[3].substring(0, fcd[3].length()-6));
            contentHandler.setTimeSeriesHeader(header);
            contentHandler.applyCurrentFields();
        }
    }

    /**
     * This method skips elements until a start element with the corresponding local name is found and returns true, if not returns false
     * Warning: if the element is not found the reader is skipped until the end of the document
     * @param localName
     * @return boolean
     * @throws XMLStreamException
     */
    private boolean goTo(String localName) throws XMLStreamException {
        do {
            if (!reader.hasNext()) return false;
            reader.next();
        } while (!reader.isStartElement() || !TextUtils.equals(reader.getLocalName(), localName));
        return true;
    }

}
  • No labels