or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdjaxb-lifecycle.mdjaxb-model.mdobject-locators.mdstrategic-patterns.mdutilities.md
tile.json

jaxb-model.mddocs/

JAXB Model Abstraction

Comprehensive abstraction layer over JAXB model information providing vendor-neutral access to type metadata, property information, and schema details through visitor pattern support. This abstraction enables tools to inspect and work with JAXB model metadata independently of the underlying JAXB implementation.

Capabilities

Core Model Interfaces

Model Information Root

interface MModelInfo<T, C> extends MCustomizable {
    Collection<MBuiltinLeafInfo<T, C>> getBuiltinLeafInfos();
    Collection<MClassInfo<T, C>> getClassInfos();
    Collection<MEnumLeafInfo<T, C>> getEnumLeafInfos();
    Collection<MElementInfo<T, C>> getElementInfos();
    
    void addBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);
    void addClassInfo(MClassInfo<T, C> info);
    void addEnumLeafInfo(MEnumLeafInfo<T, C> info);
    void addElementInfo(MElementInfo<T, C> info);
    
    void removeBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);
    void removeClassInfo(MClassInfo<T, C> info);
    void removeEnumLeafInfo(MEnumLeafInfo<T, C> info);
    void removeElementInfo(MElementInfo<T, C> info);
}

Type Information

interface MTypeInfo<T, C> extends MCustomizable {
    QName getTypeName();
    boolean isSimpleType();
    T getTargetType();
    <V> V acceptTypeInfoVisitor(MTypeInfoVisitor<T, C, V> visitor);
}

interface MClassInfo<T, C> extends MClassTypeInfo<T, C> {
    List<MPropertyInfo<T, C>> getProperties();
    MPropertyInfo<T, C> getProperty(String publicName);
    QName getElementName();
    MClassTypeInfo<T, C, ?> getBaseTypeInfo();
}

interface MEnumLeafInfo<T, C> extends MTypeInfo<T, C> {
    List<MEnumConstantInfo<T, C>> getEnumConstants();
    MEnumConstantInfo<T, C> getEnumConstant(String name);
}

interface MElementInfo<T, C> extends MPackaged, MCustomizable {
    QName getElementName();
    MTypeInfo<T, C> getTypeInfo();
    MElement getElement();
}

Property Information

interface MPropertyInfo<T, C> extends MTargeted<T>, MCustomizable {
    String getPrivateName();
    String getPublicName();
    boolean isCollection();
    boolean isRequired();
    MDefaultValue getDefaultValue();
    <V> V acceptPropertyInfoVisitor(MPropertyInfoVisitor<T, C, V> visitor);
}

// Specific property types
interface MElementPropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C>, MWrappable {
    QName getWrapperElementName();
}

interface MAttributePropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C> {
    QName getAttributeName();
    boolean isRequired();
}

interface MAnyElementPropertyInfo<T, C> extends MPropertyInfo<T, C>, MMixable {
    boolean isLax();
    Set<QName> getProcessContents();
}

interface MAnyAttributePropertyInfo<T, C> extends MPropertyInfo<T, C> {
    // Marker interface for any attribute properties
}

interface MValuePropertyInfo<T, C> extends MSingleTypePropertyInfo<T, C> {
    // Marker interface for value properties
}

interface MElementRefPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable {
    MElementInfo<T, C> getElementInfo();
}

interface MElementRefsPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable, MMixable {
    List<MElementTypeInfo<T, C>> getElementTypeInfos();
}

interface MElementsPropertyInfo<T, C> extends MPropertyInfo<T, C>, MWrappable, MMixable {
    List<MElementTypeInfo<T, C>> getElementTypeInfos();
}

Visitor Pattern Interfaces

interface MTypeInfoVisitor<T, C, V> {
    V visitBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info);
    V visitEnumLeafInfo(MEnumLeafInfo<T, C> info);
    V visitWildcardTypeInfo(MWildcardTypeInfo<T, C> info);
    <NTI extends MTypeInfo<T, C>> V visitClassInfo(MClassInfo<T, C> info);
    <NTI extends MTypeInfo<T, C>> V visitClassRef(MClassRef<T, C> info);
}

interface MClassTypeInfoVisitor<T, C, V> {
    V visitClassInfo(MClassInfo<T, C> info);
    V visitClassRef(MClassRef<T, C> info);
}

