Class: Ecoportal::API::GraphQL::Model::Template::CommandNormalizer
- Inherits:
-
Object
- Object
- Ecoportal::API::GraphQL::Model::Template::CommandNormalizer
- Defined in:
- lib/ecoportal/api/graphql/model/template/command_normalizer.rb
Overview
Normalises an ordered batch of built WorkflowCommand hashes
([{ commandKey => { ...input } }, ...]) so that batches produced by DIFFERENT
- emitters -- each of which mints its own placeholder/id tokens (`Builder
TemplateBuilder's ph_stg_1, Diff::CommandSynthesizer's ph_stg_0, CommandSynthesis's ph_stg_1`, a self-version replay's real server ids, the downstream
writers' caller-chosen tokens) -- can be compared for STRUCTURAL equivalence.
Two normalisations, both pure (no mutation of the input):
1. REFERENCE-TOKEN POSITIONING. Every value carried under a key this class
recognises as an id/placeholder REFERENCE (see `REFERENCE_KEYS`) is replaced
by a positional token `"ph_<n>"`, assigned in FIRST-APPEARANCE order across
the whole ordered batch (scanning left to right, top to bottom, depth-first
within each command's own Hash). The SAME source value always maps to the
SAME token wherever it recurs (so a mint-then-reference pair, e.g. `addStage`'s
`placeholderId` and a later `addStageSection`'s `stageId`, stays linked). Only
the KEY decides whether a String is a reference -- literal content
(`label`/`name`/`value`/`script`/`url`/...) is never touched, so a coincidental
value match with a real id never causes a false substitution.
2. KEY ORDER + correlation stripping. Each command's own input Hash (and any
nested Hash, e.g. `byType`) is recursively re-sorted by key so two batches that
differ only in the Hash literal's construction order compare equal, and any
`CORRELATION_KEYS` entry (never part of the compared shape) is dropped.
Two normalised batches are STRUCTURALLY EQUIVALENT iff Normalizer.normalize(a) == Normalizer.normalize(b) -- byte-identical once serialised (to_json), per the
DSL-08 acceptance test.
Constant Summary collapse
- REFERENCE_KEYS =
Keys whose String value addresses a node (mint or reference), across every
WorkflowCommandinput class this repo ships plus the downstream writers' own commands (placeholderId/stageId/sectionId/dataFieldId/data_field_id/optionId/forceId/referenceId/anchorId/id) -- verified against everyVALID_KEYSlist underlib/ecoportal/api/graphql/input/workflow_command/. Deliberately a CLOSED, named set (not "every String") so a literal content String (a label, a script, a URL) is never mistaken for a reference. %i[ placeholderId stageId sectionId dataFieldId data_field_id optionId forceId referenceId anchorId id ].freeze
- CORRELATION_KEYS =
Fields that exist only for request bookkeeping, never part of the compared shape.
%i[clientMutationId correlationId].freeze
Class Method Summary collapse
-
.normalize(commands) ⇒ Array<Hash>
The same batch, reference tokens repositioned, keys sorted, correlation-only keys dropped.
Instance Method Summary collapse
Class Method Details
.normalize(commands) ⇒ Array<Hash>
53 54 55 |
# File 'lib/ecoportal/api/graphql/model/template/command_normalizer.rb', line 53 def self.normalize(commands) new.normalize(commands) end |
Instance Method Details
#normalize(commands) ⇒ Object
57 58 59 60 61 |
# File 'lib/ecoportal/api/graphql/model/template/command_normalizer.rb', line 57 def normalize(commands) @tokens = {} @next_index = 0 Array(commands).map { |command| normalize_command(command) } end |