File indexing completed on 2024-04-21 03:52:04

0001 /*
0002  * BluezQt - Asynchronous BlueZ wrapper library
0003  *
0004  * SPDX-FileCopyrightText: 2019 Manuel Weichselbaumer <mincequi@web.de>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "XmlGenerator.h"
0010 
0011 #include <QDebug>
0012 #include <QFile>
0013 
0014 #include "BluezApiParser.h"
0015 #include "TypeAnnotation.h"
0016 
0017 XmlGenerator::XmlGenerator(const Config &config)
0018     : m_config(config)
0019 {
0020 }
0021 
0022 bool XmlGenerator::generate(const BluezApiParser &parser)
0023 {
0024     // Iterate interfaces
0025     for (const auto &interface : parser.interfaces()) {
0026         // Only consider interfaces with methods
0027         if (interface.methods().methods().empty()) {
0028             continue;
0029         }
0030 
0031         // Create file
0032         QFile file(interface.name() + QStringLiteral(".xml"));
0033         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
0034             qWarning() << "Error opening file for writing:" << file.fileName();
0035             return false;
0036         }
0037 
0038         // Write content
0039         QTextStream stream(&file);
0040         writeHeader(stream);
0041         writeInterface(stream, interface.name());
0042 
0043         // Iterate methods
0044         for (const auto &method : interface.methods().methods()) {
0045             // Respect config
0046             if ((method.tags().isDeprecated && !m_config.useDeprecated) || (method.tags().isOptional && !m_config.useOptional)
0047                 || (method.tags().isExperimental && !m_config.useExperimental)) {
0048                 continue;
0049             }
0050 
0051             writeMethod(stream, method);
0052         }
0053 
0054         closeInterface(stream);
0055         writeFooter(stream);
0056         file.close();
0057     }
0058 
0059     return true;
0060 }
0061 
0062 void XmlGenerator::writeHeader(QTextStream &stream)
0063 {
0064     stream << "<?xml version=\"1.0\"?>\n";
0065     stream << "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
0066               "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
0067     stream << "<node>\n";
0068 }
0069 
0070 void XmlGenerator::writeFooter(QTextStream &stream)
0071 {
0072     stream << "</node>\n";
0073 }
0074 
0075 void XmlGenerator::writeInterface(QTextStream &stream, const QString &name)
0076 {
0077     stream << "  <interface name=\"" << name << "\">\n";
0078 }
0079 
0080 void XmlGenerator::closeInterface(QTextStream &stream)
0081 {
0082     stream << "  </interface>\n";
0083 }
0084 
0085 bool XmlGenerator::writeMethod(QTextStream &stream, const Method &method)
0086 {
0087     stream << "    <method name=\"" << method.name() << "\"";
0088 
0089     // Some beautification
0090     if (method.inParameters().empty() && method.outParameters().empty()) {
0091         stream << "/>\n";
0092         return true;
0093     }
0094 
0095     stream << ">\n";
0096 
0097     for (const auto &param : method.inParameters()) {
0098         if (!writeArg(stream, param, QStringLiteral("in"))) {
0099             return false;
0100         }
0101     }
0102     for (const auto &param : method.outParameters()) {
0103         if (!writeArg(stream, param, QStringLiteral("out"))) {
0104             return false;
0105         }
0106     }
0107     for (int i = 0; i < method.inParameters().size(); ++i) {
0108         writeAnnotation(stream, method.inParameters().at(i), QStringLiteral("In"), i);
0109     }
0110     for (int i = 0; i < method.outParameters().size(); ++i) {
0111         writeAnnotation(stream, method.outParameters().at(i), QStringLiteral("Out"), i);
0112     }
0113 
0114     stream << "    </method>\n";
0115 
0116     return true;
0117 }
0118 
0119 bool XmlGenerator::writeArg(QTextStream &stream, const Parameter &param, const QString &dir)
0120 {
0121     auto dbusType = annotateType(AnnotationType::Bluez, AnnotationType::Dbus, param.type());
0122     if (dbusType.isEmpty()) {
0123         return false;
0124     }
0125     stream << "      <arg name=\"" << param.name() << "\" type=\"" << dbusType << "\" direction=\"" << dir << "\"/>\n";
0126 
0127     return true;
0128 }
0129 
0130 void XmlGenerator::writeAnnotation(QTextStream &stream, const Parameter &param, const QString &dir, int i)
0131 {
0132     auto qtType = annotateType(AnnotationType::Bluez, AnnotationType::Qt, param.type());
0133     if (qtType.isEmpty()) {
0134         return;
0135     }
0136     stream << "      <annotation name=\"org.qtproject.QtDBus.QtTypeName." << dir << QString::number(i) << "\" value=\"" << qtType << "\"/>\n";
0137 
0138     return;
0139 }