Skip to content

Extend to 1000 the possible sub-widgets number in a sitemap frame/page#5466

Draft
lolodomo wants to merge 1 commit intoopenhab:mainfrom
lolodomo:sitemap_widgetid_coding
Draft

Extend to 1000 the possible sub-widgets number in a sitemap frame/page#5466
lolodomo wants to merge 1 commit intoopenhab:mainfrom
lolodomo:sitemap_widgetid_coding

Conversation

@lolodomo
Copy link
Copy Markdown
Contributor

@lolodomo lolodomo commented Mar 31, 2026

The previous limit was 100.

An error will also be logged in case of detection of more than 1000 widgets in a sitemap frame/page when the page is opened.

Closes #5434

@lolodomo lolodomo requested a review from a team as a code owner March 31, 2026 19:48
@lolodomo
Copy link
Copy Markdown
Contributor Author

@holgerfriedrich @wborn : looks like the build system is no more working. All my PRs are impacted. This is something new since today I believe.

@holgerfriedrich
Copy link
Copy Markdown
Member

I am looking into this. Apparently one of our allowed GH actions is no longer listed in the configuration.

Before adding it again, let me check something......

@wborn
Copy link
Copy Markdown
Member

wborn commented Apr 1, 2026

I tightened the CI security a bit (triggered by the latest axios supply chain attack) and thought we removed this action as we use the Maven wrapper instead nowadays? 🤔

The previous limit was 100.

An error will also be logged in case of detection of more than 1000 widgets in a sitemap frame/page when the page is opened.

Closes openhab#5434

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
@lolodomo lolodomo force-pushed the sitemap_widgetid_coding branch from c6b390b to adb119c Compare April 1, 2026 15:36
@lolodomo lolodomo changed the title Extend to 1000 the number of possible sub-widgets in a sitemap frame/… Extend to 1000 the possible sub-widgets number in a sitemap frame/page Apr 1, 2026
@wborn wborn requested a review from Copilot April 7, 2026 21:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the sitemap widget ID encoding to support up to 1000 widgets per level (by moving from 2-digit to 3-digit per-depth encoding) and adds logging when the limit is exceeded, aligning core sitemap navigation with the constraints described in issue #5434.

Changes:

  • Increase widget ID segment width from 2 to 3 digits and adjust parsing accordingly.
  • Add an error log when a widget index exceeds the supported per-level limit.
  • Update REST sitemap test constants to reflect the new 3-digit widget ID format.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java Implements 3-digit widgetId encoding/decoding and logs when per-level widget count exceeds the supported maximum.
