/*
 * Inscoper NBO Example: Explore the Object Hierarchy
 * ==================================================
 * This example demonstrates how to discover, at run time, which concrete types
 * can substitute an abstract NBO element and which elements a given type can
 * contain.
 *
 * Prerequisites:
 * -------------
 * 1. Installation: inscoper-nbo-<version>.jar must be on the classpath.
 */

// --8<-- [start:main_logic]
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);
    }
}
// --8<-- [end:main_logic]
