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

Add event for channel #52

Merged
merged 2 commits into from
Oct 14, 2022
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
@@ -0,0 +1,44 @@
/**
* 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.internal.engine;

import java.lang.reflect.Method;

import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRulePrecondition;

/**
* The {@link JRuleChannelExecutionContext}
*
* @author Robert Delbrück - Initial contribution
*/
public class JRuleChannelExecutionContext extends JRuleExecutionContext {
private final String channel;
private final String event;

public JRuleChannelExecutionContext(JRule jRule, String logName, String[] loggingTags, String ruleName,
Method method, boolean eventParameterPresent, JRulePrecondition[] preconditions, String channel,
String event) {
super(jRule, logName, loggingTags, ruleName, method, eventParameterPresent, preconditions);
this.channel = channel;
this.event = event;
}

public String getChannel() {
return channel;
}

public String getEvent() {
return this.event;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ public class JRuleEngine implements PropertyChangeListener {

private final Map<String, List<JRule>> itemToRules = new HashMap<>();

private final Map<String, List<JRuleExecutionContext>> itemToExecutionContexts = new HashMap<>();
private final Map<String, List<JRuleItemExecutionContext>> itemToExecutionContexts = new HashMap<>();

private final Map<String, List<JRuleExecutionContext>> channelToExecutionContexts = new HashMap<>();
private final Map<String, List<JRuleChannelExecutionContext>> channelToExecutionContexts = new HashMap<>();

private final Set<String> itemNames = new HashSet<>();
private final Logger logger = LoggerFactory.getLogger(JRuleEngine.class);
Expand Down Expand Up @@ -154,8 +154,8 @@ private synchronized void clearTimers() {
timers.clear();
}

private void logInfo(String message, Object... paramteres) {
JRuleLog.info(logger, LOG_NAME_ENGINE, message, paramteres);
private void logInfo(String message, Object... parameters) {
JRuleLog.info(logger, LOG_NAME_ENGINE, message, parameters);
}

private void logDebug(String message, Object... parameters) {
Expand Down Expand Up @@ -227,12 +227,10 @@ public void add(JRule jRule) {
JRuleLog.debug(logger, logName, "Got item class: {}", itemClass);
JRuleLog.info(logger, logName, "Validating JRule item: {} trigger: {} ", jRuleWhen.item(),
jRuleWhen.trigger());
addExecutionContext(jRule, logName, loggingTags, itemClass, jRuleName.value(), jRuleWhen.trigger(),
jRuleWhen.from(), jRuleWhen.to(), jRuleWhen.update(), jRuleWhen.item(), method,
jRuleEventPresent, getDoubleFromAnnotation(jRuleWhen.lt()),
getDoubleFromAnnotation(jRuleWhen.lte()), getDoubleFromAnnotation(jRuleWhen.gt()),
getDoubleFromAnnotation(jRuleWhen.gte()), getStringFromAnnotation(jRuleWhen.eq()),
getStringFromAnnotation(jRuleWhen.neq()), preconditions);
addItemExecutionContext(jRule, logName, loggingTags, jRuleName.value(), jRuleWhen.trigger(),
jRuleWhen.update(), jRuleWhen.item(), method, jRuleEventPresent,
getStringFromAnnotation(jRuleWhen.eq()), getStringFromAnnotation(jRuleWhen.neq()),
preconditions);
itemNames.add(jRuleWhen.item());

ruleLoadingStatistics.addItemStateTrigger();
Expand All @@ -249,9 +247,8 @@ jRuleEventPresent, getDoubleFromAnnotation(jRuleWhen.lt()),
// JRuleWhen for a channel
JRuleLog.info(logger, logName, "Validating JRule channel: {} trigger: {} ", jRuleWhen.channel(),
jRuleWhen.trigger());
addChannelExecutionContext(jRule, logName, loggingTags, jRuleWhen.channel(), jRuleName.value(),
method, jRuleEventPresent, getStringFromAnnotation(jRuleWhen.eq()),
getStringFromAnnotation(jRuleWhen.neq()), preconditions);
addChannelExecutionContext(jRule, logName, loggingTags, jRuleWhen.channel(), jRuleWhen.event(),
jRuleName.value(), method, jRuleEventPresent, preconditions);
ruleLoadingStatistics.addChannelTrigger();
}
}
Expand Down Expand Up @@ -323,8 +320,8 @@ private synchronized void addTimedExecution(JRule jRule, String logName, String[
timers.add(future);
JRuleLog.info(logger, logName, "Scheduling timer for rule: {} hours: {} minutes: {} seconds: {} cron: {}",
jRuleWhen.hours(), jRuleWhen.minutes(), jRuleWhen.seconds(), jRuleWhen.cron());
JRuleExecutionContext executionContext = new JRuleExecutionContext(jRule, logName, loggingTags, method,
jRuleName, jRuleEventPresent, preconditions);
JRuleTimedExecutionContext executionContext = new JRuleTimedExecutionContext(jRule, logName, loggingTags,
method, jRuleName, jRuleEventPresent, preconditions);
Consumer<Void> consumer = t -> {
try {
invokeRule(executionContext, jRuleEventPresent ? new JRuleEvent("") : null);
Expand All @@ -342,27 +339,25 @@ private synchronized void addTimedExecution(JRule jRule, String logName, String[
}
}

private void addExecutionContext(JRule jRule, String logName, String[] loggingTags, String itemClass,
String ruleName, String trigger, String from, String to, String update, String itemName, Method method,
boolean eventParameterPresent, Double lt, Double lte, Double gt, Double gte, String eq, String neq,
JRulePrecondition[] preconditions) {
List<JRuleExecutionContext> contextList = itemToExecutionContexts.computeIfAbsent(itemName,
private void addItemExecutionContext(JRule jRule, String logName, String[] loggingTags, String ruleName,
String trigger, String update, String itemName, Method method, boolean eventParameterPresent, String eq,
String neq, JRulePrecondition[] preconditions) {
List<JRuleItemExecutionContext> contextList = itemToExecutionContexts.computeIfAbsent(itemName,
k -> new ArrayList<>());
final JRuleExecutionContext context = new JRuleExecutionContext(jRule, logName, loggingTags, trigger, from, to,
update, ruleName, itemClass, itemName, method, eventParameterPresent, lt, lte, gt, gte, eq, neq,
preconditions);
final JRuleItemExecutionContext context = new JRuleItemExecutionContext(jRule, logName, loggingTags, trigger,
null, null, update, ruleName, null, null, method, eventParameterPresent, null, null, null, null, eq,
neq, preconditions);
JRuleLog.debug(logger, logName, "ItemContextList add context: {}", context);
contextList.add(context);
}

private void addChannelExecutionContext(JRule jRule, String logName, String[] loggingTags, String channel,
String ruleName, Method method, boolean eventParameterPresent, String eq, String neq,
String event, String ruleName, Method method, boolean eventParameterPresent,
JRulePrecondition[] preconditions) {
List<JRuleExecutionContext> contextList = channelToExecutionContexts.computeIfAbsent(channel,
List<JRuleChannelExecutionContext> contextList = channelToExecutionContexts.computeIfAbsent(channel,
k -> new ArrayList<>());
final JRuleExecutionContext context = new JRuleExecutionContext(jRule, logName, loggingTags, null, null, null,
null, ruleName, null, null, method, eventParameterPresent, null, null, null, null, eq, neq,
preconditions);
final JRuleChannelExecutionContext context = new JRuleChannelExecutionContext(jRule, logName, loggingTags,
ruleName, method, eventParameterPresent, preconditions, channel, event);
JRuleLog.debug(logger, logName, "ChannelContextList add context: {}", context);
contextList.add(context);
}
Expand All @@ -380,19 +375,23 @@ public void propertyChange(PropertyChangeEvent evt) {
}

private void handleChannelEvent(ChannelTriggeredEvent channelEvent) {
List<JRuleExecutionContext> executionContexts = channelToExecutionContexts
List<JRuleChannelExecutionContext> executionContexts = channelToExecutionContexts
.get(channelEvent.getChannel().toString());
if (executionContexts == null || executionContexts.isEmpty()) {
logDebug("No execution context for channelEvent: {}", channelEvent);
return;
}
executionContexts.forEach(context -> invokeWhenMatchParameters(context,
new JRuleEvent(channelEvent.getEvent(), channelEvent.getChannel().toString())));
executionContexts.stream().filter(context -> context.getChannel().equals(channelEvent.getChannel().toString()))
.filter(context -> context.getEvent().equals(channelEvent.getEvent())).forEach(context -> {
JRuleLog.debug(logger, context.getLogName(), "invoke when context matches");
invokeRule(context, new JRuleEvent(channelEvent.getEvent(), channelEvent.getChannel().toString(),
channelEvent.getEvent()));
});
}

private void handleEventUpdate(Event event) {
final String itemName = getItemNameFromEvent(event);
final List<JRuleExecutionContext> executionContexts = itemToExecutionContexts.get(itemName);
final List<JRuleItemExecutionContext> executionContexts = itemToExecutionContexts.get(itemName);
if (executionContexts == null || executionContexts.isEmpty()) {
logDebug("No execution context for changeEvent ");
return;
Expand Down Expand Up @@ -474,7 +473,7 @@ private Boolean evaluateComparatorParameters(Double gt, Double gte, Double lt, D
return null;
}

private void invokeWhenMatchParameters(JRuleExecutionContext context, @NonNull JRuleEvent jRuleEvent) {
private void invokeWhenMatchParameters(JRuleItemExecutionContext context, @NonNull JRuleEvent jRuleEvent) {
JRuleLog.debug(logger, context.getLogName(), "invoke when context matches");

if (context.isComparatorOperation()) {
Expand Down Expand Up @@ -516,7 +515,7 @@ private String getItemNameFromEvent(Event event) {
}

private void invokeRule(JRuleExecutionContext context, JRuleEvent event) {
Object invokationResult = config.isExecutorsEnabled() ? invokeRuleInSeparateThread(context, event)
Object invocationResult = config.isExecutorsEnabled() ? invokeRuleInSeparateThread(context, event)
: invokeRuleSingleThread(context, event);
}

Expand Down Expand Up @@ -549,12 +548,12 @@ private Object invokeRuleInternal(JRuleExecutionContext context, JRuleEvent even
MDC.put(MDC_KEY_RULE, context.getRuleName());
Arrays.stream(context.getLoggingTags()).forEach(s -> MDC.put(s, s));
return context.isEventParameterPresent() ? method.invoke(rule, event) : method.invoke(rule);
} catch (IllegalAccessException | IllegalArgumentException | SecurityException e) {
JRuleLog.error(logger, context.getRuleName(), "Error {}", e);
} catch (InvocationTargetException e) {
Throwable ex = e.getCause() != null ? e.getCause() : null;
JRuleLog.error(logger, context.getRuleName(), "Error message: {}", ex.getMessage());
JRuleLog.error(logger, context.getRuleName(), "Error Stacktrace: {}", getStackTraceAsString(ex));
} catch (Exception e) {
JRuleLog.error(logger, context.getRuleName(), "Error {}", e);
} finally {
Arrays.stream(context.getLoggingTags()).forEach(MDC::remove);
MDC.remove(MDC_KEY_RULE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,12 @@
*
* @author Joseph (Seaside) Hagberg - Initial contribution
*/
public class JRuleExecutionContext {
private static final String FROM_PREFIX = " from ";
private static final String TO_PREFIX = " to ";
private static final String SPACE = " ";
public abstract class JRuleExecutionContext {
private final String logName;
private final String trigger;
private final String ruleName;
private final String itemClass;
private final String itemName;
private final String from;
private final String to;
private final Double gt;
private final Double gte;
private final Double lt;
private final Double lte;
private final String eq;
private final String neq;
private final String update;
private final JRule jRule;
private final Method method;
private final boolean eventParameterPresent;
protected final String ruleName;
protected final JRule jRule;
protected final Method method;
protected final boolean eventParameterPresent;
private final String[] loggingTags;

public JRulePrecondition[] getPreconditions() {
Expand All @@ -51,111 +36,17 @@ public JRulePrecondition[] getPreconditions() {

private final JRulePrecondition[] preconditions;

public JRuleExecutionContext(JRule jRule, String logName, String[] loggingTags, String trigger, String from,
String to, String update, String ruleName, String itemClass, String itemName, Method method,
boolean eventParameterPresent, Double lt, Double lte, Double gt, Double gte, String eq, String neq,
JRulePrecondition[] preconditions) {
public JRuleExecutionContext(JRule jRule, String logName, String[] loggingTags, String ruleName, Method method,
boolean eventParameterPresent, JRulePrecondition[] preconditions) {
this.logName = logName;
this.loggingTags = loggingTags;
this.gt = gt;
this.gte = gte;
this.lt = lt;
this.lte = lte;
this.eq = eq;
this.neq = neq;
this.jRule = jRule;
this.trigger = trigger;
this.from = from;
this.to = to;
this.update = update;
this.ruleName = ruleName;
this.itemClass = itemClass;
this.itemName = itemName;
this.method = method;
this.eventParameterPresent = eventParameterPresent;
this.preconditions = preconditions;
}

public JRuleExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method, String ruleName,
boolean jRuleEventPresent, JRulePrecondition[] preconditions) {
this(jRule, logName, loggingTags, null, null, null, null, ruleName, null, null, method, jRuleEventPresent, null,
null, null, null, null, null, preconditions);
}

@Override
public String toString() {
return "JRuleExecutionContext [trigger=" + trigger + ", ruleName=" + ruleName + ", itemClass=" + itemClass
+ ", itemName=" + itemName + ", from=" + from + ", to=" + to + ", gt=" + gt + ", gte=" + gte + ", lt="
+ lt + ", lte=" + lte + ", eq=" + eq + ", update=" + update + ", jRule=" + jRule + ", method=" + method
+ ", eventParameterPresent=" + eventParameterPresent + "]";
}

public String getTrigger() {
return trigger;
}

public String getTriggerFullString() {
if (from != null && !from.isEmpty() && to != null && !to.isEmpty()) {
return buildFromToString(trigger, from, to);
}
if (from != null && !from.isEmpty()) {
return buildFromToString(trigger, from, null);
}
if (to != null && !to.isEmpty()) {
return buildFromToString(trigger, null, to);
}
if (update != null && !update.isEmpty()) {
return buildUpdateString(trigger, update);
}
return trigger;
}

private String buildUpdateString(String trigger, String update) {
final StringBuilder builder = new StringBuilder();
builder.append(trigger);
builder.append(SPACE);
builder.append(update);
return builder.toString();
}

private String buildFromToString(String trigger, String from, String to) {
final StringBuilder builder = new StringBuilder();
builder.append(trigger);
if (from != null) {
builder.append(FROM_PREFIX);
builder.append(from);
}
if (to != null) {
builder.append(TO_PREFIX);
builder.append(to);
}
return builder.toString();
}

public String getItemClass() {
return itemClass;
}

public String getItemName() {
return itemName;
}

public String getFrom() {
return from;
}

public String getTo() {
return to;
}

public String getUpdate() {
return update;
}

public JRule getjRule() {
return jRule;
}

public String getRuleName() {
return ruleName;
}
Expand All @@ -172,38 +63,6 @@ public boolean isEventParameterPresent() {
return eventParameterPresent;
}

public Double getGt() {
return gt;
}

public Double getGte() {
return gte;
}

public Double getLt() {
return lt;
}

public Double getLte() {
return lte;
}

public String getEq() {
return eq;
}

public String getNeq() {
return neq;
}

public boolean isNumericOperation() {
return lte != null || lt != null || gt != null || gte != null;
}

public boolean isComparatorOperation() {
return lte != null || lt != null || gt != null || gte != null || eq != null || neq != null;
}

public String getLogName() {
return logName;
}
Expand Down
Loading