Skip to content

DataMapper: Refactor to cache NodePath calculation for mapping line #3180

@igarashitm

Description

@igarashitm

Please describe the task that needs to be done

Description

Problem

MappingLinksService.extractMappingLinks() performs a full mapping tree traversal on every render cycle triggered by MappingLinksProvider. Each invocation:

  1. Recursively walks the entire mapping tree
  2. Parses every XPath expression via XPathService.extractFieldPaths()
  3. Resolves each extracted field path to an IField via DocumentService.getFieldFromPathSegments()
  4. Computes visual NodePaths (inserting choice wrapper segments) for both source and target sides

This runs whenever any of these dependencies change:

  • mappingTree (object reference)
  • selectedNodePath (user clicks a node)
  • sourceParameterMap / sourceBodyDocument

In practice, even a simple node selection triggers the full extraction pipeline, including XPath parsing and field resolution that haven't changed since the last XPath edit.

Proposed Solution

Introduce a reactive NodePath index — a cache layer between the mapping model and the visualization — that separates what the mapping links are from how they're rendered:

  1. NodePath index: A derived data structure that maps each IExpressionHolder to its resolved source NodePaths and target NodePath. Rebuilt only when XPath expressions or document structure actually change — not on selection or scroll.

  2. Rendering stays lightweight: MappingLinksProvider reads from the pre-built index and only applies per-render concerns (selection highlighting, coordinate resolution via getNearestVisiblePort()).

  3. Model stays clean: The index lives outside IExpressionHolder and the mapping model — it's a derived/computed cache, not a model extension. This avoids leaking visualization concerns into the mapping data.

Key Design Constraints

  • The index must invalidate when:
    • An XPath expression changes (user edits in XPathInputAction)
    • A mapping item is added, removed, or restructured
    • Source/target document structure changes
  • The index must not invalidate on:
    • Node selection changes
    • Scroll / viewport changes
    • Visual collapse/expand of tree nodes
  • Keep IExpressionHolder holding only expression: string — no NodePath data in the model

Where to Store the Cache — Extend DocumentTreeStore

DocumentTreeStore (store/document-tree.store.ts) already holds the visual state that determines what mapping lines are drawn and where:

  • Connection ports (nodesConnectionPorts) — where lines attach
  • Expansion state — which lines are visible (collapsed nodes hide their descendant lines)
  • Selection — which lines are highlighted

The NodePath index is the same category: what lines exist, derived from user-edited XPath expressions. All of these are user-action-driven state serving the same purpose — supporting mapping line rendering.

Adding the cache here follows the existing pattern (e.g. nodesConnectionPorts is set from outside the store via setNodesConnectionPorts()). The new state would be rebuilt when XPath expressions or document structure change, and consumed by MappingLinksProvider for rendering.

Relevant Files

File Role
packages/ui/src/store/document-tree.store.ts Zustand store for visual tree state — new home for the NodePath index
packages/ui/src/services/visualization/mapping-links.service.ts Current full-recalc logic (extractMappingLinks, computeVisualSourceNodePath, computeVisualTargetNodePath)
packages/ui/src/providers/data-mapping-links.provider.tsx React provider triggering recalc via useEffect
packages/ui/src/models/datamapper/mapping.ts IExpressionHolder interface, mapping item types
packages/ui/src/models/datamapper/visualization.ts IMappingLink interface consumed by rendering
packages/ui/src/components/View/MappingLinkContainer.tsx Rendering layer consuming IMappingLink
packages/ui/src/components/Document/actions/XPathInputAction.tsx XPath edit entry point

Expected Benefit

  • Node selection, scroll, and collapse/expand no longer trigger XPath parsing and field resolution
  • Mapping line rendering becomes proportional to the number of visible links, not the total number of expressions
  • Cleaner separation: model holds data, index derives visualization-ready paths, renderer draws lines

Metadata

Metadata

Assignees

No one assigned

    Labels

    DataMapperAll issues related to the DataMappernever-staleMarks an issue to stay always open and not stale.refactoring

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions