Skip to content

Explore the Object Hierarchy

The schema describes hardware in families: a detector is a camera or a point detector, a camera is a CCD, a CMOS, or an intensified camera. Two accessors expose those families at run time, without reading the XSD.

Overview

Accessor Returns
getChildren() One instance per concrete type that may substitute this element
getSubElements() One instance per child element this type can contain
getXMLName() The tag written in the document
getTypeName() The name of the generated class

The two names differ wherever the schema puts a named complex type behind an element: the element Camera is backed by the class Camera_Type. Use getXMLName() when reasoning about documents, getTypeName() when reasoning about code.

Both accessors return NBO objects, so the same call applies to each result. Recursive exploration is a few lines, which is what a type picker in a user interface needs, or a check of which hardware the model can express.

Note

getChildren() and getSubElements() describe the schema, not the content of the object. They return the same result whether the element is empty or fully populated.

Discover substitutions and content

import inscoper_nbo

# ── Step 1: List the concrete types that may substitute an abstract element
# Detector_Type is abstract in the schema. getChildren() returns one instance per
# admissible substitution, from which the XML name and the type name are read.
detector = inscoper_nbo.Detector_Type()

for child in detector.getChildren():
    print(f"{child.getXMLName():<20} {child.getTypeName()}")

# A camera is itself a family of concrete detectors
camera = inscoper_nbo.Camera_Type()
print([child.getXMLName() for child in camera.getChildren()])

# ── Step 2: List the elements a given type can contain
# getSubElements() returns one instance per child element declared for the type.
laser = inscoper_nbo.Laser()

for sub_element in laser.getSubElements():
    print(f"{sub_element.getXMLName():<30} {sub_element.getTypeName()}")

# ── Step 3: Walk the hierarchy recursively
# Both accessors return NBO objects, so the same call can be applied again to
# each result to explore an arbitrary depth of the schema.
def print_substitutions(element, depth=0):
    for child in element.getChildren():
        print(f"{'    ' * depth}{child.getXMLName()}")
        print_substitutions(child, depth + 1)

print_substitutions(inscoper_nbo.MicroscopeStand_Type())

#include <NBO/NBO/Camera_Type.h>
#include <NBO/NBO/Detector_Type.h>
#include <NBO/NBO/Laser.h>
#include <NBO/NBO/MicroscopeStand_Type.h>
#include <NBO/Shared/Base/NBOBaseClass.h>

#include <iomanip>
#include <iostream>
#include <vector>

using namespace Inscoper;

// Step 3: Walk the hierarchy recursively
// Both accessors return NBO objects, so the same call can be applied again to
// each result to explore an arbitrary depth of the schema.
void printSubstitutions(const NBO::NBOBaseClass &element, int depth = 0) {
    for (const auto &child : element.getChildren()) {
        std::cout << std::string(4 * depth, ' ') << child->getXMLName() << std::endl;
        printSubstitutions(*child, depth + 1);
    }
}

int main() {
    // Step 1: List the concrete types that may substitute an abstract element
    // Detector_Type is abstract in the schema. getChildren() returns one instance
    // per admissible substitution, from which the XML name and the type name are read.
    NBO::Detector_Type detector;

    for (const auto &child : detector.getChildren()) {
        std::cout << std::left << std::setw(20) << child->getXMLName() << child->getTypeName()
                  << std::endl;
    }

    // A camera is itself a family of concrete detectors
    NBO::Camera_Type camera;
    for (const auto &child : camera.getChildren()) {
        std::cout << child->getXMLName() << " ";
    }
    std::cout << std::endl;

    // Step 2: List the elements a given type can contain
    // getSubElements() returns one instance per child element declared for the type.
    NBO::Laser laser;

    for (const auto &subElement : laser.getSubElements()) {
        std::cout << std::left << std::setw(30) << subElement->getXMLName()
                  << subElement->getTypeName() << std::endl;
    }

    NBO::MicroscopeStand_Type stand;
    printSubstitutions(stand);

    return 0;
}

import com.inscoper.nbo.Camera_Type;
import com.inscoper.nbo.Detector_Type;
import com.inscoper.nbo.Laser;
import com.inscoper.nbo.MicroscopeStand_Type;
import com.inscoper.nbo.NBOBaseClass;

public class ObjectHierarchy {

    // Step 3: Walk the hierarchy recursively
    // Both accessors return NBO objects, so the same call can be applied again to
    // each result to explore an arbitrary depth of the schema.
    static void printSubstitutions(NBOBaseClass element, int depth) {
        for (NBOBaseClass child : element.getChildren()) {
            System.out.println(" ".repeat(4 * depth) + child.getXMLName());
            printSubstitutions(child, depth + 1);
        }
    }

    public static void main(String[] args) {
        // Step 1: List the concrete types that may substitute an abstract element
        // Detector_Type is abstract in the schema. getChildren() returns one instance
        // per admissible substitution, from which the XML name and the type name are read.
        Detector_Type detector = new Detector_Type();

        for (NBOBaseClass child : detector.getChildren()) {
            System.out.printf("%-20s %s%n", child.getXMLName(), child.getTypeName());
        }

        // A camera is itself a family of concrete detectors
        Camera_Type camera = new Camera_Type();
        for (NBOBaseClass child : camera.getChildren()) {
            System.out.print(child.getXMLName() + " ");
        }
        System.out.println();

        // Step 2: List the elements a given type can contain
        // getSubElements() returns one instance per child element declared for the type.
        Laser laser = new Laser();

        for (NBOBaseClass subElement : laser.getSubElements()) {
            System.out.printf("%-30s %s%n", subElement.getXMLName(), subElement.getTypeName());
        }

        printSubstitutions(new MicroscopeStand_Type(), 0);
    }
}