Skip to content

Add XPath and JSON Pointer path formatters#550

Merged
david-waltermire merged 6 commits intometaschema-framework:developfrom
david-waltermire:feature/xpath-jsonpointer-paths
Dec 19, 2025
Merged

Add XPath and JSON Pointer path formatters#550
david-waltermire merged 6 commits intometaschema-framework:developfrom
david-waltermire:feature/xpath-jsonpointer-paths

Conversation

@david-waltermire
Copy link
Contributor

@david-waltermire david-waltermire commented Dec 15, 2025

Summary

This PR adds new path formatters and format-based selection to the Metaschema framework:

  • XPathFormatter - Produces namespace-qualified XPath 3.1 paths using EQName format
  • JsonPointerFormatter - Produces RFC 6901 compliant JSON Pointer paths
  • Format-based selection - Automatically uses appropriate path format based on document type

Addresses metaschema-framework/oscal-cli#32

Key Features

Path Formatters:

  • XPath with EQName namespace qualification (Q{namespace}element[position])
  • Proper handling of XML grouping (GROUPED/UNGROUPED)
  • JSON Pointer with proper handling of all JSON grouping behaviors (KEYED/LIST/SINGLETON_OR_LIST/NONE)
  • Support for JSON key flag values in KEYED collections
  • RFC 6901 escaping (~~0, /~1)

Format-Based Selection:

  • JSON/YAML documents automatically use JSON Pointer paths
  • XML documents automatically use XPath paths
  • New --path-format CLI option to override: auto, metapath, xpath, jsonpointer

Changes

Core Module

  • Add XPathFormatter - XPath 3.1 paths with EQName-qualified names
  • Add JsonPointerFormatter - RFC 6901 compliant JSON Pointer paths
  • Add PathFormatSelection enum for path format options
  • Add XPATH_PATH_FORMATTER and JSON_POINTER_PATH_FORMATTER constants to IPathFormatter
  • Remove obsolete JsonPathFormatter placeholder code
  • Update package-info.java documentation

Databind Module

  • Add Format.getPathFormatter() - returns appropriate formatter for document format
  • Add Format.resolvePathFormatter(PathFormatSelection, Format) - resolves formatter based on selection

CLI Module

  • Add --path-format option to validation commands
  • Update LoggingValidationHandler to use configurable path formatter

Test plan

  • 26 unit tests for XPathFormatter covering all node types and edge cases
  • 21 unit tests for JsonPointerFormatter covering all grouping behaviors and RFC 6901 escaping
  • 10 unit tests for Format path formatter resolution
  • Full test suite passes
  • CI build passes (mvn install -PCI -Prelease)

Summary by CodeRabbit

  • New Features

    • Added XPath 3.1 EQName-based path formatter for XML paths
    • Added RFC 6901 JSON Pointer formatter for JSON/YAML paths
    • Added --path-format CLI option for selecting path output format (auto, metapath, xpath, jsonpointer)
    • Validation output now displays paths in selected format
  • Removals

    • Removed legacy JsonPathFormatter

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 15, 2025

📝 Walkthrough

Walkthrough

Introduces two new path formatters—XPath 3.1 (EQName-based) and RFC 6901 JSON Pointer—to augment path representation capabilities. Adds XPathFormatter and JsonPointerFormatter classes implementing IPathFormatter, removes JsonPathFormatter, updates CLI to support path format selection via a new PathFormatSelection enum, and integrates formatters into validation output handling.

Changes

