Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sitemap] Add support for multiple AND conditions #3819

Merged
merged 1 commit into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.stream.Collectors;

import org.eclipse.emf.common.util.EList;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.ThreadPoolManager;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventSubscriber;
Expand All @@ -36,6 +37,7 @@
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.model.sitemap.sitemap.Chart;
import org.openhab.core.model.sitemap.sitemap.ColorArray;
import org.openhab.core.model.sitemap.sitemap.Condition;
import org.openhab.core.model.sitemap.sitemap.Frame;
import org.openhab.core.model.sitemap.sitemap.VisibilityRule;
import org.openhab.core.model.sitemap.sitemap.Widget;
Expand All @@ -47,6 +49,7 @@
*
* @author Kai Kreuzer - Initial contribution
* @author Laurent Garnier - Added support for icon color
* @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility
*/
public class PageChangeListener implements EventSubscriber {

Expand Down Expand Up @@ -121,25 +124,33 @@ private Set<Item> getAllItems(EList<Widget> widgets) {
}
// now scan visibility rules
for (VisibilityRule rule : widget.getVisibility()) {
addItemWithName(items, rule.getItem());
addItemsFromConditions(items, rule.getConditions());
}
// now scan label color rules
for (ColorArray rule : widget.getLabelColor()) {
addItemWithName(items, rule.getItem());
addItemsFromConditions(items, rule.getConditions());
}
// now scan value color rules
for (ColorArray rule : widget.getValueColor()) {
addItemWithName(items, rule.getItem());
addItemsFromConditions(items, rule.getConditions());
}
// now scan value icon rules
// now scan icon color rules
for (ColorArray rule : widget.getIconColor()) {
addItemWithName(items, rule.getItem());
addItemsFromConditions(items, rule.getConditions());
}
}
}
return items;
}

private void addItemsFromConditions(Set<Item> items, @Nullable EList<Condition> conditions) {
if (conditions != null) {
for (Condition condition : conditions) {
addItemWithName(items, condition.getItem());
}
}
}