interface MPropertyInfoVisitor<T, C, V> {
    V visitElementPropertyInfo(MElementPropertyInfo<T, C> info);
    V visitElementsPropertyInfo(MElementsPropertyInfo<T, C> info);
    V visitElementRefPropertyInfo(MElementRefPropertyInfo<T, C> info);
    V visitElementRefsPropertyInfo(MElementRefsPropertyInfo<T, C> info);
    V visitAttributePropertyInfo(MAttributePropertyInfo<T, C> info);
    V visitAnyElementPropertyInfo(MAnyElementPropertyInfo<T, C> info);
    V visitAnyAttributePropertyInfo(MAnyAttributePropertyInfo<T, C> info);
    V visitValuePropertyInfo(MValuePropertyInfo<T, C> info);
}

Supporting Interfaces

interface MCustomizable {
    MCustomizations getCustomizations();
    void setCustomizations(MCustomizations customizations);
}

interface MOriginated<O> {
    O getOrigin();
}

interface MPackaged {
    MPackageInfo getPackageInfo();
}

interface MContained {
    MContainer getContainer();
}

interface MContainer {
    Collection<? extends MContained> getContainedInfos();
}

interface MTargeted<T> {
    T getTargetType();
}

interface MWrappable {
    QName getWrapperElementName();
}

interface MMixable {
    boolean isMixed();
}

interface MNillable {
    boolean isNillable();
}

Concrete Implementation Factory

abstract class CMInfoFactory<T, C, TI extends MTypeInfo<T, C>, CI extends MClassInfo<T, C>, 
                           ELI extends MEnumLeafInfo<T, C>, EI extends MElementInfo<T, C>> {
    
    public abstract MModelInfo<T, C> createModel();
    
    // Factory methods for creating concrete model implementations
    protected abstract CI createClassInfo();
    protected abstract ELI createEnumLeafInfo();
    protected abstract EI createElementInfo();
    protected abstract MPropertyInfo<T, C> createPropertyInfo();
    // ... additional factory methods
}

Utility Classes

abstract class DefaultTypeInfoVisitor<T, C, V> implements MTypeInfoVisitor<T, C, V> {
    // Default empty implementations for all visitor methods
    public V visitBuiltinLeafInfo(MBuiltinLeafInfo<T, C> info) { return null; }
    public V visitEnumLeafInfo(MEnumLeafInfo<T, C> info) { return null; }
    public V visitWildcardTypeInfo(MWildcardTypeInfo<T, C> info) { return null; }
    public <NTI extends MTypeInfo<T, C>> V visitClassInfo(MClassInfo<T, C> info) { return null; }
    public <NTI extends MTypeInfo<T, C>> V visitClassRef(MClassRef<T, C> info) { return null; }
}

abstract class DefaultPropertyInfoVisitor<T, C, V> implements MPropertyInfoVisitor<T, C, V> {
    // Default empty implementations for all visitor methods
    public V visitElementPropertyInfo(MElementPropertyInfo<T, C> info) { return null; }
    public V visitAttributePropertyInfo(MAttributePropertyInfo<T, C> info) { return null; }
    // ... additional default methods
}

final class XmlTypeUtils {
    static QName getTypeName(Class<?> targetClass);
    // Extracts QName from @XmlType annotation
}

final class QNameCollector {
    Collection<QName> collectQNames(MModelInfo<?, ?> modelInfo);
    // Collects all QNames from model components
}

final class QNameUtils {
    static String getKey(QName name);
    // Converts QName to string key representation
}

Usage Examples

Basic Model Inspection

import org.jvnet.jaxb2_commons.xml.bind.model.*;
import org.jvnet.jaxb2_commons.xml.bind.model.concrete.*;
import javax.xml.bind.JAXBContext;

// Create model from JAXB context
JAXBContext context = JAXBContext.newInstance("com.example.schema");
CMInfoFactory<Type, Class, ?, ?, ?, ?> factory = new CMInfoFactory<Type, Class, ?, ?, ?, ?>(context);
MModelInfo<Type, Class> model = factory.createModel();

// Inspect class information
for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {
    System.out.println("Class: " + classInfo.getTargetType().getName());
    System.out.println("Element Name: " + classInfo.getElementName());
    
    // Inspect properties
    for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {
        System.out.println("  Property: " + property.getPublicName() + 
                          " (" + property.getPrivateName() + ")");
        System.out.println("    Collection: " + property.isCollection());
        System.out.println("    Required: " + property.isRequired());
    }
}

// Inspect enum information
for (MEnumLeafInfo<Type, Class> enumInfo : model.getEnumLeafInfos()) {
    System.out.println("Enum: " + enumInfo.getTargetType().getName());
    for (MEnumConstantInfo<Type, Class> constant : enumInfo.getEnumConstants()) {
        System.out.println("  Constant: " + constant.getName());
    }
}

