Skip to content

feat: support any in Java binding annotations (#220)#657

Merged
david-waltermire merged 1 commit intometaschema-framework:developfrom
david-waltermire:feature/220-any-instance
Feb 8, 2026
Merged

feat: support any in Java binding annotations (#220)#657
david-waltermire merged 1 commit intometaschema-framework:developfrom
david-waltermire:feature/220-any-instance

Conversation

@david-waltermire
Copy link
Contributor

@david-waltermire david-waltermire commented Feb 7, 2026

Summary

  • Add IAnyContent and IAnyInstance core model interfaces for the Metaschema <any/> instance type
  • Add @BoundAny annotation and IBoundInstanceModelAny databind binding layer
  • Implement XML parsing/writing: captures unmodeled child elements as W3C DOM Element instances via StAX-to-DOM conversion, round-trips with full fidelity
  • Implement JSON/YAML parsing/writing: captures unmodeled properties as Jackson ObjectNode, round-trips with full fidelity
  • Generate xs:any namespace="##other" processContents="lax" in XML Schema for assemblies with <any/>
  • Generate additionalProperties: true in JSON Schema for assemblies with <any/>
  • Update model visitor, container model, and module loading infrastructure
  • Harden XmlDomUtil.newDocument() against XXE (defense-in-depth)
  • Strengthen unit testing policy to prefer fixes over @Disabled

Specification Documentation: Metaschema language-level documentation for <any/> is tracked in companion PR metaschema-framework/metaschema#171.

Test plan

  • ContainerModelAnyInstanceTest — 8 tests for core container model getAnyInstance() behavior
  • AnyInstanceLoadingTest — verifies <any/> is processed during Metaschema module loading
  • XmlAnyContentTest — 6 unit tests for XmlAnyContent wrapper
  • JsonAnyContentTest — 10 unit tests for JsonAnyContent wrapper
  • AnyXmlRoundTripTest — 5 XML parsing/writing round-trip tests including nested elements and attributes
  • AnyJsonRoundTripTest — 8 JSON parsing/writing round-trip tests including nested objects and arrays
  • AnyJsonValueKeyTest — 5 tests verifying correct interaction between json-key flags and @BoundAny capture
  • AnyXmlSchemaGenerationTest — 2 tests for XML Schema xs:any output
  • AnyJsonSchemaGenerationTest — 2 tests for JSON Schema additionalProperties output
  • Full CI build passes: mvn clean install -PCI -Prelease

Closes #220

Summary by CodeRabbit

  • New Features

    • Added support for capturing unmodeled content in Java binding annotations, allowing applications to preserve unknown XML elements and JSON properties during deserialization and write them back during serialization.
    • New @BoundAny annotation enables fields to receive unmodeled content from assemblies.
  • Documentation

    • Updated unit testing guidelines with systematic debugging approach and CI build requirements.

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

Adds end-to-end support for metaschema : core any-model interfaces and visitor hook, databind @BoundAny and bound-any bridge, XML/JSON/YAML capture/serialization of unmodeled content, schema generator outputs (xs:any / additionalProperties), StAX↔DOM utilities, tests, PRD and implementation plan, and unit-testing policy edits.

Changes

Cohort / File(s) Summary
Core model
core/src/main/java/dev/metaschema/core/model/IAnyContent.java, core/src/main/java/dev/metaschema/core/model/IAnyInstance.java, core/src/main/java/dev/metaschema/core/model/ModelType.java, core/src/main/java/dev/metaschema/core/model/..., core/src/test/.../ContainerModelAnyInstanceTest.java
Add IAnyContent and IAnyInstance, ModelType.ANY, container/builder plumbing (getAnyInstance, builder propagation), visitor.visitAny(), constraint visitor handling, and unit tests for container/builder behavior.
Databind — binding & bridge
databind/src/main/java/dev/metaschema/databind/model/annotations/BoundAny.java, databind/src/main/java/dev/metaschema/databind/model/IBoundInstanceModelAny.java, databind/src/main/java/dev/metaschema/databind/model/impl/InstanceModelAny.java, databind/src/main/java/dev/metaschema/databind/model/metaschema/impl/AnyInstanceImpl.java, databind/src/main/java/dev/metaschema/databind/model/metaschema/impl/AssemblyModelGenerator.java
Introduce @BoundAny marker, bound-any interface and reflective InstanceModelAny, AnyInstanceImpl, and AssemblyModelGenerator wiring to detect/attach a single bound any field.
Databind — JSON/YAML I/O
databind/src/main/java/dev/metaschema/databind/io/json/JsonAnyContent.java, databind/src/main/java/dev/metaschema/databind/io/json/MetaschemaJsonReader.java, databind/src/main/java/dev/metaschema/databind/io/json/MetaschemaJsonWriter.java, databind/src/test/java/.../AnyJson*
Add JsonAnyContent (ObjectNode), reader captures unmatched properties into any-accumulator, writer emits captured properties after known fields; JSON/YAML round-trip and json-key interaction tests added.
Databind — XML I/O & utilities
databind/src/main/java/dev/metaschema/databind/io/xml/XmlAnyContent.java, databind/src/main/java/dev/metaschema/databind/io/xml/XmlDomUtil.java, databind/src/main/java/dev/metaschema/databind/io/xml/MetaschemaXmlReader.java, databind/src/main/java/dev/metaschema/databind/io/xml/MetaschemaXmlWriter.java, databind/src/test/java/.../AnyXml*
Add XmlAnyContent (List), XmlDomUtil for StAX↔DOM conversion, reader captures leftover elements into XmlAnyContent, writer serializes them back; include XML round-trip tests and XXE protections.
Schema generation
schemagen/src/main/java/dev/metaschema/schemagen/json/impl/JsonSchemaHelper.java, schemagen/src/main/java/dev/metaschema/schemagen/xml/impl/schematype/XmlComplexTypeAssemblyDefinition.java, schemagen/src/test/.../Any*, schemagen/src/test/resources/metaschema/*
JSON schema: exclude IAnyInstance from property emission and set additionalProperties=true when any-instance present. XML schema: emit xs:any (namespace="##other", processContents="lax", minOccurs="0", maxOccurs="unbounded") when any-instance present; tests/resources added.
Tests & fixtures
databind/src/test/java/.../Any*, databind/src/test/resources/metaschema/*, schemagen/src/test/..., core/src/test/...
Add many unit/integration tests and test assemblies/resources for JSON/XML round-trips, schema generation, loading, and json-key interactions; update TestMetaschema to include new test assemblies.
Docs & PRD / CI rules
.claude/CLAUDE.md, .claude/rules/unit-testing.md, PRDs/20260206-any-instance-support/*
Add PRD and implementation plan for any-instance support; update CLAUDE.md and unit-testing guidance (expanded test-failure policy).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Reader as Reader (XML/JSON)
    participant Parser as Parser (StAX / JSON parser)
    participant Model as AssemblyModel (IAnyInstance)
    participant AnyContent as AnyContent (XmlAnyContent/JsonAnyContent)
    participant Writer as Writer (XML/JSON)
    participant Output

    Client->>Reader: deserialize(data)
    Reader->>Model: check hasAnyInstance?
    alt any-instance present
        Reader->>Parser: parse known instances
        Parser->>AnyContent: capture unmodeled elements/properties
        Reader->>Model: boundAny.setAnyContent(AnyContent)
    else
        Reader->>Parser: skip or warn on unmodeled content
    end

    Client->>Writer: serialize(object)
    Writer->>Model: get bound any content
    alt any-content present
        loop per item
            AnyContent->>Writer: provide element/property
            Writer->>Output: write item
        end
    end
    Writer->>Output: finalize stream
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐇 I nibble code and hop with cheer,
Any bits once lost appear;
Elements, props, JSON trees,
Captured, kept, and written free —
Round-trip safe, the rabbit grins with glee.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.87% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: support any in Java binding annotations (#220)' accurately and specifically describes the main change in the changeset—adding support for the Metaschema instance type in Java bindings.
Linked Issues check ✅ Passed The PR fully implements the coding objectives from issue #220: adds @BoundAny annotation, implements XML/JSON/YAML parsing, captures unmodeled content, and includes comprehensive tests. All acceptance criteria are met: documentation/readme updated, PR references and closes #220, and CI/CD passes.
Out of Scope Changes check ✅ Passed All changes in the PR are directly related to supporting in Java bindings. Core model additions (IAnyContent, IAnyInstance), databind layer (@BoundAny, IBoundInstanceModelAny), parsing/writing updates, schema generation, and tests all align with issue #220 objectives. No out-of-scope changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
PRDs/20260206-any-instance-support/implementation-plan.md (1)

604-607: Minor readability nits in task steps.

Consider varying the repeated “Create …” sentence starts in Task 10/12 steps, and replace “properly” with a stronger verb for crisper flow.

Also applies to: 734-737, 868-868

core/src/main/java/dev/metaschema/core/model/IFeatureContainerModelAssembly.java (1)

68-72: Remove the @Nullable annotation from the override.

The base interface IContainerModelAssembly#getAnyInstance() already declares @Nullable on line 61. The nullability contract is inherited, so the annotation on the override is redundant and should be omitted to keep nullability contracts single-sourced.

core/src/main/java/dev/metaschema/core/model/IAnyInstance.java (1)

86-88: Remove the duplicate @NonNull annotation on the visitor parameter in the override.

The parent interface IModelElementVisitable already declares @NonNull on the visitor parameter; the duplication in this override creates unnecessary SpotBugs noise.

databind/src/main/java/dev/metaschema/databind/io/xml/XmlAnyContent.java (1)

30-32: Minor: Redundant wrapping with Collections.unmodifiableList.

List.copyOf() already returns an unmodifiable list, so the Collections.unmodifiableList() wrapper is redundant.

Suggested simplification
   public XmlAnyContent(`@NonNull` List<Element> elements) {
-    this.elements = Collections.unmodifiableList(List.copyOf(elements));
+    this.elements = List.copyOf(elements);
   }
PRDs/20260206-any-instance-support/PRD.md (1)

5-5: Consider updating status from "Draft" to reflect implementation completion.

All success criteria are marked complete, and per the PR comments, the implementation is done with 30 tests passing and CI green. The status could be updated to "Implemented" or "Complete" for accuracy.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PMD (7.21.0)
core/src/main/java/dev/metaschema/core/model/DefaultAssemblyModelBuilder.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.

core/src/main/java/dev/metaschema/core/model/IAnyContent.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.

core/src/main/java/dev/metaschema/core/model/IModelElementVisitor.java

[ERROR] Cannot load ruleset pmd/category/java/custom.xml: Cannot resolve rule/ruleset reference 'pmd/category/java/custom.xml'. Make sure the resource is a valid file or URL and is on the CLASSPATH. Use --debug (or a fine log level) to see the current classpath.
[WARN] Progressbar rendering conflicts with reporting to STDOUT. No progressbar will be shown. Try running with argument -r to output the report to a file instead.

  • 35 others

Comment @coderabbitai help to get the list of available commands and usage tips.

@david-waltermire david-waltermire linked an issue Feb 7, 2026 that may be closed by this pull request
6 tasks
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/src/main/java/dev/metaschema/core/model/DefaultAssemblyModelBuilder.java (1)

122-134: ⚠️ Potential issue | 🔴 Critical

Fix: anyInstance is lost when buildAssembly() returns empty().

When getModelInstances().isEmpty() returns true, the method returns the shared IContainerModelAssemblySupport.empty() instance regardless of whether anyInstance is set. If an assembly has only an <any/> instance without any other model instances, this discards the anyInstance. Instead, create a new DefaultContainerModelAssemblySupport instance with the anyInstance even when modelInstances is empty, since the code elsewhere treats anyInstance-only scenarios as valid (e.g., XmlComplexTypeAssemblyDefinition checks if (hasModelContent || hasAny)).

🤖 Fix all issues with AI agents
In @.claude/rules/unit-testing.md:
- Line 31: The guideline references a non‑existent skill identifier
"superpowers:systematic-debugging", which is undocumented and unclear; either
document that capability or replace it with concrete steps. Fix by (a) adding a
short description and usage docs for the "superpowers:systematic-debugging"
skill where other "superpowers:" capabilities are documented (include examples
and expected outcomes) and link to that doc from the unit-testing guideline, or
(b) remove "superpowers:systematic-debugging" from the line and replace it with
a bullet list of concrete debugging steps (e.g., reproduce failure, run targeted
test with --run, collect logs, bisect recent changes, add failing example) so
readers understand exactly what to do; ensure the change updates the same
guideline entry so references like "superpowers:systematic-debugging" are no
longer ambiguous.

In
`@databind/src/main/java/dev/metaschema/databind/io/json/MetaschemaJsonReader.java`:
- Around line 607-697: The code uses parser.getLongValue() in buildJsonValue for
VALUE_NUMBER_INT which will throw for integers outside long range; change the
VALUE_NUMBER_INT branch in buildJsonValue to obtain a BigInteger (e.g.
parser.getBigIntegerValue() or parser.getNumberValue() cast to BigInteger) and
pass that BigInteger to nodeFactory.numberNode(...) so integer values of
arbitrary size are preserved instead of failing.

In
`@databind/src/test/java/dev/metaschema/databind/io/xml/AnyXmlRoundTripTest.java`:
- Around line 104-148: The test testWriteSerializesAnyContent uses Java assert
statements that are ignored in CI; replace the two plain "assert
xmlOutput.contains(...)" checks with JUnit assertions (e.g.,
assertTrue(xmlOutput.contains("extra"), "...") and
assertTrue(xmlOutput.contains("foreign-value"), "...")) so they run under
surefire. Update imports if needed to use
org.junit.jupiter.api.Assertions.assertTrue and keep the existing xmlOutput
variable and test method unchanged otherwise.

In
`@databind/src/test/java/dev/metaschema/databind/model/metaschema/AnyInstanceLoadingTest.java`:
- Around line 34-40: The test currently casts rootDef to
DefinitionAssemblyGlobal without checking its type which can throw
ClassCastException; update AnyInstanceLoadingTest to
assertInstanceOf(DefinitionAssemblyGlobal.class, rootDef, ...) (or use
instanceof + fail) before performing the cast, then assign the cast result to a
DefinitionAssemblyGlobal variable and continue calling
getModelContainer().getAnyInstance() so failures show a clear assertion error
instead of a ClassCastException.

In `@PRDs/20260206-any-instance-support/implementation-plan.md`:
- Around line 433-872: Add a new security-hardening task (e.g., "Task 14A:
Security Review and Hardening") to Phase 2 and update Tasks 10–13 to include
concrete mitigations: when converting StAX to DOM in
XmlEventUtil/DocumentBuilderFactory used by
MetaschemaXmlReader/MetaschemaXmlWriter disable external entity resolution and
DTD processing, set entity‑expansion limits and namespace validation; when
capturing JSON into JsonAnyContent/MetaschemaJsonReader/MetaschemaJsonWriter
enforce maximum payload size and maximum nesting depth, reject or truncate
oversized ObjectNode captures, and ensure proper escaping/encoding when
serializing captured content back; add documentation that captured content is
untrusted and add automated security tests (XXE, billion laughs, large payloads,
deep nesting, malicious namespaces) and CI checks to validate these protections.
- Around line 986-1001: Add explicit documentation sub-tasks to Phase 4 by
extending Task 17 with Task 17A/B/C: Task 17A "Update User Documentation" should
add a user guide section for the `@BoundAny` annotation, document the IAnyContent
interface and its format-specific implementations, provide example code for
capturing and serializing any content, and update module reference docs to cover
<any/> declarations; Task 17B "Update API Documentation" should ensure Javadoc
completeness for all new public interfaces/classes, document namespace behavior
for XML any content, and document value-key interaction for JSON any content;
Task 17C "Update Website/Changelog" should add a feature announcement to the
website, update changelog/release notes, and link to issue `#220` so documentation
work is explicitly tracked before PR submission.
- Around line 621-643: The implementation lacks documented error handling and
validation for captured "any" content in the XML/JSON parsers (code paths around
definition.getAnyInstance(), staxToDom(), XmlAnyContent, anyInstance.setValue()
and the fallback XmlEventUtil.skipElement()); update the implementation plan to
specify: a) on malformed content or JSON parse failures decide whether to fail
the whole parse or attach an error object to the any container (recommend
attaching an error marker plus original raw content), b) whether any content is
validated or treated as opaque (recommend default opaque with optional
schema/constraint hooks), c) enforce resource limits (max bytes/elements per any
capture and abort with a clear error if exceeded), and d) how errors are
surfaced to users (structured error codes/messages and logs) and ensure both XML
(staxToDom path) and JSON capture paths follow this behavior and are explicitly
documented for consistency.
- Line 3: Remove the AI assistant directive line that reads "For Claude:
REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan
task-by-task" from the implementation plan
(PRDs/20260206-any-instance-support/implementation-plan.md) so the document is
tool-agnostic; simply delete that line or replace it with a human-facing
instruction or heading that describes the expected developer workflow without
referencing any AI agent or sub-skill.
- Around line 613-615: Replace the plan's new utility with a reference to the
existing XmlDomUtil.staxToElement() and modify XmlDomUtil (specifically
newDocument() and any use of TransformerFactory during StAX-to-DOM conversion)
to harden XML parsing against XXE by setting the DocumentBuilderFactory and
TransformerFactory external-access attributes: call
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "") and
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "") (and the equivalent on
TransformerFactory) so external DTD/schema access is denied; update any callers
of staxToElement() if necessary to use the hardened newDocument()/factory.
🧹 Nitpick comments (3)
PRDs/20260206-any-instance-support/implementation-plan.md (1)

168-189: Provide explicit strategy for discovering all interface implementors.

Adding a type parameter to IContainerModelAssemblySupport is correctly identified as a breaking change. However, the plan could be more prescriptive about discovering all affected implementors to reduce implementation risk.

Consider adding:

  • Command to discover implementors: rg "implements.*IContainerModelAssemblySupport|extends.*IContainerModelAssemblySupport" --type java
  • Expected count of affected classes across modules
  • Checklist of known critical implementors (if applicable)

This would make the breaking change more manageable and reduce the chance of missing an implementor during compilation fix passes.

core/src/main/java/dev/metaschema/core/model/IModelElementVisitor.java (1)

101-110: LGTM! Minor inconsistency in parameter naming.

The visitAny callback is correctly added to support visiting IAnyInstance elements. The Javadoc is complete and follows the existing pattern.

Nit: The parameter is named instance while all other visitor methods use item (e.g., visitFlagInstance(IFlagInstance item, ...)). Consider renaming for consistency:

🔧 Optional: Align parameter naming
-  RESULT visitAny(`@NonNull` IAnyInstance instance, CONTEXT context);
+  RESULT visitAny(`@NonNull` IAnyInstance item, CONTEXT context);

,

databind/src/main/java/dev/metaschema/databind/io/xml/XmlDomUtil.java (1)

193-216: Consider: Deeply nested XML could cause stack overflow.

The readChildren method uses recursion to process nested elements. For extremely deep XML structures, this could potentially cause a StackOverflowError. This is a known trade-off with recursive XML processing and is unlikely to be a problem in practice for typical Metaschema content.

david-waltermire added a commit to david-waltermire/metaschema-java that referenced this pull request Feb 7, 2026
- IAnyInstance.isEffectiveValueWrappedInXml() returns false instead
  of throwing UnsupportedOperationException
- Use BigInteger for integer any-content parsing to handle values
  outside long range
- Replace Java assert statements with JUnit assertTrue in
  AnyXmlRoundTripTest
- Use assertInstanceOf instead of cast in AnyInstanceLoadingTest
- Remove AI directive from implementation-plan.md
@david-waltermire
Copy link
Contributor Author

@coderabbitai Addressed outside-diff-range and nitpick comments in commit 63d733a:

Critical (outside diff range): DefaultAssemblyModelBuilder.buildAssembly() now checks getModelInstances().isEmpty() && anyInstance == null before returning the empty singleton, preserving the anyInstance when an assembly has only <any/> without other model instances.

Nit: IModelElementVisitor.visitAny() parameter renamed from instance to item for consistency with all other visitor methods.

Nit (XmlDomUtil recursive depth): Acknowledged — unlikely to be an issue in practice for typical Metaschema content. No action taken.

Nit (implementation-plan.md implementor discovery): PRD is completed; no update needed.

@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

Tip

For best results, initiate chat on the files or code changes.

@david-waltermire, thank you for addressing the feedback! I appreciate the thorough updates in commit 63d733a:

Critical fix: Great catch on the empty singleton logic—ensuring anyInstance is preserved when an assembly contains only <any/> is important for correct model representation.

Consistency improvement: Renaming the parameter to item maintains uniformity across all visitor methods.

Pragmatic decision: Acknowledged on the recursive depth concern—makes sense that typical Metaschema content won't hit problematic depths.

PRD status: Understood that the PRD is complete.

The fixes look good! 🎉

@david-waltermire
Copy link
Contributor Author

Addressed remaining review feedback in commit 9f310f1:

Code changes:

  • XmlDomUtil.java: Hardened newDocument() against XXE by setting ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA to empty strings on the DocumentBuilderFactory. While newDocument() only creates blank DOM documents (no parse() calls), this follows defense-in-depth principles. No TransformerFactory is used in XmlDomUtil.
  • unit-testing.md: Added inline description of superpowers:systematic-debugging — it's a valid managed skill from the superpowers plugin (4-phase debugging framework: root cause investigation, pattern analysis, hypothesis testing, implementation). Added cross-reference to development-workflow.md for details.

Implementation plan updates:

  • Added Task 14A: Security Hardening documenting XXE protections in XmlDomUtil, StAX parser security defaults, and Jackson StreamReadConstraints
  • Added error handling and validation documentation to Task 10 specifying behavior for malformed content, opaque content treatment, resource limits (inherited from StAX/Jackson), and error surfacing
  • Updated Task 10 Step 3 to reference existing XmlDomUtil.staxToElement() instead of creating a new utility
  • Added Task 17: Javadoc Completeness documenting required coverage for all new public interfaces/classes and namespace behavior
  • Renumbered CI build/PR task to Task 18
  • Added XmlDomUtil.java to Files Changed Summary
  • Added companion spec PR reference (feat: specify any model instance and add placement constraints metaschema#171) to plan header

Previously addressed (commits 44247ba, 63d733a):

  • MetaschemaJsonReader.java: getLongValue()getBigIntegerValue() for arbitrary-size integers
  • AnyXmlRoundTripTest.java: Java assert → JUnit assertTrue()
  • AnyInstanceLoadingTest.java: Added assertInstanceOf check before cast
  • implementation-plan.md: Removed AI directive line
  • DefaultAssemblyModelBuilder.java: Fixed critical bug preserving anyInstance when model has no other instances
  • IModelElementVisitor.java: Renamed instanceitem parameter for consistency

All 30 any-instance tests passing.

…ramework#220)

Add full support for the Metaschema <any/> instance type, enabling
assemblies to capture and round-trip unmodeled content across XML
and JSON/YAML formats.

Core model layer:
- IAnyContent interface for format-neutral unmodeled content
- IAnyInstance interface with ModelType.ANY enum constant
- Container model updates (IContainerModelAssemblySupport,
  DefaultContainerModelAssemblySupport, DefaultAssemblyModelBuilder)
- IModelElementVisitor.visitAny() callback

Databind binding layer:
- @BoundAny annotation for marking IAnyContent fields
- IBoundInstanceModelAny and InstanceModelAny implementation
- AssemblyModelGenerator scans for @BoundAny during introspection
- AnyInstanceImpl for module-loaded definitions

XML parsing and writing:
- XmlAnyContent wraps captured DOM elements
- XmlDomUtil for StAX-to-DOM and DOM-to-StAX conversion with
  XXE-hardened DocumentBuilderFactory
- MetaschemaXmlReader captures unknown child elements
- MetaschemaXmlWriter serializes captured elements back

JSON/YAML parsing and writing:
- JsonAnyContent wraps captured Jackson ObjectNode
- MetaschemaJsonReader captures unmatched properties using
  BigInteger for arbitrary-size integers
- MetaschemaJsonWriter serializes captured properties back

Schema generation:
- XML Schema: emits xs:any namespace="##other" processContents="lax"
- JSON Schema: sets additionalProperties: true

Tests: 56 new tests covering container model, module loading,
content wrappers, XML/JSON round-trips, json-value-key interaction,
and schema generation.
@david-waltermire david-waltermire force-pushed the feature/220-any-instance branch from 9f310f1 to 8e27d5d Compare February 7, 2026 19:43
Copy link
Contributor

@aj-stein aj-stein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small question, but this is a very exciting return of any!!!

@david-waltermire david-waltermire merged commit 9fef227 into metaschema-framework:develop Feb 8, 2026
6 checks passed
@david-waltermire david-waltermire deleted the feature/220-any-instance branch February 8, 2026 00:20
david-waltermire added a commit to david-waltermire/metaschema-java that referenced this pull request Feb 8, 2026
…framework#220)

The code generator now emits @BoundAny-annotated IAnyContent fields
when an assembly definition contains <any/> in its model. This
complements the runtime <any/> support added in PR metaschema-framework#657 by enabling
generated binding classes to capture unmodeled content.

Also adds a Claude rule documenting the full scope of changes required
when adding new Metaschema model features.
david-waltermire added a commit to david-waltermire/metaschema-java that referenced this pull request Feb 8, 2026
…framework#220)

The code generator now emits @BoundAny-annotated IAnyContent fields
when an assembly definition contains <any/> in its model. This
complements the runtime <any/> support added in PR metaschema-framework#657 by enabling
generated binding classes to capture unmodeled content.

Also adds a Claude rule documenting the full scope of changes required
when adding new Metaschema model features.
david-waltermire added a commit that referenced this pull request Feb 8, 2026
The code generator now emits @BoundAny-annotated IAnyContent fields
when an assembly definition contains <any/> in its model. This
complements the runtime <any/> support added in PR #657 by enabling
generated binding classes to capture unmodeled content.

Also adds a Claude rule documenting the full scope of changes required
when adding new Metaschema model features.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support any in Java binding annotations

2 participants