mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
838008568a
* add JsonUtils * update * repair * update * ident * Schema correct msg other adjusts * fix effDel, ExceptionLog, cleanup * fix travis qt5.2 * not so funny * use Qthread interrupt instead abort bool * update services
172 lines
4.1 KiB
C++
172 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
|
|
// JSON-Schema includes
|
|
#include <utils/jsonschema/QJsonSchemaChecker.h>
|
|
|
|
#include <QFile>
|
|
#include <QString>
|
|
#include <QJsonObject>
|
|
#include <QJsonDocument>
|
|
#include <QRegularExpression>
|
|
|
|
class QJsonFactory
|
|
{
|
|
public:
|
|
|
|
static int load(const QString& schema, const QString& config, QJsonObject& json)
|
|
{
|
|
// Load the schema and the config trees
|
|
QJsonObject schemaTree = readSchema(schema);
|
|
QJsonObject configTree = readConfig(config);
|
|
|
|
// create the validator
|
|
QJsonSchemaChecker schemaChecker;
|
|
schemaChecker.setSchema(schemaTree);
|
|
|
|
QStringList messages = schemaChecker.getMessages();
|
|
|
|
if (!schemaChecker.validate(configTree).first)
|
|
{
|
|
for (int i = 0; i < messages.size(); ++i)
|
|
std::cout << messages[i].toStdString() << std::endl;
|
|
|
|
std::cerr << "Validation failed for configuration file: " << config.toStdString() << std::endl;
|
|
return -3;
|
|
}
|
|
|
|
json = configTree;
|
|
return 0;
|
|
}
|
|
|
|
static QJsonObject readConfig(const QString& path)
|
|
{
|
|
QFile file(path);
|
|
QJsonParseError error;
|
|
|
|
if (!file.open(QIODevice::ReadOnly))
|
|
{
|
|
throw std::runtime_error(QString("Configuration file not found: '" + path + "' (" + file.errorString() + ")").toStdString());
|
|
}
|
|
|
|
//Allow Comments in Config
|
|
QString config = QString(file.readAll());
|
|
config.remove(QRegularExpression("([^:]?\\/\\/.*)"));
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(config.toUtf8(), &error);
|
|
file.close();
|
|
|
|
if (error.error != QJsonParseError::NoError)
|
|
{
|
|
// report to the user the failure and their locations in the document.
|
|
int errorLine(0), errorColumn(0);
|
|
|
|
for( int i=0, count=qMin( error.offset,config.size()); i<count; ++i )
|
|
{
|
|
++errorColumn;
|
|
if(config.at(i) == '\n' )
|
|
{
|
|
errorColumn = 0;
|
|
++errorLine;
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error (
|
|
QString("Failed to parse configuration: " + error.errorString() + " at Line: " + QString::number(errorLine) + ", Column: " + QString::number(errorColumn)).toStdString()
|
|
);
|
|
}
|
|
|
|
return doc.object();
|
|
}
|
|
|
|
static QJsonObject readSchema(const QString& path)
|
|
{
|
|
QFile schemaData(path);
|
|
QJsonParseError error;
|
|
|
|
if (!schemaData.open(QIODevice::ReadOnly))
|
|
{
|
|
throw std::runtime_error(QString("Schema not found: '" + path + "' (" + schemaData.errorString() + ")").toStdString());
|
|
}
|
|
|
|
QByteArray schema = schemaData.readAll();
|
|
QJsonDocument doc = QJsonDocument::fromJson(schema, &error);
|
|
schemaData.close();
|
|
|
|
if (error.error != QJsonParseError::NoError)
|
|
{
|
|
// report to the user the failure and their locations in the document.
|
|
int errorLine(0), errorColumn(0);
|
|
|
|
for( int i=0, count=qMin( error.offset,schema.size()); i<count; ++i )
|
|
{
|
|
++errorColumn;
|
|
if(schema.at(i) == '\n' )
|
|
{
|
|
errorColumn = 0;
|
|
++errorLine;
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error(QString("ERROR: Json schema wrong: " + error.errorString() +
|
|
" at Line: " + QString::number(errorLine) +
|
|
", Column: " + QString::number(errorColumn)).toStdString());
|
|
}
|
|
|
|
return resolveReferences(doc.object());
|
|
}
|
|
|
|
static QJsonObject resolveReferences(const QJsonObject& schema)
|
|
{
|
|
QJsonObject result;
|
|
|
|
for (QJsonObject::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
|
{
|
|
QString attribute = i.key();
|
|
const QJsonValue & attributeValue = *i;
|
|
|
|
if (attribute == "$ref" && attributeValue.isString())
|
|
{
|
|
try
|
|
{
|
|
result = readSchema(":/" + attributeValue.toString());
|
|
}
|
|
catch (std::runtime_error& error)
|
|
{
|
|
throw std::runtime_error(error.what());
|
|
}
|
|
}
|
|
else if (attributeValue.isObject())
|
|
result.insert(attribute, resolveReferences(attributeValue.toObject()));
|
|
else
|
|
result.insert(attribute, attributeValue);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool writeJson(const QString& filename, QJsonObject& jsonTree)
|
|
{
|
|
QJsonDocument doc;
|
|
|
|
doc.setObject(jsonTree);
|
|
QByteArray configData = doc.toJson(QJsonDocument::Indented);
|
|
|
|
QFile configFile(filename);
|
|
if (!configFile.open(QFile::WriteOnly | QFile::Truncate))
|
|
return false;
|
|
|
|
configFile.write(configData);
|
|
|
|
QFile::FileError error = configFile.error();
|
|
if (error != QFile::NoError)
|
|
return false;
|
|
|
|
configFile.close();
|
|
|
|
return true;
|
|
}
|
|
};
|