44#include <QJsonDocument>
59static QMetaType::Type metaTypeFromString(
const QString& str)
61 if (str == QLatin1String(
"string"))
62 return QMetaType::QString;
63 if (str == QLatin1String(
"double"))
64 return QMetaType::Double;
65 if (str == QLatin1String(
"float"))
66 return QMetaType::Float;
67 if (str == QLatin1String(
"int"))
68 return QMetaType::Int;
69 if (str == QLatin1String(
"bool"))
70 return QMetaType::Bool;
71 if (str == QLatin1String(
"path"))
72 return QMetaType::QString;
73 return QMetaType::QString;
78static QString metaTypeToString(QMetaType::Type type)
81 case QMetaType::QString:
82 return QStringLiteral(
"string");
83 case QMetaType::Double:
84 return QStringLiteral(
"double");
85 case QMetaType::Float:
86 return QStringLiteral(
"float");
88 return QStringLiteral(
"int");
90 return QStringLiteral(
"bool");
92 return QStringLiteral(
"string");
101 port.
name = obj.value(QLatin1String(
"name")).toString();
103 port.
required = obj.value(QLatin1String(
"required")).toBool(
true);
104 port.
description = obj.value(QLatin1String(
"description")).toString();
113 obj[QLatin1String(
"name")] = port.
name;
115 obj[QLatin1String(
"description")] = port.
description;
117 obj[QLatin1String(
"required")] =
false;
126 attr.
name = obj.value(QLatin1String(
"name")).toString();
127 attr.
type = metaTypeFromString(obj.value(QLatin1String(
"type")).toString());
128 attr.
required = obj.value(QLatin1String(
"required")).toBool(
false);
129 attr.
description = obj.value(QLatin1String(
"description")).toString();
130 if (obj.contains(QLatin1String(
"default")))
131 attr.
defaultValue = obj.value(QLatin1String(
"default")).toVariant();
140 obj[QLatin1String(
"name")] = attr.
name;
141 obj[QLatin1String(
"type")] = metaTypeToString(attr.
type);
143 obj[QLatin1String(
"required")] =
true;
145 obj[QLatin1String(
"description")] = attr.
description;
147 obj[QLatin1String(
"default")] = QJsonValue::fromVariant(attr.
defaultValue);
156 schema.
opType = obj.value(QLatin1String(
"type")).toString();
157 schema.
version = obj.value(QLatin1String(
"version")).toString();
158 schema.
binding = obj.value(QLatin1String(
"binding")).toString(QStringLiteral(
"internal"));
159 schema.
category = obj.value(QLatin1String(
"category")).toString();
160 schema.
description = obj.value(QLatin1String(
"description")).toString();
161 schema.
library = obj.value(QLatin1String(
"library")).toString();
162 schema.
executable = obj.value(QLatin1String(
"executable")).toString();
163 schema.
cliTemplate = obj.value(QLatin1String(
"cli_template")).toString();
165 const QJsonArray inputs = obj.value(QLatin1String(
"inputs")).toArray();
166 for (
const QJsonValue& v : inputs)
167 schema.
inputPorts.append(parsePort(v.toObject()));
169 const QJsonArray outputs = obj.value(QLatin1String(
"outputs")).toArray();
170 for (
const QJsonValue& v : outputs)
171 schema.
outputPorts.append(parsePort(v.toObject()));
173 const QJsonArray params = obj.value(QLatin1String(
"parameters")).toArray();
174 for (
const QJsonValue& v : params)
175 schema.
attributes.append(parseAttr(v.toObject()));
182static QJsonObject opToJson(
const MnaOpSchema& schema)
185 obj[QLatin1String(
"type")] = schema.
opType;
186 obj[QLatin1String(
"description")] = schema.
description;
189 obj[QLatin1String(
"version")] = schema.
version;
191 obj[QLatin1String(
"binding")] = schema.
binding;
193 obj[QLatin1String(
"category")] = schema.
category;
195 obj[QLatin1String(
"library")] = schema.
library;
197 obj[QLatin1String(
"executable")] = schema.
executable;
199 obj[QLatin1String(
"cli_template")] = schema.
cliTemplate;
203 inputs.append(portToJson(p));
204 obj[QLatin1String(
"inputs")] = inputs;
208 outputs.append(portToJson(p));
209 obj[QLatin1String(
"outputs")] = outputs;
213 params.append(attrToJson(a));
214 obj[QLatin1String(
"parameters")] = params;
226 if (!file.open(QIODevice::ReadOnly)) {
227 qWarning() <<
"MnaRegistryLoader: Cannot open" << path;
231 QJsonParseError parseError;
232 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
235 if (parseError.error != QJsonParseError::NoError) {
236 qWarning() <<
"MnaRegistryLoader: JSON parse error in" << path
237 <<
":" << parseError.errorString();
241 const QJsonObject root = doc.object();
244 if (!root.contains(QLatin1String(
"mna_registry_version"))) {
245 qWarning() <<
"MnaRegistryLoader: Missing 'mna_registry_version' in" << path;
249 const QJsonArray ops = root.value(QLatin1String(
"ops")).toArray();
252 for (
const QJsonValue& v : ops) {
254 if (!schema.
opType.isEmpty()) {
260 qInfo() <<
"MnaRegistryLoader: Loaded" << count <<
"ops from" << path
261 <<
"(provider:" << root.value(QLatin1String(
"provider")).toString() <<
")";
273 QString masterPath = registryDir + QStringLiteral(
"/mna-registry.json");
274 if (QFile::exists(masterPath)) {
275 int n =
loadFile(masterPath, registry);
281 QDir dropInDir(registryDir + QStringLiteral(
"/mna-registry.d"));
282 if (dropInDir.exists()) {
284 filters << QStringLiteral(
"*.json");
285 QStringList files = dropInDir.entryList(filters, QDir::Files, QDir::Name);
286 for (
const QString& fileName : files) {
287 int n =
loadFile(dropInDir.absoluteFilePath(fileName), registry);
299 const QString& provider,
303 root[QLatin1String(
"mna_registry_version")] = QStringLiteral(
"1.0");
304 root[QLatin1String(
"provider")] = provider;
308 for (
const QString& opType : opTypes)
309 ops.append(opToJson(registry.
schema(opType)));
310 root[QLatin1String(
"ops")] = ops;
313 if (!file.open(QIODevice::WriteOnly)) {
314 qWarning() <<
"MnaRegistryLoader: Cannot write" << path;
318 file.write(QJsonDocument(root).toJson(QJsonDocument::Indented));
Declarative contract for an MNA operation — expected input/output ports, attributes,...
Enums and string-conversion helpers for the MNA container vocabulary (file roles, data kinds,...
Declarative loader for MNALIB::MnaOpRegistry contents — ingests mna-registry.json manifests and overr...
Process-wide singleton catalog mapping opType strings to their MNALIB::MnaOpSchema and (for built-in ...
MNE Analysis Container Format (mna/mnx).
QString mnaDataKindToString(MnaDataKind kind)
MnaDataKind mnaDataKindFromString(const QString &str)
Process-wide lookup from opType to MnaOpSchema and implementation function.
QStringList registeredOps() const
void registerOp(const MnaOpSchema &schema)
MnaOpSchema schema(const QString &opType) const
bool required
Must be connected?
QString description
Human-readable description.
MnaDataKind dataKind
Expected data kind.
QVariant defaultValue
Default when not set.
QMetaType::Type type
Expected value type.
QString description
Human-readable description.
QString name
Attribute key.
bool required
Must be set?
Operation schema for graph validation.
QList< MnaOpSchemaPort > outputPorts
Expected output ports.
QString binding
Binding type: "internal", "cli", or "script".
QList< MnaOpSchemaPort > inputPorts
Expected input ports.
QList< MnaOpSchemaAttr > attributes
Expected attributes.
QString category
Category: "io", "preprocessing", "source_estimation", etc.
QString opType
Operation type string.
QString version
Version of the operation (e.g. "2.2.0").
QString executable
For CLI ops: executable name (e.g. "recon-all").
QString library
Which library provides the implementation.
QString description
What the operation does.
QString cliTemplate
For CLI ops: command template with {{placeholder}} tokens.
static bool saveFile(const QString &path, const QString &provider, const MnaOpRegistry ®istry)
static int loadDirectory(const QString ®istryDir, MnaOpRegistry ®istry)
static int loadFile(const QString &path, MnaOpRegistry ®istry)