Skip to content

[NAE-2261] SEARCH Node - fetch cases from mongo#385

Open
Kovy95 wants to merge 7 commits intorelease/7.0.0-rev10from
NAE-2261
Open

[NAE-2261] SEARCH Node - fetch cases from mongo#385
Kovy95 wants to merge 7 commits intorelease/7.0.0-rev10from
NAE-2261

Conversation

@Kovy95
Copy link
Contributor

@Kovy95 Kovy95 commented Nov 18, 2025

Description

  • add AuthPrincipalDto to object library
  • remove immediate data from elasticCase and add NodeInfo
  • rework of elastic Datafields to remove dependency to TextField
  • remove code from 2251 - when the search node fetches cases from mongo, its not nessessery anymore to store translations of value into elastic

Implements NAE-2261

Dependencies

none

Third party dependencies

  • No new dependencies were introduced

Blocking Pull requests

Depends on #(373) and merging rev8 into rev9

How Has Been This Tested?

manually

Test Configuration

Name Tested on
OS linux mint 21
Runtime java 21
Dependency Manager maven 3.9.9
Framework version Spring boot 3.4.4
Run parameters
Other configuration

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes have been checked, personally or remotely, with @...
  • I have commented my code, particularly in hard-to-understand areas
  • I have resolved all conflicts with the target branch of the PR
  • I have updated and synced my code with the target branch
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes:
    • Lint test
    • Unit tests
    • Integration tests
  • I have checked my contribution with code analysis tools:
  • I have made corresponding changes to the documentation:
    • Developer documentation
    • User Guides
    • Migration Guides

Summary by CodeRabbit

  • New Features

    • Added node information tracking for Elasticsearch nodes.
  • Bug Fixes

    • Map-based enumeration and multichoice values now surface as collections of translations for more complete localized display.
  • Refactor

    • Streamlined field type hierarchy and search indexing behavior for map and string-collection fields to improve data representation and search results.

- add AuthPrincipalDto to object library
- remove immediate data from elasticCase and add NodeInfo
- rework of elastic Datafields to remove dependency to TextField
- remove code from 2251 - when the search node fetches cases from mongo, its not nessessery anymore to store translations of value into elastic
@Kovy95 Kovy95 self-assigned this Nov 18, 2025
@Kovy95 Kovy95 changed the title Nae 2261 [NAE-2261] SEARCH Node - fetch cases from mongo Nov 18, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Walkthrough

Map/value translation handling changed: map field entry values now use Collection of translations instead of I18nString; several field classes switch inheritance from TextField to DataField; ElasticCase lost immediateData and gained nodeInfo; new NodeInfo value object added and a minor import added to AuthPrincipalDto.

Changes

Cohort / File(s) Summary
Elastic mapping service
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java
transformMultichoiceMapField() and transformEnumerationMapField() now emit Map.Entry values whose values are Collection<String> (translations collected) instead of I18nString.
Object library — Map & collection fields
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java, .../I18nField.java, .../StringCollectionField.java
MapField, I18nField, and StringCollectionField now extend DataField (not TextField). MapField constructors/signatures updated to accept Collection<String>, per-key I18nString translations removed, and getValue() added; I18nField.getValue() now reads from fulltextValue.
Spring adapter — MapField mapping
nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/MapField.java
Constructors updated to accept Collection<String> entries; getKeyValueTranslations() and I18nString import removed; ES mapping annotations added/updated on getters (getFulltextValue, getKeyValue).
ElasticCase model
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java
Removed immediateData field; added nodeInfo field; constructor/update adjustments for removed field.
New value object
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/NodeInfo.java
Added NodeInfo (Serializable) with nodeHost and nodePort, Lombok constructors/accessors.
Minor DTO import
nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java
Added lombok.NonNull import; no API/signature changes.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Producer as Source Case / Form
participant Mapper as ElasticCaseMappingService
participant Domain as MapField / I18nField
participant Adapter as Spring Elastic Adapter
participant ES as Elasticsearch
Producer->>Mapper: supply field (multichoice/enumeration)
Mapper->>Domain: build Map.Entry<key, Collection> (collect translations)
Domain->>Adapter: expose fulltext and keyValue arrays
Adapter->>ES: index document (MapField as Keyword/Text arrays)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 refers to the SEARCH Node feature and fetching cases from Mongo, which aligns with the PR's core objective to rework how the search node retrieves cases and update related data models, though it does not explicitly mention the data structure refactoring (removing TextField dependencies and immediateData field changes).

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


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.

