org.kalypso.model.hydrology.internal.preprocessing.writer.NetFileWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.model.hydrology.internal.preprocessing.writer.NetFileWriter.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.preprocessing.writer;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.runtime.IStatus;
import org.kalypso.contribs.eclipse.core.runtime.IStatusCollector;
import org.kalypso.contribs.eclipse.core.runtime.StatusCollector;
import org.kalypso.contribs.java.net.UrlUtilities;
import org.kalypso.model.hydrology.binding.control.NAControl;
import org.kalypso.model.hydrology.binding.model.KontEntnahme;
import org.kalypso.model.hydrology.binding.model.KontZufluss;
import org.kalypso.model.hydrology.binding.model.Ueberlauf;
import org.kalypso.model.hydrology.binding.model.nodes.Branching;
import org.kalypso.model.hydrology.binding.model.nodes.BranchingWithNode;
import org.kalypso.model.hydrology.binding.model.nodes.INode;
import org.kalypso.model.hydrology.binding.model.nodes.Node;
import org.kalypso.model.hydrology.binding.model.nodes.Verzweigung;
import org.kalypso.model.hydrology.internal.IDManager;
import org.kalypso.model.hydrology.internal.ModelNA;
import org.kalypso.model.hydrology.internal.NaAsciiDirs;
import org.kalypso.model.hydrology.internal.i18n.Messages;
import org.kalypso.model.hydrology.internal.preprocessing.NAPreprocessorException;
import org.kalypso.model.hydrology.internal.preprocessing.RelevantNetElements;
import org.kalypso.model.hydrology.internal.preprocessing.net.NetElement;
import org.kalypso.model.hydrology.internal.preprocessing.timeseries.GrapWriter;
import org.kalypso.ogc.sensor.IAxis;
import org.kalypso.ogc.sensor.IObservation;
import org.kalypso.ogc.sensor.ITupleModel;
import org.kalypso.ogc.sensor.ObservationUtilities;
import org.kalypso.ogc.sensor.SensorException;
import org.kalypso.ogc.sensor.metadata.ITimeseriesConstants;
import org.kalypso.ogc.sensor.util.ZmlLink;
import org.kalypso.ogc.sensor.zml.ZmlFactory;
import org.kalypso.ogc.sensor.zml.ZmlURL;
import org.kalypsodeegree.model.feature.Feature;

/**
 * Writes the collected net elements etc. into the .ntz file.
 *
 * @author doemming
 */
public class NetFileWriter extends AbstractCoreFileWriter {
    private final IStatusCollector m_log = new StatusCollector(ModelNA.PLUGIN_ID);

    private final UrlUtilities m_urlUtilities = new UrlUtilities();

    private final RelevantNetElements m_relevantElements;

    private final IDManager m_idManager;

    private final NAControl m_metaControl;

    private final NaAsciiDirs m_asciiDirs;

    private final URL m_zmlContext;

    public NetFileWriter(final NaAsciiDirs asciiDirs, final RelevantNetElements relevantElements,
            final IDManager idManager, final URL zmlContext, final NAControl metaControl, final Logger logger) {
        super(logger);

        m_asciiDirs = asciiDirs;

        m_relevantElements = relevantElements;
        m_idManager = idManager;
        m_zmlContext = zmlContext;
        m_metaControl = metaControl;
    }

    @Override
    protected void writeContent(final PrintWriter writer) throws IOException, NAPreprocessorException {
        final NetElement[] channels = m_relevantElements.getChannels();
        for (final NetElement netElement : channels)
            netElement.write(writer);

        final Entry<NetElement, Integer>[] rootChannels = m_relevantElements.getRootChannels();
        for (final Entry<NetElement, Integer> entry : rootChannels) {
            final NetElement netElement = entry.getKey();
            final Integer virtualChannelId = entry.getValue();
            netElement.writeRootChannel(writer, virtualChannelId);
        }

        try {
            final Node[] nodeCollector = m_relevantElements.getNodes();
            writer.append("99999\n"); //$NON-NLS-1$
            appendNodeList(nodeCollector, writer);
            writer.append("99999\n"); //$NON-NLS-1$
        } catch (final SensorException e) {
            e.printStackTrace();
            throw new NAPreprocessorException(Messages.getString("NetFileWriter_0"), e); //$NON-NLS-1$
        }
    }

