org.kalypso.model.hydrology.internal.postprocessing.BlockTimeSeries.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.model.hydrology.internal.postprocessing.BlockTimeSeries.java

Source

/*--------------- Kalypso-Header --------------------------------------------------------------------
    
 This file is part of kalypso.
 Copyright (C) 2004, 2005 by:
    
 Technical University Hamburg-Harburg (TUHH)
 Institute of River and coastal engineering
 Denickestr. 22
 21073 Hamburg, Germany
 http://www.tuhh.de/wb
    
 and
    
 Bjoernsen Consulting Engineers (BCE)
 Maria Trost 3
 56070 Koblenz, Germany
 http://www.bjoernsen.de
    
 This library 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.1 of the License, or (at your option) any later version.
    
 This library 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 this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
 Contact:
    
 E-Mail:
 belger@bjoernsen.de
 schlienger@bjoernsen.de
 v.doemming@tuhh.de
    
 ---------------------------------------------------------------------------------------------------*/
package org.kalypso.model.hydrology.internal.postprocessing;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;

import org.apache.commons.io.IOUtils;
import org.kalypso.model.hydrology.internal.NATimeSettings;

public class BlockTimeSeries {
    private static DatatypeFactory DATATYPE_FACTORY;
    static {
        try {
            DATATYPE_FACTORY = DatatypeFactory.newInstance();
        } catch (final DatatypeConfigurationException e) {
            e.printStackTrace();
        }
    }

    // simulationszeitraum: von 970101 24 uhr bis 980102 24 uhr 24.000
    // simulationszeitraum: von 970101 24 uhr bis 102 24 uhr 24.000
    //  private static final Pattern pTime = Pattern.compile( ".+simulationszeitraum.+([0-9]{6}).+?([0-9]{1,2}).+[0-9]{3,6}.+[0-9]{1,2}.+?(\\d+\\.\\d+)\\D*" ); //$NON-NLS-1$

    // synth. n.: haufigkeit: 0.100 jahre,dauer: 13.00 h , zeitschr.: 0.083 h , verteilung: 2
    private static final Pattern pSynthTime = Pattern.compile(
            ".+synth. n..+haufigkeit:.+(\\d+\\.\\d+).+jahre,dauer.+(\\d+\\.\\d+).+h , zeitschr.:.+(\\d+\\.\\d+).+"); //$NON-NLS-1$

    private static final Pattern PATTERN_BLOCK_HEADER = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D+(\\d+)\\D*"); //$NON-NLS-1$

    private final Map<String, Block> m_blocks = new HashMap<>();

    private final DateFormat m_dateFormat;

    private final ENACoreResultsFormat m_resultsFormat;

    public BlockTimeSeries(final ENACoreResultsFormat resultsFormat, final TimeZone timeZone) {
        m_resultsFormat = resultsFormat;
        m_dateFormat = new SimpleDateFormat(resultsFormat.getDateFormat()); //$NON-NLS-1$
        m_dateFormat.setTimeZone(timeZone);
    }

    public BlockTimeSeries(final ENACoreResultsFormat resultsFormat) {
        this(resultsFormat, NATimeSettings.getInstance().getTimeZone());
    }

    /**
     * imports all ts from given blockfile
     */
    public void importBlockFile(final File blockFile) {
        LineNumberReader reader = null;
        try {
            reader = new LineNumberReader(new FileReader(blockFile));

            final BlockTimeStep timeStep = searchTimeoffset(reader);

            while (reader.ready()) {
                final Entry<String, Integer> blockInfo = searchBlockHeader(reader);
                if (blockInfo == null)
                    break;

                final String key = blockInfo.getKey();
                final int valuesCount = blockInfo.getValue();

                // Add values to existing block
                final Block block = getOrCreateBlock(key, timeStep);
                block.readValues(reader, valuesCount);
            }
            reader.close();
        } catch (final Exception e) {
            e.printStackTrace();
            System.out.println("could not read blockfile "); //$NON-NLS-1$
        } finally {
            IOUtils.closeQuietly(reader);
        }
    }

    private Block getOrCreateBlock(final String key, final BlockTimeStep timeStep) {
        if (m_blocks.containsKey(key))
            return m_blocks.get(key);

        final Block block = new Block(key, timeStep);
        m_blocks.put(key, block);
        return block;
    }

