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
keyrefID 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.