view host/SimpleXMLRuleLoader.cpp @ 17:3cbd40805795 tip

Remove obsolete stuff from README
author Chris Cannam
date Tue, 03 Dec 2013 16:33:08 +0000
parents 47b0a143db39
children
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

#include "SimpleXMLRuleLoader.h"
#include "Rule.h"
#include "ImageAction.h"
#include "ExternalProcessAction.h"
#include "FDWriteAction.h"

#include <QFile>
#include <QIODevice>
#include <QXmlInputSource>

SimpleXMLRuleLoader::SimpleXMLRuleLoader() :
    m_processor(0),
    m_inPlugins(false),
    m_inRules(false),
    m_inRule(false),
    m_rule(0)
{
}

bool
SimpleXMLRuleLoader::loadFile(Processor &processor, QString fileName)
{
    QFile file(fileName);
        
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        std::cerr << "ERROR: SimpleXMLRuleLoader::load("
                  << fileName.toStdString()
                  << "): Failed to open file for reading" << std::endl;
        return false;
    }
    
    QXmlInputSource source(&file);
    return loadXml(processor, source);
}

bool
SimpleXMLRuleLoader::loadXml(Processor &processor, const QString &xmlData)
{
    QXmlInputSource source;
    source.setData(xmlData);
    return loadXml(processor, source);
}

bool
SimpleXMLRuleLoader::loadXml(Processor &processor, QXmlInputSource &source)
{
    QXmlSimpleReader reader;
    reader.setContentHandler(this);
    reader.setErrorHandler(this);
    m_processor = &processor;
    return reader.parse(source);
    m_processor = 0;
}

bool
SimpleXMLRuleLoader::startElement(const QString &namespaceURI,
                                  const QString &localName,
                                  const QString &qName,
                                  const QXmlAttributes &atts)
{
    QString name = qName.toLower();

    if (name == "plugins") {
        if (m_inPlugins) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Nested plugins elements" << std::endl;
            return false;
        } else {
            m_inPlugins = true;
        }
    } else if (name == "plugin") {
        if (!m_inPlugins) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Plugin outside plugins element" << std::endl;
            return false;
        }
        int extIndex = atts.value("index").toInt();
        if (m_externalInternalIndexMap.find(extIndex) != 
            m_externalInternalIndexMap.end()) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Duplicate plugin index "
                      << extIndex << std::endl;
            return false;
        }
        QString id = atts.value("id");
        int intIndex = m_processor->addPlugin(id);
        if (!intIndex) {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Failed to load plugin \""
                      << id.toStdString() << "\"" << std::endl;
        } else {
            std::cerr << "INFO: SimpleXMLRuleLoader: Successfully loaded plugin \"" << id.toStdString() << "\" (internal index " << intIndex << ", external index " << extIndex << ")" << std::endl;
            m_externalInternalIndexMap[extIndex] = intIndex;
        }
    } else if (name == "rules") {
        if (m_inRules) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Nested rules elements" << std::endl;
            return false;
        } else {
            m_inRules = true;
        }
    } else if (name == "outputrule") {

        if (!m_inRules) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Rule outside rules element" << std::endl;
            return false;
        }
        if (m_inRule) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Nested output rules" << std::endl;
            return false;
        }

        m_inRule = true;
        m_rule = new Rule();

    } else if (name == "condition") {

        if (!m_inRule) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Condition outside rule" << std::endl;
            return false;
        }
        
        int extIndex = atts.value("pluginIndex").toInt();

        if (m_externalInternalIndexMap.find(extIndex) ==
            m_externalInternalIndexMap.end()) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Unknown plugin index \""
                      << extIndex << "\" in rule" << std::endl;
            return false;
        }

        int intIndex = m_externalInternalIndexMap[extIndex];
        
        bool ok = false;
        int outputNumber = atts.value("outputNumber").toInt(&ok);
        if (!ok) outputNumber = 0;

        QString condStr = atts.value("condition").toLower();
        Condition::Type type(Condition::Present);

        if (condStr == "present") type = Condition::Present;
        else if (condStr == "equalto") type = Condition::EqualTo;
        else if (condStr == "greaterthan") type = Condition::GreaterThan;
        else if (condStr == "lessthan") type = Condition::LessThan;
        else if (condStr == "gapgreaterthan") type = Condition::GapGreaterThan;
        else if (condStr == "gaplessthan") type = Condition::GapLessThan;
        else if (condStr == "notequalto") type = Condition::NotEqualTo;
        else if (condStr == "changed") type = Condition::Changed;

        float arg = atts.value("argument").toFloat(&ok);
        if (!ok) arg = 0.f;

        Condition condition(intIndex, outputNumber, type, arg);

        m_rule->addCondition(condition);

    } else if (name == "action") {

        if (!m_inRule) {
            std::cerr << "ERROR: SimpleXMLRuleLoader: Action outside rule" << std::endl;
            return false;
        }

        QString type = atts.value("type").toLower();

        if (type == "image") {
            QString image = atts.value("image");
            Action *action = new ImageAction(image);
            m_rule->addAction(action);
            std::cerr << "INFO: SimpleXMLRuleLoader: Added image action" << std::endl;
        } else if (type == "process") {
            QString process = atts.value("process").toLower();
            QStringList args = atts.value("arguments").split(',');
            Action *action = new ExternalProcessAction(process, args);
            m_rule->addAction(action);
            std::cerr << "INFO: SimpleXMLRuleLoader: Added external process action" << std::endl;
        } else if (type == "fdwrite") {
            QString file = atts.value("file");
            QString data = atts.value("data");
            bool togglePrevious = false;
            if (atts.value("togglePrevious") == "true") {
                togglePrevious = true;
            }
            Action *action = new FDWriteAction(file, data, togglePrevious);
            m_rule->addAction(action);
            std::cerr << "INFO: SimpleXMLRuleLoader: Added fd write action" << std::endl;
        } else {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Unknown action type \""
                      << type.toStdString() << "\"" << std::endl;
        }
    }

    return true;
}

bool
SimpleXMLRuleLoader::characters(const QString &s)
{
    return true;
}

bool
SimpleXMLRuleLoader::endElement(const QString &namespaceURI,
                                const QString &localName,
                                const QString &qName)
{
    QString name = qName.toLower();

    if (name == "plugins") {

        if (!m_inPlugins) {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Parse problem: unexpected end of plugins element (trying to continue)" << std::endl;
        }
        m_inPlugins = false;

    } else if (name == "rules") {

        if (!m_inRules) {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Parse problem: unexpected end of rules element (trying to continue)" << std::endl;
        }
        m_inRules = false;

    } else if (name == "outputrule") {
        
        if (!m_inRule) {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Parse problem: unexpected end of outputRule element" << std::endl;
            return false;
        } else {
            m_processor->addRule(m_rule);
        }
        m_inRule = false;
    }

    return true;
}

bool
SimpleXMLRuleLoader::error(const QXmlParseException &exception)
{
    m_errorString =
	QString("ERROR: SimpleXMLRuleLoader: %1 at line %2, column %3")
	.arg(exception.message())
	.arg(exception.lineNumber())
	.arg(exception.columnNumber());
    std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
    return QXmlDefaultHandler::error(exception);
}

bool
SimpleXMLRuleLoader::fatalError(const QXmlParseException &exception)
{
    m_errorString =
	QString("FATAL ERROR: SimpleXMLRuleLoader: %1 at line %2, column %3")
	.arg(exception.message())
	.arg(exception.lineNumber())
	.arg(exception.columnNumber());
    std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
    return QXmlDefaultHandler::fatalError(exception);
}