#include "GeneratorGrantleeBase.h" #include "XmlReader.h" #include "GrantleeWrappers.h" #include #include #include #include using namespace CodeGen; GeneratorGrantleeBase::GeneratorGrantleeBase(const char *loggerName) : m_engine(new Grantlee::Engine) , m_ctx(new Grantlee::Context) , m_structBuilder(nullptr) , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName)) { } GeneratorGrantleeBase::~GeneratorGrantleeBase() { delete m_engine; delete m_ctx; } bool GeneratorGrantleeBase::initInternal(const XmlReader *reader, StructBuilder *structBuilder) { m_structBuilder = structBuilder; if (reader) { m_ctx->insert(QStringLiteral("namespace"), reader->getServiceNamespace()); m_ctx->insert(QStringLiteral("namespace_abbr"), reader->getServiceAbbr().toLower()); m_ctx->insert(QStringLiteral("namespace_abbr_upper"), reader->getServiceAbbr().toUpper()); if (reader->getServiceNamespace() == QLatin1String("Core")) m_ctx->insert(QStringLiteral("include_prefix"), QStringLiteral("DDS/%1").arg(reader->getServiceNamespace())); else m_ctx->insert(QStringLiteral("include_prefix"), reader->getServiceNamespace()); m_ctx->insert(QStringLiteral("custom_record_replay"), reader->hasCustomRecordReplayPlugin()); } return true; } bool GeneratorGrantleeBase::setTemplate(const QString &templateName, const QString &tmpl) { m_template = m_engine->newTemplate(tmpl, QStringLiteral("myTemplate")); if (m_template->error()) { WARNING_LOG(m_logger) << "Error parsing template '" << templateName << "': " << m_template->errorString(); return false; } return true; } QString GeneratorGrantleeBase::render() const { QString out = m_template->render(m_ctx); QRegExp rx(QLatin1String(";\\n([ ]+\\n)*")); out = out.replace(rx, QStringLiteral(";\n")); return out; } QString GeneratorGrantleeBase::errorString() const { return m_template->errorString(); } bool GeneratorGrantleeBase::generateData(const QString &templateName, const QString &outDirectory) { QString content; if (!readFile(templateName, content)) return false; if (!setTemplate(templateName, content)) return false; content = render(); QString outFilename; if (!getFilenameFromData(content, outFilename)) return false; QFile f(outDirectory + QLatin1Char('/') + outFilename); if (!f.open(QIODevice::WriteOnly)) { ERROR_LOG(m_logger) << "Error opening file '" << f.fileName() << "' for writing: " << f.errorString() << "(" << f.error() << ")"; return false; } const QByteArray outData = content.toUtf8(); f.write(outData); f.close(); DEBUG_LOG(m_logger) << "Written data to " << f.fileName(); return true; } bool GeneratorGrantleeBase::readFile(const QString &filename, QString &data) const { QFile f(filename); if (!f.open(QIODevice::ReadOnly)) { ERROR_LOG(m_logger) << "Error opening file " << filename << " - error: " << f.errorString(); return false; } data = QString::fromUtf8(f.readAll()); f.close(); return true; } bool GeneratorGrantleeBase::getFilenameFromData(const QString &dataToParse, QString &filename) const { const QString filenameMarker(QStringLiteral("// filename:")); int idx = dataToParse.indexOf(filenameMarker); if (idx < 0) { ERROR_LOG(m_logger) << "Could not find marker '" << filenameMarker << "' in data!"; return false; } idx += filenameMarker.length() + 1; int endIdx = dataToParse.indexOf(QLatin1Char('\n'), idx); if (endIdx < 0) { ERROR_LOG(m_logger) << "Could not find end marker '\\n' in data!"; return false; } filename = dataToParse.midRef(idx, endIdx - idx).trimmed().toString(); return true; } void GeneratorGrantleeBase::addCustomFunctions(const QVector &customFunctions) { QVariantList vlCustomDbFunctions; QVariantList vlCustomDtcFunctions; vlCustomDbFunctions.reserve(customFunctions.size()); vlCustomDtcFunctions.reserve(customFunctions.size()); for (const CustomServiceFunctionInformation &csfi : customFunctions) { const QString signature(csfi.returnValue + QLatin1Char(' ') + csfi.methodName + QLatin1Char('(') + csfi.signature + QLatin1Char(')') + (csfi.isConst ? QStringLiteral(" const") : QString())); CustomFunctionWrapper *customFunctionWrapper(new CustomFunctionWrapper(signature, this)); switch (csfi.type) { case CustomServiceFunctionInformation::Type::Db: vlCustomDbFunctions += QVariant::fromValue(customFunctionWrapper); break; case CustomServiceFunctionInformation::Type::Dtc: vlCustomDtcFunctions += QVariant::fromValue(customFunctionWrapper); break; case CustomServiceFunctionInformation::Type::DbNotify: WARNING_LOG(m_logger) << "Internal error - Trying to handle DbNotify in addCustomFunctions(): " << csfi.methodName; delete customFunctionWrapper; break; } DEBUG_LOG(m_logger) << "Added custom db function " << csfi.methodName; } m_ctx->insert(QStringLiteral("custom_dtc_procs"), vlCustomDtcFunctions); m_ctx->insert(QStringLiteral("custom_db_procs"), vlCustomDbFunctions); } void GeneratorGrantleeBase::exportUsedServices(const XmlReader *reader) { IdlServicesWrapper *idlServicesWrapper(new IdlServicesWrapper(QString(), this)); const QMap usedServices = reader->usedServices(); for (auto it = usedServices.begin(); it != usedServices.end(); ++it) { if (!it.value()) continue; const QString &svc = it.key(); const QString fullPath = reader->idlFileForService(svc); const int idx = fullPath.lastIndexOf(QLatin1Char('.')); if (idx < 0) { ERROR_LOG(m_logger) << "Could not parse file path: " << fullPath; continue; } const QString idlFile = fullPath.left(idx); if (idlFile.isEmpty()) { WARNING_LOG(m_logger) << "Could not find idl file for service " << svc; continue; } idlServicesWrapper->addService(svc, idlFile); DEBUG_LOG(m_logger) << "Added service " << svc; } m_ctx->insert(QStringLiteral("ext_services"), idlServicesWrapper); }