Property Type Analysis with Visitor Pattern

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;

public class PropertyAnalyzer extends DefaultPropertyInfoVisitor<Type, Class, Void> {
    
    @Override
    public Void visitElementPropertyInfo(MElementPropertyInfo<Type, Class> info) {
        System.out.println("Element Property: " + info.getPublicName());
        if (info.getWrapperElementName() != null) {
            System.out.println("  Wrapper: " + info.getWrapperElementName());
        }
        return null;
    }
    
    @Override
    public Void visitAttributePropertyInfo(MAttributePropertyInfo<Type, Class> info) {
        System.out.println("Attribute Property: " + info.getPublicName());
        System.out.println("  Attribute Name: " + info.getAttributeName());
        System.out.println("  Required: " + info.isRequired());
        return null;
    }
    
    @Override
    public Void visitAnyElementPropertyInfo(MAnyElementPropertyInfo<Type, Class> info) {
        System.out.println("Any Element Property: " + info.getPublicName());
        System.out.println("  Lax: " + info.isLax());
        System.out.println("  Mixed: " + info.isMixed());
        return null;
    }
    
    @Override
    public Void visitElementsPropertyInfo(MElementsPropertyInfo<Type, Class> info) {
        System.out.println("Elements Property: " + info.getPublicName());
        System.out.println("  Element Types: " + info.getElementTypeInfos().size());
        for (MElementTypeInfo<Type, Class> elementType : info.getElementTypeInfos()) {
            System.out.println("    Element: " + elementType.getElementName());
        }
        return null;
    }
}

// Usage
PropertyAnalyzer analyzer = new PropertyAnalyzer();
for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {
    for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {
        property.acceptPropertyInfoVisitor(analyzer);
    }
}

QName Collection and Analysis

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;
import javax.xml.namespace.QName;

public class SchemaAnalyzer {
    
    public void analyzeSchema(MModelInfo<Type, Class> model) {
        // Collect all QNames from the model
        QNameCollector collector = new QNameCollector();
        Collection<QName> qnames = collector.collectQNames(model);
        
        // Group by namespace
        Map<String, List<QName>> namespaceGroups = qnames.stream()
            .collect(Collectors.groupingBy(QName::getNamespaceURI));
        
        System.out.println("Schema Analysis:");
        for (Map.Entry<String, List<QName>> entry : namespaceGroups.entrySet()) {
            String namespace = entry.getKey();
            List<QName> names = entry.getValue();
            
            System.out.println("Namespace: " + (namespace.isEmpty() ? "(default)" : namespace));
            for (QName name : names) {
                System.out.println("  " + name.getLocalPart());
            }
        }
        
        // Generate unique keys for QNames
        for (QName qname : qnames) {
            String key = QNameUtils.getKey(qname);
            System.out.println("QName: " + qname + " -> Key: " + key);
        }
    }
}

Custom Type Info Visitor

import org.jvnet.jaxb2_commons.xml.bind.model.util.*;

public class TypeInfoAnalyzer extends DefaultTypeInfoVisitor<Type, Class, TypeAnalysisResult> {
    
    @Override
    public TypeAnalysisResult visitClassInfo(MClassInfo<Type, Class> info) {
        TypeAnalysisResult result = new TypeAnalysisResult();
        result.setTypeName(info.getTypeName());
        result.setJavaType(info.getTargetType());
        result.setPropertyCount(info.getProperties().size());
        
        // Analyze inheritance
        MClassTypeInfo<Type, Class, ?> baseType = info.getBaseTypeInfo();
        if (baseType != null) {
            result.setHasInheritance(true);
            result.setBaseType(baseType.getTypeName());
        }
        
        // Count different property types
        int elementProps = 0, attributeProps = 0, anyProps = 0;
        for (MPropertyInfo<Type, Class> prop : info.getProperties()) {
            prop.acceptPropertyInfoVisitor(new DefaultPropertyInfoVisitor<Type, Class, Void>() {
                @Override
                public Void visitElementPropertyInfo(MElementPropertyInfo<Type, Class> info) {
                    elementProps++;
                    return null;
                }
                @Override
                public Void visitAttributePropertyInfo(MAttributePropertyInfo<Type, Class> info) {
                    attributeProps++;
                    return null;
                }
                @Override
                public Void visitAnyElementPropertyInfo(MAnyElementPropertyInfo<Type, Class> info) {
                    anyProps++;
                    return null;
                }
            });
        }
        
        result.setElementPropertyCount(elementProps);
        result.setAttributePropertyCount(attributeProps);
        result.setAnyPropertyCount(anyProps);
        
        return result;
    }
    