    private BlockTimeStep searchTimeoffset(final LineNumberReader reader) throws ParseException, IOException {
        while (reader.ready()) {
            final String line = reader.readLine();
            if (line == null)
                break;

            if (line.startsWith("#")) //$NON-NLS-1$
                continue;

            // final Matcher m = pTime.matcher( line );
            final Matcher m = m_resultsFormat.getSimulationPeriodPattern().matcher(line);
            final Matcher synthM = pSynthTime.matcher(line);
            if (m.matches()) {
                final String sDate = m.group(1);
                final String sTime = m.group(2);
                final String sStep = m.group(3);

                final Calendar startCal = parseDate24(sDate, sTime);
                final Duration timestep = parseDuration(sStep);
                return new BlockTimeStep(startCal, timestep);
            } else if (synthM.matches()) {
                // synthetisches Ereignis hat kein Anfangsdatum, daher wird 01.01.2000 angenommen!
                final Calendar startCal = m_dateFormat.getCalendar();
                startCal.set(2000, 1, 1, 0, 0);

                final String sStep = synthM.group(3);
                final Duration timestep = parseDuration(sStep);
                return new BlockTimeStep(startCal, timestep);
            }
        }

        return null;
    }

    private Entry<String, Integer> searchBlockHeader(final LineNumberReader reader)
            throws NumberFormatException, IOException {
        while (reader.ready()) {
            final String line = reader.readLine();
            if (line == null)
                break;

            if (line.startsWith("#")) //$NON-NLS-1$
                continue;

            final Matcher m = PATTERN_BLOCK_HEADER.matcher(line);
            if (m.matches()) {
                final String key = m.group(1);
                final int valuesCount = Integer.parseInt(m.group(3));

                // HACK: create singleton map in order to create entry
                return Collections.singletonMap(key, valuesCount).entrySet().iterator().next();
            }
        }

        return null;
    }

    private Duration parseDuration(final String sStep) {
        // TRICKY: the read value is in hours.
        // If we just calculate the millies from that, we cannot really compute with that duration and get strange effects
        // due to skip-seconds etc.

        final float hours = Float.parseFloat(sStep);

        // Try to find the best match

        // month and year do not have a fixed number of hours, so we cannot match

        final Duration dayMatch = getDurationAsDays(hours);
        if (dayMatch != null)
            return dayMatch;

        final Duration hourMatch = getDurationAsHours(hours);
        if (hourMatch != null)
            return hourMatch;

        final Duration minuteMatch = getDurationAsMinutes(hours);
        return minuteMatch;

        // TODO: implement SECONDS?

        //
        //    if( "0.083".equals( sStep ) ) //$NON-NLS-1$
        // return DATATYPE_FACTORY.newDuration( 300000l );
        // else
        // {
        // float step = Float.parseFloat( sStep );
        // return DATATYPE_FACTORY.newDuration( ((long) (step * 1000f)) * 3600l );
        // }
    }

    private Duration getDurationAsDays(final float hours) {
        final float days = hours / 24.0f;
        final int daysRounded = Math.round(days);

        if (days == Integer.valueOf(daysRounded).floatValue())
            return DATATYPE_FACTORY.newDuration(true, 0, 0, daysRounded, 0, 0, 0);

        return null;
    }

    private Duration getDurationAsHours(final float hours) {
        final int hoursRounded = Math.round(hours);
        if (hours == hoursRounded)
            return DATATYPE_FACTORY.newDuration(true, 0, 0, 0, hoursRounded, 0, 0);

        return null;
    }

    // TODO: check
    // we assume, that the smallest amount here is minutes; so we just round the hours.
    // Actually, the hours of the calculation core have too less digits e.g. 0.083 is 4.98 minutes, but the real timestep
    // is 5.0 minutes. We need to change the calc core in order to return more digits!
    private Duration getDurationAsMinutes(final float hours) {
        final float minutes = hours * 60.0f;
        final int minutesRounded = Math.round(minutes);

        // if( minutes == daysRounded )
        return DATATYPE_FACTORY.newDuration(true, 0, 0, 0, 0, minutesRounded, 0);

        // return null;
    }

    private Calendar parseDate24(final String sDate, final String sTime) throws ParseException {
        final Date parseDate = m_dateFormat.parse(sDate);
        // final Calendar startCal = Calendar.getInstance( KalypsoCorePlugin.getDefault().getTimeZone() );
        final Calendar startCal = Calendar.getInstance(NATimeSettings.getInstance().getTimeZone());
        startCal.setTime(parseDate);

        int hours = Integer.parseInt(sTime);
        // 24 means 0 same day ! (RRM/fortran-logic)
        if (hours == 24)
            hours = 0; //$NON-NLS-1$

        startCal.add(Calendar.HOUR_OF_DAY, hours);

        return startCal;
    }

    public String[] getKeys() {
        return m_blocks.keySet().toArray(new String[m_blocks.keySet().size()]);
    }

    public void exportToFile(final String key, final File exportFile, final DateFormat dateFormat)
            throws IOException {
        if (m_blocks.containsKey(key)) {
            final Block block = m_blocks.get(key);
            block.exportToFile(exportFile, dateFormat);
        }
    }

    public Block getTimeSerie(final String key) {
        return m_blocks.get(key);
    }

    public boolean dataExistsForKey(final String key) {
        return m_blocks.containsKey(key);
    }
}