bundles/org.openhab.core.io.rest.sitemap/src/test/java/org/openhab/core/io/rest/sitemap/internal/SitemapResourceTest.java Updates expected widgetId strings to 3 digits.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +780 to 787
int widgetID = Integer.parseInt(id.substring(0, WIDGET_ID_CODING_SIZE));
if (widgetID < sitemap.getWidgets().size()) {
w = sitemap.getWidgets().get(widgetID);
for (int i = 2; i < id.length(); i += 2) {
int childWidgetID = Integer.parseInt(id.substring(i, i + 2));
for (int i = WIDGET_ID_CODING_SIZE; i < id.length(); i += WIDGET_ID_CODING_SIZE) {
int childWidgetID = Integer.parseInt(id.substring(i, i + WIDGET_ID_CODING_SIZE));
if (childWidgetID < ((LinkableWidget) w).getWidgets().size()) {
w = ((LinkableWidget) w).getWidgets().get(childWidgetID);
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

getWidget(Sitemap, String) now assumes the widgetId has at least WIDGET_ID_CODING_SIZE chars and that every segment is present. Requests using legacy 2-digit IDs (e.g. existing bookmarks) or malformed IDs can trigger StringIndexOutOfBoundsException (substring) or IndexOutOfBoundsException (negative values pass the < size check and then get(-1)), resulting in 500s. Please validate length/segment boundaries (>=0 and < size), ensure w is a LinkableWidget before casting, and return null for invalid paths; consider accepting the legacy 2-digit encoding for backward compatibility.

Copilot uses AI. Check for mistakes.
Comment on lines 1059 to 1064
while (w.getParent() instanceof LinkableWidget parent) {
String index = String.valueOf(parent.getWidgets().indexOf(w));
if (index.length() == 1) {
index = "0" + index; // make it two digits
}
int num = parent.getWidgets().indexOf(w);
error |= (num >= MAX_SUPPORTED_CHILDREN);
String index = String.format(WIDGET_ID_CODING_FORMAT, num);
id = index + id;
w = parent;
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

When num >= MAX_SUPPORTED_CHILDREN, String.format(WIDGET_ID_CODING_FORMAT, num) produces more than WIDGET_ID_CODING_SIZE digits (e.g. 1000 -> "1000"). That breaks the fixed-width encoding and can lead to collisions or decode errors downstream. Consider not generating numeric IDs for out-of-range widgets (e.g., fallback to item-name IDs when possible, otherwise fail fast) so the system degrades cleanly beyond the supported limit.

Copilot uses AI. Check for mistakes.
Comment on lines +1053 to 1056
// Build the id by concatenating the child index at each level from top (main page) to bottom (sub-page),
// using WIDGET_ID_CODING_SIZE (3) digits at each level.
// This coding allows until MAX_SUPPORTED_CHILDREN (1000) items at each level.
String id = "";
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

getWidgetId’s updated 3-digit encoding changes the externally visible widgetId format (used by REST /sitemaps and /proxy). The ItemUIRegistry interface JavaDoc still describes the old 2-digit encoding (example "0503"), which is now misleading. Please update the public API docs accordingly so clients understand the new format/limits.

Copilot uses AI. Check for mistakes.
Comment on lines 1047 to +1076
public String getWidgetId(Widget widget) {
Widget w2 = defaultWidgets.get(widget);
if (w2 != null) {
return getWidgetId(w2);
}

// Build the id by concatenating the child index at each level from top (main page) to bottom (sub-page),
// using WIDGET_ID_CODING_SIZE (3) digits at each level.
// This coding allows until MAX_SUPPORTED_CHILDREN (1000) items at each level.
String id = "";
Widget w = widget;
boolean error = false;
while (w.getParent() instanceof LinkableWidget parent) {
String index = String.valueOf(parent.getWidgets().indexOf(w));
if (index.length() == 1) {
index = "0" + index; // make it two digits
}
int num = parent.getWidgets().indexOf(w);
error |= (num >= MAX_SUPPORTED_CHILDREN);
String index = String.format(WIDGET_ID_CODING_FORMAT, num);
id = index + id;
w = parent;
}
if (w.getParent() instanceof Sitemap sitemap) {
String index = String.valueOf(sitemap.getWidgets().indexOf(w));
if (index.length() == 1) {
index = "0" + index; // make it two digits
}
int num = sitemap.getWidgets().indexOf(w);
error |= (num >= MAX_SUPPORTED_CHILDREN);
String index = String.format(WIDGET_ID_CODING_FORMAT, num);
id = index + id;
}
if (error) {
logger.error(
"You have too many sub-widgets at a certain level of your sitemap; openHAB only supports a maximum of {}",
MAX_SUPPORTED_CHILDREN);
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This PR changes widgetId encoding/decoding logic, but there are no unit tests covering (a) 3-digit roundtrip getWidgetId -> getWidget, (b) backward compatibility with the previous 2-digit IDs (if intended), and (c) behavior for malformed/negative IDs and the 999/1000 boundary. Adding focused tests in ItemUIRegistryImplTest would help prevent regressions for REST/proxy consumers.

Copilot uses AI. Check for mistakes.
@lolodomo
Copy link
Copy Markdown
Contributor Author

Even if it was not my choice as I wanted to keep that as simple as possible considering that this probably impacts only very users all over the world, it is of course possible to implement something more complex in the coding of these ID so that old ID coding are still supported.

@lolodomo lolodomo marked this pull request as draft April 12, 2026 15:28
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.

[sitemap] Extend the number of widgets supported in a frame and any sub-page

4 participants