Skip to content

[WIP] fix(DataMapper): Add VariableItem and refactor other mapping item c…#3028

Draft
igarashitm wants to merge 1 commit intoKaotoIO:mainfrom
igarashitm:2362-2837
Draft

[WIP] fix(DataMapper): Add VariableItem and refactor other mapping item c…#3028
igarashitm wants to merge 1 commit intoKaotoIO:mainfrom
igarashitm:2362-2837

Conversation

@igarashitm
Copy link
Member

@igarashitm igarashitm commented Mar 10, 2026

…lasses to follow XSLT terminology

#3026 needs to go in before this one.

Fixes: #2837
Fixes: #2838

Add VariableItem and refactor other mapping items. Align class names to follow correct terminology from XSLT perspective. Currently ConditionItem contains ForEachItem but for-each is not a condition. Rename it to InstructionItem to be accurate. Also, remove ExpressionItem abstract class from hierarchy and introduce ExpressionHolder interface to properly represent the mapping item with expressions. A side effect is that we are no longer able to do if (item instanceof ExpressionItem), which is replaced with the usage of isExpressionHolder() function. Also removed unused isCondition property.

Summary by CodeRabbit

Release Notes

  • Refactor

    • Redesigned the mapping model and instruction handling for more consistent, reliable data mapping and expression handling across the UI.
    • Improved internal type validation and traversal so mapping operations (including cloning, iteration, and conditional branches) behave more predictably.
  • Tests

    • Added extensive tests covering mapping structures, cloning semantics, and expression-related behaviors to reduce regressions.

@igarashitm igarashitm added the WIP label Mar 10, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Refactors datamapper model: renames ConditionItem → InstructionItem, replaces ExpressionItem with IExpressionHolder & MappingItem intersection types, adds VariableItem and ValueType, updates cloning and hierarchy, and propagates type/signature changes across UI components, services, tests, and visualization/drag-and-drop handlers.

Changes

