Skip to content

Commit

Permalink
Breaking: Enrich memberOf with more granular options
Browse files Browse the repository at this point in the history
Allow group memberOf to listen for either member item changes, group change itself, both or none.
  • Loading branch information
querdenker2k authored Feb 12, 2023
1 parent b9a7076 commit b3cb4a4
Show file tree
Hide file tree
Showing 15 changed files with 278 additions and 53 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,14 @@ public void testPower(JRuleEvent event) {

## Example 35

Use case: Want to listen on all Item events of a group (without the groupstate must change)
Use case: Want to listen on all Item events of a group (without the groupstate must change).
Alternatively you could just listen to just Group changes or (real) Item changes

```java
@JRuleName("MemberOfUpdateTrigger")
@JRuleWhenItemReceivedUpdate(item = _MySwitchGroup.ITEM, memberOf = true)
@JRuleWhenItemReceivedUpdate(item = _MySwitchGroup.ITEM, memberOf = JRuleMemberOf.All)
//@JRuleWhenItemReceivedUpdate(item = _MySwitchGroup.ITEM, memberOf = JRuleMemberOf.Items)
//@JRuleWhenItemReceivedUpdate(item = _MySwitchGroup.ITEM, memberOf = JRuleMemberOf.Groups)
public synchronized void memberOfUpdateTrigger(JRuleItemEvent event) {
final String memberThatChangedStatus = event.getMemberName();
logInfo("Member that changed the status of the Group of switches: {}", memberThatChangedStatus);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.automation.jrule.exception.JRuleItemNotFoundException;
import org.openhab.automation.jrule.exception.JRuleRuntimeException;
import org.openhab.automation.jrule.internal.JRuleConfig;
import org.openhab.automation.jrule.internal.JRuleLog;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleChannelExecutionContext;
Expand All @@ -58,6 +59,7 @@
import org.openhab.automation.jrule.rules.JRuleCondition;
import org.openhab.automation.jrule.rules.JRuleDebounce;
import org.openhab.automation.jrule.rules.JRuleLogName;
import org.openhab.automation.jrule.rules.JRuleMemberOf;
import org.openhab.automation.jrule.rules.JRuleName;
import org.openhab.automation.jrule.rules.JRulePrecondition;
import org.openhab.automation.jrule.rules.JRuleTag;
Expand All @@ -71,9 +73,7 @@
import org.openhab.automation.jrule.rules.event.JRuleEvent;
import org.openhab.automation.jrule.things.JRuleThingStatus;
import org.openhab.core.events.AbstractEvent;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.*;
import org.openhab.core.items.events.ItemEvent;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.scheduler.CronScheduler;
Expand Down Expand Up @@ -278,8 +278,17 @@ private JRuleItemExecutionContext.JRuleAdditionalItemCheckData getAdditionalChec
} catch (ItemNotFoundException e) {
throw new IllegalStateException("this can never occur", e);
}
}).map(item -> new JRuleItemExecutionContext.JRuleAdditionalItemCheckData(item.getGroupNames()))
.orElse(new JRuleItemExecutionContext.JRuleAdditionalItemCheckData(List.of()));
}).map(item -> new JRuleItemExecutionContext.JRuleAdditionalItemCheckData(item.getType().equals(GroupItem.TYPE),
item.getGroupNames()))
.orElse(new JRuleItemExecutionContext.JRuleAdditionalItemCheckData(false, List.of()));
}

private Item getItem(String name) {
try {
return itemRegistry.getItem(name);
} catch (ItemNotFoundException e) {
throw new JRuleRuntimeException(String.format("cannot find item: %s", name), e);
}
}

public boolean matchPrecondition(JRuleExecutionContext jRuleExecutionContext) {
Expand Down Expand Up @@ -353,18 +362,14 @@ public synchronized void reset() {
}

public boolean watchingForItem(String itemName) {
List<String> belongingGroups = Optional.of(itemName).map(s -> {
try {
return itemRegistry.getItem(s);
} catch (ItemNotFoundException e) {
throw new IllegalStateException("this can never occur", e);
}
}).map(Item::getGroupNames).orElse(List.of());
List<String> parentGroups = Optional.of(itemName).map(this::getItem).map(Item::getGroupNames).orElse(List.of());

boolean b = this.contextList.stream().filter(context -> context instanceof JRuleItemExecutionContext)
.map(context -> ((JRuleItemExecutionContext) context))
.anyMatch(context -> (context.getItemName().equals(itemName) && !context.isMemberOf())
|| (belongingGroups.contains(context.getItemName()) && context.isMemberOf()));
.anyMatch(context -> (context.getItemName().equals(itemName)
&& context.getMemberOf() == JRuleMemberOf.None)
|| (parentGroups.contains(context.getItemName())
&& context.getMemberOf() != JRuleMemberOf.None));
logDebug("watching for item: '{}'? -> {}", itemName, b);
return b;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.openhab.automation.jrule.internal.handler.JRuleEventHandler;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRuleMemberOf;
import org.openhab.automation.jrule.rules.event.JRuleEvent;
import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
import org.openhab.core.events.AbstractEvent;
Expand All @@ -41,7 +42,7 @@ public class JRuleItemChangeExecutionContext extends JRuleItemExecutionContext {
private final Optional<JRuleConditionContext> previousConditionContext;

public JRuleItemChangeExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
String itemName, boolean memberOf, Optional<JRuleConditionContext> conditionContext,
String itemName, JRuleMemberOf memberOf, Optional<JRuleConditionContext> conditionContext,
Optional<JRuleConditionContext> previousConditionContext,
List<JRulePreconditionContext> preconditionContextList, Optional<String> from, Optional<String> to,
Duration timedLock) {
Expand All @@ -66,28 +67,41 @@ && matchCondition(((ItemStateChangedEvent) event).getItemState().toString(),
&& to.map(s -> ((ItemStateChangedEvent) event).getItemState().toString().equals(s)).orElse(true))) {
return false;
}
if (!isMemberOf() && ((ItemStateChangedEvent) event).getItemName().equals(this.getItemName())) {
if (getMemberOf() == JRuleMemberOf.None
&& ((ItemStateChangedEvent) event).getItemName().equals(this.getItemName())) {
return true;
}
if (isMemberOf() && checkData instanceof JRuleAdditionalItemCheckData
&& ((JRuleAdditionalItemCheckData) checkData).getBelongingGroups().contains(this.getItemName())) {
return true;
if (getMemberOf() != JRuleMemberOf.None && checkData instanceof JRuleAdditionalItemCheckData) {
JRuleAdditionalItemCheckData itemCheckData = (JRuleAdditionalItemCheckData) checkData;
switch (getMemberOf()) {
case All:
return itemCheckData.getBelongingGroups().contains(this.getItemName());
case Groups:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && itemCheckData.isGroup();
case Items:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && !itemCheckData.isGroup();
default:
return false;
}
}
return false;
}

@Override
public JRuleEvent createJRuleEvent(AbstractEvent event) {
final String itemName;
final String memberName;
if (isMemberOf()) {
if (getMemberOf() != JRuleMemberOf.None) {
itemName = this.getItemName();
memberName = ((ItemEvent) event).getItemName();
} else {
itemName = this.getItemName();
memberName = event instanceof GroupItemStateChangedEvent
? ((GroupItemStateChangedEvent) event).getMemberName()
: null;
}

return new JRuleItemEvent(this.getItemName(), memberName,
return new JRuleItemEvent(itemName, memberName,
JRuleEventHandler.get().toValue(((ItemStateChangedEvent) event).getItemState()),
JRuleEventHandler.get().toValue(((ItemStateChangedEvent) event).getOldItemState()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.commons.lang3.math.NumberUtils;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRuleCondition;
import org.openhab.automation.jrule.rules.JRuleMemberOf;
import org.openhab.core.library.types.QuantityType;

/**
Expand All @@ -30,11 +31,11 @@
*/
public abstract class JRuleItemExecutionContext extends JRuleExecutionContext {
protected final String itemName;
protected final boolean memberOf;
protected final JRuleMemberOf memberOf;
protected final Optional<JRuleConditionContext> conditionContext;

public JRuleItemExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method, String itemName,
boolean memberOf, Optional<JRuleConditionContext> conditionContext,
JRuleMemberOf memberOf, Optional<JRuleConditionContext> conditionContext,
List<JRulePreconditionContext> preconditionContextList, Duration timedLock) {
super(jRule, logName, loggingTags, method, preconditionContextList, timedLock);
this.itemName = itemName;
Expand All @@ -50,24 +51,30 @@ public boolean matchCondition(String state, String previousState) {
return conditionContext.map(c -> c.matchCondition(state)).orElse(true);
}

public boolean isMemberOf() {
public JRuleMemberOf getMemberOf() {
return memberOf;
}

public static class JRuleAdditionalItemCheckData extends JRuleAdditionalCheckData {
private final boolean group;
private final List<String> belongingGroups;

public JRuleAdditionalItemCheckData(List<String> belongingGroups) {
public JRuleAdditionalItemCheckData(boolean group, List<String> belongingGroups) {
this.group = group;
this.belongingGroups = belongingGroups;
}

public List<String> getBelongingGroups() {
return belongingGroups;
}

public boolean isGroup() {
return group;
}

@Override
public String toString() {
return "JRuleAdditionalItemCheckData{" + "belongingGroups=" + belongingGroups + '}';
return "JRuleAdditionalItemCheckData{" + "group=" + group + ", belongingGroups=" + belongingGroups + '}';
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.openhab.automation.jrule.internal.handler.JRuleEventHandler;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRuleMemberOf;
import org.openhab.automation.jrule.rules.event.JRuleEvent;
import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
import org.openhab.core.events.AbstractEvent;
Expand All @@ -38,7 +39,7 @@ public class JRuleItemReceivedCommandExecutionContext extends JRuleItemExecution
protected final Optional<String> command;

public JRuleItemReceivedCommandExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
String itemName, boolean memberOf, Optional<JRuleConditionContext> conditionContext,
String itemName, JRuleMemberOf memberOf, Optional<JRuleConditionContext> conditionContext,
List<JRulePreconditionContext> preconditionContextList, Optional<String> command, Duration timedLock) {
super(jRule, logName, loggingTags, method, itemName, memberOf, conditionContext, preconditionContextList,
timedLock);
Expand All @@ -53,26 +54,39 @@ && matchCondition(((ItemCommandEvent) event).getItemCommand().toString(), null)
return false;
}

if (!isMemberOf() && ((ItemCommandEvent) event).getItemName().equals(this.getItemName())) {
if (getMemberOf() == JRuleMemberOf.None
&& ((ItemCommandEvent) event).getItemName().equals(this.getItemName())) {
return true;
}
if (isMemberOf() && checkData instanceof JRuleAdditionalItemCheckData
&& ((JRuleAdditionalItemCheckData) checkData).getBelongingGroups().contains(this.getItemName())) {
return true;
if (getMemberOf() != JRuleMemberOf.None && checkData instanceof JRuleAdditionalItemCheckData) {
JRuleAdditionalItemCheckData itemCheckData = (JRuleAdditionalItemCheckData) checkData;
switch (getMemberOf()) {
case All:
return true;
case Groups:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && itemCheckData.isGroup();
case Items:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && !itemCheckData.isGroup();
default:
return false;
}
}
return false;
}

@Override
public JRuleEvent createJRuleEvent(AbstractEvent event) {
final String itemName;
final String memberName;
if (isMemberOf()) {
if (getMemberOf() != JRuleMemberOf.None) {
memberName = ((ItemEvent) event).getItemName();
itemName = ((ItemEvent) event).getItemName();
} else {
memberName = null;
itemName = this.getItemName();
}

return new JRuleItemEvent(this.getItemName(), memberName,
return new JRuleItemEvent(itemName, memberName,
JRuleEventHandler.get().toValue(((ItemCommandEvent) event).getItemCommand()), null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.openhab.automation.jrule.internal.handler.JRuleEventHandler;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRuleMemberOf;
import org.openhab.automation.jrule.rules.event.JRuleEvent;
import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
import org.openhab.core.events.AbstractEvent;
Expand All @@ -38,7 +39,7 @@ public class JRuleItemReceivedUpdateExecutionContext extends JRuleItemExecutionC
private final Optional<String> state;

public JRuleItemReceivedUpdateExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
String itemName, boolean memberOf, Optional<JRuleConditionContext> conditionContext,
String itemName, JRuleMemberOf memberOf, Optional<JRuleConditionContext> conditionContext,
List<JRulePreconditionContext> preconditionContextList, Optional<String> state, Duration timedLock) {
super(jRule, logName, loggingTags, method, itemName, memberOf, conditionContext, preconditionContextList,
timedLock);
Expand All @@ -52,26 +53,38 @@ && matchCondition(((ItemStateEvent) event).getItemState().toString(), null)
&& state.map(s -> ((ItemStateEvent) event).getItemState().toString().equals(s)).orElse(true))) {
return false;
}
if (!isMemberOf() && ((ItemStateEvent) event).getItemName().equals(this.getItemName())) {
if (getMemberOf() == JRuleMemberOf.None && ((ItemStateEvent) event).getItemName().equals(this.getItemName())) {
return true;
}
if (isMemberOf() && checkData instanceof JRuleAdditionalItemCheckData
&& ((JRuleAdditionalItemCheckData) checkData).getBelongingGroups().contains(this.getItemName())) {
return true;
if (getMemberOf() != JRuleMemberOf.None && checkData instanceof JRuleAdditionalItemCheckData) {
JRuleAdditionalItemCheckData itemCheckData = (JRuleAdditionalItemCheckData) checkData;
switch (getMemberOf()) {
case All:
return true;
case Groups:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && itemCheckData.isGroup();
case Items:
return itemCheckData.getBelongingGroups().contains(this.getItemName()) && !itemCheckData.isGroup();
default:
return false;
}
}
return false;
}

@Override
public JRuleEvent createJRuleEvent(AbstractEvent event) {
final String itemName;
final String memberName;
if (isMemberOf()) {
if (getMemberOf() != JRuleMemberOf.None) {
memberName = ((ItemEvent) event).getItemName();
itemName = ((ItemEvent) event).getItemName();
} else {
memberName = null;
itemName = this.getItemName();
}

return new JRuleItemEvent(this.getItemName(), memberName,
return new JRuleItemEvent(itemName, memberName,
JRuleEventHandler.get().toValue(((ItemStateEvent) event).getItemState()), null);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright (c) 2010-2022 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.jrule.rules;

/**
* The {@link JRuleMemberOf}
*
* @author Robert Delbrück
*/
public enum JRuleMemberOf {
/**
* Not using memberOf
*/
None,
/**
* Listen on all child items
*/
All,
/**
* Just listen on child groups
*/
Groups,
/**
* Just listen on concrete Items (without groups)
*/
Items
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

String to() default "";

boolean memberOf() default false;
JRuleMemberOf memberOf() default JRuleMemberOf.None;

JRuleCondition condition() default @JRuleCondition;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

String command() default "";

boolean memberOf() default false;
JRuleMemberOf memberOf() default JRuleMemberOf.None;

JRuleCondition condition() default @JRuleCondition;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

String state() default "";

boolean memberOf() default false;
JRuleMemberOf memberOf() default JRuleMemberOf.None;

JRuleCondition condition() default @JRuleCondition;
}
Loading

0 comments on commit b3cb4a4

Please sign in to comment.