/************************************************************************ ** ** @file vdomdocument.cpp ** @author Roman Telezhinsky ** @date November 15, 2013 ** ** @brief ** @copyright ** This source code is part of the Valentine project, a pattern making ** program, whose allow create and modeling patterns of clothing. ** Copyright (C) 2013 Valentina project ** All Rights Reserved. ** ** Valentina 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. ** ** Valentina 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 Valentina. If not, see . ** *************************************************************************/ #include "vdomdocument.h" #include "../exception/vexceptionconversionerror.h" #include "../exception/vexceptionemptyparameter.h" #include "../exception/vexceptionbadid.h" #include #include #include #include //This class need for validation pattern file using XSD shema class MessageHandler : public QAbstractMessageHandler { public: MessageHandler() : QAbstractMessageHandler(0), m_messageType(QtMsgType()), m_description(QString()), m_sourceLocation(QSourceLocation()){} inline QString statusMessage() const {return m_description;} inline qint64 line() const {return m_sourceLocation.line();} inline qint64 column() const {return m_sourceLocation.column();} protected: virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) { Q_UNUSED(type); Q_UNUSED(identifier); m_messageType = type; m_description = description; m_sourceLocation = sourceLocation; } private: QtMsgType m_messageType; QString m_description; QSourceLocation m_sourceLocation; }; VDomDocument::VDomDocument(VContainer *data) : QDomDocument(), data(data), map(QHash()) { } QDomElement VDomDocument::elementById(const QString& id) { if (map.contains(id)) { QDomElement e = map[id]; if (e.parentNode().nodeType() != QDomNode::BaseNode) { return e; } map.remove(id); } if (this->find(this->documentElement(), id)) { return map[id]; } return QDomElement(); } void VDomDocument::removeAllChilds(QDomElement &element) { QDomNode domNode = element.firstChild(); while (domNode.isNull() == false) { if (domNode.isElement()) { QDomElement domElement = domNode.toElement(); if (domElement.isNull() == false) { element.removeChild(domElement); } } domNode = element.firstChild(); } } bool VDomDocument::find(const QDomElement &node, const QString& id) { if (node.hasAttribute("id")) { const QString value = node.attribute("id"); this->map[value] = node; if (value == id) { return true; } } for (qint32 i=0; ifind(n.toElement(), id)) { return true; } } } return false; } quint32 VDomDocument::GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); bool ok = false; const QString parametr = GetParametrString(domElement, name, defValue); const quint32 id = parametr.toUInt(&ok); if (ok == false) { throw VExceptionConversionError(tr("Can't convert toUInt parameter"), name); } return id; } QString VDomDocument::GetParametrString(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); const QString parameter = domElement.attribute(name, defValue); if (parameter.isEmpty()) { throw VExceptionEmptyParameter(tr("Got empty parameter"), name, domElement); } return parameter; } qreal VDomDocument::GetParametrDouble(const QDomElement &domElement, const QString &name, const QString &defValue) const { Q_ASSERT_X(name.isEmpty() == false, Q_FUNC_INFO, "name of parametr is empty"); Q_ASSERT_X(domElement.isNull() == false, Q_FUNC_INFO, "domElement is null"); bool ok = false; QString parametr = GetParametrString(domElement, name, defValue); const qreal param = parametr.replace(",", ".").toDouble(&ok); if (ok == false) { throw VExceptionConversionError(tr("Can't convert toDouble parameter"), name); } return param; } QString VDomDocument::UniqueTagText(const QString &tagName, const QString &defVal) const { const QDomNodeList nodeList = this->elementsByTagName(tagName); if (nodeList.isEmpty()) { return defVal; } else { const QDomNode domNode = nodeList.at(0); if (domNode.isNull() == false && domNode.isElement()) { const QDomElement domElement = domNode.toElement(); if (domElement.isNull() == false) { return domElement.text(); } } } return defVal; } bool VDomDocument::ValidatePattern(const QString &schema, const QString &fileName, QString &errorMsg, qint64 &errorLine, qint64 &errorColumn) { errorLine = -1; errorColumn = -1; QFile pattern(fileName); if (pattern.open(QIODevice::ReadOnly) == false) { errorMsg = QString(tr("Can't open file %1:\n%2.").arg(fileName).arg(pattern.errorString())); return false; } QFile fileSchema(schema); if (fileSchema.open(QIODevice::ReadOnly) == false) { errorMsg = QString(tr("Can't open schema file %1:\n%2.").arg(schema).arg(fileSchema.errorString())); return false; } MessageHandler messageHandler; QXmlSchema sch; sch.setMessageHandler(&messageHandler); sch.load(&fileSchema, QUrl::fromLocalFile(fileSchema.fileName())); bool errorOccurred = false; if (sch.isValid() == false) { errorOccurred = true; } else { QXmlSchemaValidator validator(sch); if (validator.validate(&pattern, QUrl::fromLocalFile(pattern.fileName())) == false) { errorOccurred = true; } } if (errorOccurred) { errorMsg = messageHandler.statusMessage(); errorLine = messageHandler.line(); errorColumn = messageHandler.column(); return false; } else { return true; } }