Cohort / File(s) Summary
Core model
packages/ui/src/models/datamapper/mapping.ts
Introduces MappingTree, MappingItem changes, InstructionItem (replacing ConditionItem), IExpressionHolder + isExpressionHolder, new VariableItem, ValueSelector refactor, ValueType enum, and deep-clone behavior; expands public type surface.
Model tests
packages/ui/src/models/datamapper/mapping.test.ts
New/expanded tests exercising isExpressionHolder, clone semantics, and behaviors for IfItem, ChooseItem, WhenItem, OtherwiseItem, ForEachItem, ValueSelector, VariableItem, and MappingTree.
XPath components & tests
packages/ui/src/components/Document/actions/XPathEditorAction.tsx, packages/ui/src/components/Document/actions/XPathInputAction.tsx, packages/ui/src/components/XPath/XPathEditor.tsx, packages/ui/src/components/XPath/XPathEditorLayout.tsx, packages/ui/src/components/XPath/XPathEditorModal.tsx, packages/ui/src/components/XPath/XPathEditorLayout.test.tsx, packages/ui/src/components/XPath/XPathEditorModal.test.tsx
Updated props/imports: ExpressionItemIExpressionHolder or IExpressionHolder & MappingItem (type/signature changes only).
Delete mapping action
packages/ui/src/components/Document/actions/DeleteMappingItemAction.tsx
Replaced ConditionItem references with InstructionItem in imports and runtime instanceof checks used for delete confirmation/warnings.
Visualization & editor node types
packages/ui/src/models/datamapper/visualization.ts, packages/ui/src/services/visualization.service.ts, packages/ui/src/services/visualization.service.test.ts
Editor node mapping type updated to IExpressionHolder & MappingItem; getExpressionItemForNode returns `IExpressionHolder & MappingItem
Mapping service & serializer
packages/ui/src/services/mapping.service.ts, packages/ui/src/services/mapping-serializer.service.ts
Replaced Condition/Expression-specific logic with InstructionItem and isExpressionHolder; renamed getConditional* → getInstruction* methods; updated traversal, removal, rename, and delete logic to use new types/guards.
Mapping links service
packages/ui/src/services/mapping-links.service.ts
Signature and import updates: ExpressionItemIExpressionHolder & MappingItem; uses isExpressionHolder in extraction logic.
DnD handler
packages/ui/src/providers/dnd/ExpressionEditorDnDHandler.ts
Removed explicit type assertion for editor node, added explicit no-op implementations for drag handlers (callable/no side effects).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • lordrip
  • PVinaches

Poem

🐰 I hopped through types and made them right,
InstructionItems leap into the light,
ExpressionHolders hold their clue,
Variables join the mapping crew,
A carrot-coded refactor delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is truncated with '[WIP]' prefix and ellipsis, making it difficult to assess the full scope of changes described. Expand the title to be complete and descriptive without truncation; remove '[WIP]' prefix or ensure the full title clearly conveys the main changes (renaming ConditionItem to InstructionItem, adding VariableItem, etc.).
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The pull request successfully addresses all coding requirements from linked issues #2837 and #2838: renames ConditionItem to InstructionItem, introduces IExpressionHolder interface, removes ExpressionItem class, updates class hierarchies with proper implementations, adds VariableItem with proper inheritance and cloning, and includes comprehensive unit tests.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issue objectives; no out-of-scope modifications detected beyond the intended refactoring of mapping items and introduction of VariableItem.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@igarashitm
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/ui/src/services/mapping-serializer.service.ts (2)

13-26: ⚠️ Potential issue | 🔴 Critical

Round-trip VariableItem through the serializer.

The new VariableItem model never reaches the XSLT document: populateMapping() has no VariableItem branch, and restoreMapping() has no xsl:variable case. Saving or reopening a mapping tree will silently drop every variable node.

Possible fix
 import {
   ChooseItem,
   FieldItem,
   ForEachItem,
   IfItem,
   InstructionItem,
   MappingItem,
   MappingParentType,
   MappingTree,
   OtherwiseItem,
+  VariableItem,
   ValueSelector,
   ValueType,
   WhenItem,
 } from '../models/datamapper/mapping';
@@
     } else if (mapping instanceof WhenItem) {
       child = MappingSerializerService.populateWhenItem(parent, mapping);
     } else if (mapping instanceof OtherwiseItem) {
       child = MappingSerializerService.populateOtherwiseItem(parent, mapping);
+    } else if (mapping instanceof VariableItem) {
+      child = MappingSerializerService.populateVariableItem(parent, mapping);
     }
@@
+  private static populateVariableItem(parent: Element, mapping: VariableItem) {
+    const xsltDocument = parent.ownerDocument;
+    const xslVariable = xsltDocument.createElementNS(NS_XSL, 'variable');
+    xslVariable.setAttribute('name', mapping.name);
+    xslVariable.setAttribute('select', mapping.expression);
+    parent.appendChild(xslVariable);
+    return xslVariable;
+  }
+
@@
         case 'otherwise': {
           mappingItem = new OtherwiseItem(parentMapping);
           break;
         }
+        case 'variable': {
+          const name = item.getAttribute('name');
+          if (!name) return;
+          const variableItem = new VariableItem(parentMapping, name);
+          variableItem.expression = item.getAttribute('select') || '';
+          mappingItem = variableItem;
+          break;
+        }
         case 'for-each': {
           const forEachItem = new ForEachItem(parentMapping);
           forEachItem.expression = item.getAttribute('select') || '';
           mappingItem = forEachItem;
           break;

Also applies to: 129-145, 285-338

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/services/mapping-serializer.service.ts` around lines 13 - 26,
The serializer currently drops VariableItem nodes because populateMapping and
restoreMapping lack VariableItem handling; update populateMapping to recognize
MappingItem entries where item.type === 'variable' (or the VariableItem class)
and serialize them into an xsl:variable element with the same
attributes/children/value structure you use for other items (e.g., set name,
select/content and preserve nested MappingTree if any), and update
restoreMapping to handle incoming xsl:variable elements by creating a
VariableItem (populate its identifier, value/children and any metadata like
valueType/selector) so variables round-trip; mirror how other branches (e.g.,
ForEachItem/WhenItem) map attributes and children to ensure consistency and
include VariableItem in any switch/if chains in both populateMapping and
restoreMapping.

