Skip to content

Comments

feat: add list-allowed-values command and visitor#666

Open
david-waltermire wants to merge 3 commits intometaschema-framework:developfrom
david-waltermire:feature/list-allowed-values
Open

feat: add list-allowed-values command and visitor#666
david-waltermire wants to merge 3 commits intometaschema-framework:developfrom
david-waltermire:feature/list-allowed-values

Conversation

@david-waltermire
Copy link
Contributor

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

Summary

  • Migrate AllowedValueCollectingNodeItemVisitor from liboscal-java to core module at dev.metaschema.core.metapath.item.node, making it available to all Metaschema users
  • Add list-allowed-values CLI command that generates a YAML listing of allowed-values constraints for any Metaschema module
  • Register the new command in MetaschemaCommands and the module-info service provider

Motivation

The visitor and command were previously in liboscal-java and oscal-cli respectively, but contain zero OSCAL-specific logic. All imports are dev.metaschema.core.* types. Moving them to metaschema-java makes this functionality available to all Metaschema-based projects.

Changes

File Change
core/.../AllowedValueCollectingNodeItemVisitor.java New - visitor migrated from liboscal-java with Javadoc added
core/.../AllowedValueCollectingNodeItemVisitorTest.java New - 3 tests using mock model builder infrastructure
metaschema-cli/.../ListAllowedValuesCommand.java New - CLI command following GenerateDiagramCommand pattern
metaschema-cli/.../MetaschemaCommands.java Register new command
metaschema-cli/module-info.java Add requires for Jackson YAML and provides entry
metaschema-cli/.../CLITest.java Add help and execution test cases

Test plan

  • AllowedValueCollectingNodeItemVisitorTest - 3 tests (finds constraints, empty for no constraints, handles multiple)
  • CLITest - list-allowed-values --help returns OK
  • CLITest - list-allowed-values <module> returns OK with YAML output
  • Full CI build: mvn clean install -PCI -Prelease passes
  • Manual CLI verification: correct YAML output for test module

Summary by CodeRabbit

  • New Features

    • Added "list-allowed-values" CLI command to generate YAML reports of allowed-values constraints (locations, targets, values).
    • Added a module-level visitor to collect and organize allowed-values constraints for reporting.
  • Tests

    • Added unit and CLI tests validating the collector, command help/usage, and YAML output.

Migrate AllowedValueCollectingNodeItemVisitor from liboscal-java to the
core module, making it available to all Metaschema users. The visitor
traverses a module's node items to collect allowed-values constraints
organized by target node.

Add a new list-allowed-values CLI command that generates a YAML listing
of all allowed-values constraints for a given Metaschema module. This
command was previously only available in oscal-cli with OSCAL-specific
module loading hardcoded; the generic version accepts any Metaschema
module via a positional argument.
@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

📝 Walkthrough

Walkthrough

Adds a visitor to collect allowed-values constraints across Metaschema modules, a CLI command that emits those constraints as YAML, tests for both visitor and CLI, and module descriptor updates for YAML support and command registration.

Changes

Cohort / File(s) Summary
Visitor Implementation
core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java
New public visitor class that traverses module node items (flags, fields, assemblies, assembly instance groups), applies Let-bindings to build a DynamicContext, evaluates allowed-values targets, and aggregates results into NodeItemRecord and AllowedValuesRecord collections accessible via getAllowedValueLocations().
Visitor Tests
core/src/test/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitorTest.java
New test suite verifying discovery of allowed-values constraints, handling of modules without constraints, and multiple-constraint scenarios using mocked module builders and assertions on collected records.
CLI Command
metaschema-cli/src/main/java/dev/metaschema/cli/commands/ListAllowedValuesCommand.java
New terminal command list-allowed-values that loads a module, invokes the visitor to collect constraints, and emits a structured YAML report grouped by target definition; supports stdout or file output and returns specific exit codes for argument, IO, and runtime errors.
CLI Registry & Module Descriptor
metaschema-cli/src/main/java/dev/metaschema/cli/commands/MetaschemaCommands.java, metaschema-cli/src/main/java/module-info.java
Registers the new ListAllowedValuesCommand in the command registry and updates the module descriptor to requires com.fasterxml.jackson.dataformat.yaml; and to provides the new command implementation.
CLI Tests
metaschema-cli/src/test/java/dev/metaschema/cli/CLITest.java
Adds CLI test invocations for list-allowed-values --help and an execution that writes YAML output to a file with assertions validating generated YAML content.

Sequence Diagram

sequenceDiagram
    participant User as User/CLI
    participant Cmd as ListAllowedValuesCommand
    participant Loader as Module Loader
    participant Visitor as AllowedValueCollectingNodeItemVisitor
    participant Module as IModule
    participant YAML as YAML Generator
    participant Output as File/Stdout

    User->>Cmd: list-allowed-values module.xml [output.yaml]
    Cmd->>Loader: resolve & load module
    Loader->>Module: parse module
    Cmd->>Visitor: create visitor with DynamicContext
    Cmd->>Visitor: visit(module)
    Visitor->>Module: traverse node items (flags/fields/assemblies)
    Visitor->>Visitor: apply Let-bindings, evaluate targets
    Visitor->>Visitor: collect AllowedValuesRecords into NodeItemRecords
    Visitor-->>Cmd: return collected records
    Cmd->>YAML: generate structured YAML grouped by target
    YAML->>Output: write to file or stdout
    Output-->>User: display/save results
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Poem