Cohort / File(s) Summary
PRD & Specification
PRDs/20251215-path-formatters/plan.md
Documents XPath 3.1 and RFC 6901 JSON Pointer path formatter specifications, implementation phases, architecture, and testing strategy.
New Formatter Implementations
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java, core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java
Implements XPath 3.1 EQName-based path formatting with grouped wrapper support and RFC 6901 JSON Pointer formatting with escape rules (~0, ~1) and 0-based indexing.
Formatter Interface & Selection
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java, core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java
Adds public static constants XPATH_PATH_FORMATTER and JSON_POINTER_PATH_FORMATTER to IPathFormatter; introduces PathFormatSelection enum (AUTO, METAPATH, XPATH, JSON_POINTER) for formatter selection.
Format Integration
databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java
Adds getPathFormatter() and resolvePathFormatter() methods to resolve appropriate formatter based on document format or explicit selection.
Removed Formatter
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPathFormatter.java
Deleted implementation.
CLI Path Format Support
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java, metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java, metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java
Adds --path-format CLI option, path formatter resolution logic, and PathFormatSelection completion registry.
Documentation
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java
Updates package documentation to describe XPath and JSON Pointer formatters, examples, and expanded formatter ecosystem.
Formatter Tests
core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatterTest.java, core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java
Comprehensive unit tests covering formatters' node-type handling, grouping behaviors, escaping rules, and path composition.
Format Integration Tests
databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java
Tests Format.getPathFormatter() and resolvePathFormatter() across all selection modes and document formats.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • XPathFormatter and JsonPointerFormatter implementations: Verify correctness of EQName and RFC 6901 escaping logic, grouping behavior handling (GROUPED, KEYED, LIST, SINGLETON_OR_LIST), and edge cases for null instances.
  • Path formatter selection logic in AbstractValidateContentCommand: Ensure CLI option parsing and delegation to Format.resolvePathFormatter() are correctly wired; validate case-insensitive string-to-enum mapping and AUTO fallback behavior.
  • Integration points (LoggingValidationHandler, Format enum): Confirm that toPath(pathFormatter) replaces getMetapath() appropriately and that getPathFormatter()/resolvePathFormatter() logic aligns with new formatter availability.
  • Test coverage: Validate that test scenarios cover grouping behaviors, escaping rules (especially RFC 6901 tilde/slash rules), boundary conditions, and end-to-end path composition.

Possibly related PRs

  • Add shell completion command to cli-processor #551: Modifies CLI.java to register enum-based completion types (Format, SchemaFormat); similarly this PR adds PathFormatSelection registration and extends CLI command parsing, indicating continued CLI infrastructure enhancements.

Poem

🐰 Two paths unfold where data flows,
XPath blooms and JSON Pointer glows,
With EQNames and RFC's grace,
Formatters now find their rightful place!
CLI summons the perfect one to choose,
No validation path shall lose!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add XPath and JSON Pointer path formatters' directly and clearly summarizes the main changes in the PR, which focuses on adding two new path formatter implementations (XPathFormatter and JsonPointerFormatter) to the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.19.0)
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.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.

metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.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/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.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.

  • 9 others

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

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: 4

🧹 Nitpick comments (3)
PRDs/20251215-path-formatters/plan.md (3)

88-92: Document performance considerations for SINGLETON_OR_LIST sibling counting.

The specification for SINGLETON_OR_LIST requires counting siblings at runtime to determine if indexing is needed. This could be expensive if called frequently or on large structures. Document the expected performance characteristics and consider whether caching or optimization strategies should be mentioned.

Consider adding a subsection under "Risks and Mitigations" or the implementation tasks to address this, such as:

  • Whether traversal can be optimized (e.g., stop counting after finding 2 siblings)
  • Whether results should be cached at the instance level
  • Expected typical sibling counts in real Metaschema models

265-297: Expand test strategy to cover edge cases and error scenarios.

The test strategy is comprehensive but lacks coverage for:

Missing XPath test cases:

  • Empty namespace handling (local names without namespace)
  • Very deeply nested paths (performance/stack concerns)

Missing JSON Pointer test cases:

  • Position indexing: verify 0-based in JSON Pointer vs. 1-based in XPath (lines 230, 234)
  • Complex property names with multiple special characters (e.g., a/b~c)
  • Error scenarios: missing key flags, malformed key values

Missing for both:

  • Round-trip verification (if available)
  • Performance tests for deep structures or large sibling counts
  • Integration tests with actual Metaschema OSCAL modules (the test infrastructure mentions this but doesn't specify which)

Add subsections under "XPathFormatter Test Cases" and "JsonPointerFormatter Test Cases" for error/edge cases. Also specify which real Metaschema modules will be used for integration tests.


298-307: Provide more specific risk mitigation details.

The risks table is good but mitigations are vague:

Line 302: Risk about toEQName() format - mitigation should include:

  • Reference to XPath 3.1 spec or EQName standard
  • Specific assertion checks in unit tests (e.g., assert format matches regex Q\{[^}]*\}[a-zA-Z])

Line 304: Risk about getJsonName() returning null - clarify:

  • Under what conditions can this occur?
  • Is fallback to getEffectiveName() always safe?
  • Should this be guarded with a precondition check?

Line 305: Risk about JSON key flag not found - consider:

  • Is the fallback to numeric index acceptable per RFC 6901 compliance?
  • Should this emit a warning or error log?

Expand the risks section with specific preconditions, API assumptions, and logging strategies.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 77b2cd3 and 0f241e0.

