44#include <QJsonDocument>
59static QMetaType::Type metaTypeFromString(
const QString& str)
61 if (str == QLatin1String(
"string"))
return QMetaType::QString;
62 if (str == QLatin1String(
"double"))
return QMetaType::Double;
63 if (str == QLatin1String(
"float"))
return QMetaType::Float;
64 if (str == QLatin1String(
"int"))
return QMetaType::Int;
65 if (str == QLatin1String(
"bool"))
return QMetaType::Bool;
66 if (str == QLatin1String(
"path"))
return QMetaType::QString;
67 return QMetaType::QString;
72static QString metaTypeToString(QMetaType::Type type)
75 case QMetaType::QString:
return QStringLiteral(
"string");
76 case QMetaType::Double:
return QStringLiteral(
"double");
77 case QMetaType::Float:
return QStringLiteral(
"float");
78 case QMetaType::Int:
return QStringLiteral(
"int");
79 case QMetaType::Bool:
return QStringLiteral(
"bool");
80 default:
return QStringLiteral(
"string");
89 port.
name = obj.value(QLatin1String(
"name")).toString();
91 port.
required = obj.value(QLatin1String(
"required")).toBool(
true);
92 port.
description = obj.value(QLatin1String(
"description")).toString();
101 obj[QLatin1String(
"name")] = port.
name;
103 obj[QLatin1String(
"description")] = port.
description;
105 obj[QLatin1String(
"required")] =
false;
114 attr.
name = obj.value(QLatin1String(
"name")).toString();
115 attr.
type = metaTypeFromString(obj.value(QLatin1String(
"type")).toString());
116 attr.
required = obj.value(QLatin1String(
"required")).toBool(
false);
117 attr.
description = obj.value(QLatin1String(
"description")).toString();
118 if (obj.contains(QLatin1String(
"default")))
119 attr.
defaultValue = obj.value(QLatin1String(
"default")).toVariant();
128 obj[QLatin1String(
"name")] = attr.
name;
129 obj[QLatin1String(
"type")] = metaTypeToString(attr.
type);
131 obj[QLatin1String(
"required")] =
true;
133 obj[QLatin1String(
"description")] = attr.
description;
135 obj[QLatin1String(
"default")] = QJsonValue::fromVariant(attr.
defaultValue);
144 schema.
opType = obj.value(QLatin1String(
"type")).toString();
145 schema.
version = obj.value(QLatin1String(
"version")).toString();
146 schema.
binding = obj.value(QLatin1String(
"binding")).toString(QStringLiteral(
"internal"));
147 schema.
category = obj.value(QLatin1String(
"category")).toString();
148 schema.
description = obj.value(QLatin1String(
"description")).toString();
149 schema.
library = obj.value(QLatin1String(
"library")).toString();
150 schema.
executable = obj.value(QLatin1String(
"executable")).toString();
151 schema.
cliTemplate = obj.value(QLatin1String(
"cli_template")).toString();
153 const QJsonArray inputs = obj.value(QLatin1String(
"inputs")).toArray();
154 for (
const QJsonValue& v : inputs)
155 schema.
inputPorts.append(parsePort(v.toObject()));
157 const QJsonArray outputs = obj.value(QLatin1String(
"outputs")).toArray();
158 for (
const QJsonValue& v : outputs)
159 schema.
outputPorts.append(parsePort(v.toObject()));
161 const QJsonArray params = obj.value(QLatin1String(
"parameters")).toArray();
162 for (
const QJsonValue& v : params)
163 schema.
attributes.append(parseAttr(v.toObject()));
170static QJsonObject opToJson(
const MnaOpSchema& schema)
173 obj[QLatin1String(
"type")] = schema.
opType;
174 obj[QLatin1String(
"description")] = schema.
description;
177 obj[QLatin1String(
"version")] = schema.
version;
179 obj[QLatin1String(
"binding")] = schema.
binding;
181 obj[QLatin1String(
"category")] = schema.
category;
183 obj[QLatin1String(
"library")] = schema.
library;
185 obj[QLatin1String(
"executable")] = schema.
executable;
187 obj[QLatin1String(
"cli_template")] = schema.
cliTemplate;
191 inputs.append(portToJson(p));
192 obj[QLatin1String(
"inputs")] = inputs;
196 outputs.append(portToJson(p));
197 obj[QLatin1String(
"outputs")] = outputs;
201 params.append(attrToJson(a));
202 obj[QLatin1String(
"parameters")] = params;
214 if (!file.open(QIODevice::ReadOnly)) {
215 qWarning() <<
"MnaRegistryLoader: Cannot open" << path;
219 QJsonParseError parseError;
220 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &parseError);
223 if (parseError.error != QJsonParseError::NoError) {
224 qWarning() <<
"MnaRegistryLoader: JSON parse error in" << path
225 <<
":" << parseError.errorString();
229 const QJsonObject root = doc.object();
232 if (!root.contains(QLatin1String(
"mna_registry_version"))) {
233 qWarning() <<
"MnaRegistryLoader: Missing 'mna_registry_version' in" << path;
237 const QJsonArray ops = root.value(QLatin1String(
"ops")).toArray();
240 for (
const QJsonValue& v : ops) {
242 if (!schema.
opType.isEmpty()) {
248 qInfo() <<
"MnaRegistryLoader: Loaded" << count <<
"ops from" << path
249 <<
"(provider:" << root.value(QLatin1String(
"provider")).toString() <<
")";
261 QString masterPath = registryDir + QStringLiteral(
"/mna-registry.json");
262 if (QFile::exists(masterPath)) {
263 int n =
loadFile(masterPath, registry);
264 if (n > 0) total += n;
268 QDir dropInDir(registryDir + QStringLiteral(
"/mna-registry.d"));
269 if (dropInDir.exists()) {
271 filters << QStringLiteral(
"*.json");
272 QStringList files = dropInDir.entryList(filters, QDir::Files, QDir::Name);
273 for (
const QString& fileName : files) {
274 int n =
loadFile(dropInDir.absoluteFilePath(fileName), registry);
275 if (n > 0) total += n;
285 const QString& provider,
289 root[QLatin1String(
"mna_registry_version")] = QStringLiteral(
"1.0");
290 root[QLatin1String(
"provider")] = provider;
294 for (
const QString& opType : opTypes)
295 ops.append(opToJson(registry.
schema(opType)));
296 root[QLatin1String(
"ops")] = ops;
299 if (!file.open(QIODevice::WriteOnly)) {
300 qWarning() <<
"MnaRegistryLoader: Cannot write" << path;
304 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 MnaOpRegistry contents — ingests mna-registry.json manifests and overrides the...
Process-wide singleton catalog mapping opType strings to their MnaOpSchema and (for built-in ops) exe...
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)