🐰 I hop through schemas, sniffing each rule,
I bind every Let and chase each trail,
I gather allowed-values from flag, field, and hall,
Then I spit out neat YAML for one and all,
Crunching constraints with a twitch of my tail!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 clearly and concisely summarizes the main changes: adding a visitor for collecting allowed values and a CLI command to list them.

✏️ 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

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/metapath/item/node/AllowedValueCollectingNodeItemVisitor.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.


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

Verify the YAML output contains expected constraint locations, types,
target paths, allowed values, and allow-other settings by writing to a
file and checking the content.
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.

🧹 Nitpick comments (1)
core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java (1)

188-196: Consider returning an unmodifiable list from getAllowedValues.
This prevents external mutation of the internal collection while preserving the addAllowedValues API.

♻️ Suggested change
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@
   `@NonNull`
   public List<AllowedValuesRecord> getAllowedValues() {
-    return allowedValues;
+    return Collections.unmodifiableList(allowedValues);
   }

Prevents external mutation of the internal allowed-values collection
while preserving the addAllowedValues API for internal use.
@david-waltermire
Copy link
Contributor Author

@coderabbitai Addressed in commit ab75ed8. Returning Collections.unmodifiableList(allowedValues) from NodeItemRecord.getAllowedValues() to prevent external mutation.

@coderabbitai
Copy link

coderabbitai bot commented Feb 18, 2026

Tip

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

@david-waltermire, thank you for addressing this! Returning an unmodifiable list from getAllowedValues() is the right approach to ensure the internal collection cannot be modified by callers. This maintains proper encapsulation. ✨

   (\__/)
   (='.'=)
   (")_(")
  Happy bunny!

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.

🧹 Nitpick comments (2)
core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java (2)

199-208: Consider reducing visibility of addAllowedValues.

The PR commit message indicates the intent to "prevent external mutation of the internal allowed-values collection." While getAllowedValues() correctly returns an unmodifiable list, the public addAllowedValues() method still allows external callers to add records directly. Since NodeItemRecord instances are only created internally (private constructor), consider making addAllowedValues package-private to fully enforce the immutability contract from the caller's perspective.

Suggested change
-    /**
-     * Add an allowed-values constraint record to this node item.
-     *
-     * `@param` record
-     *          the allowed-values record to add
-     */
-    public void addAllowedValues(`@NonNull` AllowedValuesRecord record) {
+    // Package-private: only used by the enclosing visitor
+    void addAllowedValues(`@NonNull` AllowedValuesRecord record) {
       this.allowedValues.add(record);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java`
around lines 199 - 208, The public method addAllowedValues(`@NonNull`
AllowedValuesRecord record) on AllowedValueCollectingNodeItemVisitor allows
external mutation despite getAllowedValues() returning an unmodifiable list;
change the visibility of addAllowedValues from public to package-private (remove
the public modifier) so only classes in the same package (and internal creation
of NodeItemRecord) can add records, leaving getAllowedValues() intact to return
the unmodifiable view.

52-55: Consider returning an unmodifiable view for consistency.

The method returns nodeItemAnalysis.values() directly, which is a live view backed by the map. While typical usage completes visitation before calling this method, wrapping in Collections.unmodifiableCollection() would align with the PR's intent (per commit message) of returning unmodifiable collections from public APIs.

Suggested change
   `@NonNull`
   public Collection<NodeItemRecord> getAllowedValueLocations() {
-    return nodeItemAnalysis.values();
+    return Collections.unmodifiableCollection(nodeItemAnalysis.values());
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java`
around lines 52 - 55, The method getAllowedValueLocations in
AllowedValueCollectingNodeItemVisitor currently returns the live collection
nodeItemAnalysis.values(); change it to return an unmodifiable view (wrap the
collection with Collections.unmodifiableCollection(...)) so callers cannot
mutate the returned collection while preserving the backing data; update imports
if necessary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@core/src/main/java/dev/metaschema/core/metapath/item/node/AllowedValueCollectingNodeItemVisitor.java`:
- Around line 199-208: The public method addAllowedValues(`@NonNull`
AllowedValuesRecord record) on AllowedValueCollectingNodeItemVisitor allows
external mutation despite getAllowedValues() returning an unmodifiable list;
change the visibility of addAllowedValues from public to package-private (remove
the public modifier) so only classes in the same package (and internal creation
of NodeItemRecord) can add records, leaving getAllowedValues() intact to return
the unmodifiable view.
- Around line 52-55: The method getAllowedValueLocations in
AllowedValueCollectingNodeItemVisitor currently returns the live collection
nodeItemAnalysis.values(); change it to return an unmodifiable view (wrap the
collection with Collections.unmodifiableCollection(...)) so callers cannot
mutate the returned collection while preserving the backing data; update imports
if necessary.

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.

1 participant