Fork me on GitHub

Loading Metaschema Modules

This guide explains how to load and work with Metaschema module definitions.

Metaschema modules define the structure of data models. Loading a module allows you to:

  • Generate Java binding classes
  • Validate documents against the model
  • Execute Metapath expressions
  • Generate XML/JSON schemas
import dev.metaschema.core.model.IModule;
import dev.metaschema.core.model.MetaschemaLoader;

import java.nio.file.Path;

// Create a loader
MetaschemaLoader loader = new MetaschemaLoader();

// Load a module
IModule module = loader.load(Path.of("my-metaschema.xml"));

// Access module information
System.out.println("Module: " + module.getName());
System.out.println("Namespace: " + module.getXmlNamespace());
import java.net.URL;

URL resource = getClass().getResource("/metaschema/my-model.xml");
IModule module = loader.load(resource);
import java.net.URI;

IModule module = loader.load(
    URI.create("https://example.com/schemas/model.xml"));

A loaded module contains:

// Get all definitions
module.getAssemblyDefinitions().forEach(assembly -> {
    System.out.println("Assembly: " + assembly.getName());
});

module.getFieldDefinitions().forEach(field -> {
    System.out.println("Field: " + field.getName());
});

module.getFlagDefinitions().forEach(flag -> {
    System.out.println("Flag: " + flag.getName());
});

Modules can import other modules:

// Get imported modules
module.getImportedModules().forEach(imported -> {
    System.out.println("Imports: " + imported.getName());
});

// Get the complete module chain (recursive)
module.getImportedModules();

Assemblies are complex structures containing other elements:

import dev.metaschema.core.model.IAssemblyDefinition;

IAssemblyDefinition assembly = module.getAssemblyDefinitionByName("catalog");
if (assembly != null) {
    System.out.println("Root: " + assembly.isRoot());

    // Get child definitions
    assembly.getModelInstances().forEach(instance -> {
        System.out.println("  Contains: " + instance.getName());
    });
}

Fields are simple values with optional flags:

import dev.metaschema.core.model.IFieldDefinition;

IFieldDefinition field = module.getFieldDefinitionByName("title");
if (field != null) {
    System.out.println("Data type: " + field.getJavaTypeAdapter());
}

Flags are attributes/properties on assemblies and fields:

import dev.metaschema.core.model.IFlagDefinition;

IFlagDefinition flag = module.getFlagDefinitionByName("id");
if (flag != null) {
    System.out.println("Required: " + flag.isRequired());
}

Modules define validation constraints:

import dev.metaschema.core.model.constraint.IConstraint;

// Get constraints from a definition
assembly.getConstraints().forEach(constraint -> {
    System.out.println("Constraint: " + constraint.getId());
    System.out.println("Level: " + constraint.getLevel());
});

The loader caches modules by URI to avoid reloading:

// Same module, loaded once
IModule module1 = loader.load(Path.of("model.xml"));
IModule module2 = loader.load(Path.of("model.xml"));
// module1 == module2 (same instance)
import dev.metaschema.core.model.MetaschemaException;

import java.io.IOException;
import java.nio.file.Path;

try {
    IModule module = loader.load(Path.of("invalid.xml"));
} catch (MetaschemaException e) {
    System.err.println("Failed to load module: " + e.getMessage());
} catch (IOException e) {
    System.err.println("IO error: " + e.getMessage());
}
IModule module = loader.load(path);

// Check for root assembly (document root)
boolean hasRoot = module.getAssemblyDefinitions().stream()
    .anyMatch(IAssemblyDefinition::isRoot);

if (!hasRoot) {
    System.err.println("Module has no root assembly");
}
public void listDefinitions(IModule module) {
    System.out.println("=== " + module.getName() + " ===");

    System.out.println("\nAssemblies:");
    module.getAssemblyDefinitions().forEach(a ->
        System.out.println("  " + a.getName() +
            (a.isRoot() ? " (root)" : "")));

    System.out.println("\nFields:");
    module.getFieldDefinitions().forEach(f ->
        System.out.println("  " + f.getName()));

    System.out.println("\nFlags:");
    module.getFlagDefinitions().forEach(f ->
        System.out.println("  " + f.getName()));
}
import dev.metaschema.core.model.IAssemblyDefinition;
import dev.metaschema.core.model.IFieldDefinition;
import dev.metaschema.core.model.IModule;
import dev.metaschema.core.model.INamedModelDefinition;

public INamedModelDefinition findDefinition(IModule module, String name) {
    IAssemblyDefinition assembly = module.getAssemblyDefinitionByName(name);
    if (assembly != null) return assembly;

    IFieldDefinition field = module.getFieldDefinitionByName(name);
    if (field != null) return field;

    return module.getFlagDefinitionByName(name);
}
  1. Reuse loaders - The loader caches modules
  2. Handle errors - Modules may have syntax errors
  3. Check for imports - Modules may depend on others
  4. Use absolute paths - Relative paths resolved from loader location

Continue learning about the Metaschema Java Tools with these related guides: