aboutsummaryrefslogtreecommitdiffstats
path: root/Plugins/XmlExport/xmlexport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/XmlExport/xmlexport.cpp')
-rw-r--r--Plugins/XmlExport/xmlexport.cpp468
1 files changed, 468 insertions, 0 deletions
diff --git a/Plugins/XmlExport/xmlexport.cpp b/Plugins/XmlExport/xmlexport.cpp
new file mode 100644
index 0000000..746d246
--- /dev/null
+++ b/Plugins/XmlExport/xmlexport.cpp
@@ -0,0 +1,468 @@
+#include "xmlexport.h"
+#include "services/exportmanager.h"
+#include "common/unused.h"
+#include <QTextCodec>
+
+const QString XmlExport::docBegin = QStringLiteral("<?xml version=\"1.0\" encoding=\"%1\"?>\n");
+
+XmlExport::XmlExport()
+{
+}
+
+QString XmlExport::getFormatName() const
+{
+ return QStringLiteral("XML");
+}
+
+ExportManager::StandardConfigFlags XmlExport::standardOptionsToEnable() const
+{
+ return ExportManager::CODEC;
+}
+
+QString XmlExport::getExportConfigFormName() const
+{
+ return QStringLiteral("XmlExportConfig");
+}
+
+CfgMain* XmlExport::getConfig()
+{
+ return &cfg;
+}
+
+void XmlExport::validateOptions()
+{
+ bool useNs = cfg.XmlExport.UseNamespace.get();
+ EXPORT_MANAGER->updateVisibilityAndEnabled(cfg.XmlExport.Namespace, true, useNs);
+
+ bool nsValid = !useNs || !cfg.XmlExport.Namespace.get().isEmpty();
+ EXPORT_MANAGER->handleValidationFromPlugin(nsValid, cfg.XmlExport.Namespace, tr("Enter the namespace to use (for example: http://my.namespace.org"));
+}
+
+QString XmlExport::defaultFileExtension() const
+{
+ return QStringLiteral("xml");
+}
+
+bool XmlExport::beforeExportQueryResults(const QString& query, QList<QueryExecutor::ResultColumnPtr>& columns, const QHash<ExportManager::ExportProviderFlag, QVariant> providedData)
+{
+ UNUSED(providedData);
+
+ setupConfig();
+
+ write(docBegin.arg(codecName));
+
+ writeln(QString("<results%2>").arg(nsStr));
+ incrIndent();
+
+ writeln("<query>");
+ incrIndent();
+ writeln(escape(query));
+ decrIndent();
+ writeln("</query>");
+
+ QList<DataType> columnTypes = QueryExecutor::resolveColumnTypes(db, columns, true);
+ writeln("<columns>");
+ incrIndent();
+ int i = 0;
+ DataType type;
+ for (QueryExecutor::ResultColumnPtr col : columns)
+ {
+ type = columnTypes[i];
+
+ writeln("<column>");
+ incrIndent();
+ writeln("<displayName>"+ escape(col->displayName) + "</displayName>");
+ writeln("<name>"+ escape(col->column) + "</name>");
+ writeln("<table>"+ escape(col->table) + "</table>");
+ writeln("<database>"+ escape(col->database) + "</database>");
+ writeln("<type>"+ escape(type.toFullTypeString()) + "</type>");
+ decrIndent();
+ writeln("</column>");
+ i++;
+ }
+ decrIndent();
+ writeln("</columns>");
+
+ writeln("<rows>");
+ incrIndent();
+ return true;
+}
+
+bool XmlExport::exportQueryResultsRow(SqlResultsRowPtr row)
+{
+ static const QString rowTpl = QStringLiteral("<value column=\"%1\">%2</value>");
+ static const QString nullTpl = QStringLiteral("<value column=\"%1\" null=\"true\"/>");
+
+ writeln("<row>");
+ incrIndent();
+
+ int i = 0;
+ for (const QVariant& value : row->valueList())
+ {
+ if (value.isNull())
+ writeln(nullTpl.arg(i));
+ else
+ writeln(rowTpl.arg(i).arg(escape(value.toString())));
+ }
+
+ decrIndent();
+ writeln("</row>");
+ return true;
+}
+
+bool XmlExport::afterExportQueryResults()
+{
+ decrIndent();
+ write("</rows>");
+ decrIndent();
+ write("</results>");
+ return true;
+}
+
+bool XmlExport::exportTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateTablePtr createTable, const QHash<ExportManager::ExportProviderFlag, QVariant> providedData)
+{
+ UNUSED(columnNames);
+ UNUSED(providedData);
+ if (isTableExport())
+ {
+ setupConfig();
+ write(docBegin.arg(codecName));
+ }
+
+ writeln(QString("<table%1>").arg(isTableExport() ? nsStr : ""));
+ incrIndent();
+
+ writeln("<database>" + escape(database) + "</database>");
+ writeln("<name>" + escape(table) + "</name>");
+ if (!createTable->withOutRowId.isNull())
+ writeln(QString("<withoutRowId>true</withoutRowId>"));
+
+ writeln("<ddl>" + escape(ddl) + "</ddl>");
+
+ writeln("<columns>");
+ incrIndent();
+ for (SqliteCreateTable::Column* col : createTable->columns)
+ {
+ writeln("<column>");
+ incrIndent();
+ writeln("<name>"+ col->name + "</name>");
+ writeln(QString("<type>%1</type>").arg((col->type ? col->type->toDataType().toFullTypeString() : "")));
+ if (col->constraints.size() > 0)
+ {
+ writeln("<constraints>");
+ incrIndent();
+ for (SqliteCreateTable::Column::Constraint* constr : col->constraints)
+ {
+ writeln("<constraint>");
+ incrIndent();
+ writeln("<type>" + constr->typeString() + "</type>");
+ writeln("<definition>" + constr->detokenize() + "</definition>");
+ decrIndent();
+ writeln("</constraint>");
+ }
+ decrIndent();
+ writeln("</constraints>");
+ }
+ decrIndent();
+ writeln("</column>");
+ }
+ decrIndent();
+ writeln("</columns>");
+
+ if (createTable->constraints.size() > 0)
+ {
+ writeln("<constraints>");
+ incrIndent();
+ for (SqliteCreateTable::Constraint* constr : createTable->constraints)
+ {
+ writeln("<constraint>");
+ incrIndent();
+ writeln("<type>" + constr->typeString() + "</type>");
+ writeln("<definition>" + constr->detokenize() + "</definition>");
+ decrIndent();
+ writeln("</constraint>");
+ }
+ decrIndent();
+ writeln("</constraints>");
+ }
+
+ writeln("<rows>");
+ incrIndent();
+ return true;
+}
+
+bool XmlExport::exportVirtualTable(const QString& database, const QString& table, const QStringList& columnNames, const QString& ddl, SqliteCreateVirtualTablePtr createTable, const QHash<ExportManager::ExportProviderFlag, QVariant> providedData)
+{
+ UNUSED(providedData);
+
+ if (isTableExport())
+ {
+ setupConfig();
+ write(docBegin.arg(codecName));
+ }
+
+ writeln(QString("<table%1>").arg(isTableExport() ? nsStr : ""));
+ incrIndent();
+
+ writeln("<database>" + escape(database) + "</database>");
+ writeln("<name>" + escape(table) + "</name>");
+ writeln("<virtual>true</name>");
+ writeln("<module>" + escape(createTable->module) + "</module>");
+
+ writeln("<ddl>" + escape(ddl) + "</ddl>");
+
+ writeln("<columns>");
+ incrIndent();
+ for (const QString& col : columnNames)
+ {
+ writeln("<column>");
+ incrIndent();
+ writeln("<name>"+ col + "</name>");
+ decrIndent();
+ writeln("</column>");
+ }
+ decrIndent();
+ writeln("</columns>");
+
+ if (createTable->args.size() > 0)
+ {
+ writeln("<moduleArgs>");
+ incrIndent();
+ for (const QString& arg : createTable->args)
+ writeln("<arg>" + arg + "</arg>");
+
+ decrIndent();
+ writeln("</moduleArgs>");
+ }
+
+ writeln("<rows>");
+ incrIndent();
+ return true;
+}
+
+bool XmlExport::exportTableRow(SqlResultsRowPtr data)
+{
+ return exportQueryResultsRow(data);
+}
+
+bool XmlExport::afterExportTable()
+{
+ decrIndent();
+ writeln("</rows>");
+ decrIndent();
+ writeln("</table>");
+ return true;
+}
+
+bool XmlExport::beforeExportDatabase(const QString& database)
+{
+ setupConfig();
+ write(docBegin.arg(codecName));
+
+ writeln(QString("<database%1>").arg(nsStr));
+ incrIndent();
+ writeln("<name>" + escape(database) + "</name>");
+
+ return true;
+}
+
+bool XmlExport::exportIndex(const QString& database, const QString& name, const QString& ddl, SqliteCreateIndexPtr createIndex)
+{
+ writeln("<index>");
+ incrIndent();
+
+ writeln("<database>" + escape(database) + "</database>");
+ writeln("<name>" + escape(name) + "</name>");
+ if (createIndex->uniqueKw)
+ writeln("<unique>true</unique>");
+
+ if (createIndex->where)
+ writeln("<partial>" + createIndex->where->detokenize() + "</partial>");
+
+ writeln("<ddl>" + escape(ddl) + "</ddl>");
+
+ decrIndent();
+ writeln("</index>");
+ return true;
+}
+
+bool XmlExport::exportTrigger(const QString& database, const QString& name, const QString& ddl, SqliteCreateTriggerPtr createTrigger)
+{
+ UNUSED(createTrigger);
+ writeln("<trigger>");
+ incrIndent();
+
+ writeln("<database>" + escape(database) + "</database>");
+ writeln("<name>" + escape(name) + "</name>");
+ writeln("<ddl>" + escape(ddl) + "</ddl>");
+
+ QString timing = SqliteCreateTrigger::time(createTrigger->eventTime);
+ writeln("<timing>" + escape(timing) + "</timing>");
+
+ QString event = createTrigger->event ? SqliteCreateTrigger::Event::typeToString(createTrigger->event->type) : "";
+ writeln("<action>" + escape(event) + "</action>");
+
+ QString tag;
+ if (createTrigger->eventTime == SqliteCreateTrigger::Time::INSTEAD_OF)
+ tag = "<view>";
+ else
+ tag = "<table>";
+
+ writeln(tag + escape(createTrigger->table) + tag);
+
+ if (createTrigger->precondition)
+ writeln("<precondition>" + escape(createTrigger->precondition->detokenize()) + "</precondition>");
+
+ QStringList queryStrings;
+ for (SqliteQuery* q : createTrigger->queries)
+ queryStrings << q->detokenize();
+
+ writeln("<code>" + escape(queryStrings.join("\n")) + "</code>");
+
+ decrIndent();
+ writeln("</trigger>");
+ return true;
+}
+
+bool XmlExport::exportView(const QString& database, const QString& name, const QString& ddl, SqliteCreateViewPtr createView)
+{
+ UNUSED(createView);
+ writeln("<view>");
+ incrIndent();
+
+ writeln("<database>" + escape(database) + "</database>");
+ writeln("<name>" + escape(name) + "</name>");
+ writeln("<ddl>" + escape(ddl) + "</ddl>");
+ writeln("<select>" + escape(createView->select->detokenize()) + "</select>");
+ decrIndent();
+ writeln("</view>");
+ return true;
+}
+
+bool XmlExport::afterExportDatabase()
+{
+ decrIndent();
+ writeln("</database>");
+ return true;
+}
+
+void XmlExport::setupConfig()
+{
+ codecName = codec->name();
+ indentDepth = 0;
+ newLineStr = "";
+ indentStr = "";
+ indent = (cfg.XmlExport.Format.get() == "format");
+ if (indent)
+ newLineStr = "\n";
+
+ nsStr = QString();
+ if (cfg.XmlExport.UseNamespace.get())
+ nsStr = " xmlns=\"" + cfg.XmlExport.Namespace.get() + "\"";
+
+ if (cfg.XmlExport.Escaping.get() == "ampersand")
+ {
+ useAmpersand = true;
+ useCdata = false;
+ }
+ else if (cfg.XmlExport.Escaping.get() == "cdata")
+ {
+ useAmpersand = false;
+ useCdata = true;
+ }
+ else
+ {
+ useAmpersand = true;
+ useCdata = true;
+ }
+}
+
+void XmlExport::incrIndent()
+{
+ if (indent)
+ {
+ indentDepth++;
+ updateIndent();
+ }
+}
+
+void XmlExport::decrIndent()
+{
+ if (indent)
+ {
+ indentDepth--;
+ updateIndent();
+ }
+}
+
+void XmlExport::updateIndent()
+{
+ indentStr = QString(" ").repeated(indentDepth);
+}
+
+void XmlExport::writeln(const QString& str)
+{
+ QString newStr;
+ if (str.contains("\n"))
+ {
+ QStringList lines = str.split("\n");
+ QMutableStringListIterator it(lines);
+ while (it.hasNext())
+ it.value().prepend(indentStr);
+
+ newStr = lines.join("\n") + newLineStr;
+ }
+ else
+ {
+ newStr = indentStr + str + newLineStr;
+ }
+ GenericExportPlugin::write(newStr);
+}
+
+QString XmlExport::escape(const QString& str)
+{
+ if (useAmpersand && useCdata)
+ {
+ if (str.length() >= minLenghtForCdata)
+ return escapeCdata(str);
+ else
+ return escapeAmpersand(str);
+ }
+ else if (useAmpersand)
+ {
+ return escapeAmpersand(str);
+ }
+ else
+ {
+ return escapeCdata(str);
+ }
+}
+
+QString XmlExport::escapeCdata(const QString& str)
+{
+ if (str.contains('"') || str.contains('&') || str.contains('<') || str.contains('>'))
+ return "<![CDATA[" + str + "]]>";
+
+ return str;
+}
+
+QString XmlExport::escapeAmpersand(const QString& str)
+{
+ return str.toHtmlEscaped();
+}
+
+QString XmlExport::toString(bool value)
+{
+ return value ? "true" : "false";
+}
+
+bool XmlExport::init()
+{
+ Q_INIT_RESOURCE(xmlexport);
+ return GenericExportPlugin::init();
+}
+
+void XmlExport::deinit()
+{
+ Q_CLEANUP_RESOURCE(xmlexport);
+}