package nl.wldelft.fews.pi;

import nl.wldelft.util.geodatum.GeoDatum;
import nl.wldelft.util.io.LineReader;
import nl.wldelft.util.io.VirtualInputDir;
import nl.wldelft.util.io.VirtualInputDirConsumer;
import nl.wldelft.util.io.XmlParser;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.LockableContentHandler;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;
import nl.wldelft.util.timeseries.TimeSeriesHeader;
import org.apache.log4j.Logger;

import javax.xml.stream.XMLStreamReader;
import java.io.BufferedInputStream;
import java.io.File;

public class PiMapStackParser implements XmlParser<TimeSeriesContentHandler>, VirtualInputDirConsumer {
    private static final Logger log = Logger.getLogger(PiMapStackParser.class);

    private DefaultTimeSeriesHeader timeSeriesHeader = new DefaultTimeSeriesHeader();
    private VirtualInputDir virtualInputDir = null;
    private PiMapStacksReader mapStackReader = null;
    private LockableContentHandler contentHandler = null;
    private String virtualFileName = null;

    @Override
    public void parse(XMLStreamReader reader, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {
        this.virtualFileName = virtualFileName;
        this.mapStackReader = new PiMapStacksReader(reader, virtualFileName, contentHandler.getDefaultTimeZone(), contentHandler.getDefaultGeoDatum());
        try {
            parse(contentHandler);
        } finally {
            mapStackReader.close();
        }
    }

    private void parse(final TimeSeriesContentHandler contentHandler) throws Exception {
        GeoDatum mapStackGeoDatum = mapStackReader.getGeoDatum();
        final GeoDatum geoDatum = mapStackGeoDatum != null ? mapStackGeoDatum : contentHandler.getDefaultGeoDatum();

        this.contentHandler = new LockableContentHandler(contentHandler) {
            @Override
            public void setNewTimeSeriesHeader(TimeSeriesHeader header) {
                // only called for bil files
                timeSeriesHeader.setEnsembleMemberIndex(timeSeriesHeader.getEnsembleMemberIndex() + 1);

                contentHandler.setNewTimeSeriesHeader(timeSeriesHeader);
            }

            @Override
            public GeoDatum getDefaultGeoDatum() {
                return geoDatum;
            }
        };

        this.contentHandler.setLockedHeader(timeSeriesHeader);
        this.contentHandler.setHeaderLocked(true);


        while (mapStackReader.next()) {
            timeSeriesHeader.setLocationId(mapStackReader.getLocationId());
            timeSeriesHeader.setParameterId(mapStackReader.getParameterId());
            timeSeriesHeader.setTimeStep(mapStackReader.getTimeStep());
            timeSeriesHeader.setEnsembleMemberIndex(-1);
            contentHandler.setComment(mapStackReader.getComment());


            long[] times = mapStackReader.getTimes();

            switch (mapStackReader.getFormatType()) {
                case ASCII:
                    parseAscii(times);
                    break;

                case PCRGRID:
                    parsePcRaster(times);
                    break;

                case USGS:
                    parseUsgs(times);
                    break;
            }
        }
    }

    private void parseAscii(long[] times) throws Exception {
        String fileNamePattern = mapStackReader.getFileName();
        contentHandler.setNewTimeSeriesHeader(timeSeriesHeader);
        EsriAsciiGridParser ascParser = new EsriAsciiGridParser();
        for (int i = 0; i < times.length; i++) {
            ascParser.setTime(times[i]);
            String fileName = PiMapStackUtils.replacePattern(fileNamePattern, i, times.length);
            if (!virtualInputDir.exists(fileName)) {
                log.error(fileName + " referenced in " + virtualFileName + " is missing");
                contentHandler.setTime(times[i]);
                contentHandler.setCoverageValues(null);
                contentHandler.applyCurrentFields();
                continue;
            }
            LineReader ascReader = virtualInputDir.getReader(fileName);
            try {
                ascParser.parse(ascReader, fileName, contentHandler);
            } finally {
                ascReader.close();
            }
        }
    }

    private void parsePcRaster(long[] times) throws Exception {
        String fileNamePattern = mapStackReader.getFileName();
        contentHandler.setNewTimeSeriesHeader(timeSeriesHeader);
        PcRasterParser pcrParser = new PcRasterParser();
        for (int i = 0; i < times.length; i++) {
            pcrParser.setTime(times[i]);
            String fileName = PiMapStackUtils.replacePattern(fileNamePattern, i, times.length);
            if (!virtualInputDir.exists(fileName)) {
                if (log.isDebugEnabled()) log.debug(fileName + " is missing, assume missing value grid");
                contentHandler.setTime(times[i]);
                contentHandler.setCoverageValues(null);
                contentHandler.applyCurrentFields();
                continue;
            }
            // todo handle virtual file
            File file = new File(fileName);
            if (!file.isAbsolute()) {
                File defaultDir = new File(virtualFileName).getParentFile();
                file = new File(defaultDir, fileName);
            }
            pcrParser.parse(file, this.contentHandler);
        }
    }

    private void parseUsgs(long[] times) throws Exception {
        PiBilParser bilParser = new PiBilParser();
        bilParser.setTimes(times);
        bilParser.setVirtualInputDir(virtualInputDir);
        bilParser.setOverrulingHeaderFileName(mapStackReader.getHeaderFileName());
        BufferedInputStream inputStream = virtualInputDir.getInputStream(mapStackReader.getFileName());
        try {
            bilParser.parse(inputStream, mapStackReader.getFileName(), this.contentHandler);
        } finally {
            inputStream.close();
        }
    }

    @Override
    public void setVirtualInputDir(VirtualInputDir virtualInputDir) {
        this.virtualInputDir = virtualInputDir;
    }
}
  • No labels