Skip to content

Commit

Permalink
[Sitemap] Add support for multiple AND conditions
Browse files Browse the repository at this point in the history
Concerns labelcolor, valuecolor and visibility

Also fix wrong positions of ")" in Sitemap.xtext

Closes openhab#3058

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo committed Oct 2, 2023
1 parent dda021a commit c690073
Show file tree
Hide file tree
Showing 7 changed files with 471 additions and 270 deletions.
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,8 @@
* @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 +772,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

0 comments on commit c690073

Please sign in to comment.