Skip to content

VSAM files -> Spring Data repositories (#3617) - #3648

Merged
squid-protocol merged 2 commits into
mainfrom
feat/vsam-repos-3617
Sep 25, 2026
Merged

squid-protocol merged 2 commits into
mainfrom
feat/vsam-repos-3617

Conversation

@squid-protocol

@squid-protocol squid-protocol commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Closes #3617 (epic #3625). Builds on #3616 (#3640, merged).

What each VSAM file becomes

The unit is the data store: a base cluster, shared by CICS (through CSD FILE names) and batch (through JCL DDs). The new engine join GalaxyIR.vsam_stores() assembles each store from:

  • IDCAMS: KEYS(len off), RECORDSIZE, organization, and each AIX with its PATHs;
  • CSD: the FILEs whose DSNAME is the cluster or one of its paths;
  • CICS programs: each program's EXEC CICS FILE commands (verbs, lines, INTO/FROM layouts), with each RIDFLD placed in the record. A group RIDFLD is placed through its fields' run.
  • Batch programs: each keyed SELECT, with its FD layout, RECORD KEY and OPEN modes from the JCL lineage.

The generator (cobol_to_java_repository_forge.py) turns each store into:

fact generated
the record layout (the one matching RECORDSIZE; then the one whose fields carry the most keys) an @Entity in entity.vsam (@Entity(name = "Vsam…"), table vsam_<qualifier>)
IDCAMS key = one field @Id on it
key = a group (e.g. FD-TRANCAT-ACCT-ID + TYPE-CD + CD, 17 bytes) an @Embeddable …Key + @EmbeddedId (plain mode: value equals/hashCode)
ESDS / RRDS a generated Long id, saying why
STARTBR + READNEXT / READPREV findBy<Key>GreaterThanEqualOrderBy<Key>Asc(key, Pageable) / …LessThanEqual…Desc
AIX via PATH findBy<AltField>(…): Optional for UNIQUEKEY, else List
each program's verbs (CICS) / OPEN modes (batch) read… / write… / rewrite… / delete… / browse… / readAll… in that program's service, only those it uses, each citing its lines

Honesty rules:

  • A program whose record differs from the entity's gets a mapping TODO.
  • A key that is not one field or a group run stays a String vsamKey with a TODO.
  • A DD with no known OPEN mode gets no method, just a TODO (nothing assumed).
  • A store used only by programs this generator doesn't convert (DSF's PL/I) is listed in the audit, not generated.

On the corpora

corpus entities + repositories one-field key not generated
CardDemo 11 7 (ACCT-ID, CARD-NUM, CUST-ID, TRAN-ID, …) + 3 group keys as @EmbeddedId 4 (no program touches them)
CBSA 2 (both group keys) 0 2 (@BANK_PREFIX@ defines, see below)
GENAPP 2 1 2
zECS 1 1 2
DSF 0 – 72 (PL/I only, #3623)

CardDemo's CARDXREF picks the CICS copybook over the batch FD: in the copybook, the AIX key at offset 25 is the field XREF-ACCT-ID, while the FD folds it into a filler. The CICS path read becomes readCxacaix(Long xrefAcctId) → findByXrefAcctId.

No guessing on install symbols. CBSA's IDCAMS defines @BANK_PREFIX@.CUSTOMER while its CSD says CBSA.CICSBSA.CUSTOMER. They are not joined by name. The CICS store keys from the programs' RIDFLD instead: CUSTOMER-KEY at offset 4, 16 bytes. That is exactly the unjoined IDCAMS KEYS(16 4), two independent sources agreeing.

Attributes consumed (consumer audit, new in the modernization skill)

attribute from keyed?
IDCAMS KEYS / RECORDSIZE / AIX RELATE / UNIQUEKEY / PATHENTRY VSAM defines keyed
CICS FILE verb, name, INTO/FROM record, line CICS resources keyed
CSD FILE DSNAME CSD resources keyed
SELECT org / access / RECORD KEY / ALTERNATE KEY file control keyed
OPEN modes per DD inputs / outputs keyed
RIDFLD operand cics_resource_data.attributes unverified. Spot-checked: its placed position equals the IDCAMS key on every CardDemo CICS store and on CBSA
field offsets / widths in a record layout record_layout (computed from PIC / USAGE) unverified: the record fields key compares names only. Spot-checked: the computed positions equal IDCAMS KEYS on 10 of CardDemo's 11 clusters (the 11th is CBEXPORT's key on a WORKING-STORAGE item, already flagged key_in_record=False), the 25/11 AIX, and CBSA's 4/16 and 0/12