    private void appendNodeList(final Node[] nodes, final PrintWriter netBuffer)
            throws IOException, SensorException {
        // FIXME: theses nodes do not contain the branching nodes
        final Map<Node, ZuflussBean> nodeInfos = new LinkedHashMap<>();

        /* First collect info and potentially add branching nodes */
        for (final Node node : nodes) {
            final ZuflussBean zuflussBean = createZuflussBean(node);

            // FIXME: strange we map the source-node here...
            nodeInfos.put(node, zuflussBean);

            final Node branchingNode = zuflussBean.getBranchingNode();
            if (branchingNode != null) {
                // FIXME: ... but check for the target node here; this can't be right, can it?
                // FIXME: comment is not correct
                /* Do not overwrite existing info */

                // FIXME: in reality, we make sure a node that is the target of a branching, gets a default bean; but this happens anyways, so what? -> if the target itself has a branching, it might get
                // removed, if the nodes are in the correct order...
                if (!nodeInfos.containsKey(branchingNode))
                    nodeInfos.put(branchingNode, new ZuflussBean(0, 0, 0, 0, 0, null, StringUtils.EMPTY));
            }
        }

        /* Write thes infos to file */
        final Set<Entry<Node, ZuflussBean>> entrySet = nodeInfos.entrySet();
        for (final Entry<Node, ZuflussBean> entry : entrySet) {
            final Node node = entry.getKey();
            final ZuflussBean zuflussBean = entry.getValue();

            final int nodeID = m_idManager.getAsciiID(node);

            netBuffer.format("%5d", nodeID); //$NON-NLS-1$

            netBuffer.format("%5d", zuflussBean.getIzug()); //$NON-NLS-1$
            netBuffer.format("%5d", zuflussBean.getIabg()); //$NON-NLS-1$
            netBuffer.format("%5d", zuflussBean.getIueb()); //$NON-NLS-1$
            netBuffer.format("%5d", zuflussBean.getIzuf()); //$NON-NLS-1$
            netBuffer.format("%5d\n", zuflussBean.getIvzwg()); //$NON-NLS-1$ //$NON-NLS-2$

            netBuffer.append(zuflussBean.getArgument());

            // FIXME: what additional nodes?
            /* TODO: we should also consider the additional nodes by QQ rleations; but as QQ rleations do not work..... */
        }

        // ENDKNOTEN
        netBuffer.append(" 9001    0    0    0    0    0\n"); //$NON-NLS-1$
        netBuffer.append("10000    0    0    0    0    0\n"); //$NON-NLS-1$
    }

    private ZuflussBean createZuflussBean(final Node node) throws SensorException, IOException {
        /* first create all possible beans, so we can check if we have multiple branchings */
        final ZuflussBean qqRelationBean = createQQRelationZuflussBean(node);
        final ZuflussBean branchingBean = createBranchingZuflussBean(node);
        final ZuflussBean zuflussLinkBean = createZuflussLinkZuflussBean(node);

        /* validation */
        final int count = countZuflussBeans(qqRelationBean, branchingBean, zuflussLinkBean);
        if (count > 1)
            m_log.add(IStatus.WARNING, Messages.getString("NetFileWriter.0"), null, node.getName()); //$NON-NLS-1$

        // QQ has the priority over "Verzweigung", and all of them are mutually exclusive so this is safe
        if (qqRelationBean != null)
            return qqRelationBean;

        // REMARK: only one branching can be used at the same time. Also, braching and zufluss cannot appear at
        // the same time. This is intended.
        if (branchingBean != null)
            return branchingBean;

        if (zuflussLinkBean != null)
            return zuflussLinkBean;

        return new ZuflussBean(0, 0, 0, 0, 0, null, StringUtils.EMPTY);
    }

    private int countZuflussBeans(final ZuflussBean... beans) {
        int count = 0;
        for (final ZuflussBean bean : beans) {
            if (bean != null)
                count++;
        }

        return count;
    }

    private ZuflussBean createQQRelationZuflussBean(final Node node) throws SensorException {
        final Node relatedNode = node.getQQRelatedNode();
        if (relatedNode == null)
            return null;

        final IObservation observation = (IObservation) node.getProperty(INode.PROPERTY_QQ_RELATION);
        if (observation == null)
            return null;

        /* serialize the qq relation */
        final StringBuilder buffer = new StringBuilder();
        final IAxis[] axisList = observation.getAxes();
        final IAxis q1Axis = ObservationUtilities.findAxisByType(axisList, ITimeseriesConstants.TYPE_RUNOFF);
        final IAxis q2Axis = ObservationUtilities.findAxisByType(axisList, ITimeseriesConstants.TYPE_RUNOFF_RHB);
        final ITupleModel values = observation.getValues(null);
        final int count = values.size();
        if (count < 1)
            return null;
        buffer.append(String.format("%4d %6s\n", count, m_idManager.getAsciiID(relatedNode))); //$NON-NLS-1$
        for (int row = 0; row < count; row++) {
            final double q1 = (Double) values.get(row, q1Axis);
            final double q2 = (Double) values.get(row, q2Axis);
            buffer.append(String.format(Locale.ENGLISH, "%8.3f %8.3f\n", q1, q2)); //$NON-NLS-1$
        }

        final String value = buffer.toString();

        return new ZuflussBean(0, 0, 0, 0, 2, relatedNode, value);
    }

