Skip to content

Commit

Permalink
Allow multiple conditions with AND operator in visibility/color/icon …
Browse files Browse the repository at this point in the history
…rules

Closes #3058

Signed-off-by: Laurent Garnier <[email protected]>

Fix
  • Loading branch information
lolodomo committed Sep 28, 2023
1 parent 4379d71 commit ff068bd
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 265 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,8 +37,9 @@
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.IconArray;
import org.openhab.core.model.sitemap.sitemap.IconRule;
import org.openhab.core.model.sitemap.sitemap.VisibilityRule;
import org.openhab.core.model.sitemap.sitemap.Widget;
import org.openhab.core.types.State;
Expand All @@ -48,7 +50,7 @@
*
* @author Kai Kreuzer - Initial contribution
* @author Laurent Garnier - Added support for icon color
* @author Laurent Garnier - New widget icon parameter based on conditional rules
* @author Laurent Garnier - New widget icon parameter based on conditional rules + multiple AND conditions
*/
public class PageChangeListener implements EventSubscriber {

Expand Down Expand Up @@ -122,30 +124,38 @@ private Set<Item> getAllItems(EList<Widget> widgets) {
items.addAll(getAllItems(frame.getChildren()));
}
// now scan dynamic icon rules
for (IconArray rule : widget.getDynamicIcon()) {
addItemWithName(items, rule.getItem());
for (IconRule rule : widget.getDynamicIcon()) {
addItemFromConditions(items, rule.getConditions());
}
// now scan visibility rules
for (VisibilityRule rule : widget.getVisibility()) {
addItemWithName(items, rule.getItem());
addItemFromConditions(items, rule.getConditions());
}
// now scan label color rules
for (ColorArray rule : widget.getLabelColor()) {
addItemWithName(items, rule.getItem());
addItemFromConditions(items, rule.getConditions());
}
// now scan value color rules
for (ColorArray rule : widget.getValueColor()) {
addItemWithName(items, rule.getItem());
addItemFromConditions(items, rule.getConditions());
}
// now scan icon color rules
for (ColorArray rule : widget.getIconColor()) {
addItemWithName(items, rule.getItem());
addItemFromConditions(items, rule.getConditions());
}
}
}
return items;
}

private void addItemFromConditions(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 @@ -247,11 +257,19 @@ private Item getItemForWidget(Widget w) {
}

private boolean definesVisibilityOrColorOrIcon(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()))
|| w.getDynamicIcon().stream().anyMatch(r -> name.equals(r.getItem()));
return w.getVisibility().stream().anyMatch(r -> r != null && conditionsDependsOnItem(r.getConditions(), name))
|| w.getLabelColor().stream()
.anyMatch(r -> r != null && conditionsDependsOnItem(r.getConditions(), name))
|| w.getValueColor().stream()
.anyMatch(r -> r != null && conditionsDependsOnItem(r.getConditions(), name))
|| w.getIconColor().stream()
.anyMatch(r -> r != null && conditionsDependsOnItem(r.getConditions(), name))
|| w.getDynamicIcon().stream()
.anyMatch(r -> r != null && 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 @@ -78,8 +78,9 @@
import org.openhab.core.model.sitemap.SitemapProvider;
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.IconArray;
import org.openhab.core.model.sitemap.sitemap.IconRule;
import org.openhab.core.model.sitemap.sitemap.Image;
import org.openhab.core.model.sitemap.sitemap.Input;
import org.openhab.core.model.sitemap.sitemap.LinkableWidget;
Expand Down Expand Up @@ -132,7 +133,7 @@
* @author Wouter Born - Migrated to OpenAPI annotations
* @author Laurent Garnier - Added support for icon color
* @author Mark Herwege - Added pattern and unit fields
* @author Laurent Garnier - New widget icon parameter based on conditional rules
* @author Laurent Garnier - New widget icon parameter based on conditional rules + multiple AND conditions
*/
@Component(service = { RESTResource.class, EventSubscriber.class })
@JaxrsResource
Expand Down Expand Up @@ -757,55 +758,43 @@ 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);
}
} catch (ItemNotFoundException e) {
// ignore
}
}
for (ColorArray rule : colorList) {
getItemsInConditions(rule.getConditions(), items);
}
return items;
}

private Set<GenericItem> getItemsInIconCond(EList<IconArray> ruleList) {
private Set<GenericItem> getItemsInIconCond(EList<IconRule> ruleList) {
Set<GenericItem> items = new HashSet<>();
for (IconArray rule : ruleList) {
String itemName = rule.getItem();
if (itemName != null) {
try {
Item item = itemUIRegistry.getItem(itemName);
if (item instanceof GenericItem genericItem) {
items.add(genericItem);
for (IconRule rule : ruleList) {
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 @@ -335,28 +336,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);
Condition conditon = mock(Condition.class);
when(conditon.getItem()).thenReturn(VISIBILITY_RULE_ITEM_NAME);
BasicEList<Condition> conditions = new BasicEList<>();
conditions.add(conditon);
when(visibilityRule.getConditions()).thenReturn(conditions);
BasicEList<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);
BasicEList<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);
BasicEList<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);
BasicEList<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 Down
Loading

0 comments on commit ff068bd

Please sign in to comment.