private void addItemWithName(Set<Item> items, String itemName) {
if (itemName != null) {
try {
Expand Down Expand Up @@ -238,10 +249,14 @@ private Item getItemForWidget(Widget w) {
}

private boolean definesVisibilityOrColor(Widget w, String name) {
return w.getVisibility().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getLabelColor().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getValueColor().stream().anyMatch(r -> name.equals(r.getItem()))
|| w.getIconColor().stream().anyMatch(r -> name.equals(r.getItem()));
return w.getVisibility().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|| w.getLabelColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|| w.getValueColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name))
|| w.getIconColor().stream().anyMatch(r -> conditionsDependsOnItem(r.getConditions(), name));
}

private boolean conditionsDependsOnItem(@Nullable EList<Condition> conditions, String name) {
return conditions != null && conditions.stream().anyMatch(c -> name.equals(c.getItem()));
}

public void sitemapContentChanged(EList<Widget> widgets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import org.openhab.core.model.sitemap.sitemap.Buttongrid;
import org.openhab.core.model.sitemap.sitemap.Chart;
import org.openhab.core.model.sitemap.sitemap.ColorArray;
import org.openhab.core.model.sitemap.sitemap.Condition;
import org.openhab.core.model.sitemap.sitemap.Frame;
import org.openhab.core.model.sitemap.sitemap.Image;
import org.openhab.core.model.sitemap.sitemap.Input;
Expand Down Expand Up @@ -135,6 +136,7 @@
* @author Mark Herwege - Added pattern and unit fields
* @author Laurent Garnier - Added support for new sitemap element Buttongrid
* @author Laurent Garnier - Added icon field for mappings used for switch element
* @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility
*/
@Component(service = { RESTResource.class, EventSubscriber.class })
@JaxrsResource
Expand Down Expand Up @@ -769,37 +771,35 @@ private Set<GenericItem> getAllItems(EList<Widget> widgets) {
private Set<GenericItem> getItemsInVisibilityCond(EList<VisibilityRule> ruleList) {
Set<GenericItem> items = new HashSet<>();
for (VisibilityRule rule : ruleList) {
String itemName = rule.getItem();
if (itemName != null) {
try {
Item item = itemUIRegistry.getItem(itemName);
if (item instanceof GenericItem genericItem) {
items.add(genericItem);
}
} catch (ItemNotFoundException e) {
// ignore
}
}
getItemsInConditions(rule.getConditions(), items);
}
return items;
}

private Set<GenericItem> getItemsInColorCond(EList<ColorArray> colorList) {
Set<GenericItem> items = new HashSet<>();
for (ColorArray color : colorList) {
String itemName = color.getItem();
if (itemName != null) {
try {
Item item = itemUIRegistry.getItem(itemName);
if (item instanceof GenericItem genericItem) {
items.add(genericItem);
for (ColorArray rule : colorList) {
getItemsInConditions(rule.getConditions(), items);
}
return items;
}

private void getItemsInConditions(@Nullable EList<Condition> conditions, Set<GenericItem> items) {
if (conditions != null) {
for (Condition condition : conditions) {
String itemName = condition.getItem();
if (itemName != null) {
try {
Item item = itemUIRegistry.getItem(itemName);
if (item instanceof GenericItem genericItem) {
items.add(genericItem);
}
} catch (ItemNotFoundException e) {
// ignore
}
} catch (ItemNotFoundException e) {
// ignore
}
}
}
return items;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.openhab.core.library.types.PercentType;
import org.openhab.core.model.sitemap.SitemapProvider;
import org.openhab.core.model.sitemap.sitemap.ColorArray;
import org.openhab.core.model.sitemap.sitemap.Condition;
import org.openhab.core.model.sitemap.sitemap.Sitemap;
import org.openhab.core.model.sitemap.sitemap.VisibilityRule;
import org.openhab.core.model.sitemap.sitemap.Widget;
Expand Down Expand Up @@ -251,6 +252,30 @@ public void whenLongPollingShouldObserveItemsFromValueColorConditions() {
// return
}

@Test
public void whenLongPollingShouldObserveItemsFromIconColorConditions() {
ItemEvent itemEvent = mock(ItemEvent.class);
when(itemEvent.getItemName()).thenReturn(iconColorItem.getName());
new Thread(() -> {
try {
Thread.sleep(STATE_UPDATE_WAIT_TIME); // wait for the #getPageData call and listeners to attach to the
// item
sitemapResource.receive(itemEvent);
} catch (InterruptedException e) {
}
}).start();

// non-null is sufficient here.
when(headersMock.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(List.of());

Response response = sitemapResource.getPageData(headersMock, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null,
false);

PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
// return
}

@Test
public void whenGetPageDataShouldReturnPageBean() throws ItemNotFoundException {
item.setState(new PercentType(50));
Expand Down Expand Up @@ -333,28 +358,44 @@ private EList<Widget> initSitemapWidgets() {

// add visibility rules to the mock widget:
VisibilityRule visibilityRule = mock(VisibilityRule.class);
when(visibilityRule.getItem()).thenReturn(VISIBILITY_RULE_ITEM_NAME);
BasicEList<VisibilityRule> visibilityRules = new BasicEList<>(1);
Condition conditon = mock(Condition.class);
when(conditon.getItem()).thenReturn(VISIBILITY_RULE_ITEM_NAME);
EList<Condition> conditions = new BasicEList<>();
conditions.add(conditon);
when(visibilityRule.getConditions()).thenReturn(conditions);
EList<VisibilityRule> visibilityRules = new BasicEList<>(1);
visibilityRules.add(visibilityRule);
when(w1.getVisibility()).thenReturn(visibilityRules);

// add label color conditions to the item:
ColorArray labelColor = mock(ColorArray.class);
when(labelColor.getItem()).thenReturn(LABEL_COLOR_ITEM_NAME);
Condition conditon1 = mock(Condition.class);
when(conditon1.getItem()).thenReturn(LABEL_COLOR_ITEM_NAME);
EList<Condition> conditions1 = new BasicEList<>();
conditions1.add(conditon1);
when(labelColor.getConditions()).thenReturn(conditions1);
EList<ColorArray> labelColors = new BasicEList<>();
labelColors.add(labelColor);
when(w1.getLabelColor()).thenReturn(labelColors);

// add value color conditions to the item:
ColorArray valueColor = mock(ColorArray.class);
when(valueColor.getItem()).thenReturn(VALUE_COLOR_ITEM_NAME);
Condition conditon2 = mock(Condition.class);
when(conditon2.getItem()).thenReturn(VALUE_COLOR_ITEM_NAME);
EList<Condition> conditions2 = new BasicEList<>();
conditions2.add(conditon2);
when(valueColor.getConditions()).thenReturn(conditions2);
EList<ColorArray> valueColors = new BasicEList<>();
valueColors.add(valueColor);
when(w1.getValueColor()).thenReturn(valueColors);

// add icon color conditions to the item:
ColorArray iconColor = mock(ColorArray.class);
when(iconColor.getItem()).thenReturn(ICON_COLOR_ITEM_NAME);
Condition conditon3 = mock(Condition.class);
when(conditon3.getItem()).thenReturn(ICON_COLOR_ITEM_NAME);
EList<Condition> conditions3 = new BasicEList<>();
conditions3.add(conditon3);
when(iconColor.getConditions()).thenReturn(conditions3);
EList<ColorArray> iconColors = new BasicEList<>();
iconColors.add(iconColor);
when(w1.getIconColor()).thenReturn(iconColors);
Expand All @@ -376,7 +417,7 @@ private EList<Widget> initSitemapWidgets() {
when(w2.getValueColor()).thenReturn(valueColors);
when(w2.getIconColor()).thenReturn(iconColors);

BasicEList<Widget> widgets = new BasicEList<>(2);
EList<Widget> widgets = new BasicEList<>(2);
widgets.add(w1);
widgets.add(w2);
return widgets;
Expand Down
Loading