205-210: ⚠️ Potential issue | 🟠 Major

Persist ForEachItem.sortItems as xsl:sort children.

ForEachItem.sortItems is now part of the model, but populateForEachItem() only writes select and restoreMapping() ignores xsl:sort. Any configured sort criteria disappear as soon as the mapping is serialized or reopened.

Possible fix
   private static populateForEachItem(parent: Element, mapping: ForEachItem) {
     const xsltDocument = parent.ownerDocument;
     const xslForEach = xsltDocument.createElementNS(NS_XSL, 'for-each');
     xslForEach.setAttribute('select', mapping.expression);
+    mapping.sortItems.forEach((sortItem) => {
+      const xslSort = xsltDocument.createElementNS(NS_XSL, 'sort');
+      xslSort.setAttribute('select', sortItem.expression);
+      xslSort.setAttribute('order', sortItem.order);
+      xslForEach.appendChild(xslSort);
+    });
     parent.appendChild(xslForEach);
     return xslForEach;
   }
@@
         case 'for-each': {
           const forEachItem = new ForEachItem(parentMapping);
           forEachItem.expression = item.getAttribute('select') || '';
           mappingItem = forEachItem;
           break;
         }
+        case 'sort': {
+          if (!(parentMapping instanceof ForEachItem)) return;
+          parentMapping.sortItems.push({
+            expression: item.getAttribute('select') || '',
+            order: (item.getAttribute('order') as 'ascending' | 'descending') || 'ascending',
+          });
+          return;
+        }
         case 'attribute': {
           if (parentField instanceof PrimitiveDocument) return;
           const field = MappingSerializerService.getOrCreateAttributeField(item, parentField);
           if (!field) return;
           fieldItem = field;

Also applies to: 285-338

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/services/mapping-serializer.service.ts` around lines 205 -
210, populateForEachItem currently only emits an xsl:for-each with select and
drops any ForEachItem.sortItems causing configured sort criteria to be lost;
update populateForEachItem to iterate mapping.sortItems and append xsl:sort
children to the created xslForEach (use xsltDocument.createElementNS(NS_XSL,
'sort') and set appropriate attributes like 'select', 'order', 'data-type' based
on each SortItem), and also update the complementary restoreMapping logic to
parse xsl:sort children back into ForEachItem.sortItems so
serialization/deserialization round-trips sort criteria (ensure you modify both
populateForEachItem and the corresponding restoreMapping/deserialization block
referenced around lines ~285-338).
packages/ui/src/models/datamapper/mapping.ts (1)

127-143: ⚠️ Potential issue | 🟠 Major

Return otherwise as optional to match the documented contract.

The docblock explicitly states the fallback branch is optional, but the getter casts find() to OtherwiseItem, which hides the undefined possibility. This violates TypeScript strict mode by misrepresenting the actual return type. Although existing callers handle this carefully (using && or !! checks), the unsafe type signature creates a maintenance hazard and misleads future callers.

Suggested fix
-  get otherwise() {
-    return this.children.find((c) => c instanceof OtherwiseItem) as OtherwiseItem;
+  get otherwise(): OtherwiseItem | undefined {
+    return this.children.find((c): c is OtherwiseItem => c instanceof OtherwiseItem);
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/models/datamapper/mapping.ts` around lines 127 - 143, The
otherwise getter on ChooseItem misrepresents its return type by casting
children.find(...) to OtherwiseItem even though the fallback is optional; update
the ChooseItem.otherwise getter to return OtherwiseItem | undefined (remove the
force-cast) so it accurately reflects that children.find(...) may return
undefined, and adjust any local JSDoc or usages in the file to accept the
optional OtherwiseItem where needed.
🧹 Nitpick comments (3)
packages/ui/src/services/mapping-links.service.ts (1)

32-39: Add a service-level test for the new isExpressionHolder() branch.

This path now depends on duck-typing instead of the old class hierarchy, but the PR only adds guard/clone tests. A dedicated extractMappingLinks() test for at least one VariableItem and one non-holder item would catch silent link rendering regressions here.

Also applies to: 67-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/services/mapping-links.service.ts` around lines 32 - 39, Add
service-level tests that cover the new isExpressionHolder() branch so we catch
silent regressions: write at least two tests invoking
MappingLinksService.doExtractMappingLinks (or the public extractMappingLinks
wrapper) with (1) a VariableItem instance that satisfies MappingItem and
isExpressionHolder(item) and assert the returned links include the expected
mapping link(s), and (2) a MappingItem-derived instance that is not an
expression holder and assert it returns the expected empty or different link
set; use the same sourceParameterMap/sourceBody/selectedNodeRef shapes used
elsewhere in tests to replicate behavior and fail if link rendering changes.
packages/ui/src/models/datamapper/mapping.test.ts (2)

56-59: Avoid as never in the ChooseItem fixture.

This bypasses the real field contract, so the test can pass with an impossible object shape and won’t protect ChooseItem.clone() if it starts reading more field metadata. Prefer a minimal typed field fixture/helper instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/models/datamapper/mapping.test.ts` around lines 56 - 59, The
test uses an unsafe type cast ("as never") when constructing the ChooseItem
fixture which bypasses the real field contract; replace this with a properly
typed minimal field fixture that matches the expected Field/interface used by
ChooseItem (e.g., create a small helper or inline object typed as Field) and use
that instead of "as never", then call new ChooseItem(tree, field) and assert on
item.clone() to ensure clone() is validated against the real field shape;
reference ChooseItem and its clone() method when updating the test fixture.

39-52: Assert that cloned children are re-parented to the clone.

These tests currently prove copied values, but not cloned topology. After the hierarchy refactor, a clone that leaves child.parent pointing at the original item would still pass here and later break nodePath/contextPath consumers. Add an assertion like expect(cloned.children[0].parent).toBe(cloned).

Also applies to: 67-80, 110-123, 140-153

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/models/datamapper/mapping.test.ts` around lines 39 - 52, The
tests for IfItem.clone() and similar cases (e.g., the blocks around lines 67-80,
110-123, 140-153) verify copied values but not that cloned children are
re-parented; update each relevant test (the one creating an IfItem,
ValueSelector, calling clone()) to assert that each cloned child's parent points
to the cloned item (e.g., add an assertion that cloned.children[0].parent is the
cloned instance) so clone() verifies topology is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ui/src/models/datamapper/mapping.ts`:
- Around line 54-58: MappingItem.clone() deep-copies children but doesn't update
each cloned child's parent, leaving cloned descendants pointing to the original
tree and causing incorrect nodePath/contextPath; update the clone routine (in
MappingItem.clone and any other clone entry points that call doClone()) to set
cloned.children = this.children.map(c => { const cc = c.clone(); cc.parent =
cloned; return cc; }) or equivalent so each child's parent is reassigned to the
new cloned parent (ensuring any path recalculation reads the new ancestry).
Ensure the same parent-fixing pattern is applied to other clone call sites that
produce subtrees so all descendants have their parent refs updated.

In `@packages/ui/src/services/mapping.service.ts`:
- Around line 244-246: Escape regex metacharacters in oldDocumentId before
building the RegExp to avoid ReDoS and incorrect matches: compute an
escapedOldDocumentId (e.g., oldDocumentId.replace(/[.*+?^${}()|[\]\\]/g,
'\\$&')) and use it in the replacement call inside the isExpressionHolder branch
so the RegExp becomes new RegExp(`\\$${escapedOldDocumentId}\\b`, 'g') and the
replacement uses `$${newDocumentId}`; update the code references to
escapedOldDocumentId, isExpressionHolder(child), child.expression, oldDocumentId
and newDocumentId accordingly.

---

Outside diff comments:
In `@packages/ui/src/models/datamapper/mapping.ts`:
- Around line 127-143: The otherwise getter on ChooseItem misrepresents its
return type by casting children.find(...) to OtherwiseItem even though the
fallback is optional; update the ChooseItem.otherwise getter to return
OtherwiseItem | undefined (remove the force-cast) so it accurately reflects that
children.find(...) may return undefined, and adjust any local JSDoc or usages in
the file to accept the optional OtherwiseItem where needed.

In `@packages/ui/src/services/mapping-serializer.service.ts`:
- Around line 13-26: The serializer currently drops VariableItem nodes because
populateMapping and restoreMapping lack VariableItem handling; update
populateMapping to recognize MappingItem entries where item.type === 'variable'
(or the VariableItem class) and serialize them into an xsl:variable element with
the same attributes/children/value structure you use for other items (e.g., set
name, select/content and preserve nested MappingTree if any), and update
restoreMapping to handle incoming xsl:variable elements by creating a
VariableItem (populate its identifier, value/children and any metadata like
valueType/selector) so variables round-trip; mirror how other branches (e.g.,
ForEachItem/WhenItem) map attributes and children to ensure consistency and
include VariableItem in any switch/if chains in both populateMapping and
restoreMapping.
- Around line 205-210: populateForEachItem currently only emits an xsl:for-each
with select and drops any ForEachItem.sortItems causing configured sort criteria
to be lost; update populateForEachItem to iterate mapping.sortItems and append
xsl:sort children to the created xslForEach (use
xsltDocument.createElementNS(NS_XSL, 'sort') and set appropriate attributes like
'select', 'order', 'data-type' based on each SortItem), and also update the
complementary restoreMapping logic to parse xsl:sort children back into
ForEachItem.sortItems so serialization/deserialization round-trips sort criteria
(ensure you modify both populateForEachItem and the corresponding
restoreMapping/deserialization block referenced around lines ~285-338).

---

Nitpick comments:
In `@packages/ui/src/models/datamapper/mapping.test.ts`:
- Around line 56-59: The test uses an unsafe type cast ("as never") when
constructing the ChooseItem fixture which bypasses the real field contract;
replace this with a properly typed minimal field fixture that matches the
expected Field/interface used by ChooseItem (e.g., create a small helper or
inline object typed as Field) and use that instead of "as never", then call new
ChooseItem(tree, field) and assert on item.clone() to ensure clone() is
validated against the real field shape; reference ChooseItem and its clone()
method when updating the test fixture.
- Around line 39-52: The tests for IfItem.clone() and similar cases (e.g., the
blocks around lines 67-80, 110-123, 140-153) verify copied values but not that
cloned children are re-parented; update each relevant test (the one creating an
IfItem, ValueSelector, calling clone()) to assert that each cloned child's
parent points to the cloned item (e.g., add an assertion that
cloned.children[0].parent is the cloned instance) so clone() verifies topology
is preserved.

In `@packages/ui/src/services/mapping-links.service.ts`:
- Around line 32-39: Add service-level tests that cover the new
isExpressionHolder() branch so we catch silent regressions: write at least two
tests invoking MappingLinksService.doExtractMappingLinks (or the public
extractMappingLinks wrapper) with (1) a VariableItem instance that satisfies
MappingItem and isExpressionHolder(item) and assert the returned links include
the expected mapping link(s), and (2) a MappingItem-derived instance that is not
an expression holder and assert it returns the expected empty or different link
set; use the same sourceParameterMap/sourceBody/selectedNodeRef shapes used
elsewhere in tests to replicate behavior and fail if link rendering changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6123f338-856e-4c7d-a0bf-5f12b8458b0b

📥 Commits

Reviewing files that changed from the base of the PR and between 7b98890 and 1953968.

📒 Files selected for processing (17)
  • packages/ui/src/components/Document/actions/DeleteMappingItemAction.tsx
  • packages/ui/src/components/Document/actions/XPathEditorAction.tsx
  • packages/ui/src/components/Document/actions/XPathInputAction.tsx
  • packages/ui/src/components/XPath/XPathEditor.tsx
  • packages/ui/src/components/XPath/XPathEditorLayout.test.tsx
  • packages/ui/src/components/XPath/XPathEditorLayout.tsx
  • packages/ui/src/components/XPath/XPathEditorModal.test.tsx
  • packages/ui/src/components/XPath/XPathEditorModal.tsx
  • packages/ui/src/models/datamapper/mapping.test.ts
  • packages/ui/src/models/datamapper/mapping.ts
  • packages/ui/src/models/datamapper/visualization.ts
  • packages/ui/src/providers/dnd/ExpressionEditorDnDHandler.ts
  • packages/ui/src/services/mapping-links.service.ts
  • packages/ui/src/services/mapping-serializer.service.ts
  • packages/ui/src/services/mapping.service.ts
  • packages/ui/src/services/visualization.service.test.ts
  • packages/ui/src/services/visualization.service.ts

@igarashitm
Copy link
Member Author

@coderabbitai VariableItem handling in serialize/deserialize is planned in one of following subtasks. This PR focuses on model refactoring. SortItem is not supported soon, just model object is declared.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 11, 2026

Tip

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

@igarashitm, thanks for the clarification! That makes sense — keeping this PR focused purely on the model refactoring is a clean approach. I'll keep in mind that VariableItem serialize/deserialize and SortItem support are deferred to future subtasks.


✏️ Learnings added
Learnt from: igarashitm
URL: https://github.com/KaotoIO/kaoto/pull/3028

Timestamp: 2026-03-11T01:02:20.789Z
Learning: In PR `#3028` of the KaotoIO/kaoto repository, `VariableItem` handling in serialize/deserialize is intentionally not implemented — it is planned for a future subtask. The PR focuses only on model refactoring.

Learnt from: igarashitm
URL: https://github.com/KaotoIO/kaoto/pull/3028

Timestamp: 2026-03-11T01:02:20.789Z
Learning: In PR `#3028` of the KaotoIO/kaoto repository, `SortItem` is declared as a model object only and is not yet supported. Full support is planned for a future subtask.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@igarashitm igarashitm force-pushed the 2362-2837 branch 3 times, most recently from e7be3b3 to 05edeb7 Compare March 11, 2026 01:22
…lasses to follow XSLT terminology

Fixes: KaotoIO#2837
Fixes: KaotoIO#2838

Add `VariableItem` and refactor other mapping items. Align class names to follow correct terminology from XSLT perspective. Currently `ConditionItem` contains `ForEachItem` but `for-each` is not a condition. Rename it to `InstructionItem` to be accurate. Also, remove `ExpressionItem` abstract class from hierarchy and introduce `ExpressionHolder` interface to properly represent the mapping item with expressions. A side effect is that we are no longer able to do `if (item instanceof ExpressionItem)`, which is replaced with the usage of `isExpressionHolder()` function. Also removed unused `isCondition` property.
@sonarqubecloud
Copy link

@igarashitm
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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)
packages/ui/src/components/Document/actions/XPathInputAction.tsx (1)