No defects found. Follow-up to key the two unverified attributes: #3649.

A near-miss worth recording: a fixture with RECORDSIZE(38 38) past column 72 read as 3. That is correct: IDCAMS SYSIN is columns 1–72. The fixture was fixed and a note added.

Verified

  • Compile: all 6 corpora × 13 configs compile via java_target_matrix.py --scan; CI runs it.
  • Snapshot: refraction_snapshot.py check shows 0 differ.
  • Suite: 11,583 passed, with the pinned corpora.
  • Audits: ruff, mypy and dead-key are clean.
  • New tests (test_vsam_repositories.py, a real scan with IDCAMS + CSD + CICS + batch + a group key): the store join, group RIDFLD placement, entities / repositories / services per verb and OPEN mode, and plain-mode key equality.

🤖 Generated with Claude Code

https://claude.ai/code/session_017ZsVaAkb86P5r5JXDC2Y9g

…ep in the skill

Engine (galaxy_ir). vsam_stores() treats each VSAM base cluster as one
store, joining:
- its IDCAMS DEFINE (KEYS, RECORDSIZE, organization);
- its AIXs and PATHs;
- the CSD FILEs whose DSNAME is the cluster or a path;
- every CICS program's EXEC CICS FILE commands (verbs, lines, INTO / FROM
  layouts, each RIDFLD placed in the record);
- every batch program's keyed SELECT (FD layout, RECORD KEY, and the
  OPEN modes from the JCL lineage).
_position_in places a group RIDFLD by its fields' run in the record. On
CBSA, CUSTOMER-KEY lands at offset 4 for 16 bytes and ABND-VSAM-KEY at
0 for 12, matching the IDCAMS KEYS of clusters we deliberately do not
join by installation-symbol name. The key is never guessed.

Generator (cobol_to_java_repository_forge.py). Each store used by a
converted program becomes:
- an entity (entity.vsam, @entity(name = "Vsam...")): the layout of the
  cluster's RECORDSIZE, then the one where the most keys are fields; @id
  on the IDCAMS key field, a group key as an @EmbeddedId class, an ESDS /
  RRDS a generated Long id;
- a repository (repository.vsam): JpaRepository plus STARTBR / READNEXT
  and READPREV as ordered range queries, and a finder per alternate index
  (Optional for UNIQUEKEY, else List).
Each program's service gains read / write / rewrite / delete / browse
methods for exactly the verbs it uses (CICS) or the OPEN modes it has
(batch), each citing its lines. A differing record, an unplaced key, or
a DD with no OPEN mode gets a TODO. The audit lists stores not generated
and why.

The estate skeleton gains vsam_stores. The modernization skill gains
the consumer-audit step (#3616's lesson: list the attributes a
generator consumes and check each is keyed) plus the #3617 notes.

Verification:
- 6 corpora x 13 configs compile via --scan.
- The refraction snapshot shows 0 differ.
- Full suite: 11,583 passed.
- ruff, mypy and dead-key audits clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ZsVaAkb86P5r5JXDC2Y9g
Comment thread gitgalaxy/tools/cobol_to_java/cobol_to_java_repository_forge.py Fixed
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

…slot (#3617)

CodeQL flagged the unused _n. Output is identical: all 1,504 generated
Java files across 6 corpora x 3 configs are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ZsVaAkb86P5r5JXDC2Y9g
@squid-protocol
squid-protocol merged commit 96c0583 into main Sep 25, 2026
36 checks passed
@squid-protocol
squid-protocol deleted the feat/vsam-repos-3617 branch September 25, 2026 18:18
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.

Java conversion: CICS FILE (VSAM) operations + FILE-CONTROL / IDCAMS -> Spring Data repositories

2 participants