| 1 | /* |
| 2 | * BluezQt - Asynchronous BlueZ wrapper library |
| 3 | * |
| 4 | * SPDX-FileCopyrightText: 2019 Manuel Weichselbaumer <mincequi@web.de> |
| 5 | * |
| 6 | * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
| 7 | */ |
| 8 | |
| 9 | #include "XmlGenerator.h" |
| 10 | |
| 11 | #include <QDebug> |
| 12 | #include <QFile> |
| 13 | |
| 14 | #include "BluezApiParser.h" |
| 15 | #include "TypeAnnotation.h" |
| 16 | |
| 17 | XmlGenerator::XmlGenerator(const Config &config) |
| 18 | : m_config(config) |
| 19 | { |
| 20 | } |
| 21 | |
| 22 | bool XmlGenerator::generate(const BluezApiParser &parser) |
| 23 | { |
| 24 | // Iterate interfaces |
| 25 | for (const auto &interface : parser.interfaces()) { |
| 26 | // Only consider interfaces with methods |
| 27 | if (interface.methods().methods().empty()) { |
| 28 | continue; |
| 29 | } |
| 30 | |
| 31 | // Create file |
| 32 | QFile file(interface.name() + QStringLiteral(".xml" )); |
| 33 | if (!file.open(flags: QIODevice::WriteOnly | QIODevice::Text)) { |
| 34 | qWarning() << "Error opening file for writing:" << file.fileName(); |
| 35 | return false; |
| 36 | } |
| 37 | |
| 38 | // Write content |
| 39 | QTextStream stream(&file); |
| 40 | writeHeader(stream); |
| 41 | writeInterface(stream, name: interface.name()); |
| 42 | |
| 43 | // Iterate methods |
| 44 | for (const auto &method : interface.methods().methods()) { |
| 45 | // Respect config |
| 46 | if ((method.tags().isDeprecated && !m_config.useDeprecated) || (method.tags().isOptional && !m_config.useOptional) |
| 47 | || (method.tags().isExperimental && !m_config.useExperimental)) { |
| 48 | continue; |
| 49 | } |
| 50 | |
| 51 | writeMethod(stream, method); |
| 52 | } |
| 53 | |
| 54 | closeInterface(stream); |
| 55 | writeFooter(stream); |
| 56 | file.close(); |
| 57 | } |
| 58 | |
| 59 | return true; |
| 60 | } |
| 61 | |
| 62 | void XmlGenerator::(QTextStream &stream) |
| 63 | { |
| 64 | stream << "<?xml version=\"1.0\"?>\n" ; |
| 65 | stream << "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" " |
| 66 | "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" ; |
| 67 | stream << "<node>\n" ; |
| 68 | } |
| 69 | |
| 70 | void XmlGenerator::(QTextStream &stream) |
| 71 | { |
| 72 | stream << "</node>\n" ; |
| 73 | } |
| 74 | |
| 75 | void XmlGenerator::writeInterface(QTextStream &stream, const QString &name) |
| 76 | { |
| 77 | stream << " <interface name=\"" << name << "\">\n" ; |
| 78 | } |
| 79 | |
| 80 | void XmlGenerator::closeInterface(QTextStream &stream) |
| 81 | { |
| 82 | stream << " </interface>\n" ; |
| 83 | } |
| 84 | |
| 85 | bool XmlGenerator::writeMethod(QTextStream &stream, const Method &method) |
| 86 | { |
| 87 | stream << " <method name=\"" << method.name() << "\"" ; |
| 88 | |
| 89 | // Some beautification |
| 90 | if (method.inParameters().empty() && method.outParameters().empty()) { |
| 91 | stream << "/>\n" ; |
| 92 | return true; |
| 93 | } |
| 94 | |
| 95 | stream << ">\n" ; |
| 96 | |
| 97 | for (const auto ¶m : method.inParameters()) { |
| 98 | if (!writeArg(stream, param, QStringLiteral("in" ))) { |
| 99 | return false; |
| 100 | } |
| 101 | } |
| 102 | for (const auto ¶m : method.outParameters()) { |
| 103 | if (!writeArg(stream, param, QStringLiteral("out" ))) { |
| 104 | return false; |
| 105 | } |
| 106 | } |
| 107 | for (int i = 0; i < method.inParameters().size(); ++i) { |
| 108 | writeAnnotation(stream, param: method.inParameters().at(i), QStringLiteral("In" ), i); |
| 109 | } |
| 110 | for (int i = 0; i < method.outParameters().size(); ++i) { |
| 111 | writeAnnotation(stream, param: method.outParameters().at(i), QStringLiteral("Out" ), i); |
| 112 | } |
| 113 | |
| 114 | stream << " </method>\n" ; |
| 115 | |
| 116 | return true; |
| 117 | } |
| 118 | |
| 119 | bool XmlGenerator::writeArg(QTextStream &stream, const Parameter ¶m, const QString &dir) |
| 120 | { |
| 121 | auto dbusType = annotateType(from: AnnotationType::Bluez, to: AnnotationType::Dbus, type: param.type()); |
| 122 | if (dbusType.isEmpty()) { |
| 123 | return false; |
| 124 | } |
| 125 | stream << " <arg name=\"" << param.name() << "\" type=\"" << dbusType << "\" direction=\"" << dir << "\"/>\n" ; |
| 126 | |
| 127 | return true; |
| 128 | } |
| 129 | |
| 130 | void XmlGenerator::writeAnnotation(QTextStream &stream, const Parameter ¶m, const QString &dir, int i) |
| 131 | { |
| 132 | auto qtType = annotateType(from: AnnotationType::Bluez, to: AnnotationType::Qt, type: param.type()); |
| 133 | if (qtType.isEmpty()) { |
| 134 | return; |
| 135 | } |
| 136 | stream << " <annotation name=\"org.qtproject.QtDBus.QtTypeName." << dir << QString::number(i) << "\" value=\"" << qtType << "\"/>\n" ; |
| 137 | |
| 138 | return; |
| 139 | } |
| 140 | |