    private ZuflussBean createZuflussLinkZuflussBean(final Node node) throws SensorException, IOException {
        final ZmlLink zuflussLink = node.getZuflussLink();
        if (!zuflussLink.isLinkSet())
            return null;

        /* write zufluss file */
        final String zuflussFileName = getZuflussEingabeDateiString(node);
        final File targetFile = new File(m_asciiDirs.zuflussDir, zuflussFileName);

        final String zuflussFile = ZmlURL.getIdentifierPart(zuflussLink.getHref());
        final URL linkURL = m_urlUtilities.resolveURL(m_zmlContext, zuflussFile);
        if (!targetFile.exists()) {
            final StringBuilder writer = new StringBuilder();
            final IObservation observation = ZmlFactory.parseXML(linkURL); //$NON-NLS-1$

            // FIXME: this functionality is currently deactivated, because it is wrongly implemented.
            final boolean isSynteticZufluss = false;
            // node.isSynteticZufluss();
            if (isSynteticZufluss) {
                final Integer minutesOfTimestep = m_metaControl.getMinutesOfTimestep();

                if (m_metaControl.isUsePrecipitationForm()) {
                    final ITupleModel values = observation.getValues(null);
                    final IAxis[] axis = observation.getAxes();
                    final IAxis dateAxis = ObservationUtilities.findAxisByType(axis,
                            ITimeseriesConstants.TYPE_DATE);
                    final long simulationStartDateMillis = ((Date) values.get(0, dateAxis)).getTime();
                    final long simulationEndDateMillis = ((Date) values.get(values.size() - 1, dateAxis)).getTime();

                    // FIXME: this will not work correctly with timezones

                    final Date simulationStartDate = new Date(100, 0, 1);
                    final Date simulationEndDate = new Date(
                            simulationStartDate.getTime() + simulationEndDateMillis - simulationStartDateMillis);

                    final GrapWriter grapWriter = new GrapWriter(ITimeseriesConstants.TYPE_RUNOFF, observation);
                    grapWriter.writeSyntheticFile(writer, simulationStartDate, simulationEndDate,
                            minutesOfTimestep);
                } else {
                    final Date simulationStart = m_metaControl.getSimulationStart();
                    final Date simulationEnd = m_metaControl.getSimulationEnd();
                    final GrapWriter grapWriter = new GrapWriter(ITimeseriesConstants.TYPE_RUNOFF, observation);
                    grapWriter.writeSyntheticFile(writer, simulationStart, simulationEnd, minutesOfTimestep);
                }
            } else {
                final GrapWriter grapWriter = new GrapWriter(ITimeseriesConstants.TYPE_RUNOFF, observation);
                grapWriter.write(writer);
            }

            FileUtils.writeStringToFile(targetFile, writer.toString());
        }

        /* create arguent */
        final StringBuilder buffer = new StringBuilder();
        buffer.append("    1234\n"); // dummyLine //$NON-NLS-1$
        buffer.append("..").append(File.separator).append("zufluss").append(File.separator).append(zuflussFileName) //$NON-NLS-1$//$NON-NLS-2$
                .append("\n"); //$NON-NLS-1$
        final String argument = buffer.toString();

        /* create bean entry */
        return new ZuflussBean(0, 0, 0, 5, 0, null, argument);
    }

    private ZuflussBean createBranchingZuflussBean(final Node node) {
        final Branching branching = node.getBranching();
        if (branching == null)
            return null;

        final Node branchNode;
        if (branching instanceof BranchingWithNode)
            branchNode = ((BranchingWithNode) branching).getNode();
        else
            branchNode = null;

        String branchIdArgument = StringUtils.EMPTY;
        if (branchNode != null) {
            final int branchNodeID = m_idManager.getAsciiID(branchNode);
            branchIdArgument = String.format(" %7d\n", branchNodeID); //$NON-NLS-1$
        }

        if (branching instanceof KontZufluss) {
            final double qzug = ((KontZufluss) branching).getQZug();
            final String argument = String.format(Locale.US, "%10.3f", qzug); //$NON-NLS-1$
            return new ZuflussBean(1, 0, 0, 0, 0, branchNode, argument);
        }

        if (branching instanceof Verzweigung) {
            final double zproz = ((Verzweigung) branching).getZProz();
            final String argument = String.format(Locale.US, "%10.3f", zproz); //$NON-NLS-1$
            return new ZuflussBean(0, 0, 0, 0, 1, branchNode, argument + branchIdArgument);
        }

        if (branching instanceof KontEntnahme) {
            final double qabg = ((KontEntnahme) branching).getQAbg();
            final String argument = String.format(Locale.US, "%10.3f", qabg); //$NON-NLS-1$
            return new ZuflussBean(0, 1, 0, 0, 0, branchNode, argument + branchIdArgument);
        }

        if (branching instanceof Ueberlauf) {
            final double queb = ((Ueberlauf) branching).getQUeb();
            final String argument = String.format(Locale.US, "%10.3f", queb); //$NON-NLS-1$
            return new ZuflussBean(0, 0, 1, 0, 0, branchNode, argument + branchIdArgument);
        }

        throw new IllegalArgumentException("Illegal branching type: " + branching.getClass()); //$NON-NLS-1$
    }

    private String getZuflussEingabeDateiString(final Feature nodeFE) {
        final int asciiID = m_idManager.getAsciiID(nodeFE);
        return "Z_" + Integer.toString(asciiID).trim() + ".zufluss"; //$NON-NLS-1$ //$NON-NLS-2$
    }

    public IStatus getStatus() {
        return m_log.asMultiStatusOrOK(Messages.getString("NetFileWriter.2")); //$NON-NLS-1$
    }
}