22-25: Consider using the intersection type for consistency.

While IExpressionHolder is technically sufficient since this component only accesses mapping.expression, the sibling XPathEditorAction component uses IExpressionHolder & MappingItem. Using the same intersection type would maintain consistency across components and reflect that all callers pass the full intersection type from VisualizationService.getExpressionItemForNode().

♻️ Suggested change for consistency
+import { IExpressionHolder, MappingItem } from '../../../models/datamapper/mapping';
-import { IExpressionHolder } from '../../../models/datamapper/mapping';

 type XPathInputProps = {
-  mapping: IExpressionHolder;
+  mapping: IExpressionHolder & MappingItem;
   onUpdate: () => void;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/components/Document/actions/XPathInputAction.tsx` around
lines 22 - 25, Change the XPathInputProps type to use the same intersection used
elsewhere so callers and future maintainers see the full shape: update the
XPathInputProps definition to reference IExpressionHolder & MappingItem (instead
of just IExpressionHolder), keeping the existing property names (mapping:
IExpressionHolder & MappingItem; onUpdate: () => void) so XPathInputAction and
XPathEditorAction remain consistent with values returned by
VisualizationService.getExpressionItemForNode(); ensure no other call sites
break by adjusting any narrow typings 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 `@packages/ui/src/components/Document/actions/XPathInputAction.tsx`:
- Around line 22-25: Change the XPathInputProps type to use the same
intersection used elsewhere so callers and future maintainers see the full
shape: update the XPathInputProps definition to reference IExpressionHolder &
MappingItem (instead of just IExpressionHolder), keeping the existing property
names (mapping: IExpressionHolder & MappingItem; onUpdate: () => void) so
XPathInputAction and XPathEditorAction remain consistent with values returned by
VisualizationService.getExpressionItemForNode(); ensure no other call sites
break by adjusting any narrow typings if necessary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 970c7329-cd02-495a-b00b-2cfffb26b31e

📥 Commits

Reviewing files that changed from the base of the PR and between 1953968 and a352642.

📒 Files selected for processing (17)
  • packages/ui/src/components/Document/actions/DeleteMappingItemAction.tsx
  • packages/ui/src/components/Document/actions/XPathEditorAction.tsx
  • packages/ui/src/components/Document/actions/XPathInputAction.tsx
  • packages/ui/src/components/XPath/XPathEditor.tsx
  • packages/ui/src/components/XPath/XPathEditorLayout.test.tsx
  • packages/ui/src/components/XPath/XPathEditorLayout.tsx
  • packages/ui/src/components/XPath/XPathEditorModal.test.tsx
  • packages/ui/src/components/XPath/XPathEditorModal.tsx
  • packages/ui/src/models/datamapper/mapping.test.ts
  • packages/ui/src/models/datamapper/mapping.ts
  • packages/ui/src/models/datamapper/visualization.ts
  • packages/ui/src/providers/dnd/ExpressionEditorDnDHandler.ts
  • packages/ui/src/services/mapping-links.service.ts
  • packages/ui/src/services/mapping-serializer.service.ts
  • packages/ui/src/services/mapping.service.ts
  • packages/ui/src/services/visualization.service.test.ts
  • packages/ui/src/services/visualization.service.ts
🚧 Files skipped from review as they are similar to previous changes (11)
  • packages/ui/src/components/XPath/XPathEditorLayout.test.tsx
  • packages/ui/src/components/Document/actions/DeleteMappingItemAction.tsx
  • packages/ui/src/services/mapping-serializer.service.ts
  • packages/ui/src/components/XPath/XPathEditor.tsx
  • packages/ui/src/components/Document/actions/XPathEditorAction.tsx
  • packages/ui/src/services/visualization.service.ts
  • packages/ui/src/models/datamapper/mapping.test.ts
  • packages/ui/src/services/visualization.service.test.ts
  • packages/ui/src/models/datamapper/visualization.ts
  • packages/ui/src/providers/dnd/ExpressionEditorDnDHandler.ts
  • packages/ui/src/components/XPath/XPathEditorLayout.tsx

@codecov
Copy link

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 95.55556% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.81%. Comparing base (7b98890) to head (a352642).

Files with missing lines Patch % Lines
...ui/src/providers/dnd/ExpressionEditorDnDHandler.ts 0.00% 3 Missing ⚠️
packages/ui/src/services/mapping.service.ts 96.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3028      +/-   ##
==========================================
+ Coverage   89.73%   89.81%   +0.08%     
==========================================
  Files         563      563              
  Lines       20984    21018      +34     
  Branches     4904     4907       +3     
==========================================
+ Hits        18829    18878      +49     
- Misses       2028     2138     +110     
+ Partials      127        2     -125     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

xsl:variable : No.2 Add VariableItem xsl:variable : No.1 Refactor model

1 participant