    @Override
    public TypeAnalysisResult visitEnumLeafInfo(MEnumLeafInfo<Type, Class> info) {
        TypeAnalysisResult result = new TypeAnalysisResult();
        result.setTypeName(info.getTypeName());
        result.setJavaType(info.getTargetType());
        result.setEnumConstantCount(info.getEnumConstants().size());
        return result;
    }
}

// Analysis result class
public class TypeAnalysisResult {
    private QName typeName;
    private Class javaType;
    private int propertyCount;
    private boolean hasInheritance;
    private QName baseType;
    private int elementPropertyCount;
    private int attributePropertyCount;
    private int anyPropertyCount;
    private int enumConstantCount;
    
    // getters and setters...
}

// Usage
TypeInfoAnalyzer analyzer = new TypeInfoAnalyzer();
for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {
    TypeAnalysisResult analysis = classInfo.acceptTypeInfoVisitor(analyzer);
    System.out.println("Analysis for " + analysis.getTypeName() + ":");
    System.out.println("  Java Type: " + analysis.getJavaType().getSimpleName());
    System.out.println("  Properties: " + analysis.getPropertyCount());
    System.out.println("  Elements: " + analysis.getElementPropertyCount());
    System.out.println("  Attributes: " + analysis.getAttributePropertyCount());
    if (analysis.isHasInheritance()) {
        System.out.println("  Base Type: " + analysis.getBaseType());
    }
}

Model Validation and Consistency Checking

public class ModelValidator {
    
    public void validateModel(MModelInfo<Type, Class> model) {
        Set<String> errors = new HashSet<>();
        
        // Validate class information
        for (MClassInfo<Type, Class> classInfo : model.getClassInfos()) {
            validateClassInfo(classInfo, errors);
        }
        
        // Validate element information
        for (MElementInfo<Type, Class> elementInfo : model.getElementInfos()) {
            validateElementInfo(elementInfo, errors);
        }
        
        // Report validation results
        if (errors.isEmpty()) {
            System.out.println("Model validation passed");
        } else {
            System.out.println("Model validation failed with errors:");
            errors.forEach(System.out::println);
        }
    }
    
    private void validateClassInfo(MClassInfo<Type, Class> classInfo, Set<String> errors) {
        if (classInfo.getTypeName() == null) {
            errors.add("Class " + classInfo.getTargetType().getName() + " has null type name");
        }
        
        // Check for duplicate property names
        Set<String> propertyNames = new HashSet<>();
        for (MPropertyInfo<Type, Class> property : classInfo.getProperties()) {
            String publicName = property.getPublicName();
            if (!propertyNames.add(publicName)) {
                errors.add("Class " + classInfo.getTargetType().getName() + 
                          " has duplicate property: " + publicName);
            }
            
            validatePropertyInfo(property, classInfo, errors);
        }
    }
    
    private void validatePropertyInfo(MPropertyInfo<Type, Class> property, 
                                    MClassInfo<Type, Class> owner, Set<String> errors) {
        if (property.getPublicName() == null || property.getPublicName().trim().isEmpty()) {
            errors.add("Property in class " + owner.getTargetType().getName() + 
                      " has null or empty public name");
        }
        
        if (property.getPrivateName() == null || property.getPrivateName().trim().isEmpty()) {
            errors.add("Property " + property.getPublicName() + " in class " + 
                      owner.getTargetType().getName() + " has null or empty private name");
        }
    }
    
    private void validateElementInfo(MElementInfo<Type, Class> elementInfo, Set<String> errors) {
        if (elementInfo.getElementName() == null) {
            errors.add("Element info has null element name");
        }
        
        if (elementInfo.getTypeInfo() == null) {
            errors.add("Element " + elementInfo.getElementName() + " has null type info");
        }
    }
}

Model Abstraction Architecture

The model abstraction provides several key benefits:

  1. Vendor Independence: Works with different JAXB implementations (RI, MOXy, etc.)
  2. Visitor Pattern: Enables type-safe traversal and analysis of model components
  3. Complete Metadata Access: Exposes all JAXB model information including types, properties, and relationships
  4. Extensibility: Supports custom analysis and transformation through visitor implementations
  5. Origin Tracking: Maintains links to original JAXB model components where available

This abstraction is essential for tools that need to analyze, validate, or transform JAXB models independently of the underlying JAXB implementation.