Subversion Repositories public iLand

Rev

Rev 1221 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/********************************************************************************************
**    iLand - an individual based forest landscape and disturbance model
**    http://iland.boku.ac.at
**    Copyright (C) 2009-  Werner Rammer, Rupert Seidl
**
**    This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
**
**    This program 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 General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program.  If not, see <http://www.gnu.org/licenses/>.
********************************************************************************************/


#ifndef OUTPUT_H
#define OUTPUT_H
#include <QtCore/QString>
#include <QtCore/QVariant>
#include <QtSql/QSqlQuery>
#include <QtCore/QVector>

#include "global.h"

enum OutputDatatype { OutInteger, OutDouble, OutString };
enum OutputMode { OutDatabase, OutFile, OutText };

class XmlHelper;
class Output;
class GlobalSettings;
class OutputColumn
{
public:
    OutputColumn(const QString name, const QString description, const OutputDatatype datatype):
            mName(name), mDescription(description), mDatatype(datatype) {}
    static OutputColumn year() { return OutputColumn("year", "simulation year", OutInteger); }
    static OutputColumn species() { return OutputColumn("species", "tree species", OutString); }
    static OutputColumn ru() { return OutputColumn("ru", "index of ressource unit", OutInteger); }
    static OutputColumn id() { return OutputColumn("rid", "id of ressource unit (-1: no ids set)", OutInteger); }
    const QString &name() const { return mName; }
    const QString &description() const { return mDescription; }
    QString datatype() const { switch(mDatatype) { case OutInteger: return QString("integer"); case OutDouble: return QString("double"); default: return QString("string"); } }
private:
    QString mName;
    QString mDescription;
    OutputDatatype mDatatype;
friend class Output;
};

class Output
{
public:
    Output(); ///< ctor. Override in derived class to craete columns, etc.
    virtual ~Output();
    virtual void setup(); ///< setup() is called during project setup and can be ovveridden for specific setup

    void open(); ///< open output connection (create actual db connection, ...)
    bool isOpen() const { return mOpen; } ///< returns true if output is open, i.e. has a open database connection
    void close(); ///< shut down the connection.
    bool isEnabled() const { return mEnabled; } ///< returns true if output is enabled, i.e. is "turned on"
    void setEnabled(const bool enabled) { mEnabled=enabled; if(enabled) open(); }
    bool isRowEmpty() const { return mIndex==0; } ///< returns true if the buffer of the current row is empty

    virtual void exec(); ///< main function that executes the output

    // properties
    const QList<OutputColumn> getColumns() const { return mColumns; }

    const QString name() const { return mName;  } ///< descriptive name of the ouptut
    const QString description() const { return mDescription; } ///< description of output
    const QString tableName() const { return mTableName; } ///< internal output name (no spaces allowed)
    QString wikiFormat() const; ///< return output description in a (tiki)-wiki format

    // save data
    Output & operator<< ( const double& value ) { add(value); return *this; }
    Output & operator<< ( const int value ) { add(value); return *this; }
    Output & operator<< ( const QString &value ) { add(value); return *this; }

protected:
    void setName(const QString &name, const QString tableName) { mName = name; mTableName=tableName; }
    void setDescription(const QString &description) { mDescription=description; }
    QList<OutputColumn> &columns()  { return mColumns; }
    int currentYear() const { return gl->currentYear(); }
    const XmlHelper &settings() const { return gl->settings(); } ///< access XML settings (see class description)
    // add data
    void writeRow(); ///< saves the current row/line of data to database/file. Must be called f

    inline void add(const double &value);
    void add(const double &value1, const double &value2) { add(value1); add(value2); }
    void add(const double &value1, const double &value2, const double &value3) { add(value1, value2); add(value3); }
    void add(const double &value1, const double &value2, const double &value3, const double &value4) { add(value1, value2); add(value3, value4); }
    void add(const double &value1, const double &value2, const double &value3, const double &value4, const double value5) { add(value1, value2); add(value3, value4, value5); }
    inline void add(const int intValue);
    inline void add(const QString &stringValue);

private:
    static const GlobalSettings *gl; ///< pointer to globalsettings object
    void newRow(); ///< starts a new row (resets the internal counter)
    void openDatabase(); ///< database open, create output table and prepare insert statement
    inline void saveDatabase(); ///< database save (exeute the "insert" statement)
    OutputMode mMode;
    bool mOpen;
    bool mEnabled;
    QString mName; ///< name of the output
    QString mTableName; ///< name of the table/output file
    QString mDescription; ///< textual description of the content
    QList<OutputColumn> mColumns; ///< list of columns of output
    QVector<QVariant> mRow; ///< current row
    QSqlQuery mInserter;
    int mCount;
    int mIndex;

};


void Output::add(const double &value)
{
    DBG_IF(mIndex>=mCount || mIndex<0,"Output::add(double)","output index out of range!");
    mRow[mIndex++].setValue(value);
}
void Output::add(const QString &value)
{
    DBG_IF(mIndex>=mCount || mIndex<0,"Output::add(string)","output index out of range!");
    mRow[mIndex++].setValue(value);
}
void Output::add(const int value)
{
    DBG_IF(mIndex>=mCount || mIndex<0,"Output::add(int)","output index out of range!");
    mRow[mIndex++].setValue(value);
}
#endif // OUTPUT_H