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
17XmlGenerator::XmlGenerator(const Config &config)
18 : m_config(config)
19{
20}
21
22bool 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
62void XmlGenerator::writeHeader(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
70void XmlGenerator::writeFooter(QTextStream &stream)
71{
72 stream << "</node>\n";
73}
74
75void XmlGenerator::writeInterface(QTextStream &stream, const QString &name)
76{
77 stream << " <interface name=\"" << name << "\">\n";
78}
79
80void XmlGenerator::closeInterface(QTextStream &stream)
81{
82 stream << " </interface>\n";
83}
84
85bool 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 &param : method.inParameters()) {
98 if (!writeArg(stream, param, QStringLiteral("in"))) {
99 return false;
100 }
101 }
102 for (const auto &param : 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
119bool XmlGenerator::writeArg(QTextStream &stream, const Parameter &param, 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
130void XmlGenerator::writeAnnotation(QTextStream &stream, const Parameter &param, 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

source code of bluez-qt/tools/bluezapi2qt/XmlGenerator.cpp