view host/SimpleXMLRuleLoader.cpp @ 4:f0e9092bd3e4

...
author cannam
date Mon, 06 Nov 2006 14:41:46 +0000
parents 86914ea77b7b
children b30fcffc5000
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 <QFile>
#include <QIODevice>
#include <QXmlInputSource>

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

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;
        }

        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();
        Rule::Condition condition(Rule::Present);

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

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

        Rule rule(intIndex, outputNumber, condition, arg);

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

        if (action == "image") {
            QString image = atts.value("image").toLower();
            m_processor->addImageRule(rule, image);
            std::cerr << "INFO: SimpleXMLRuleLoader: Added image rule" << std::endl;
        } else {
            std::cerr << "WARNING: SimpleXMLRuleLoader: Unknown action \""
                      << action.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;
    }
    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);
}