📒 Files selected for processing (2)
  • .gitignore (1 hunks)
  • PRDs/20251215-path-formatters/plan.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
PRDs/20251215-path-formatters/plan.md

35-35: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Website
  • GitHub Check: Code
🔇 Additional comments (2)
.gitignore (1)

37-39: LGTM!

Excluding Git worktrees is a best practice for managing local development artifacts and keeps the repository clean.

PRDs/20251215-path-formatters/plan.md (1)

163-168: Clarify JsonPathFormatter removal vs. replacement.

Phase 3 task at line 164 states "Remove or replace commented JsonPathFormatter.java". The PRD should specify:

  • Is the file definitely being removed or is replacement still under consideration?
  • If removing, confirm no active code depends on it
  • If replacing, document the replacement strategy
  • The AI summary indicates it was removed in this PR, so update task to "Remove obsolete JsonPathFormatter.java"

Update the task to be definitive based on PR status.

Comment on lines +243 to +252
private String getJsonKeyValue(IModelNodeItem<?, ?> item, INamedModelInstance instance) {
IFlagInstance keyFlag = instance.getEffectiveJsonKey();
if (keyFlag != null) {
IFlagNodeItem flagItem = item.getFlagByName(keyFlag.getEffectiveName());
if (flagItem != null) {
return flagItem.toAtomicItem().asString();
}
}
return String.valueOf(item.getPosition() - 1); // fallback
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read the relevant section
fd "plan.md" PRDs/20251215-path-formatters/

Repository: metaschema-framework/metaschema-java

Length of output: 117


🏁 Script executed:

# Read the file to see lines 243-252 and surrounding context
wc -l PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 121


🏁 Script executed:

# Get lines around 243-252 with context
sed -n '220,270p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 1460


🏁 Script executed:

# Read more of the file to understand the full context and specification
sed -n '1,100p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 4233


🏁 Script executed:

# Check for test strategy and specification details
sed -n '260,314p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 2326


🏁 Script executed:

# Look for any existing implementations or related code
fd -e java | xargs grep -l "getJsonKeyValue\|JsonPointerFormatter" | head -10

Repository: metaschema-framework/metaschema-java

Length of output: 62


🏁 Script executed:

# Search for any existing implementations of JsonPointerFormatter
fd -e java | xargs grep -l "JsonPointerFormatter" 2>/dev/null | head -10

Repository: metaschema-framework/metaschema-java

Length of output: 62


🏁 Script executed:

# Look for warning/logging patterns in similar formatters
fd -e java | xargs grep -l "getJsonKeyValue\|JsonPointerFormatter\|XPathFormatter" 2>/dev/null | head -10

Repository: metaschema-framework/metaschema-java

Length of output: 62


🏁 Script executed:

# Check if there are any existing test files for formatters
fd -e java path | xargs grep -l "PathFormatter" 2>/dev/null | head -10

Repository: metaschema-framework/metaschema-java

Length of output: 525


🏁 Script executed:

# Check the IPathFormatter interface to understand the contract
cat -n core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java

Repository: metaschema-framework/metaschema-java

Length of output: 5013


🏁 Script executed:

# Check the existing MetapathFormatter implementation for error handling patterns
cat -n core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/MetapathFormatter.java

Repository: metaschema-framework/metaschema-java

Length of output: 3239


🏁 Script executed:

# Check the deprecated JsonPathFormatter for reference
cat -n core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPathFormatter.java

Repository: metaschema-framework/metaschema-java

Length of output: 3353


🏁 Script executed:

# Look at the risk mitigation section more carefully
sed -n '275,285p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 595


🏁 Script executed:

# Check if there are any logging patterns in the codebase
rg "LOGGER|log\(" core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/ -A 2 | head -20

Repository: metaschema-framework/metaschema-java

Length of output: 62


🏁 Script executed:

# Search for similar fallback patterns with warnings in the codebase
rg "fallback|warning" core/src/main/java/gov/nist/secauto/metaschema/core/ -B 2 -A 2 | head -30

Repository: metaschema-framework/metaschema-java

Length of output: 3477


🏁 Script executed:

# Check the risk section more carefully to confirm the warning recommendation
sed -n '272,290p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 1054


🏁 Script executed:

# Look for patterns of how null safety is handled in similar code
rg "getEffectiveName\|getJsonName" core/src/main/java/gov/nist/secauto/metaschema/core/ -B 2 -A 2 | head -40

Repository: metaschema-framework/metaschema-java

Length of output: 62


🏁 Script executed:

# Get the exact risk section from the PRD
sed -n '272,295p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 1197


🏁 Script executed:

# Check if there are any comments or TODOs about null handling in similar methods
rg "TODO|FIXME" core/src/main/java/gov/nist/secauto/metaschema/core/metapath/ -B 1 -A 1 | head -30

Repository: metaschema-framework/metaschema-java

Length of output: 2925


🏁 Script executed:

# Search for the complete risk section
grep -n "Risks and Mitigations" PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 108


🏁 Script executed:

# Get lines around the risks section
sed -n '268,310p' PRDs/20251215-path-formatters/plan.md

Repository: metaschema-framework/metaschema-java

Length of output: 2003


Add warning/logging to the getJsonKeyValue() fallback as specified in the Risks and Mitigations section.

The code example (lines 243-252) falls back silently to numeric index when the key flag is not found, but the risk mitigation table (line 304) explicitly requires this fallback to include "with warning". The current implementation should emit a warning when falling back to numeric index instead of using the actual key value for KEYED collections, as callers rely on key-based addressing per the JSON Pointer specification.

The null safety checks are appropriate; ensure the warning is also issued if getEffectiveJsonKey() returns null.

private String getJsonKeyValue(IModelNodeItem<?, ?> item, INamedModelInstance instance) {
  IFlagInstance keyFlag = instance.getEffectiveJsonKey();
  if (keyFlag != null) {
    IFlagNodeItem flagItem = item.getFlagByName(keyFlag.getEffectiveName());
    if (flagItem != null) {
      return flagItem.toAtomicItem().asString();
    }
  }
  // Add warning here before fallback
  return String.valueOf(item.getPosition() - 1); // fallback
}
🤖 Prompt for AI Agents
In PRDs/20251215-path-formatters/plan.md around lines 243 to 252, the
getJsonKeyValue() method silently falls back to a numeric index when no json key
is available; add a warning log whenever the function returns the numeric
fallback (including when getEffectiveJsonKey() is null) so callers and operators
are alerted. Use the module’s standard logger to emit a clear warning that
includes the item identity (e.g., path or position) and that a numeric index is
being used as a fallback, then return the numeric index as before; keep the
existing null-safety checks and only add the warning at the fallback point.

@david-waltermire david-waltermire marked this pull request as ready for review December 17, 2025 00:29
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: 3

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7260fb and d5d28c9.

📒 Files selected for processing (1)
  • PRDs/20251215-path-formatters/plan.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
PRDs/20251215-path-formatters/plan.md

105-105: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


170-170: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Code
  • GitHub Check: Website

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: 1

♻️ Duplicate comments (2)
PRDs/20251215-path-formatters/plan.md (2)

105-117: Add language identifier to code fence.

This code fence is missing a language identifier, which was flagged in a previous review. The block describes an integration flow diagram.

Apply this diff:

-```
+```text
 CLI Command
     ↓ parses --path-format option
 PathFormatSelection
     ↓ combined with
 Format (from document or --as option)
     ↓ resolved via
 IPathFormatter.resolveFormatter()
     ↓ passed to
 AbstractConstraintValidationHandler.setPathFormatter()
     ↓ used by
 Validation result messages
-```
+```

170-175: Add language identifier to code fence.

This code fence is missing a language identifier, which was flagged in a previous review. The block shows an architecture tree structure.

Apply this diff:

-```
+```tree
 IPathFormatter (interface)
 ├── MetapathFormatter (existing)
 ├── XPathFormatter (new)
 └── JsonPointerFormatter (new)
-```
+```
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27eaa36 and d0efab6.

📒 Files selected for processing (2)
  • PRDs/20251215-path-formatters/plan.md (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.java: All code changes must follow the Javadoc style guide (docs/javadoc-style-guide.md). New code requires 100% Javadoc coverage on public/protected members. Modified code must add/update Javadoc on any members touched. All Javadoc must include @param, @return, @throws tags in the correct order (BLOCKING)
Java target version must be Java 11. Use SpotBugs annotations (@nonnull, @nullable) for null safety in code.
Follow package naming convention gov.nist.secauto.metaschema.* for all Java packages
Follow Test-Driven Development (TDD) principles: write tests first before implementing functionality, verify tests fail with current implementation, implement minimal code to pass tests, then refactor while keeping tests green

Files:

  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java
**/metapath/**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.

Files:

  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/metapath/**/*.java : Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.
📚 Learning: 2025-12-17T13:27:43.669Z
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/metapath/**/*.java : Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.

Applied to files:

  • PRDs/20251215-path-formatters/plan.md
🧬 Code graph analysis (1)
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java (1)
core/src/main/java/gov/nist/secauto/metaschema/core/util/ObjectUtils.java (1)
  • ObjectUtils (18-135)
🔇 Additional comments (5)
PRDs/20251215-path-formatters/plan.md (1)

84-85: Typo fixed.

The previous typo METAPATH_PATH_FORMATER has been corrected to METAPATH_PATH_FORMATTER. This resolves the naming inconsistency flagged in an earlier review.

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java (4)

179-186: LGTM!

The countSiblings implementation correctly:

  • Handles the edge case of no parent (returns 1)
  • Uses getModelItemsByName() to find all siblings sharing the same QName
  • Returns the total count including the item itself

This aligns with the SINGLETON_OR_LIST behavior requirement to check sibling count at runtime.


198-201: LGTM!

The RFC 6901 escaping implementation is correct:

  • Escapes ~ to ~0 first (line 200)
  • Then escapes / to ~1
  • Order is critical and correctly implemented
  • ObjectUtils.notNull() ensures the @NonNull contract is maintained

111-140: LGTM!

The formatModelItem implementation correctly handles all JSON grouping behaviors:

  • Proper null safety for instances without metadata (lines 112-116)
  • KEYED: Extracts and escapes key values (lines 122-124)
  • LIST: Uses correct 0-based indexing (line 127)
  • SINGLETON_OR_LIST: Conditionally adds index only when multiple siblings exist (lines 129-135)
  • NONE: Returns name without index (line 138)

All escaping is properly applied per RFC 6901, and position arithmetic correctly converts from 1-based to 0-based indexing.


152-170: Implementation correctly uses getQName() for flag lookup; PRD example contains a bug.

The implementation properly uses keyFlag.getQName() to obtain an IEnhancedQName parameter for getFlagByName(). The method signature requires @NonNull IEnhancedQName name, which the code correctly provides. The PRD example in plan.md (lines 407-408) incorrectly uses getEffectiveName(), which returns a String and is incompatible with the expected parameter type.

The warning logging at lines 165-168 correctly addresses the previous review concern about alerting operators when falling back to numeric index.

aj-stein
aj-stein previously approved these changes Dec 19, 2025
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.

Very useful, I look forward to using this feature.

Implement two new IPathFormatter implementations:

- XPathFormatter: Produces XPath 3.1 paths with EQName format
  (e.g., /Q{http://example.com}catalog/Q{http://example.com}control[1])
  Handles GROUPED/UNGROUPED XmlGroupAsBehavior for wrapper elements

- JsonPointerFormatter: Produces RFC 6901 compliant JSON Pointer paths
  (e.g., /catalog/controls/0/id)
  Handles all JsonGroupAsBehavior modes (NONE, LIST, KEYED, SINGLETON_OR_LIST)
  Implements proper RFC 6901 escaping (~ -> ~0, / -> ~1)

Add constants to IPathFormatter:
- XPATH_PATH_FORMATTER
- JSON_POINTER_PATH_FORMATTER

Remove obsolete JsonPathFormatter (was commented out placeholder code).

Update package-info.java with documentation for new formatters.
Add design for:
- PathFormatSelection enum (AUTO, METAPATH, XPATH, JSON_POINTER)
- IPathFormatter.resolveFormatter() for format-based selection
- CLI --path-format option for explicit override
- Default behavior uses AUTO (format-based selection)

Mark Phases 1-3 as completed, add Phase 4 implementation tasks and test cases.
Implement automatic path format selection based on document type:
- JSON/YAML documents use JSON Pointer paths by default
- XML documents use XPath paths by default

Add --path-format CLI option to override the default:
- auto (default): select based on document format
- metapath: force Metapath format
- xpath: force XPath 3.1 EQName format
- jsonpointer: force RFC 6901 JSON Pointer format

Changes:
- Add PathFormatSelection enum in core module
- Add Format.getPathFormatter() and Format.resolvePathFormatter() in databind
- Add --path-format option to AbstractValidateContentCommand
- Update LoggingValidationHandler to accept configurable path formatter
- Add unit tests for Format path formatter resolution
- Fix PRD markdown code fence language identifiers (lines 105, 170)
- Fix typo: METAPATH_PATH_FORMATER -> METAPATH_PATH_FORMATTER in PRD
- Clarify PRD tasks for countSiblings() and getJsonKeyValue() helpers
- Add warning logging when getJsonKeyValue() falls back to numeric index
Add .type(PathFormatSelection.class) to PATH_FORMAT_OPTION and
register PathFormatSelection enum in CompletionTypeRegistry for
shell completion support from PR 551.
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: 0

🧹 Nitpick comments (4)
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java (2)

103-112: The .type(PathFormatSelection.class) on the Option is ineffective since parsing is done manually.

The Option is declared with .type(PathFormatSelection.class), but commandLine.getOptionValue() returns a String which is then manually parsed in parsePathFormatSelection(). The .type() method on Apache Commons CLI Options doesn't automatically convert values to enum types. Consider removing the misleading .type() call or adding a clarifying comment.

🔎 Suggested simplification
   @NonNull
   private static final Option PATH_FORMAT_OPTION = ObjectUtils.notNull(
       Option.builder()
           .longOpt("path-format")
           .hasArg()
           .argName("FORMAT")
-          .type(PathFormatSelection.class)
           .desc("path format in validation output: auto (default, selects based on document format), "
               + "metapath, xpath, jsonpointer")
           .get());

366-390: Consider using a Map-based lookup for cleaner maintainability.

The switch-based parsing works correctly with Locale.ROOT for case-insensitive comparison. The logging of unrecognized values with a fallback to AUTO is a good defensive pattern. However, a map-based approach could be more maintainable as formats are added.

🔎 Alternative map-based approach (optional)
private static final Map<String, PathFormatSelection> PATH_FORMAT_MAP = Map.of(
    "auto", PathFormatSelection.AUTO,
    "metapath", PathFormatSelection.METAPATH,
    "xpath", PathFormatSelection.XPATH,
    "jsonpointer", PathFormatSelection.JSON_POINTER,
    "json-pointer", PathFormatSelection.JSON_POINTER
);

@NonNull
private PathFormatSelection parsePathFormatSelection(@NonNull String value) {
  PathFormatSelection selection = PATH_FORMAT_MAP.get(value.toLowerCase(Locale.ROOT));
  if (selection == null) {
    LOGGER.warn("Unrecognized path format '{}', using auto", value);
    return PathFormatSelection.AUTO;
  }
  return selection;
}
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java (2)

43-55: Consider adding brief Javadoc to these public override methods.

Per coding guidelines, public members require Javadoc coverage. While these are @Override methods with documentation in the interface, adding brief method-level Javadoc (or {@inheritDoc}) would ensure 100% coverage compliance. The implementation returning empty strings to produce leading "/" is correctly documented via inline comments.

🔎 Example Javadoc addition
+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatMetaschema(IModuleNodeItem metaschema) {
     // Returns empty string to produce leading "/" via join in format method
     return "";
   }

+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatDocument(IDocumentNodeItem document) {
     // Returns empty string to produce leading "/" via join in format method
     return "";
   }

57-85: Missing Javadoc on public override methods.

Per coding guidelines, all public members require Javadoc. The methods formatRootAssembly, formatAssembly (both overloads), formatField, and formatFlag lack documentation. Consider adding {@inheritDoc} tags for interface contract documentation.

🔎 Add Javadoc to public methods
+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatRootAssembly(IRootAssemblyNodeItem root) {
     return ObjectUtils.notNull(root.getQName().toEQName());
   }

+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatAssembly(IAssemblyNodeItem assembly) {
     return formatModelItem(assembly);
   }

+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatAssembly(IAssemblyInstanceGroupedNodeItem assembly) {
     return formatModelItem(assembly);
   }

+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatField(IFieldNodeItem field) {
     return formatModelItem(field);
   }

+  /** {@inheritDoc} */
   @Override
   @NonNull
   public String formatFlag(IFlagNodeItem flag) {
     return ObjectUtils.notNull("@" + flag.getQName().toEQName());
   }

As per coding guidelines, new code requires 100% Javadoc coverage on public/protected members.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0efab6 and 7cf592d.

📒 Files selected for processing (14)
  • PRDs/20251215-path-formatters/plan.md (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPathFormatter.java (0 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java (1 hunks)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java (4 hunks)
  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java (1 hunks)
  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatterTest.java (1 hunks)
  • databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java (3 hunks)
  • databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java (1 hunks)
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java (2 hunks)
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java (7 hunks)
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java (4 hunks)
💤 Files with no reviewable changes (1)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPathFormatter.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatter.java
  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatterTest.java
🧰 Additional context used
📓 Path-based instructions (3)
**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.java: All code changes must follow the Javadoc style guide (docs/javadoc-style-guide.md). New code requires 100% Javadoc coverage on public/protected members. Modified code must add/update Javadoc on any members touched. All Javadoc must include @param, @return, @throws tags in the correct order (BLOCKING)
Java target version must be Java 11. Use SpotBugs annotations (@nonnull, @nullable) for null safety in code.
Follow package naming convention gov.nist.secauto.metaschema.* for all Java packages
Follow Test-Driven Development (TDD) principles: write tests first before implementing functionality, verify tests fail with current implementation, implement minimal code to pass tests, then refactor while keeping tests green

Files:

  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java
  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java
  • databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java
  • databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java
**/metapath/**/*.java

📄 CodeRabbit inference engine (CLAUDE.md)

Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.

Files:

  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java
  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java
**/*Test.java

📄 CodeRabbit inference engine (CLAUDE.md)

@test methods do not require Javadoc if they use descriptive method names. Use JUnit 5 for testing with parallel execution enabled.

Files:

  • core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java
  • databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/metapath/**/*.java : Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.
📚 Learning: 2025-12-17T13:27:43.669Z
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/metapath/**/*.java : Metapath is an implementation of XPath 3.1. Use the XPath 3.1 specification (https://www.w3.org/TR/xpath-31/) and XPath Functions 3.1 (https://www.w3.org/TR/xpath-functions-31/) as authoritative reference when implementing new functions, fixing bugs, or understanding error handling. Raise clarification before making changes if implementation differs from spec.

Applied to files:

  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java
  • PRDs/20251215-path-formatters/plan.md
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java
  • metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java
  • databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java
  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java
  • databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java
📚 Learning: 2025-12-17T13:27:43.669Z
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/*.java : Follow package naming convention gov.nist.secauto.metaschema.* for all Java packages

Applied to files:

  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java
  • databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java
📚 Learning: 2024-11-14T18:19:40.200Z
Learnt from: david-waltermire
Repo: metaschema-framework/metaschema-java PR: 245
File: core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBooleanItem.java:86-104
Timestamp: 2024-11-14T18:19:40.200Z
Learning: In the file `core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBooleanItem.java`, the 3-step approach in the `cast` method is consistent with the XPath 3.1 specification.

Applied to files:

  • core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java
📚 Learning: 2025-12-17T13:27:43.669Z
Learnt from: CR
Repo: metaschema-framework/metaschema-java PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-17T13:27:43.669Z
Learning: Applies to **/*.java : Java target version must be Java 11. Use SpotBugs annotations (NonNull, Nullable) for null safety in code.

Applied to files:

  • databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java
🧬 Code graph analysis (4)
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java (1)
cli-processor/src/main/java/gov/nist/secauto/metaschema/cli/processor/completion/CompletionTypeRegistry.java (1)
  • CompletionTypeRegistry (30-154)
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java (1)
metaschema-maven-plugin/src/main/java/gov/nist/secauto/metaschema/maven/plugin/AbstractMetaschemaMojo.java (1)
  • LoggingValidationHandler (575-701)
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java (1)
metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java (1)
  • LoggingValidationHandler (37-248)
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java (1)
core/src/main/java/gov/nist/secauto/metaschema/core/util/ObjectUtils.java (1)
  • ObjectUtils (18-135)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Code
  • GitHub Check: Website
🔇 Additional comments (19)
core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/IPathFormatter.java (2)

36-46: LGTM!

The XPATH_PATH_FORMATTER constant is well-documented with clear Javadoc, an illustrative example, and proper @see reference to the implementation class.


48-60: LGTM!

The JSON_POINTER_PATH_FORMATTER constant is properly documented with comprehensive Javadoc, RFC 6901 reference, and appropriate @see tags.

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/package-info.java (1)

23-66: LGTM!

The package documentation accurately reflects the expanded path formatter ecosystem with clear examples and usage patterns for all three formatters (Metapath, XPath, JSON Pointer).

PRDs/20251215-path-formatters/plan.md (1)

1-493: PRD documentation is informational.

This is a planning document that provides design specifications and implementation guidance. Previous review comments have been addressed in commits, and no further review is needed for this planning artifact.

metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/CLI.java (1)

15-15: LGTM!

The PathFormatSelection import and registration follow the established pattern for enum completion support, enabling shell autocomplete for the new path format options.

Also applies to: 74-74

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/PathFormatSelection.java (1)

1-54: LGTM!

The PathFormatSelection enum is well-designed with comprehensive Javadoc coverage on all constants. The AUTO option's behavior is clearly documented, and examples for each format help users understand the differences.

databind/src/test/java/gov/nist/secauto/metaschema/databind/io/FormatPathFormatterTest.java (1)

1-125: LGTM!

Comprehensive test coverage for path formatter resolution logic. Tests verify correct formatter selection for all Format types (XML, JSON, YAML) and all PathFormatSelection options (AUTO, METAPATH, XPATH, JSON_POINTER), including the null fallback case.

databind/src/main/java/gov/nist/secauto/metaschema/databind/io/Format.java (2)

93-109: LGTM!

The getPathFormatter() method correctly maps each Format to its appropriate path formatter (XPath for XML, JSON Pointer for JSON/YAML). Javadoc is comprehensive and follows the style guide.


111-140: LGTM!

The resolvePathFormatter() method correctly implements the selection logic for AUTO and explicit path format choices. The fallback to METAPATH_PATH_FORMATER when format is null is appropriate. Javadoc is comprehensive with proper @param and @return tags per coding guidelines.

core/src/test/java/gov/nist/secauto/metaschema/core/metapath/format/JsonPointerFormatterTest.java (1)

1-519: LGTM!

Comprehensive test coverage for JsonPointerFormatter across all node types, JSON grouping behaviors (NONE, LIST, SINGLETON_OR_LIST, KEYED), and RFC 6901 escaping rules. Tests validate correct 0-based indexing, key extraction, sibling counting, and full path composition.

metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/util/LoggingValidationHandler.java (4)

47-48: LGTM!

The @NonNull annotation on the pathFormatter field properly ensures null safety. The field declaration follows the SpotBugs annotation conventions.


77-104: LGTM!

The two factory methods are well-documented with complete Javadoc including @param and @return tags. The method signatures properly use @NonNull annotations for both parameters and return types, following the null safety conventions. The design pattern of providing both a simple factory (withPathFormatter) and a full-featured factory (withSettings) offers good flexibility.


106-113: LGTM!

The constructor chaining correctly delegates to the new overload with a default path formatter (IPathFormatter.METAPATH_PATH_FORMATER), maintaining backward compatibility for the existing singleton instances.


163-184: The code change is correct and safe.

The toPath() method is called with pathFormatter, which is annotated as @NonNull and initialized in the constructor, guaranteeing a non-null value. No null-handling verification needed.

metaschema-cli/src/main/java/gov/nist/secauto/metaschema/cli/commands/AbstractValidateContentCommand.java (2)

340-364: LGTM!

The resolvePathFormatter method is well-documented with complete Javadoc. The logic correctly defaults to PathFormatSelection.AUTO and delegates to Format.resolvePathFormatter() for format-specific resolution. The null check on line 358 properly guards against missing option values.


332-336: LGTM!

The integration correctly resolves the path formatter before creating the handler, and the handler is properly instantiated using the new withPathFormatter() factory method. This ensures validation findings are formatted according to user preference or document format default.

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/format/XPathFormatter.java (3)

23-40: LGTM! Class Javadoc is comprehensive.

The class-level documentation clearly explains the EQName format, provides an example path, and documents the XML grouping behavior. The @see tag properly references the IEnhancedQName.toEQName() method.


87-120: LGTM! The private helper method is well-documented and correctly implements XML grouping logic.

The formatModelItem method properly handles the XmlGroupAsBehavior.GROUPED case by prepending the wrapper element with [1] position (since the wrapper appears exactly once). The EQName format with position predicates follows XPath 3.1 syntax. The null checks on instance and wrapperQName are defensive and appropriate.

Based on learnings, this implementation aligns with XPath 3.1 specification for path expressions with EQName notation and positional predicates.


81-85: Clarify the purpose of the @ prefix notation in flag formatting.

The @ prefix is standard XPath abbreviated syntax for the attribute axis, and EQName format Q{namespace}localname is correct per XPath 3.1 specification. However, this method formats flag nodes in the Metapath data model, not XML attribute nodes. Since Metapath uses a custom node model distinct from XPath (with flag, field, and assembly nodes rather than element/attribute nodes), verify that @Q{namespace}localname is the intended representation for formatted flag references in this context. If this is a serialization format rather than an executable XPath expression, confirm the documentation or comments clarify the purpose.

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 XPath for XML and JSON Pointer for JSON/YAML in validation output in CLI default and SARIF output modes

2 participants