@coderabbitai coderabbitai bot added improvement A change that improves on an existing feature Medium labels Dec 9, 2025
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.

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/StringCollectionField.java (1)

10-17: Consider using private access modifier for collectionValue field.

The field collectionValue on line 12 is declared as public, which breaks encapsulation. Since the class uses Lombok @Data, getters and setters are already generated. Consider making it private for consistency with typical Java bean conventions.

Also note: the constructor stores values both in the parent class via super(values) (which sets fulltextValue) and in collectionValue. If this dual storage is intentional for different Elasticsearch query patterns (similar to the caseValue/fulltextValue pattern in CaseField), this is fine. Otherwise, consider whether both are necessary.

-    public String[] collectionValue;
+    private String[] collectionValue;
♻️ Duplicate comments (1)
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java (1)

136-136: Same null handling concern applies here.

Similar to the multichoice map field transformation, if selectedKey is not present in the options map, the result will be an entry with an empty collection of translations.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46e49ec and b7d12ff.

📒 Files selected for processing (8)
  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java (2 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/NodeInfo.java (1 hunks)
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/StringCollectionField.java (1 hunks)
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/MapField.java (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 339
File: application-engine/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy:341-341
Timestamp: 2025-08-19T20:07:15.621Z
Learning: In the Elasticsearch migration, the stringId property was removed from ElasticCase and ElasticTask, with the id property now containing the MongoDB case/task object ID directly. This consolidation eliminates redundancy and simplifies the data model.
📚 Learning: 2025-08-19T20:07:15.621Z
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 339
File: application-engine/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy:341-341
Timestamp: 2025-08-19T20:07:15.621Z
Learning: In the Elasticsearch migration, the stringId property was removed from ElasticCase and ElasticTask, with the id property now containing the MongoDB case/task object ID directly. This consolidation eliminates redundancy and simplifies the data model.

Applied to files:

  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java
📚 Learning: 2025-08-19T20:13:40.087Z
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 339
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/CaseField.java:16-16
Timestamp: 2025-08-19T20:13:40.087Z
Learning: In CaseField.java, fulltextValue is mapped as a keyword field type in Elasticsearch (for exact matches, filtering, aggregations), while the separate caseValue field serves different Elasticsearch query requirements, allowing the system to support multiple query patterns on the same data through different field mappings.

Applied to files:

  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/StringCollectionField.java
  • nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/MapField.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java
📚 Learning: 2025-08-19T20:07:43.748Z
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 339
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/CaseField.java:16-16
Timestamp: 2025-08-19T20:07:43.748Z
Learning: In CaseField.java, the separate caseValue field (List<String>) is intentionally maintained alongside fulltextValue for specific Elasticsearch query requirements, rather than being derived on-the-fly from fulltextValue.

Applied to files:

  • application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/StringCollectionField.java
  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java
📚 Learning: 2025-06-23T13:30:13.096Z
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 318
File: nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java:60-62
Timestamp: 2025-06-23T13:30:13.096Z
Learning: In MenuItemConstants enum in nae-object-library/src/main/java/com/netgrif/application/engine/objects/workflow/domain/menu/MenuItemConstants.java, the field `attributeId` will be renamed to `value` to make it more generic and appropriate for both dataset attribute identifiers and technical constants like PATH_SEPARATOR.

Applied to files:

  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java
📚 Learning: 2025-12-02T14:35:05.305Z
Learnt from: renczesstefan
Repo: netgrif/application-engine PR: 373
File: nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/actions/ActionApi.java:98-98
Timestamp: 2025-12-02T14:35:05.305Z
Learning: In ActionApi, the deleteCase method intentionally does not include an AuthPrincipalDto parameter because it does not require author information, unlike createCase which needs the author via authPrincipalDto.

Applied to files:

  • nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java
🧬 Code graph analysis (2)
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nStringUtils.java (1)
  • I18nStringUtils (8-18)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/NodeInfo.java (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java (1)
  • Data (18-126)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: task-list-completed
  • GitHub Check: task-list-completed
  • GitHub Check: Build
🔇 Additional comments (10)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java (1)

11-24: LGTM!

The DTO structure is well-designed. Excluding sessionId from toString and equals/hashCode is a good practice—it prevents accidental logging of sensitive session data and ensures object equality is based on identity attributes rather than transient session state.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java (2)

14-24: LGTM on the DataField migration.

The inheritance change to DataField and constructor update align with the broader refactoring in this PR.


26-32: Verify single-value behavior is intentional.

The getValue() method only uses fulltextValue[0] when constructing the I18nString. If fulltextValue can contain multiple elements (since values is a Set passed to the constructor), confirm this single-value extraction is the intended behavior.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java (3)

82-107: LGTM on constructor logic.

The constructor properly initializes all case-related fields from the source Case object, with appropriate null-safety checks for tasks and proper use of defensive copies for collections.


109-125: LGTM on update method.

The update method correctly synchronizes relevant mutable fields while incrementing the version counter.


80-81: Remove the unused nodeInfo field or integrate it properly.

The nodeInfo field is declared at line 80 but is not initialized in the constructor, not updated in the update() method, and is never accessed anywhere in the codebase. Either remove this unused field or integrate it fully by initializing it during construction and updating it in the update() method.

Likely an incorrect or invalid review comment.

nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/MapField.java (1)

14-31: LGTM!

The constructor signatures correctly align with the base class refactoring from I18nString to Collection. The Elasticsearch field annotations are properly applied: Text type for full-text search and Keyword type for exact matching and aggregations.

nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java (3)

12-12: Architectural change aligns with PR objectives.

The change from extending TextField to DataField removes the dependency on TextField as stated in the PR objectives. This is part of the broader refactoring to decouple Elasticsearch datafields from TextField.


16-29: Constructor implementation is correct.

The refactored constructors properly handle the transition from I18nString to Collection:

  • Single-entry constructor delegates to the list constructor
  • List constructor correctly extracts keys into keyValue array and flattens all translation collections into fulltextValue

31-38: getValue() method provides convenient API.

The new getValue() method returns:

  • A single key as String for enumeration fields
  • A LinkedHashSet of keys for multichoice fields
  • null for empty/null keyValue

The LinkedHashSet preserves insertion order while ensuring uniqueness, which is appropriate for multichoice selections.

Comment on lines +96 to 99
List<Map.Entry<String, Collection<String>>> values = new ArrayList<>();
for (String key : (Set<String>) mapValues) {
I18nString selectedValue = options.get(key);
values.add(new AbstractMap.SimpleEntry<>(key, selectedValue != null ? selectedValue : new I18nString("")));
values.add(new AbstractMap.SimpleEntry<>(key, I18nStringUtils.collectTranslations(options.get(key))));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the file and the complete method context
cat -n application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java | sed -n '80,110p'

Repository: netgrif/application-engine

Length of output: 2089


🏁 Script executed:

# Search for I18nStringUtils.collectTranslations implementation
find . -type f -name "*.java" | xargs grep -l "I18nStringUtils" | head -5

Repository: netgrif/application-engine

Length of output: 292


🏁 Script executed:

# Look for the I18nStringUtils class definition
fd -type f -name "I18nStringUtils.java"

Repository: netgrif/application-engine

Length of output: 240


🏁 Script executed:

# Read the I18nStringUtils file to see the collectTranslations implementation
cat -n nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nStringUtils.java

Repository: netgrif/application-engine

Length of output: 786


🏁 Script executed:

# Search for getFieldOptions implementation
rg -nA10 "getFieldOptions" application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java

Repository: netgrif/application-engine

Length of output: 1830


🏁 Script executed:

# Search for tests related to transformMultichoiceMapField
fd -type f -name "*.java" | xargs grep -l "transformMultichoiceMapField\|ElasticCaseMappingService" | grep -i test

Repository: netgrif/application-engine

Length of output: 240


🏁 Script executed:

# Search for tests of ElasticCaseMappingService
find . -type f -name "*.java" -path "*/test/*" | xargs grep -l "ElasticCaseMappingService" 2>/dev/null | head -3

Repository: netgrif/application-engine

Length of output: 52


🏁 Script executed:

# Search for any validation or warnings about missing keys
rg -n "mapValues|options\.get" application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java -B2 -A2

Repository: netgrif/application-engine

Length of output: 1025


🏁 Script executed:

# Check if there's any logging or warning in the surrounding code
rg -n "logger|log\.|warn|error" application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java | head -20

Repository: netgrif/application-engine

Length of output: 1771


🏁 Script executed:

# Check the git history of this specific method to understand its evolution
git log --oneline -n 20 -- application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java

Repository: netgrif/application-engine

Length of output: 150


Inconsistent error handling: missing options keys are silently converted to empty translations.

The code at line 98 does not validate that all keys from mapValues exist in the options map. While I18nStringUtils.collectTranslations(null) handles null gracefully by returning an empty list, this pattern is inconsistent with the error handling established elsewhere in this class. Other methods (e.g., lines 163, 180, 194) log errors when encountering data inconsistencies. Consider either adding validation to ensure all keys are present in the options map, or logging a warning when options.get(key) returns null to make data issues visible during debugging.

🤖 Prompt for AI Agents
In
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java
around lines 96-99, the code blindly calls options.get(key) and passes the
result to I18nStringUtils.collectTranslations, silently producing empty
translations for missing keys; change this to first check
options.containsKey(key) and if the key is missing log a warning (including the
missing key and identifying context such as the parent map or document id), then
either continue with an explicit empty translation list or handle it
consistently with the class’s error strategy (throw or collect an error),
ensuring missing keys are visible in logs rather than silently ignored.

Comment on lines 3 to 6
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Remove unused import.

lombok.NonNull is imported but not used in this class.

 import lombok.Data;
 import lombok.EqualsAndHashCode;
-import lombok.NonNull;
 import lombok.ToString;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
🤖 Prompt for AI Agents
In
nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java
around lines 3 to 6, the import lombok.NonNull is unused; remove that import
line and keep only the required lombok imports (Data, EqualsAndHashCode,
ToString) so there are no unused imports.

@machacjozef machacjozef changed the base branch from release/7.0.0-rev9 to release/7.0.0-rev10 December 15, 2025 14:26
# Conflicts:
#	nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/AuthPrincipalDto.java
#	nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java
#	nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java
#	nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/elastic/domain/MapField.java
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.

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java (1)

113-135: 🧹 Nitpick | 🔵 Trivial

Consider consistency: other fields handle null explicitly, but nodeInfo is completely absent.

All other fields in update() explicitly handle null cases (e.g., taskIds = useCase.getTaskIds() == null ? new HashSet<>() : ...). The nodeInfo field is not addressed at all.

If the intent is for nodeInfo to remain unchanged during updates, consider adding a brief comment to clarify this design decision for future maintainers:

// nodeInfo intentionally not updated - represents the originating search node
🤖 Fix all issues with AI agents
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java`:
- Around line 82-83: The nodeInfo field in class ElasticCase is declared but
never initialized or copied; update the constructor (the ElasticCase(...)
initializer that sets other fields like id, title, etc.) to initialize
this.nodeInfo from the source ElasticCase (e.g., this.nodeInfo =
source.getNodeInfo() or new NodeInfo(source.getNodeInfo()) if a defensive copy
is needed) and also modify the update(...) method to set/replace nodeInfo the
same way when copying fields from another ElasticCase (ensure you use the same
copying semantics used for other complex fields in this class to maintain
immutability/defensive copying).

In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java`:
- Around line 35-38: I18nField's getValue() currently returns only
fulltextValue[0], but the constructor accepts Set<String> inputs and populates
fulltextValue and keyValue as parallel arrays, causing a cardinality mismatch;
either enforce single-value semantics in the constructor (in I18nField's
constructor validate that fulltextValue/keyValue sets contain exactly one
element and throw an IllegalArgumentException if not) or change getValue() to
return a multi-value representation (e.g., return a collection or map of
keys->values, or a list of I18nString instances) so that each index in
fulltextValue/keyValue is preserved; update usages of getValue() accordingly to
handle the chosen representation and keep translations consistent.

In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java`:
- Around line 21-27: In the MapField constructor the call
values.addAll(valuePairs.get(i).getValue()) can NPE if an entry's value is null;
update the constructor (MapField(List<Map.Entry<String, Collection<String>>>
valuePairs)) to null-safe aggregate by retrieving the entry value into a local
variable, defaulting to Collections.emptyList() (or new ArrayList<>()) when
null, then addAll that safe collection to values while still populating
keyValue[i]; ensure keyValue and values sizing logic remains unchanged.

Comment on lines +82 to +83
private NodeInfo nodeInfo;

Copy link

@coderabbitai coderabbitai bot Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find where nodeInfo is set/used
echo "=== Searching for nodeInfo usage patterns ==="
rg -n 'nodeInfo' --type=java -C2

Repository: netgrif/application-engine

Length of output: 760


🏁 Script executed:

#!/bin/bash
# Find where NodeInfo is instantiated
echo "=== Searching for NodeInfo instantiation ==="
rg -n 'new NodeInfo\(' --type=java -C3

Repository: netgrif/application-engine

Length of output: 114


🏁 Script executed:

#!/bin/bash
# Search for setNodeInfo method calls
echo "=== Searching for setNodeInfo calls ==="
rg -n 'setNodeInfo' --type=java -C2

Repository: netgrif/application-engine

Length of output: 109


🏁 Script executed:

#!/bin/bash
# Find NodeInfo class definition
echo "=== Searching for NodeInfo class definition ==="
rg -n 'class NodeInfo|interface NodeInfo' --type=java -C3

Repository: netgrif/application-engine

Length of output: 1019


🏁 Script executed:

#!/bin/bash
# Check ElasticCase for getter/setter methods related to nodeInfo
echo "=== Searching for nodeInfo getter/setter in ElasticCase ==="
rg -n 'getNodeInfo|setNodeInfo|nodeInfo' nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java -C1

Repository: netgrif/application-engine

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Search for any assignment to nodeInfo field
echo "=== Searching for nodeInfo field assignments ==="
rg -n 'this\.nodeInfo\s*=' --type=java -C2

Repository: netgrif/application-engine

Length of output: 118


🏁 Script executed:

#!/bin/bash
# Look at the complete ElasticCase file around the nodeInfo field and constructor
echo "=== ElasticCase constructor and nodeInfo field context ==="
cat -n nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java | sed -n '78,140p'

Repository: netgrif/application-engine

Length of output: 4641


Initialize nodeInfo in the constructor and update it in the update() method.

The nodeInfo field is declared (line 82) but never initialized in the constructor (lines 84-111) or updated in the update() method (lines 113-135). Unlike all other fields in this class which are explicitly initialized and copied, nodeInfo will remain null. Either this field should be initialized from the source ElasticCase like other fields, or justify why it requires different handling.

🤖 Prompt for AI Agents
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/ElasticCase.java`
around lines 82 - 83, The nodeInfo field in class ElasticCase is declared but
never initialized or copied; update the constructor (the ElasticCase(...)
initializer that sets other fields like id, title, etc.) to initialize
this.nodeInfo from the source ElasticCase (e.g., this.nodeInfo =
source.getNodeInfo() or new NodeInfo(source.getNodeInfo()) if a defensive copy
is needed) and also modify the update(...) method to set/replace nodeInfo the
same way when copying fields from another ElasticCase (ensure you use the same
copying semantics used for other complex fields in this class to maintain
immutability/defensive copying).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kovy95 shouldnt be it at least updated?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 35 to 38
public Object getValue() {
if (textValue != null && textValue.length > 0) {
return new I18nString(textValue[0], translations);
if (fulltextValue != null && fulltextValue.length > 0) {
return new I18nString(fulltextValue[0], translations);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's read the I18nField.java file to see its full structure
find . -type f -name "I18nField.java" | head -5

Repository: netgrif/application-engine

Length of output: 402


🏁 Script executed:

# Search for fulltextValue usage across the codebase to understand the pattern
rg -n "fulltextValue" --type java | head -30

Repository: netgrif/application-engine

Length of output: 2581


🏁 Script executed:

# Let's specifically look at CaseField.java since the learning mentions it has a related pattern
find . -type f -name "CaseField.java" | head -3

Repository: netgrif/application-engine

Length of output: 402


🏁 Script executed:

# Read the I18nField.java file in elastic domain
cat -n ./nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java

Repository: netgrif/application-engine

Length of output: 1606


🏁 Script executed:

# Read the CaseField.java file to understand the separate field pattern
cat -n ./nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/CaseField.java

Repository: netgrif/application-engine

Length of output: 1133


🏁 Script executed:

# Check how I18nField is populated/instantiated
rg -n "new I18nField|I18nField(" -A 5 --type java | head -50

Repository: netgrif/application-engine

Length of output: 168


🏁 Script executed:

# Fix regex syntax to search for I18nField instantiation
rg "I18nField\(" -A 3 --type java | head -50

Repository: netgrif/application-engine

Length of output: 6140


🏁 Script executed:

# Find concrete implementations/subclasses of I18nField
rg "extends I18nField|class.*I18nField" --type java

Repository: netgrif/application-engine

Length of output: 783


🏁 Script executed:

# Search for tests related to I18nField
find . -type f -name "*I18nField*Test*.java" -o -name "*Test*I18nField*.java"

Repository: netgrif/application-engine

Length of output: 52


🏁 Script executed:

# Check DataField to see how it handles single vs multi-value
cat -n ./nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/DataField.java

Repository: netgrif/application-engine

Length of output: 1267


🏁 Script executed:

# Check if I18nField has abstract methods that might clarify intent
cat -n ./nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java

Repository: netgrif/application-engine

Length of output: 1606


🏁 Script executed:

# Search for concrete implementations of the elastic I18nField
rg "class.*extends.*I18nField" -A 3 --type java | grep -A 3 "elastic"

Repository: netgrif/application-engine

Length of output: 685


🏁 Script executed:

# Check how I18nField is actually used in the codebase (elastic domain variant)
rg "I18nField\(.*Set" --type java -A 2 | head -20

Repository: netgrif/application-engine

Length of output: 1058


🏁 Script executed:

# Look for actual tests of the elastic domain module
find ./nae-object-library -type f -name "*Test*.java" | xargs grep -l "I18nField" 2>/dev/null | head -5

Repository: netgrif/application-engine

Length of output: 52


Address cardinality mismatch between constructor design and getValue() implementation.

The constructor accepts Set<String> keys and values (supporting multiple entries) and stores them in parallel arrays, but getValue() returns only fulltextValue[0]. This creates a design inconsistency: either enforce single-value semantics in the constructor or return all values. The parallel keyValue array suggests each index should correspond to a value, making the silent truncation of additional entries problematic. Consider enforcing single-value semantics explicitly (fail fast) or returning a multi-value representation like CaseField does with its separate caseValue field.

🤖 Prompt for AI Agents
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/I18nField.java`
around lines 35 - 38, I18nField's getValue() currently returns only
fulltextValue[0], but the constructor accepts Set<String> inputs and populates
fulltextValue and keyValue as parallel arrays, causing a cardinality mismatch;
either enforce single-value semantics in the constructor (in I18nField's
constructor validate that fulltextValue/keyValue sets contain exactly one
element and throw an IllegalArgumentException if not) or change getValue() to
return a multi-value representation (e.g., return a collection or map of
keys->values, or a list of I18nString instances) so that each index in
fulltextValue/keyValue is preserved; update usages of getValue() accordingly to
handle the chosen representation and keep translations consistent.

Comment on lines +21 to +27
public MapField(List<Map.Entry<String, Collection<String>>> valuePairs) {
super(new String[0]);
this.keyValue = new String[valueTranslationPairs.size()];
this.keyValue = new String[valuePairs.size()];
List<String> values = new ArrayList<>();
this.keyValueTranslations = new HashMap<>();
for (int i = 0; i < valueTranslationPairs.size(); i++) {
this.keyValue[i] = valueTranslationPairs.get(i).getKey();
values.addAll(I18nStringUtils.collectTranslations(valueTranslationPairs.get(i).getValue()));
this.keyValueTranslations.put(valueTranslationPairs.get(i).getKey(), valueTranslationPairs.get(i).getValue());
for (int i = 0; i < valuePairs.size(); i++) {
keyValue[i] = valuePairs.get(i).getKey();
values.addAll(valuePairs.get(i).getValue());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Null-safe aggregation of entry values to prevent NPEs.

values.addAll(valuePairs.get(i).getValue()) will throw if any entry carries a null collection. Consider guarding or defaulting to an empty collection to keep indexing resilient.

🔧 Proposed fix
         for (int i = 0; i < valuePairs.size(); i++) {
             keyValue[i] = valuePairs.get(i).getKey();
-            values.addAll(valuePairs.get(i).getValue());
+            Collection<String> entryValues = valuePairs.get(i).getValue();
+            if (entryValues != null) {
+                values.addAll(entryValues);
+            }
         }
🤖 Prompt for AI Agents
In
`@nae-object-library/src/main/java/com/netgrif/application/engine/objects/elastic/domain/MapField.java`
around lines 21 - 27, In the MapField constructor the call
values.addAll(valuePairs.get(i).getValue()) can NPE if an entry's value is null;
update the constructor (MapField(List<Map.Entry<String, Collection<String>>>
valuePairs)) to null-safe aggregate by retrieving the entry value into a local
variable, defaulting to Collections.emptyList() (or new ArrayList<>()) when
null, then addAll that safe collection to values while still populating
keyValue[i]; ensure keyValue and values sizing logic remains unchanged.

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.

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseMappingService.java (1)

136-141: ⚠️ Potential issue | 🟡 Minor

Same silent null handling pattern as transformMultichoiceMapField.

If selectedKey does not exist in the options map, options.get(selectedKey) returns null and collectTranslations will return an empty list without any indication of data inconsistency. This contrasts with transformEnumerationField (line 198) which logs an error when encountering unexpected data.

Consider adding validation or logging consistent with the class's error handling strategy:

🛡️ Suggested validation
     protected Optional<DataField> transformEnumerationMapField
             (com.netgrif.application.engine.objects.workflow.domain.DataField enumMap, EnumerationMapField netField) {
         Map<String, I18nString> options = this.getFieldOptions(enumMap, netField);
         String selectedKey = (String) enumMap.getValue();
+        if (!options.containsKey(selectedKey)) {
+            log.warn("EnumerationMapField selected key '{}' not found in options map", selectedKey);
+        }
         return Optional.of(new com.netgrif.application.engine.adapter.spring.elastic.domain.MapField(new AbstractMap.SimpleEntry<>(selectedKey, I18nStringUtils.collectTranslations(options.get(selectedKey)))));
     }

Copy link
Contributor

@Retoocs Retoocs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and tests are failing

Comment on lines +82 to +83
private NodeInfo nodeInfo;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kovy95 shouldnt be it at least updated?

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

Labels

improvement A change that improves on an existing feature Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants