Skip to content

Code Generation

This page describes how the library is produced from nbo.xsd and how each XSD construct appears in C++, Python, and Java. For the model itself, see The NBO Model.

Why a generated binding

NBO defines the language and its structure; it does not ship the software objects an application needs in order to speak it. OME has had such libraries for years, which is part of why it was adopted so widely. When Inscoper started this work, no equivalent binding existed for NBO. The specification is published as an XSD precisely so that developers can generate code from it, for databases or for other software; this library is that step carried out once and shared.

xsd2cpp.py reads nbo.xsd and writes the C++ classes, then SWIG wraps them for Python and Java. Nothing is written by hand, so the code cannot drift from the schema.

Language mapping

The generator maps each XSD construct to the closest native construct in each language.

XSD construct C++ Python Java
Primitive type std::string, int, double, bool, long long str, int, float, bool String, int, long, float, double, boolean
Complex element std::shared_ptr<T>, aliased as InstrumentPtr An object, with memory managed automatically An object, with memory managed automatically
Optional attribute or element std::optional<T> has<Name>(), get<Name>(), set<Name>(), reset<Name>() The same four methods
Repeated element (maxOccurs="unbounded") std::vector<T> A typed vector, with addTo<Name>_List() The same typed vector classes
<choice> group std::variant, with generated is<T>(), as<T>(), and set<T>() helpers is<T>(), contains<T>(), add<T>(), and set<T>() helpers The same helpers
Restricted simple type A class validating the value on set() The same class, raising InscoperNBOValidationException The same class; the generated getters carry no throws clause, so catch Exception

Python and Java are wrapped from the same C++ core, so the two bindings expose the same method names and differ only in the native types they accept.

Design choices

Two further design choices affect how the library is consumed.

  • Validation is part of the model. A restricted value is checked when it is set, and required attributes are checked on import and on export, which keeps non-compliant values out of the tree. The checks are per field: the library runs no XML Schema validation, and does not resolve keyref ID references. See Restricted Types and Validation and The NBO Model.
  • The C++ classes use the Pimpl idiom. Private members stay out of the public headers, so the binary interface is stable across patch releases and consumer builds stay fast.