names) {
- this.from = from;
- this.to = to;
- this.names = names;
- }
-
- /**
- * @param dateTime {@link ZonedDateTime} instance
- * @return The field time or date value from {@code dateTime}
- */
- abstract int getValue(ZonedDateTime dateTime);
-
- /**
- * @param dateTime Initial {@link ZonedDateTime} instance to use
- * @param value to set for this field in {@code dateTime}
- * @return {@link ZonedDateTime} with {@code value} set for this field and all smaller fields cleared
- */
- abstract ZonedDateTime setValue(ZonedDateTime dateTime, int value);
-
- /**
- * Handle when this field overflows and the next higher field should be incremented
- *
- * @param dateTime Initial {@link ZonedDateTime} instance to use
- * @return {@link ZonedDateTime} with the next greater field incremented and all smaller fields cleared
- */
- abstract ZonedDateTime overflow(ZonedDateTime dateTime);
- }
-
- private final String expr;
- private final SimpleField secondField;
- private final SimpleField minuteField;
- private final SimpleField hourField;
- private final DayOfWeekField dayOfWeekField;
- private final SimpleField monthField;
- private final DayOfMonthField dayOfMonthField;
-
- public JRuleCronExpression(final String expr) {
- this(expr, true);
- }
-
- public JRuleCronExpression(final String expr, final boolean withSeconds) {
- if (expr == null) {
- throw new IllegalArgumentException("expr is null"); //$NON-NLS-1$
- }
-
- this.expr = expr;
-
- final int expectedParts = withSeconds ? 6 : 5;
- final String[] parts = expr.split("\\s+"); //$NON-NLS-1$
- if (parts.length != expectedParts) {
- throw new IllegalArgumentException(String.format("Invalid cron expression [%s], expected %s field, got %s",
- expr, expectedParts, parts.length));
- }
-
- int ix = withSeconds ? 1 : 0;
- this.secondField = new SimpleField(CronFieldType.SECOND, withSeconds ? parts[0] : "0");
- this.minuteField = new SimpleField(CronFieldType.MINUTE, parts[ix++]);
- this.hourField = new SimpleField(CronFieldType.HOUR, parts[ix++]);
- this.dayOfMonthField = new DayOfMonthField(parts[ix++]);
- this.monthField = new SimpleField(CronFieldType.MONTH, parts[ix++]);
- this.dayOfWeekField = new DayOfWeekField(parts[ix++]);
- }
-
- public static JRuleCronExpression create(final String expr) {
- return new JRuleCronExpression(expr, true);
- }
-
- public static JRuleCronExpression createWithoutSeconds(final String expr) {
- return new JRuleCronExpression(expr, false);
- }
-
- public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime) {
- // will search for the next time within the next 4 years. If there is no
- // time matching, an InvalidArgumentException will be thrown (it is very
- // likely that the cron expression is invalid, like the February 30th).
- return nextTimeAfter(afterTime, afterTime.plusYears(4));
- }
-
- public LocalDateTime nextLocalDateTimeAfter(LocalDateTime dateTime) {
- return nextTimeAfter(ZonedDateTime.of(dateTime, ZoneId.systemDefault())).toLocalDateTime();
- }
-
- public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime, long durationInMillis) {
- // will search for the next time within the next durationInMillis
- // millisecond. Be aware that the duration is specified in millis,
- // but in fact the limit is checked on a day-to-day basis.
- return nextTimeAfter(afterTime, afterTime.plus(Duration.ofMillis(durationInMillis)));
- }
-
- public ZonedDateTime nextTimeAfter(ZonedDateTime afterTime, ZonedDateTime dateTimeBarrier) {
- ZonedDateTime[] nextDateTime = { afterTime.plusSeconds(1).withNano(0) };
-
- while (true) {
- checkIfDateTimeBarrierIsReached(nextDateTime[0], dateTimeBarrier);
- if (!monthField.nextMatch(nextDateTime)) {
- continue;
- }
- if (!findDay(nextDateTime, dateTimeBarrier)) {
- continue;
- }
- if (!hourField.nextMatch(nextDateTime)) {
- continue;
- }
- if (!minuteField.nextMatch(nextDateTime)) {
- continue;
- }
- if (!secondField.nextMatch(nextDateTime)) {
- continue;
- }
-
- checkIfDateTimeBarrierIsReached(nextDateTime[0], dateTimeBarrier);
- return nextDateTime[0];
- }
- }
-
- /**
- * Find the next match for the day field.
- *
- * This is handled different than all other fields because there are two ways to describe the day and it is easier
- * to handle them together in the same method.
- *
- * @param dateTime Initial {@link ZonedDateTime} instance to start from
- * @param dateTimeBarrier At which point stop searching for next execution time
- * @return {@code true} if a match was found for this field or {@code false} if the field overflowed
- * @see {@link SimpleField#nextMatch(ZonedDateTime[])}
- */
- private boolean findDay(ZonedDateTime[] dateTime, ZonedDateTime dateTimeBarrier) {
- int month = dateTime[0].getMonthValue();
-
- while (!(dayOfMonthField.matches(dateTime[0].toLocalDate())
- && dayOfWeekField.matches(dateTime[0].toLocalDate()))) {
- dateTime[0] = dateTime[0].plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
- if (dateTime[0].getMonthValue() != month) {
- return false;
- }
- }
- return true;
- }
-
- private static void checkIfDateTimeBarrierIsReached(ZonedDateTime nextTime, ZonedDateTime dateTimeBarrier) {
- if (nextTime.isAfter(dateTimeBarrier)) {
- throw new IllegalArgumentException(
- "No next execution time could be determined that is before the limit of " + dateTimeBarrier);
- }
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "<" + expr + ">";
- }
-
- static class FieldPart implements Comparable {
- private int from = -1, to = -1, increment = -1;
- private String modifier, incrementModifier;
-
- @Override
- public int compareTo(FieldPart o) {
- return Integer.compare(from, o.from);
- }
- }
-
- abstract static class BasicField {
- private static final Pattern CRON_FIELD_REGEXP = Pattern.compile(
- "(?: # start of group 1\n"
- + " (?:(?\\*)|(?\\?)|(?L)) # global flag (L, ?, *)\n"
- + " | (?[0-9]{1,2}|[a-z]{3,3}) # or start number or symbol\n"
- + " (?: # start of group 2\n"
- + " (?L|W) # modifier (L,W)\n"
- + " | -(?[0-9]{1,2}|[a-z]{3,3}) # or end nummer or symbol (in range)\n"
- + " )? # end of group 2\n"
- + ") # end of group 1\n"
- + "(?:(?/|\\#)(?[0-9]{1,7}))? # increment and increment modifier (/ or \\#)\n",
- Pattern.CASE_INSENSITIVE | Pattern.COMMENTS);
-
- final CronFieldType fieldType;
- final List parts = new ArrayList<>();
-
- private BasicField(CronFieldType fieldType, String fieldExpr) {
- this.fieldType = fieldType;
- parse(fieldExpr);
- }
-
- private void parse(String fieldExpr) { // NOSONAR
- String[] rangeParts = fieldExpr.split(",");
- for (String rangePart : rangeParts) {
- Matcher m = CRON_FIELD_REGEXP.matcher(rangePart);
- if (!m.matches()) {
- throw new IllegalArgumentException(
- "Invalid cron field '" + rangePart + "' for field [" + fieldType + "]");
- }
- String startNummer = m.group("start");
- String modifier = m.group("mod");
- String sluttNummer = m.group("end");
- String incrementModifier = m.group("incmod");
- String increment = m.group("inc");
-
- FieldPart part = new FieldPart();
- part.increment = 999;
- if (startNummer != null) {
- part.from = mapValue(startNummer);
- part.modifier = modifier;
- if (sluttNummer != null) {
- part.to = mapValue(sluttNummer);
- part.increment = 1;
- } else if (increment != null) {
- part.to = fieldType.to;
- } else {
- part.to = part.from;
- }
- } else if (m.group("all") != null) {
- part.from = fieldType.from;
- part.to = fieldType.to;
- part.increment = 1;
- } else if (m.group("ignore") != null) {
- part.modifier = m.group("ignore");
- } else if (m.group("last") != null) {
- part.modifier = m.group("last");
- } else {
- throw new IllegalArgumentException("Invalid cron part: " + rangePart);
- }
-
- if (increment != null) {
- part.incrementModifier = incrementModifier;
- part.increment = Integer.parseInt(increment);
- }
-
- validateRange(part);
- validatePart(part);
- parts.add(part);
- }
-
- Collections.sort(parts);
- }
-
- protected void validatePart(FieldPart part) {
- if (part.modifier != null) {
- throw new IllegalArgumentException(String.format("Invalid modifier [%s]", part.modifier));
- } else if (part.incrementModifier != null && !"/".equals(part.incrementModifier)) {
- throw new IllegalArgumentException(
- String.format("Invalid increment modifier [%s]", part.incrementModifier));
- }
- }
-
- private void validateRange(FieldPart part) {
- if ((part.from != -1 && part.from < fieldType.from) || (part.to != -1 && part.to > fieldType.to)) {
- throw new IllegalArgumentException(String.format("Invalid interval [%s-%s], must be %s<=_<=%s",
- part.from, part.to, fieldType.from, fieldType.to));
- } else if (part.from != -1 && part.to != -1 && part.from > part.to) {
- throw new IllegalArgumentException(String.format(
- "Invalid interval [%s-%s]. Rolling periods are not supported (ex. 5-1, only 1-5) since this won't give a deterministic result. Must be %s<=_<=%s",
- part.from, part.to, fieldType.from, fieldType.to));
- }
- }
-
- protected int mapValue(String value) {
- int idx;
- if (fieldType.names != null
- && (idx = fieldType.names.indexOf(value.toUpperCase(Locale.getDefault()))) >= 0) {
- return idx + fieldType.from;
- }
- return Integer.parseInt(value);
- }
-
- protected boolean matches(int val, FieldPart part) {
- return val >= part.from && val <= part.to && (val - part.from) % part.increment == 0;
- }
-
- protected int nextMatch(int val, FieldPart part) {
- if (val > part.to) {
- return -1;
- }
- int nextPotential = Math.max(val, part.from);
- if (part.increment == 1 || nextPotential == part.from) {
- return nextPotential;
- }
-
- int remainder = ((nextPotential - part.from) % part.increment);
- if (remainder != 0) {
- nextPotential += part.increment - remainder;
- }
-
- return nextPotential <= part.to ? nextPotential : -1;
- }
- }
-
- static class SimpleField extends BasicField {
- SimpleField(CronFieldType fieldType, String fieldExpr) {
- super(fieldType, fieldExpr);
- }
-
- public boolean matches(int val) {
- if (val >= fieldType.from && val <= fieldType.to) {
- for (FieldPart part : parts) {
- if (matches(val, part)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Find the next match for this field. If a match cannot be found force an overflow and increase the next
- * greatest field.
- *
- * @param dateTime {@link ZonedDateTime} array so the reference can be modified
- * @return {@code true} if a match was found for this field or {@code false} if the field overflowed
- */
- protected boolean nextMatch(ZonedDateTime[] dateTime) {
- int value = fieldType.getValue(dateTime[0]);
-
- for (FieldPart part : parts) {
- int nextMatch = nextMatch(value, part);
- if (nextMatch > -1) {
- if (nextMatch != value) {
- dateTime[0] = fieldType.setValue(dateTime[0], nextMatch);
- }
- return true;
- }
- }
-
- dateTime[0] = fieldType.overflow(dateTime[0]);
- return false;
- }
- }
-
- static class DayOfWeekField extends BasicField {
-
- DayOfWeekField(String fieldExpr) {
- super(CronFieldType.DAY_OF_WEEK, fieldExpr);
- }
-
- boolean matches(LocalDate dato) {
- for (FieldPart part : parts) {
- if ("L".equals(part.modifier)) {
- YearMonth ym = YearMonth.of(dato.getYear(), dato.getMonth().getValue());
- return dato.getDayOfWeek() == DayOfWeek.of(part.from)
- && dato.getDayOfMonth() > (ym.lengthOfMonth() - 7);
- } else if ("#".equals(part.incrementModifier)) {
- if (dato.getDayOfWeek() == DayOfWeek.of(part.from)) {
- int num = dato.getDayOfMonth() / 7;
- return part.increment == (dato.getDayOfMonth() % 7 == 0 ? num : num + 1);
- }
- return false;
- } else if (matches(dato.getDayOfWeek().getValue(), part)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected int mapValue(String value) {
- // Use 1-7 for weedays, but 0 will also represent sunday (linux practice)
- return "0".equals(value) ? 7 : super.mapValue(value);
- }
-
- @Override
- protected boolean matches(int val, FieldPart part) {
- return "?".equals(part.modifier) || super.matches(val, part);
- }
-
- @Override
- protected void validatePart(FieldPart part) {
- if (part.modifier != null && Arrays.asList("L", "?").indexOf(part.modifier) == -1) {
- throw new IllegalArgumentException(String.format("Invalid modifier [%s]", part.modifier));
- } else if (part.incrementModifier != null
- && Arrays.asList("/", "#").indexOf(part.incrementModifier) == -1) {
- throw new IllegalArgumentException(
- String.format("Invalid increment modifier [%s]", part.incrementModifier));
- }
- }
- }
-
- static class DayOfMonthField extends BasicField {
- DayOfMonthField(String fieldExpr) {
- super(CronFieldType.DAY_OF_MONTH, fieldExpr);
- }
-
- boolean matches(LocalDate dato) {
- for (FieldPart part : parts) {
- if ("L".equals(part.modifier)) {
- YearMonth ym = YearMonth.of(dato.getYear(), dato.getMonth().getValue());
- return dato.getDayOfMonth() == (ym.lengthOfMonth() - (part.from == -1 ? 0 : part.from));
- } else if ("W".equals(part.modifier)) {
- if (dato.getDayOfWeek().getValue() <= 5) {
- if (dato.getDayOfMonth() == part.from) {
- return true;
- } else if (dato.getDayOfWeek().getValue() == 5) {
- return dato.plusDays(1).getDayOfMonth() == part.from;
- } else if (dato.getDayOfWeek().getValue() == 1) {
- return dato.minusDays(1).getDayOfMonth() == part.from;
- }
- }
- } else if (matches(dato.getDayOfMonth(), part)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- protected void validatePart(FieldPart part) {
- if (part.modifier != null && Arrays.asList("L", "W", "?").indexOf(part.modifier) == -1) {
- throw new IllegalArgumentException(String.format("Invalid modifier [%s]", part.modifier));
- } else if (part.incrementModifier != null && !"/".equals(part.incrementModifier)) {
- throw new IllegalArgumentException(
- String.format("Invalid increment modifier [%s]", part.incrementModifier));
- }
- }
-
- @Override
- protected boolean matches(int val, FieldPart part) {
- return "?".equals(part.modifier) || super.matches(val, part);
- }
- }
-}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java
index 6601e77a..aff0c390 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/JRuleEngine.java
@@ -14,120 +14,82 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.lang.reflect.Parameter;
-import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
+import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.automation.jrule.exception.JRuleItemNotFoundException;
import org.openhab.automation.jrule.internal.JRuleConfig;
-import org.openhab.automation.jrule.internal.JRuleConstants;
import org.openhab.automation.jrule.internal.JRuleLog;
-import org.openhab.automation.jrule.internal.JRuleUtil;
-import org.openhab.automation.jrule.internal.cron.JRuleCronExpression;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleChannelExecutionContext;
-import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleContextValueComparators;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemChangeExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedCommandExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedUpdateExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRulePreconditionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimeTimerExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedCronExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedExecutionContext;
+import org.openhab.automation.jrule.internal.engine.timer.TimerExecutor;
import org.openhab.automation.jrule.internal.events.JRuleEventSubscriber;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRuleEvent;
+import org.openhab.automation.jrule.rules.JRuleCondition;
import org.openhab.automation.jrule.rules.JRuleLogName;
import org.openhab.automation.jrule.rules.JRuleName;
import org.openhab.automation.jrule.rules.JRulePrecondition;
import org.openhab.automation.jrule.rules.JRuleTag;
-import org.openhab.automation.jrule.rules.JRuleWhen;
-import org.openhab.core.common.ThreadPoolManager;
-import org.openhab.core.events.Event;
+import org.openhab.automation.jrule.rules.JRuleWhenChannelTrigger;
+import org.openhab.automation.jrule.rules.JRuleWhenCronTrigger;
+import org.openhab.automation.jrule.rules.JRuleWhenItemChange;
+import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand;
+import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate;
+import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger;
+import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger;
+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.events.GroupItemStateChangedEvent;
-import org.openhab.core.items.events.ItemCommandEvent;
-import org.openhab.core.items.events.ItemEvent;
-import org.openhab.core.items.events.ItemStateChangedEvent;
-import org.openhab.core.items.events.ItemStateEvent;
import org.openhab.core.library.types.QuantityType;
-import org.openhab.core.thing.events.ChannelTriggeredEvent;
-import org.openhab.core.thing.events.ThingStatusInfoChangedEvent;
+import org.openhab.core.scheduler.CronScheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
/**
- * The {@link JRuleConstants} class defines common constants, which are
- * used across the Java Rule automation.
+ * The {@link JRuleEngine}
*
- * @author Joseph (Seaside) Hagberg - Initial contribution
+ * @author Robert Delbrück
*/
public class JRuleEngine implements PropertyChangeListener {
-
- private static final String MDC_KEY_RULE = "rule";
- private static final int AWAIT_TERMINATION_THREAD_SECONDS = 2;
- private static final String RECEIVED_COMMAND = "received command";
- private static final String RECEIVED_COMMAND_APPEND = RECEIVED_COMMAND + " ";
-
- private static final String CHANGED_FROM_TO_PATTERN = "Changed from %1$s to %2$s";
- private static final String CHANGED_FROM = "Changed from ";
- private static final String CHANGED_TO = "Changed to ";
- private static final String CHANGED = "Changed";
-
- private static final String RECEIVED_UPDATE = "received update";
- private static final String RECEIVED_UPDATE_APPEND = RECEIVED_UPDATE + " ";
-
- private static final String LOG_NAME_ENGINE = "JRuleEngine";
private static final String[] EMPTY_LOG_TAGS = new String[0];
-
- private static volatile JRuleEngine instance;
-
- private ThreadPoolExecutor ruleExecutorService;
-
- private JRuleConfig config;
-
- private final Map> itemToRules = new HashMap<>();
-
- private final Map> itemToExecutionContexts = new HashMap<>();
-
- private final Map> channelToExecutionContexts = new HashMap<>();
- private final Map> thingToExecutionContexts = new HashMap<>();
-
- private final Set itemNames = new HashSet<>();
+ private static final int AWAIT_TERMINATION_THREAD_SECONDS = 2;
+ private List contextList = new ArrayList<>();
+ private TimerExecutor timerExecutor = new TimerExecutor(this);
+ private static final String MDC_KEY_RULE = "rule";
+ protected ThreadPoolExecutor ruleExecutorService;
+ protected JRuleConfig config;
private final Logger logger = LoggerFactory.getLogger(JRuleEngine.class);
- private final Set> timers = new HashSet<>();
- protected final ScheduledExecutorService scheduler = ThreadPoolManager
- .getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON);
- private ItemRegistry itemRegistry;
-
- private JRuleLoadingStatistics ruleLoadingStatistics;
-
- private JRuleEngine() {
- ruleLoadingStatistics = new JRuleLoadingStatistics(null);
- }
+ protected ItemRegistry itemRegistry;
+ protected JRuleLoadingStatistics ruleLoadingStatistics;
+ private static volatile JRuleEngine instance;
public static JRuleEngine get() {
if (instance == null) {
@@ -140,567 +102,284 @@ public static JRuleEngine get() {
return instance;
}
- public Set getItemNames() {
- return itemNames;
- }
-
- public Set getChannelNames() {
- return channelToExecutionContexts.keySet();
- }
-
- public Set getThingUIDs() {
- return thingToExecutionContexts.keySet();
- }
-
- public synchronized void reset() {
- itemNames.clear();
- itemToExecutionContexts.clear();
- channelToExecutionContexts.clear();
- itemToRules.clear();
- thingToExecutionContexts.clear();
- clearTimers();
-
- ruleLoadingStatistics = new JRuleLoadingStatistics(ruleLoadingStatistics);
- }
-
- private synchronized void clearTimers() {
- timers.forEach(timer -> timer.cancel(true));
- timers.clear();
- }
-
- private void logInfo(String message, Object... parameters) {
- JRuleLog.info(logger, LOG_NAME_ENGINE, message, parameters);
- }
-
- private void logDebug(String message, Object... parameters) {
- JRuleLog.debug(logger, LOG_NAME_ENGINE, message, parameters);
- }
-
- private void logWarn(String message, Object... parameters) {
- JRuleLog.warn(logger, LOG_NAME_ENGINE, message, parameters);
- }
-
- private void logError(String message, Object... parameters) {
- JRuleLog.error(logger, LOG_NAME_ENGINE, message, parameters);
+ private JRuleEngine() {
+ this.ruleLoadingStatistics = new JRuleLoadingStatistics(null);
}
public void add(JRule jRule) {
logDebug("Adding rule: {}", jRule);
- Class> clazz = jRule.getClass();
- for (Method method : clazz.getDeclaredMethods()) {
- logDebug("Adding rule method: {}", method.getName());
- if (!method.isAnnotationPresent(JRuleName.class)) {
- logDebug("Rule method ignored since JRuleName annotation is missing: {}", method.getName());
- continue;
- }
- // Check if method is public, else execution will fail at runtime
- boolean isPublic = (method.getModifiers() & Modifier.PUBLIC) != 0;
- if (!isPublic) {
- logWarn("Rule method ignored since method isn't public: {}", method.getName());
- continue;
- }
-
- if (method.getAnnotationsByType(JRuleWhen.class).length == 0) {
- logWarn("Rule ignored since JWhens annotation is missing");
- logWarn("Rule JWhen present: {}", method.isAnnotationPresent(JRuleWhen.class));
- final JRuleWhen[] jRuleWhens = method.getAnnotationsByType(JRuleWhen.class);
- logDebug("Got jrule whens size: {}", jRuleWhens.length);
- continue;
- }
- final JRuleName jRuleName = method.getDeclaredAnnotation(JRuleName.class);
- final JRuleLogName jRuleLogName = method.isAnnotationPresent(JRuleLogName.class)
- ? method.getDeclaredAnnotation(JRuleLogName.class)
- : null;
-
- final JRulePrecondition[] preconditions = method.getAnnotationsByType(JRulePrecondition.class);
-
- final JRuleWhen[] jRuleWhens = method.getAnnotationsByType(JRuleWhen.class);
- logDebug("Got jrule whens size: {}", jRuleWhens.length);
- final Parameter[] parameters = method.getParameters();
- boolean jRuleEventPresent = Arrays.stream(parameters)
- .anyMatch(param -> (param.getType().equals(JRuleEvent.class)));
-
- String logName = (jRuleLogName != null && !jRuleLogName.value().isEmpty()) ? jRuleLogName.value()
- : jRuleName.value();
-
- final JRuleTag jRuleTags = method.isAnnotationPresent(JRuleTag.class)
- ? method.getDeclaredAnnotation(JRuleTag.class)
- : null;
- final String[] loggingTags = jRuleTags != null ? jRuleTags.value() : EMPTY_LOG_TAGS;
- // TODO: Do validation on syntax in when annotations
- // Loop for other ORs
- for (JRuleWhen jRuleWhen : jRuleWhens) {
- JRuleLog.debug(logger, logName, "Processing jRule when: {}", jRuleWhen);
- if (!jRuleWhen.item().isEmpty()) {
- // JRuleWhen for an item
-
- String itemPackage = config.getGeneratedItemPackage();
- String prefix = config.getGeneratedItemPrefix();
- String itemClass = String.format("%s.%s%s", itemPackage, prefix, jRuleWhen.item());
-
- JRuleLog.debug(logger, logName, "Got item class: {}", itemClass);
- JRuleLog.info(logger, logName, "Validating JRule item: {} trigger: {} ", jRuleWhen.item(),
- jRuleWhen.trigger());
- addItemExecutionContext(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);
- itemNames.add(jRuleWhen.item());
-
- ruleLoadingStatistics.addItemStateTrigger();
- } else if (jRuleWhen.hours() != -1 || jRuleWhen.minutes() != -1 || jRuleWhen.seconds() != -1
- || !jRuleWhen.cron().isEmpty()) {
- // JRuleWhen for a time trigger
- JRuleLog.info(logger, logName,
- "Validating JRule: Scheduling timer for hours: {} minutes: {} seconds: {} cron: {}",
- jRuleWhen.hours(), jRuleWhen.minutes(), jRuleWhen.seconds(), jRuleWhen.cron());
- addTimedExecution(jRule, logName, loggingTags, jRuleName.value(), jRuleWhen, method,
- jRuleEventPresent, preconditions);
- ruleLoadingStatistics.addTimedTrigger();
- } else if (!jRuleWhen.channel().isEmpty()) {
- // 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);
- ruleLoadingStatistics.addChannelTrigger();
- } else if (!jRuleWhen.thing().isEmpty()) {
- // JRuleWhen for a thing
- JRuleLog.info(logger, logName, "Validating JRule thing: {} trigger: {} ", jRuleWhen.thing(),
- jRuleWhen.trigger());
- if (JRuleUtil.isNotEmpty(jRuleWhen.trigger())) {
- addThingExecutionContext(jRule, logName, loggingTags, jRuleWhen.thing(), jRuleName.value(),
- jRuleWhen.trigger(), jRuleWhen.from(), jRuleWhen.to(), method, jRuleEventPresent,
- preconditions);
- ruleLoadingStatistics.addThingTrigger();
- } else {
- JRuleLog.warn(logger, logName, "Ignoring rule as no trigger is specified");
- }
- }
- }
- if (jRuleWhens.length > 0) {
- ruleLoadingStatistics.addRuleMethod();
- }
-
- }
ruleLoadingStatistics.addRuleClass();
- }
-
- private Double getDoubleFromAnnotation(double d) {
- if (d == Double.MIN_VALUE) {
- return null;
- }
- return d;
- }
-
- private String getStringFromAnnotation(String s) {
- return s.isEmpty() ? null : s;
- }
-
- private CompletableFuture createTimer(String logName, String cronExpressionStr) {
- try {
- final JRuleCronExpression cronExpression = new JRuleCronExpression(cronExpressionStr);
- final ZonedDateTime nextTimeAfter = cronExpression.nextTimeAfter(ZonedDateTime.now());
- Date futureTime = Date.from(nextTimeAfter.toInstant());
- return createTimer(logName, futureTime);
- } catch (IllegalArgumentException x) {
- JRuleLog.error(logger, logName, "Failed to parse cron expression for cron: {} message: {}",
- cronExpressionStr, x.getMessage());
- return null;
- }
- }
-
- private CompletableFuture createTimer(String logName, int hours, int minutes, int seconds) {
- Calendar calFuture = Calendar.getInstance();
- Calendar now = Calendar.getInstance();
- calFuture.set(Calendar.HOUR_OF_DAY, hours == -1 ? 0 : hours);
- calFuture.set(Calendar.MINUTE, minutes == -1 ? 0 : minutes);
- calFuture.set(Calendar.SECOND, seconds == -1 ? 0 : seconds);
- calFuture.set(Calendar.MILLISECOND, 0);
- calFuture.set(Calendar.HOUR_OF_DAY, hours);
- if (calFuture.before(now)) {
- if (hours != -1) {
- calFuture.add(Calendar.DAY_OF_MONTH, 1);
- } else if (minutes != -1) {
- calFuture.add(Calendar.HOUR, 1);
- } else if (seconds != -1) {
- calFuture.add(Calendar.MINUTE, 1);
- }
- }
- return createTimer(logName, calFuture.getTime());
- }
-
- private CompletableFuture createTimer(String logName, Date date) {
- long initialDelay = new Date(date.getTime() - System.currentTimeMillis()).getTime();
- JRuleLog.debug(logger, logName, "Schedule cron: {} initialDelay: {}", date, initialDelay);
- Executor delayedExecutor = CompletableFuture.delayedExecutor(initialDelay, TimeUnit.MILLISECONDS, scheduler);
- return CompletableFuture.supplyAsync(() -> null, delayedExecutor);
- }
-
- private synchronized void addTimedExecution(JRule jRule, String logName, String[] loggingTags, String jRuleName,
- JRuleWhen jRuleWhen, Method method, boolean jRuleEventPresent, JRulePrecondition[] preconditions) {
- CompletableFuture future = (!jRuleWhen.cron().isEmpty()) ? createTimer(logName, jRuleWhen.cron())
- : createTimer(logName, jRuleWhen.hours(), jRuleWhen.minutes(), jRuleWhen.seconds());
- if (future != null) {
- // If ie cron expression fails to parse, null will be returned
- timers.add(future);
- JRuleLog.info(logger, logName, "Scheduling timer for rule: {} hours: {} minutes: {} seconds: {} cron: {}",
- jRuleWhen.hours(), jRuleWhen.minutes(), jRuleWhen.seconds(), jRuleWhen.cron());
- JRuleTimedExecutionContext executionContext = new JRuleTimedExecutionContext(jRule, logName, loggingTags,
- method, jRuleName, jRuleEventPresent, preconditions);
- Consumer consumer = t -> {
- try {
- invokeRule(executionContext, jRuleEventPresent ? new JRuleEvent("") : null);
- } finally {
- timers.remove(future);
- }
- };
- future.thenAccept(consumer).thenAccept(s -> {
- JRuleLog.info(logger, logName, "Timer has finished");
- addTimedExecution(jRule, logName, loggingTags, jRuleName, jRuleWhen, method, jRuleEventPresent,
- preconditions);
- });
- } else {
- JRuleLog.error(logger, logName, "Failed to add timed execution - check previous log statements");
+ for (Method method : jRule.getClass().getDeclaredMethods()) {
+ this.add(method, jRule);
}
}
- private void addItemExecutionContext(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 contextList = itemToExecutionContexts.computeIfAbsent(itemName,
- k -> new ArrayList<>());
- final JRuleItemExecutionContext context = new JRuleItemExecutionContext(jRule, logName, loggingTags, trigger,
- from, to, update, ruleName, itemClass, itemName, method, eventParameterPresent, lt, lte, gt, gte, 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,
- JRulePrecondition[] preconditions) {
- List contextList = channelToExecutionContexts.computeIfAbsent(channel,
- k -> new ArrayList<>());
- final JRuleChannelExecutionContext context = new JRuleChannelExecutionContext(jRule, logName, loggingTags,
- ruleName, method, eventParameterPresent, preconditions, channel, eq, neq);
- JRuleLog.debug(logger, logName, "ChannelContextList add context: {}", context);
- contextList.add(context);
- }
-
- private void addThingExecutionContext(JRule jRule, String logName, String[] loggingTags, String thing,
- String ruleName, String trigger, String from, String to, Method method, boolean eventParameterPresent,
- JRulePrecondition[] preconditions) {
- List contextList = thingToExecutionContexts.computeIfAbsent(thing,
- k -> new ArrayList<>());
- final JRuleThingExecutionContext context = new JRuleThingExecutionContext(jRule, logName, loggingTags, trigger,
- from, to, ruleName, thing, method, eventParameterPresent, preconditions);
- JRuleLog.debug(logger, logName, "ThingContextList add context: {}", context);
- contextList.add(context);
- }
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_ITEM_EVENT)) {
- logDebug("Property change item event! : {}", ((Event) evt.getNewValue()).getTopic());
- handleItemEvent((Event) evt.getNewValue());
- } else if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_CHANNEL_EVENT)) {
- logDebug("Channel event! : {}", ((Event) evt.getNewValue()).getTopic());
- handleChannelEvent((ChannelTriggeredEvent) evt.getNewValue());
- } else if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT)) {
- logDebug("Thing status event! : {}", ((Event) evt.getNewValue()).getTopic());
- handleThingStatusChangedEvent((ThingStatusInfoChangedEvent) evt.getNewValue());
- }
- }
+ private void add(Method method, JRule jRule) {
+ logDebug("Adding rule method: {}", method.getName());
- private void handleThingStatusChangedEvent(ThingStatusInfoChangedEvent thingStatusChangedEvent) {
- List thingExecutionContexts = thingToExecutionContexts
- .get(thingStatusChangedEvent.getThingUID().toString());
- List executionContextsWildcard = thingToExecutionContexts
- .get(JRuleThingExecutionContext.ANY_THING_UID);
- List executionContexts = new ArrayList<>();
- if (executionContextsWildcard != null) {
- executionContexts.addAll(executionContextsWildcard);
- }
- if (thingExecutionContexts != null) {
- executionContexts.addAll(thingExecutionContexts);
+ if (!method.isAnnotationPresent(JRuleName.class)) {
+ logWarn("Skipping method {} on class {} since JRuleName annotation is missing", method.getName(),
+ jRule.getClass().getName());
+ return;
}
- if (executionContexts == null || executionContexts.isEmpty()) {
- logDebug("No execution context for thingStatusEvent: {}", thingStatusChangedEvent);
+ // Check if method is public, else execution will fail at runtime
+ boolean isPublic = (method.getModifiers() & Modifier.PUBLIC) != 0;
+ if (!isPublic) {
+ logWarn("Skipping non-public method {} on class {}", method.getName(), jRule.getClass().getName());
return;
}
- final Set triggerValues = new HashSet<>(5);
- String newStatus = thingStatusChangedEvent.getStatusInfo().getStatus().toString();
- String oldStatus = thingStatusChangedEvent.getOldStatusInfo().getStatus().toString();
-
- if (JRuleUtil.isNotEmpty(oldStatus) && JRuleUtil.isNotEmpty(newStatus)) {
- triggerValues.add(String.format(CHANGED_FROM_TO_PATTERN, oldStatus, newStatus));
- triggerValues.add(CHANGED_FROM.concat(oldStatus));
- triggerValues.add(CHANGED_TO.concat(newStatus));
- triggerValues.add(CHANGED);
- } else if (JRuleUtil.isNotEmpty(oldStatus)) {
- triggerValues.add(CHANGED_FROM.concat(oldStatus));
- triggerValues.add(CHANGED);
- } else if (JRuleUtil.isNotEmpty(newStatus)) {
- triggerValues.add(CHANGED_TO.concat(newStatus));
- triggerValues.add(CHANGED);
- } else {
- triggerValues.add(CHANGED);
+ // Check if method is has none or a single parameter
+ if (method.getParameterCount() > 1) {
+ logWarn("Skipping method {} on class {}. Rule methods should have none or a single parameter",
+ method.getName(), jRule.getClass().getName());
+ return;
}
- if (!triggerValues.isEmpty()) {
- executionContexts.stream().filter(context -> triggerValues.contains(context.getTriggerFullString()))
- .forEach(context -> invokeWhenMatchParameters(context,
- new JRuleEvent(newStatus, thingStatusChangedEvent.getThingUID().toString(), newStatus)));
- } else {
- logDebug("Execution ignored, no trigger values for thing: {}", thingStatusChangedEvent.getThingUID());
+ final String logName = Optional.ofNullable(method.getDeclaredAnnotation(JRuleLogName.class))
+ .map(JRuleLogName::value).orElse(method.getDeclaredAnnotation(JRuleName.class).value());
+
+ List jRulePreconditionContexts = Arrays
+ .stream(method.getAnnotationsByType(JRulePrecondition.class)).map(jRulePrecondition -> {
+ JRuleCondition jRuleCondition = jRulePrecondition.condition();
+ return new JRulePreconditionContext(jRulePrecondition.item(),
+ Optional.of(jRuleCondition.lt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.lte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.eq()).filter(StringUtils::isNotEmpty),
+ Optional.of(jRuleCondition.neq()).filter(StringUtils::isNotEmpty));
+ }).collect(Collectors.toList());
+
+ final String[] loggingTags = Optional.ofNullable(method.getDeclaredAnnotation(JRuleTag.class))
+ .map(JRuleTag::value).orElse(EMPTY_LOG_TAGS);
+
+ ruleLoadingStatistics.addRuleMethod();
+ AtomicBoolean addedToContext = new AtomicBoolean(false);
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenItemReceivedUpdate.class)).forEach(jRuleWhen -> {
+ JRuleCondition jRuleCondition = jRuleWhen.condition();
+ addToContext(new JRuleItemReceivedUpdateExecutionContext(jRule, logName, loggingTags, method,
+ jRuleWhen.item(), Optional.of(jRuleCondition.lt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.lte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.eq()).filter(StringUtils::isNotEmpty),
+ Optional.of(jRuleCondition.neq()).filter(StringUtils::isNotEmpty), jRulePreconditionContexts,
+ Optional.of(jRuleWhen.state()).filter(StringUtils::isNotEmpty)));
+ ruleLoadingStatistics.addItemStateTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenItemReceivedCommand.class)).forEach(jRuleWhen -> {
+ JRuleCondition jRuleCondition = jRuleWhen.condition();
+ addToContext(new JRuleItemReceivedCommandExecutionContext(jRule, logName, loggingTags, method,
+ jRuleWhen.item(), Optional.of(jRuleCondition.lt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.lte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.eq()).filter(StringUtils::isNotEmpty),
+ Optional.of(jRuleCondition.neq()).filter(StringUtils::isNotEmpty), jRulePreconditionContexts,
+ Optional.of(jRuleWhen.command()).filter(StringUtils::isNotEmpty)));
+ ruleLoadingStatistics.addItemStateTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenItemChange.class)).forEach(jRuleWhen -> {
+ JRuleCondition jRuleCondition = jRuleWhen.condition();
+ addToContext(new JRuleItemChangeExecutionContext(jRule, logName, loggingTags, method, jRuleWhen.item(),
+ Optional.of(jRuleCondition.lt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.lte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gt()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.gte()).filter(aDouble -> aDouble != Double.MIN_VALUE),
+ Optional.of(jRuleCondition.eq()).filter(StringUtils::isNotEmpty),
+ Optional.of(jRuleCondition.neq()).filter(StringUtils::isNotEmpty), jRulePreconditionContexts,
+ Optional.of(jRuleWhen.from()).filter(StringUtils::isNotEmpty),
+ Optional.of(jRuleWhen.to()).filter(StringUtils::isNotEmpty)));
+ ruleLoadingStatistics.addItemStateTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenChannelTrigger.class)).forEach(jRuleWhen -> {
+ addToContext(
+ new JRuleChannelExecutionContext(jRule, logName, loggingTags, method, jRulePreconditionContexts,
+ jRuleWhen.channel(), Optional.of(jRuleWhen.event()).filter(StringUtils::isNotEmpty)));
+ ruleLoadingStatistics.addChannelTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenCronTrigger.class)).forEach(jRuleWhen -> {
+ addToContext(new JRuleTimedCronExecutionContext(jRule, logName, loggingTags, method,
+ jRulePreconditionContexts, jRuleWhen.cron()));
+ ruleLoadingStatistics.addTimedTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenTimeTrigger.class)).forEach(jRuleWhen -> {
+ addToContext(new JRuleTimeTimerExecutionContext(jRule, logName, loggingTags, method,
+ jRulePreconditionContexts, Optional.of(jRuleWhen.hours()).filter(i -> i != -1),
+ Optional.of(jRuleWhen.minutes()).filter(i -> i != -1),
+ Optional.of(jRuleWhen.seconds()).filter(i -> i != -1)));
+ ruleLoadingStatistics.addTimedTrigger();
+ addedToContext.set(true);
+ });
+
+ Arrays.stream(method.getAnnotationsByType(JRuleWhenThingTrigger.class)).forEach(jRuleWhen -> {
+ ruleLoadingStatistics.addThingTrigger();
+ addToContext(new JRuleThingExecutionContext(jRule, logName, loggingTags, method,
+ Optional.of(jRuleWhen.thing()).filter(StringUtils::isNotEmpty).filter(s -> !s.equals("*")),
+ Optional.of(jRuleWhen.from()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN),
+ Optional.of(jRuleWhen.to()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN),
+ jRulePreconditionContexts));
+ addedToContext.set(true);
+ });
+
+ // Check if any rule triggers are present
+ if (!addedToContext.get()) {
+ logWarn("Skipping rule method {} on class {} with no JRuleWhenXXX annotation triggers", method.getName(),
+ jRule.getClass().getName());
}
}
- private void handleChannelEvent(ChannelTriggeredEvent channelEvent) {
- List executionContexts = channelToExecutionContexts
- .get(channelEvent.getChannel().toString());
- if (executionContexts == null || executionContexts.isEmpty()) {
- logDebug("No execution context for channelEvent: {}", channelEvent);
- return;
+ private boolean addToContext(JRuleExecutionContext context) {
+ logDebug("add to context: {}", context);
+ if (context instanceof JRuleTimedExecutionContext) {
+ timerExecutor.add(context);
+ } else {
+ contextList.add(context);
}
- executionContexts.stream().filter(context -> context.getChannel().equals(channelEvent.getChannel().toString()))
- .filter(context -> matchesChannelEvent(context, channelEvent)).forEach(context -> {
- JRuleLog.debug(logger, context.getLogName(), "invoke when context matches");
- invokeRule(context, new JRuleEvent(channelEvent.getEvent(), channelEvent.getChannel().toString(),
- channelEvent.getEvent()));
- });
+ return true;
}
- private boolean matchesChannelEvent(JRuleChannelExecutionContext context, ChannelTriggeredEvent event) {
- return (context.getEq() != null && context.getEq().equals(event.getEvent()))
- || (context.getNeq() != null && !context.getNeq().equals(event.getEvent()))
- || context.getEq() == null && context.getNeq() == null;
+ public void fire(AbstractEvent event) {
+ contextList.stream().filter(context -> context.match(event)).filter(this::matchPrecondition)
+ .forEach(context -> invokeRule(context, context.createJRuleEvent(event)));
}
- private void handleItemEvent(Event event) {
- final String itemName = getItemNameFromEvent(event);
- final List executionContexts = itemToExecutionContexts.get(itemName);
- if (executionContexts == null || executionContexts.isEmpty()) {
- logDebug("No execution context for changeEvent ");
- return;
- }
- final String type = event.getType();
-
- final Set triggerValues = new HashSet<>(5);
- final String stringNewValue;
- final String stringOldValue;
- String memberName = null;
- if (event instanceof GroupItemStateChangedEvent) {
- memberName = ((GroupItemStateChangedEvent) event).getMemberName();
- }
-
- if (event instanceof ItemStateEvent) {
- stringNewValue = ((ItemStateEvent) event).getItemState().toFullString();
- stringOldValue = null;
- triggerValues.add(RECEIVED_UPDATE);
- triggerValues.add(RECEIVED_UPDATE_APPEND.concat(stringNewValue));
- } else if (event instanceof ItemCommandEvent) {
- stringNewValue = ((ItemCommandEvent) event).getItemCommand().toFullString();
- stringOldValue = null;
- triggerValues.add(RECEIVED_COMMAND);
- triggerValues.add(RECEIVED_COMMAND_APPEND.concat(stringNewValue));
- } else if (event instanceof ItemStateChangedEvent) {
- stringNewValue = ((ItemStateChangedEvent) event).getItemState().toFullString();
- stringOldValue = ((ItemStateChangedEvent) event).getOldItemState().toFullString();
-
- if (JRuleUtil.isNotEmpty(stringOldValue) && JRuleUtil.isNotEmpty(stringNewValue)) {
- triggerValues.add(String.format(CHANGED_FROM_TO_PATTERN, stringOldValue, stringNewValue));
- triggerValues.add(CHANGED_FROM.concat(stringOldValue));
- triggerValues.add(CHANGED_TO.concat(stringNewValue));
- triggerValues.add(CHANGED);
+ private boolean matchPrecondition(JRuleExecutionContext jRuleExecutionContext) {
+ return jRuleExecutionContext.getPreconditionContextList().stream().allMatch(context -> {
+ final Item item;
+ try {
+ item = itemRegistry.getItem(context.getItem());
+ } catch (ItemNotFoundException e) {
+ throw new JRuleItemNotFoundException("Cannot find item for precondition", e);
}
+ final String state = item.getState().toString();
+ if (context.getEq().isPresent() && context.getEq().filter(state::equals).isEmpty()) {
+ logDebug("precondition mismatch: {} = {}", state, context.getEq());
+ return false;
+ }
+ if (context.getNeq().isPresent() && context.getNeq().filter(ref -> !state.equals(ref)).isEmpty()) {
+ logDebug("precondition mismatch: {} != {}", state, context.getEq());
+ return false;
+ }
+ if (context.getLt().isPresent()
+ && context.getLt().filter(ref -> QuantityType.valueOf(state).doubleValue() < ref).isEmpty()) {
+ logDebug("precondition mismatch: {} < {}", state, context.getEq());
+ return false;
+ }
+ if (context.getLte().isPresent()
+ && context.getLte().filter(ref -> QuantityType.valueOf(state).doubleValue() <= ref).isEmpty()) {
+ logDebug("precondition mismatch: {} <= {}", state, context.getEq());
+ return false;
+ }
+ if (context.getGt().isPresent()
+ && context.getGt().filter(ref -> QuantityType.valueOf(state).doubleValue() > ref).isEmpty()) {
+ logDebug("precondition mismatch: {} > {}", state, context.getEq());
+ return false;
+ }
+ if (context.getGte().isPresent()
+ && context.getGte().filter(ref -> QuantityType.valueOf(state).doubleValue() >= ref).isEmpty()) {
+ logDebug("precondition mismatch: {} >= {}", state, context.getEq());
+ return false;
+ }
+ return true;
+ });
+ }
- logDebug("newValue: {} oldValue: {} type: {}", stringNewValue, stringOldValue, type);
- logDebug("Invoked execution contexts: {}", executionContexts.size());
- logDebug("Execution topic Topic: {}", event.getTopic());
- logDebug("Execution topic Payload: {}", event.getPayload());
- logDebug("Execution topic Source: {}", event.getSource());
- logDebug("Execution topic Type: {}", event.getType());
- logDebug("Execution eventToString: {}", event);
- } else {
- logDebug("Unhandled case: {}", event.getClass());
- return;
- }
-
- if (!triggerValues.isEmpty()) {
- String member = memberName == null ? "" : memberName;
- executionContexts.stream().filter(context -> triggerValues.contains(context.getTriggerFullString()))
- .forEach(context -> invokeWhenMatchParameters(context,
- new JRuleEvent(stringNewValue, stringOldValue, itemName, member)));
- } else {
- logDebug("Execution ignored, no trigger values for itemName: {} eventType: {}", itemName, type);
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_ITEM_EVENT)
+ || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_CHANNEL_EVENT)
+ || evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT)) {
+ fire((AbstractEvent) evt.getNewValue());
}
}
- private Boolean evaluateComparatorParameters(Double gt, Double gte, Double lt, Double lte, String eq, String neq,
- String stateValue) {
- if (eq != null) {
- return stateValue.equals(eq);
- } else if (neq != null) {
- return !stateValue.equals(neq);
- } else {
- // valueAsDouble may be null if unparseable ("NULL" or "UNDEF")
- Double valueAsDouble = getValueAsDouble(stateValue);
- if (valueAsDouble == null) {
- return null;
- } else if (gt != null) {
- return valueAsDouble > gt;
- } else if (gte != null) {
- return valueAsDouble >= gte;
- } else if (lt != null) {
- return valueAsDouble < lt;
- } else if (lte != null) {
- return valueAsDouble <= lte;
+ public void dispose() {
+ if (config.isExecutorsEnabled()) {
+ ruleExecutorService.shutdownNow();
+ try {
+ ruleExecutorService.awaitTermination(AWAIT_TERMINATION_THREAD_SECONDS, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ logWarn("Not all rules ran to completion before rule engine shutdown", e);
}
}
- return null;
}
- private void invokeWhenMatchParameters(JRuleExecutionContext context, @NonNull JRuleEvent jRuleEvent) {
- JRuleLog.debug(logger, context.getLogName(), "invoke when context matches");
-
- if (context instanceof JRuleContextValueComparators) {
- JRuleContextValueComparators comparators = (JRuleContextValueComparators) context;
- if (comparators.hasCompartorsSet()) {
+ public synchronized void reset() {
+ contextList.clear();
+ timerExecutor.clear();
- final Boolean evalCompare = evaluateComparatorParameters(comparators.getGt(), comparators.getGte(),
- comparators.getLt(), comparators.getLte(), comparators.getEq(), comparators.getNeq(),
- jRuleEvent.getState().getValue());
- if (evalCompare == null) {
- logError("Failed to compare values for context: {} event: {}", context, jRuleEvent);
- return;
- }
- if (!evalCompare) {
- logDebug("Not invoking rule since comparator compare is false context: {} event: {}", context,
- jRuleEvent);
- return;
- }
- }
- }
- invokeRule(context, jRuleEvent);
+ ruleLoadingStatistics = new JRuleLoadingStatistics(ruleLoadingStatistics);
}
- private Double getValueAsDouble(String value) {
- double parseDouble = 0;
- if (value == null || value.isEmpty()) {
- return null;
- }
- try {
- parseDouble = QuantityType.valueOf(value).doubleValue();
- } catch (Exception x) {
- logError("Failed to parse value: {} as double", value, x);
- return null;
- }
- return parseDouble;
+ public boolean watchingForItem(String itemName) {
+ boolean b = this.contextList.stream().filter(context -> context instanceof JRuleItemExecutionContext)
+ .map(context -> ((JRuleItemExecutionContext) context))
+ .anyMatch(context -> context.getItemName().equals(itemName));
+ logDebug("watching for item: '{}'? -> {}", itemName, b);
+ return b;
}
- @Nullable
- private String getItemNameFromEvent(Event event) {
- if (event instanceof ItemEvent) {
- return ((ItemEvent) event).getItemName();
- }
- return null;
+ public boolean watchingForChannel(String channel) {
+ boolean b = this.contextList.stream().filter(context -> context instanceof JRuleChannelExecutionContext)
+ .map(context -> ((JRuleChannelExecutionContext) context))
+ .anyMatch(context -> context.getChannel().equals(channel));
+ logDebug("watching for channel: '{}'? -> {}", channel, b);
+ return b;
}
- private void invokeRule(JRuleExecutionContext context, JRuleEvent event) {
- Object invocationResult = config.isExecutorsEnabled() ? invokeRuleInSeparateThread(context, event)
- : invokeRuleSingleThread(context, event);
+ public boolean watchingForThing(String thing) {
+ boolean b = this.contextList.stream().filter(context -> context instanceof JRuleThingExecutionContext)
+ .map(context -> ((JRuleThingExecutionContext) context))
+ .anyMatch(context -> context.getThing().map(s -> s.equals(thing)).orElse(true));
+ logDebug("watching for thing: '{}'? -> {}", thing, b);
+ return b;
}
- private Object invokeRuleInSeparateThread(JRuleExecutionContext context, JRuleEvent event) {
- return ruleExecutorService.submit(() -> invokeRuleInternal(context, event));
+ public void setCronScheduler(CronScheduler cronScheduler) {
+ this.timerExecutor.setCronScheduler(cronScheduler);
}
- private synchronized Object invokeRuleSingleThread(JRuleExecutionContext context, JRuleEvent event) {
- return invokeRuleInternal(context, event);
+ public JRuleLoadingStatistics getRuleLoadingStatistics() {
+ return this.ruleLoadingStatistics;
}
- private Object invokeRuleInternal(JRuleExecutionContext context, JRuleEvent event) {
- JRuleLog.debug(logger, context.getLogName(), "Invoking rule for context: {}", context);
-
- // Check preconditions
- boolean preconditionsSatisified = true;
- JRulePrecondition[] preconditions = context.getPreconditions();
- if (preconditions != null) {
- for (JRulePrecondition precondition : preconditions) {
- preconditionsSatisified &= evaluatePrecondition(context, precondition);
- }
- }
-
- if (preconditionsSatisified) {
- final JRule rule = context.getJrule();
- final Method method = context.getMethod();
- rule.setRuleLogName(context.getLogName());
- try {
- JRuleLog.debug(logger, context.getRuleName(), "setting mdc tags: {}", context.getLoggingTags());
- 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 (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);
- }
- } else {
- JRuleLog.debug(logger, context.getLogName(), "Preconditions failed for context: {}", context);
- }
- return null;
+ protected void logInfo(String message, Object... parameters) {
+ JRuleLog.info(logger, JRuleEngine.class.getSimpleName(), message, parameters);
}
- private boolean evaluatePrecondition(JRuleExecutionContext context, JRulePrecondition precondition) {
- try {
- final Item item = itemRegistry.getItem(precondition.item());
- final String state = item.getState().toString();
- Boolean evalComparatorParams = evaluateComparatorParameters(getDoubleFromAnnotation(precondition.gt()),
- getDoubleFromAnnotation(precondition.gte()), getDoubleFromAnnotation(precondition.lt()),
- getDoubleFromAnnotation(precondition.lte()), getStringFromAnnotation(precondition.eq()),
- getStringFromAnnotation(precondition.neq()), state);
- if (evalComparatorParams == null) {
- logError("Failed to evaluate precondition context: {} precondition: {} state: {}", context,
- toString(precondition), state);
- }
- return evalComparatorParams == null || evalComparatorParams;
- } catch (ItemNotFoundException e) {
- JRuleLog.error(logger, context.getRuleName(), "Precondition item not found: {}", precondition.item());
- }
- return true; // For now
+ protected void logDebug(String message, Object... parameters) {
+ JRuleLog.debug(logger, JRuleEngine.class.getSimpleName(), message, parameters);
}
- private String toString(JRulePrecondition precondition) {
- return "item=" + precondition.item() + " eq=" + precondition.eq() + " neq=" + precondition.neq() + " gt="
- + precondition.gt() + " gte=" + precondition.gte() + " lt=" + precondition.lt() + " lte="
- + precondition.lte();
+ protected void logWarn(String message, Object... parameters) {
+ JRuleLog.warn(logger, JRuleEngine.class.getSimpleName(), message, parameters);
}
- private synchronized static String getStackTraceAsString(Throwable throwable) {
- try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
- throwable.printStackTrace(pw);
- return sw.toString();
- } catch (IOException ioe) {
- throw new IllegalStateException(ioe);
- }
+ protected void logError(String message, Object... parameters) {
+ JRuleLog.error(logger, JRuleEngine.class.getSimpleName(), message, parameters);
}
public void setConfig(@NonNull JRuleConfig config) {
this.config = config;
}
+ public void setItemRegistry(ItemRegistry itemRegistry) {
+ this.itemRegistry = itemRegistry;
+ }
+
public void initialize() {
if (config.isExecutorsEnabled()) {
logInfo("Initializing Java Rule Engine with Separate Thread Executors min: {} max: {}",
@@ -725,22 +404,39 @@ public Thread newThread(Runnable runnable) {
}
}
- public void dispose() {
+ public void invokeRule(JRuleExecutionContext context, JRuleEvent event) {
if (config.isExecutorsEnabled()) {
- ruleExecutorService.shutdownNow();
- try {
- ruleExecutorService.awaitTermination(AWAIT_TERMINATION_THREAD_SECONDS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- logWarn("Not all rules ran to completion before rule engine shutdown", e);
- }
+ ruleExecutorService.submit(() -> invokeRuleInternal(context, event));
+ } else {
+ invokeRuleInternal(context, event);
}
}
- public void setItemRegistry(ItemRegistry itemRegistry) {
- this.itemRegistry = itemRegistry;
- }
+ private void invokeRuleInternal(JRuleExecutionContext context, JRuleEvent event) {
+ JRuleLog.debug(logger, context.getLogName(), "Invoking rule for context: {}", context);
- public JRuleLoadingStatistics getRuleLoadingStatistics() {
- return ruleLoadingStatistics;
+ final JRule rule = context.getJrule();
+ final Method method = context.getMethod();
+ rule.setRuleLogName(context.getLogName());
+ try {
+ JRuleLog.debug(logger, context.getMethod().getName(), "setting mdc tags: {}", context.getLoggingTags());
+ MDC.put(MDC_KEY_RULE, context.getMethod().getName());
+ Arrays.stream(context.getLoggingTags()).forEach(s -> MDC.put(s, s));
+ if (context.hasEventParameterPresent()) {
+ method.invoke(rule, event);
+ } else {
+ method.invoke(rule);
+ }
+ } catch (IllegalAccessException | IllegalArgumentException | SecurityException e) {
+ JRuleLog.error(logger, context.getMethod().getName(), "Error {}", e);
+ } catch (InvocationTargetException e) {
+ Throwable ex = e.getCause() != null ? e.getCause() : null;
+ JRuleLog.error(logger, context.getMethod().getName(), "Error message", ex);
+ JRuleLog.error(logger, context.getMethod().getName(), "Error Stacktrace: {}",
+ ExceptionUtils.getStackTrace(ex));
+ } finally {
+ Arrays.stream(context.getLoggingTags()).forEach(MDC::remove);
+ MDC.remove(MDC_KEY_RULE);
+ }
}
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleChannelExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleChannelExecutionContext.java
index 4d0559f7..d68d12fa 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleChannelExecutionContext.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleChannelExecutionContext.java
@@ -13,9 +13,14 @@
package org.openhab.automation.jrule.internal.engine.excutioncontext;
import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRulePrecondition;
+import org.openhab.automation.jrule.rules.event.JRuleChannelEvent;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.core.events.AbstractEvent;
+import org.openhab.core.thing.events.ChannelTriggeredEvent;
/**
* The {@link JRuleChannelExecutionContext}
@@ -24,29 +29,33 @@
*/
public class JRuleChannelExecutionContext extends JRuleExecutionContext {
private final String channel;
+ private final Optional event;
- private String eq;
-
- private String neq;
-
- public JRuleChannelExecutionContext(JRule jRule, String logName, String[] loggingTags, String ruleName,
- Method method, boolean eventParameterPresent, JRulePrecondition[] preconditions, String channel, String eq,
- String neq) {
- super(jRule, logName, loggingTags, ruleName, method, eventParameterPresent, preconditions);
+ public JRuleChannelExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ List preconditionContextList, String channel, Optional event) {
+ super(jRule, logName, loggingTags, method, preconditionContextList);
this.channel = channel;
- this.eq = eq;
- this.neq = neq;
+ this.event = event;
}
public String getChannel() {
return channel;
}
- public String getEq() {
- return eq;
+ public Optional getEvent() {
+ return this.event;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return event instanceof ChannelTriggeredEvent
+ && ((ChannelTriggeredEvent) event).getChannel().getAsString().equals(this.channel)
+ && this.event.map(e -> e.equals(((ChannelTriggeredEvent) event).getEvent())).orElse(true);
}
- public String getNeq() {
- return neq;
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleChannelEvent(((ChannelTriggeredEvent) event).getChannel().getAsString(),
+ ((ChannelTriggeredEvent) event).getEvent());
}
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleContextValueComparators.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleContextValueComparators.java
deleted file mode 100644
index 024f18d6..00000000
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleContextValueComparators.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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.excutioncontext;
-
-/**
- * The {@link JRuleContextValueComparators} interface defines the common comparison methods (less than, greater than
- * etc)
- *
- * @author Arne Seime - Initial contribution
- */
-public interface JRuleContextValueComparators {
-
- Double getGt();
-
- Double getGte();
-
- Double getLt();
-
- Double getLte();
-
- String getEq();
-
- String getNeq();
-
- default boolean hasCompartorsSet() {
- return getGt() != null || getGte() != null || getLt() != null || getLte() != null || getEq() != null
- || getNeq() != null;
- }
-}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleExecutionContext.java
index 9bf4fca2..975bde4f 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleExecutionContext.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleExecutionContext.java
@@ -13,9 +13,12 @@
package org.openhab.automation.jrule.internal.engine.excutioncontext;
import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRulePrecondition;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.core.events.AbstractEvent;
/**
* The {@link JRuleExecutionContext}
@@ -24,31 +27,18 @@
*/
public abstract class JRuleExecutionContext {
private final String logName;
- protected final String ruleName;
protected final JRule jRule;
protected final Method method;
- protected final boolean eventParameterPresent;
private final String[] loggingTags;
+ private final List preconditionContextList;
- public JRulePrecondition[] getPreconditions() {
- return preconditions;
- }
-
- private final JRulePrecondition[] preconditions;
-
- public JRuleExecutionContext(JRule jRule, String logName, String[] loggingTags, String ruleName, Method method,
- boolean eventParameterPresent, JRulePrecondition[] preconditions) {
+ public JRuleExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ List preconditionContextList) {
this.logName = logName;
this.loggingTags = loggingTags;
this.jRule = jRule;
- this.ruleName = ruleName;
this.method = method;
- this.eventParameterPresent = eventParameterPresent;
- this.preconditions = preconditions;
- }
-
- public String getRuleName() {
- return ruleName;
+ this.preconditionContextList = preconditionContextList;
}
public JRule getJrule() {
@@ -59,8 +49,9 @@ public Method getMethod() {
return method;
}
- public boolean isEventParameterPresent() {
- return eventParameterPresent;
+ public boolean hasEventParameterPresent() {
+ return Arrays.stream(method.getParameters())
+ .anyMatch(param -> (JRuleEvent.class.isAssignableFrom(param.getType())));
}
public String getLogName() {
@@ -70,4 +61,12 @@ public String getLogName() {
public String[] getLoggingTags() {
return loggingTags;
}
+
+ public abstract boolean match(AbstractEvent event);
+
+ public abstract JRuleEvent createJRuleEvent(AbstractEvent event);
+
+ public List getPreconditionContextList() {
+ return preconditionContextList;
+ }
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemChangeExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemChangeExecutionContext.java
new file mode 100644
index 00000000..e594bcb7
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemChangeExecutionContext.java
@@ -0,0 +1,63 @@
+/**
+ * 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.excutioncontext;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+import org.openhab.automation.jrule.rules.JRule;
+import org.openhab.automation.jrule.rules.JRuleEventState;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
+import org.openhab.core.events.AbstractEvent;
+import org.openhab.core.items.events.GroupItemStateChangedEvent;
+import org.openhab.core.items.events.ItemStateChangedEvent;
+
+/**
+ * The {@link JRuleItemChangeExecutionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRuleItemChangeExecutionContext extends JRuleItemExecutionContext {
+ private final Optional from;
+ private final Optional to;
+
+ public JRuleItemChangeExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ String itemName, Optional lt, Optional lte, Optional gt, Optional gte,
+ Optional eq, Optional neq, List preconditionContextList,
+ Optional from, Optional to) {
+ super(jRule, logName, loggingTags, method, itemName, lt, lte, gt, gte, eq, neq, preconditionContextList);
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return event instanceof ItemStateChangedEvent
+ && ((ItemStateChangedEvent) event).getItemName().equals(this.getItemName())
+ && from.map(s -> ((ItemStateChangedEvent) event).getOldItemState().toString().equals(s)).orElse(true)
+ && to.map(s -> ((ItemStateChangedEvent) event).getItemState().toString().equals(s)).orElse(true)
+ && super.matchCondition(((ItemStateChangedEvent) event).getItemState().toString());
+ }
+
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ String memberName = event instanceof GroupItemStateChangedEvent
+ ? ((GroupItemStateChangedEvent) event).getMemberName()
+ : null;
+ return new JRuleItemEvent(this.getItemName(), memberName,
+ new JRuleEventState(((ItemStateChangedEvent) event).getItemState().toString()),
+ new JRuleEventState(((ItemStateChangedEvent) event).getOldItemState().toString()));
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemExecutionContext.java
index 0e234a7a..85d45a55 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemExecutionContext.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemExecutionContext.java
@@ -13,44 +13,31 @@
package org.openhab.automation.jrule.internal.engine.excutioncontext;
import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRulePrecondition;
+import org.openhab.core.library.types.QuantityType;
/**
* The {@link JRuleItemExecutionContext}
*
* @author Robert Delbrück - Initial contribution
*/
-public class JRuleItemExecutionContext extends JRuleExecutionContext implements JRuleContextValueComparators {
- private static final String FROM_PREFIX = " from ";
- private static final String TO_PREFIX = " to ";
- private static final String SPACE = " ";
-
- private final String itemClass;
+public abstract class JRuleItemExecutionContext extends JRuleExecutionContext {
private final String itemName;
- private final String trigger;
- private final String update;
- private final String from;
- private final String to;
- private final Double gt;
- private final Double gte;
- private final Double lt;
- private final Double lte;
- protected final String eq;
- protected final String neq;
-
- public JRuleItemExecutionContext(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) {
- super(jRule, logName, loggingTags, ruleName, method, eventParameterPresent, preconditions);
- this.itemClass = itemClass;
+ private final Optional gt;
+ private final Optional gte;
+ private final Optional lt;
+ private final Optional lte;
+ protected final Optional eq;
+ protected final Optional neq;
+
+ public JRuleItemExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method, String itemName,
+ Optional lt, Optional lte, Optional gt, Optional gte, Optional eq,
+ Optional neq, List preconditionContextList) {
+ super(jRule, logName, loggingTags, method, preconditionContextList);
this.itemName = itemName;
- this.trigger = trigger;
- this.update = update;
- this.from = from;
- this.to = to;
this.gt = gt;
this.gte = gte;
this.lt = lt;
@@ -63,73 +50,51 @@ public String getItemName() {
return itemName;
}
- public Double getGt() {
+ public boolean matchCondition(String state) {
+ if (getEq().isPresent() && getEq().filter(state::equals).isEmpty()) {
+ return false;
+ }
+ if (getNeq().isPresent() && getNeq().filter(ref -> !state.equals(ref)).isEmpty()) {
+ return false;
+ }
+ if (getLt().isPresent() && getLt().filter(ref -> QuantityType.valueOf(state).doubleValue() < ref).isEmpty()) {
+ return false;
+ }
+ if (getLte().isPresent()
+ && getLte().filter(ref -> QuantityType.valueOf(state).doubleValue() <= ref).isEmpty()) {
+ return false;
+ }
+ if (getGt().isPresent() && getGt().filter(ref -> QuantityType.valueOf(state).doubleValue() > ref).isEmpty()) {
+ return false;
+ }
+ if (getGte().isPresent()
+ && getGte().filter(ref -> QuantityType.valueOf(state).doubleValue() >= ref).isEmpty()) {
+ return false;
+ }
+ return true;
+ }
+
+ public Optional getGt() {
return gt;
}
- public Double getGte() {
+ public Optional getGte() {
return gte;
}
- public Double getLt() {
+ public Optional getLt() {
return lt;
}
- public Double getLte() {
+ public Optional getLte() {
return lte;
}
- public String getEq() {
+ public Optional getEq() {
return eq;
}
- public String getNeq() {
+ public Optional getNeq() {
return neq;
}
-
- public String getTrigger() {
- return trigger;
- }
-
- 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();
- }
-
- private String buildUpdateString(String trigger, String update) {
- return trigger + SPACE + update;
- }
-
- 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;
- }
-
- @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 + "]";
- }
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedCommandExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedCommandExecutionContext.java
new file mode 100644
index 00000000..b8ef0bbb
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedCommandExecutionContext.java
@@ -0,0 +1,54 @@
+/**
+ * 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.excutioncontext;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+import org.openhab.automation.jrule.rules.JRule;
+import org.openhab.automation.jrule.rules.JRuleEventState;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
+import org.openhab.core.events.AbstractEvent;
+import org.openhab.core.items.events.ItemCommandEvent;
+
+/**
+ * The {@link JRuleItemReceivedCommandExecutionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRuleItemReceivedCommandExecutionContext extends JRuleItemExecutionContext {
+ private final Optional command;
+
+ public JRuleItemReceivedCommandExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ String itemName, Optional lt, Optional lte, Optional gt, Optional gte,
+ Optional eq, Optional neq, List preconditionContextList,
+ Optional command) {
+ super(jRule, logName, loggingTags, method, itemName, lt, lte, gt, gte, eq, neq, preconditionContextList);
+ this.command = command;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return event instanceof ItemCommandEvent && ((ItemCommandEvent) event).getItemName().equals(this.getItemName())
+ && command.map(s -> ((ItemCommandEvent) event).getItemCommand().toString().equals(s)).orElse(true)
+ && super.matchCondition(((ItemCommandEvent) event).getItemCommand().toString());
+ }
+
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleItemEvent(this.getItemName(), null,
+ new JRuleEventState(((ItemCommandEvent) event).getItemCommand().toString()), null);
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedUpdateExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedUpdateExecutionContext.java
new file mode 100644
index 00000000..611ac11a
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleItemReceivedUpdateExecutionContext.java
@@ -0,0 +1,54 @@
+/**
+ * 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.excutioncontext;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+import org.openhab.automation.jrule.rules.JRule;
+import org.openhab.automation.jrule.rules.JRuleEventState;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleItemEvent;
+import org.openhab.core.events.AbstractEvent;
+import org.openhab.core.items.events.ItemStateEvent;
+
+/**
+ * The {@link JRuleItemReceivedUpdateExecutionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRuleItemReceivedUpdateExecutionContext extends JRuleItemExecutionContext {
+ private final Optional state;
+
+ public JRuleItemReceivedUpdateExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ String itemName, Optional lt, Optional lte, Optional gt, Optional gte,
+ Optional eq, Optional neq, List preconditionContextList,
+ Optional state) {
+ super(jRule, logName, loggingTags, method, itemName, lt, lte, gt, gte, eq, neq, preconditionContextList);
+ this.state = state;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return event instanceof ItemStateEvent && ((ItemStateEvent) event).getItemName().equals(this.getItemName())
+ && state.map(s -> ((ItemStateEvent) event).getItemState().toString().equals(s)).orElse(true)
+ && super.matchCondition(((ItemStateEvent) event).getItemState().toString());
+ }
+
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleItemEvent(this.getItemName(), null,
+ new JRuleEventState(((ItemStateEvent) event).getItemState().toString()), null);
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRulePreconditionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRulePreconditionContext.java
new file mode 100644
index 00000000..8870be11
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRulePreconditionContext.java
@@ -0,0 +1,70 @@
+/**
+ * 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.excutioncontext;
+
+import java.util.Optional;
+
+/**
+ * The {@link JRulePreconditionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRulePreconditionContext {
+
+ private final String item;
+ private final Optional lt;
+ private final Optional lte;
+ private final Optional gt;
+ private final Optional gte;
+ private final Optional eq;
+ private final Optional neq;
+
+ public JRulePreconditionContext(String item, Optional lt, Optional lte, Optional gt,
+ Optional gte, Optional eq, Optional neq) {
+ this.item = item;
+ this.lt = lt;
+ this.lte = lte;
+ this.gt = gt;
+ this.gte = gte;
+ this.eq = eq;
+ this.neq = neq;
+ }
+
+ public String getItem() {
+ return item;
+ }
+
+ public Optional getLt() {
+ return lt;
+ }
+
+ public Optional getLte() {
+ return lte;
+ }
+
+ public Optional getGt() {
+ return gt;
+ }
+
+ public Optional getGte() {
+ return gte;
+ }
+
+ public Optional getEq() {
+ return eq;
+ }
+
+ public Optional getNeq() {
+ return neq;
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleThingExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleThingExecutionContext.java
index 63b3e8c9..502afab5 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleThingExecutionContext.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleThingExecutionContext.java
@@ -13,9 +13,15 @@
package org.openhab.automation.jrule.internal.engine.excutioncontext;
import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRulePrecondition;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleThingEvent;
+import org.openhab.automation.jrule.things.JRuleThingStatus;
+import org.openhab.core.events.AbstractEvent;
+import org.openhab.core.thing.events.ThingStatusInfoChangedEvent;
/**
* The {@link JRuleThingExecutionContext} - execution context for thing triggers
@@ -23,64 +29,43 @@
* @author Arne Seime - Initial contribution
*/
public class JRuleThingExecutionContext extends JRuleExecutionContext {
- public static final String ANY_THING_UID = "*"; // Wildcard, allows registering rules that listen for all thing
- private static final String FROM_PREFIX = " from ";
- private static final String TO_PREFIX = " to ";
+ private final Optional thing;
+ private final Optional from;
+ private final Optional to;
- private final String thing;
- private final String trigger;
- private final String from;
- private final String to;
-
- public JRuleThingExecutionContext(JRule jRule, String logName, String[] loggingTags, String trigger, String from,
- String to, String ruleName, String thing, Method method, boolean eventParameterPresent,
- JRulePrecondition[] preconditions) {
- super(jRule, logName, loggingTags, ruleName, method, eventParameterPresent, preconditions);
+ public JRuleThingExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ Optional thing, Optional from, Optional to,
+ List preconditions) {
+ super(jRule, logName, loggingTags, method, preconditions);
this.thing = thing;
- this.trigger = trigger;
this.from = from;
this.to = to;
}
- public String getThing() {
+ public Optional getThing() {
return thing;
}
- 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);
- }
-
- return trigger;
+ @Override
+ public String toString() {
+ return "JRuleThingExecutionContext{" + "thing='" + thing + '\'' + ", from='" + from + '\'' + ", to='" + to
+ + '\'' + '}';
}
- 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);
+ @Override
+ public boolean match(AbstractEvent event) {
+ if (!(event instanceof ThingStatusInfoChangedEvent)) {
+ return false;
}
- return builder.toString();
+ ThingStatusInfoChangedEvent evt = (ThingStatusInfoChangedEvent) event;
+ return thing.map(s -> evt.getThingUID().toString().equals(s)).orElse(true)
+ && from.map(s -> evt.getOldStatusInfo().getStatus().name().equals(s.name())).orElse(true)
+ && to.map(s -> evt.getStatusInfo().getStatus().name().equals(s.name())).orElse(true);
}
@Override
- public String toString() {
- return "JRuleThingExecutionContext{" + "thing='" + thing + '\'' + ", trigger='" + trigger + '\'' + ", from='"
- + from + '\'' + ", to='" + to + '\'' + '}';
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleThingEvent(((ThingStatusInfoChangedEvent) event).getThingUID().toString(),
+ ((ThingStatusInfoChangedEvent) event).getStatusInfo().getStatus().name());
}
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimeTimerExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimeTimerExecutionContext.java
new file mode 100644
index 00000000..eff7a1be
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimeTimerExecutionContext.java
@@ -0,0 +1,64 @@
+/**
+ * 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.excutioncontext;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+import org.openhab.automation.jrule.rules.JRule;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleTimerEvent;
+import org.openhab.core.events.AbstractEvent;
+
+/**
+ * The {@link JRuleTimeTimerExecutionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRuleTimeTimerExecutionContext extends JRuleTimedExecutionContext {
+ private final Optional hour;
+ private final Optional minute;
+ private final Optional second;
+
+ public JRuleTimeTimerExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ List preconditionContextList, Optional hour, Optional minute,
+ Optional second) {
+ super(jRule, logName, loggingTags, method, preconditionContextList);
+ this.hour = hour;
+ this.minute = minute;
+ this.second = second;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return false;
+ }
+
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleTimerEvent();
+ }
+
+ public Optional getHour() {
+ return hour;
+ }
+
+ public Optional getMinute() {
+ return minute;
+ }
+
+ public Optional getSecond() {
+ return second;
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedCronExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedCronExecutionContext.java
new file mode 100644
index 00000000..92652d8d
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedCronExecutionContext.java
@@ -0,0 +1,50 @@
+/**
+ * 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.excutioncontext;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.openhab.automation.jrule.rules.JRule;
+import org.openhab.automation.jrule.rules.event.JRuleEvent;
+import org.openhab.automation.jrule.rules.event.JRuleTimerEvent;
+import org.openhab.core.events.AbstractEvent;
+
+/**
+ * The {@link JRuleTimedCronExecutionContext}
+ *
+ * @author Robert Delbrück - Initial contribution
+ */
+public class JRuleTimedCronExecutionContext extends JRuleTimedExecutionContext {
+ private final String cron;
+
+ public JRuleTimedCronExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ List preconditionContextList, String cron) {
+ super(jRule, logName, loggingTags, method, preconditionContextList);
+ this.cron = cron;
+ }
+
+ @Override
+ public boolean match(AbstractEvent event) {
+ return false;
+ }
+
+ @Override
+ public JRuleEvent createJRuleEvent(AbstractEvent event) {
+ return new JRuleTimerEvent();
+ }
+
+ public String getCron() {
+ return cron;
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedExecutionContext.java b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedExecutionContext.java
index 78798deb..996ffb8b 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedExecutionContext.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/excutioncontext/JRuleTimedExecutionContext.java
@@ -13,18 +13,18 @@
package org.openhab.automation.jrule.internal.engine.excutioncontext;
import java.lang.reflect.Method;
+import java.util.List;
import org.openhab.automation.jrule.rules.JRule;
-import org.openhab.automation.jrule.rules.JRulePrecondition;
/**
* The {@link JRuleTimedExecutionContext}
*
* @author Robert Delbrück - Initial contribution
*/
-public class JRuleTimedExecutionContext extends JRuleExecutionContext {
- public JRuleTimedExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method, String ruleName,
- boolean jRuleEventPresent, JRulePrecondition[] preconditions) {
- super(jRule, logName, loggingTags, ruleName, method, jRuleEventPresent, preconditions);
+public abstract class JRuleTimedExecutionContext extends JRuleExecutionContext {
+ public JRuleTimedExecutionContext(JRule jRule, String logName, String[] loggingTags, Method method,
+ List preconditionContextList) {
+ super(jRule, logName, loggingTags, method, preconditionContextList);
}
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/engine/timer/TimerExecutor.java b/src/main/java/org/openhab/automation/jrule/internal/engine/timer/TimerExecutor.java
new file mode 100644
index 00000000..099b52de
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/internal/engine/timer/TimerExecutor.java
@@ -0,0 +1,74 @@
+/**
+ * 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.timer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openhab.automation.jrule.internal.JRuleLog;
+import org.openhab.automation.jrule.internal.engine.JRuleEngine;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimeTimerExecutionContext;
+import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedCronExecutionContext;
+import org.openhab.core.scheduler.CronScheduler;
+import org.openhab.core.scheduler.ScheduledCompletableFuture;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link TimerExecutor}
+ *
+ * @author Robert Delbrück
+ */
+public class TimerExecutor {
+ private final Logger logger = LoggerFactory.getLogger(TimerExecutor.class);
+ private final List> timers = new ArrayList<>();
+ private final JRuleEngine jRuleEngine;
+ private CronScheduler cronScheduler;
+
+ public TimerExecutor(JRuleEngine jRuleEngine) {
+ this.jRuleEngine = jRuleEngine;
+ }
+
+ public void add(JRuleTimedCronExecutionContext executionContext) {
+ timers.add(cronScheduler.schedule(
+ () -> jRuleEngine.invokeRule(executionContext, executionContext.createJRuleEvent(null)),
+ executionContext.getCron()));
+ }
+
+ public void add(JRuleTimeTimerExecutionContext executionContext) {
+ String cron = String.format("%s %s %s %s %s %s", executionContext.getSecond().map(String::valueOf).orElse("*"),
+ executionContext.getMinute().map(String::valueOf).orElse("*"),
+ executionContext.getHour().map(String::valueOf).orElse("*"), "*", "*", "*");
+ JRuleLog.info(logger, TimerExecutor.class.getSimpleName(), "Generated cron for timer: {}", cron);
+ timers.add(cronScheduler.schedule(
+ () -> jRuleEngine.invokeRule(executionContext, executionContext.createJRuleEvent(null)), cron));
+ }
+
+ public void add(JRuleExecutionContext context) {
+ if (context instanceof JRuleTimedCronExecutionContext) {
+ this.add((JRuleTimedCronExecutionContext) context);
+ } else if (context instanceof JRuleTimeTimerExecutionContext) {
+ this.add((JRuleTimeTimerExecutionContext) context);
+ }
+ }
+
+ public void setCronScheduler(CronScheduler cronScheduler) {
+ this.cronScheduler = cronScheduler;
+ }
+
+ public void clear() {
+ timers.forEach(timer -> timer.cancel(true));
+ timers.clear();
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java b/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java
index 1ae2f871..4c2f3d92 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/events/JRuleEventSubscriber.java
@@ -24,7 +24,6 @@
import org.openhab.automation.jrule.internal.JRuleLog;
import org.openhab.automation.jrule.internal.JRuleUtil;
import org.openhab.automation.jrule.internal.engine.JRuleEngine;
-import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
import org.openhab.core.events.EventSubscriber;
@@ -70,17 +69,12 @@ public class JRuleEventSubscriber implements EventSubscriber {
private final Set subscribedEventTypes = new HashSet<>();
- private final Set jRuleMonitoredItems = new HashSet<>();
-
- private final Set jRuleMonitoredChannels = new HashSet<>();
-
- private final Set jRuleMonitoredThings = new HashSet<>();
-
private final PropertyChangeSupport propertyChangeSupport;
private final Queue eventQueue = new ConcurrentLinkedQueue<>();
private volatile boolean queueEvents = false;
+ private JRuleEngine jRuleEngine = JRuleEngine.get();
public JRuleEventSubscriber() {
propertyChangeSupport = new PropertyChangeSupport(this);
@@ -112,25 +106,12 @@ public Set getSubscribedEventTypes() {
public void startSubscriber() {
JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Starting subscriber");
- registerSubscribedItemsAndChannels();
propertyChangeSupport.addPropertyChangeListener(JRuleEngine.get());
}
- public void registerSubscribedItemsAndChannels() {
- jRuleMonitoredItems.clear();
- jRuleMonitoredChannels.clear();
- jRuleMonitoredThings.clear();
-
- jRuleMonitoredItems.addAll(JRuleEngine.get().getItemNames());
- jRuleMonitoredChannels.addAll(JRuleEngine.get().getChannelNames());
- jRuleMonitoredThings.addAll(JRuleEngine.get().getThingUIDs());
- }
-
public void stopSubscriber() {
- jRuleMonitoredItems.clear();
- jRuleMonitoredChannels.clear();
- jRuleMonitoredThings.clear();
propertyChangeSupport.removePropertyChangeListener(JRuleEngine.get());
+ propertyChangeSupport.removePropertyChangeListener(jRuleEngine);
}
/**
@@ -168,7 +149,8 @@ public void receive(Event event) {
}
private void processEvent(Event event) {
- final String itemFromTopic = JRuleUtil.getItemNameFromTopic(event.getTopic());
+ JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Received event '{}' with topic '{}' and payload '{}'",
+ event.getType(), event.getTopic(), event.getPayload());
if (event.getType().equals(ItemAddedEvent.TYPE) //
|| event.getType().equals(ItemRemovedEvent.TYPE) //
|| event.getType().equals(ItemUpdatedEvent.TYPE)) {
@@ -180,14 +162,19 @@ private void processEvent(Event event) {
JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "event processed as {}: topic {} payload: {}",
PROPERTY_THING_REGISTRY_EVENT, event.getTopic(), event.getPayload());
propertyChangeSupport.firePropertyChange(PROPERTY_THING_REGISTRY_EVENT, null, event);
- } else if (jRuleMonitoredItems.contains(itemFromTopic)) {
- JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}",
- PROPERTY_ITEM_EVENT, event.getTopic(), event.getPayload());
- propertyChangeSupport.firePropertyChange(PROPERTY_ITEM_EVENT, null, event);
+ } else if (event.getType().equals(ItemStateEvent.TYPE) || event.getType().equals(ItemCommandEvent.TYPE)
+ || event.getType().equals(ItemStateChangedEvent.TYPE)
+ || event.getType().equals(GroupItemStateChangedEvent.TYPE)) {
+ final String itemFromTopic = JRuleUtil.getItemNameFromTopic(event.getTopic());
+ if (jRuleEngine.watchingForItem(itemFromTopic)) {
+ JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}",
+ PROPERTY_ITEM_EVENT, event.getTopic(), event.getPayload());
+ propertyChangeSupport.firePropertyChange(PROPERTY_ITEM_EVENT, null, event);
+ }
} else if (event.getType().equals(ChannelTriggeredEvent.TYPE)) {
ChannelTriggeredEvent channelTriggeredEvent = (ChannelTriggeredEvent) event;
String channel = channelTriggeredEvent.getChannel().toString();
- if (jRuleMonitoredChannels.contains(channel)) {
+ if (jRuleEngine.watchingForChannel(channel)) {
JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}",
PROPERTY_CHANNEL_EVENT, event.getTopic(), event.getPayload());
propertyChangeSupport.firePropertyChange(PROPERTY_CHANNEL_EVENT, null, event);
@@ -196,8 +183,7 @@ private void processEvent(Event event) {
ThingStatusInfoChangedEvent thingStatusChangedEvent = (ThingStatusInfoChangedEvent) event;
String thingUID = thingStatusChangedEvent.getThingUID().toString();
- if (jRuleMonitoredThings.contains(thingUID)
- || jRuleMonitoredThings.contains(JRuleThingExecutionContext.ANY_THING_UID)) {
+ if (jRuleEngine.watchingForThing(thingUID)) {
JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}",
PROPERTY_THING_STATUS_EVENT, event.getTopic(), event.getPayload());
propertyChangeSupport.firePropertyChange(PROPERTY_THING_STATUS_EVENT, null, event);
diff --git a/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleHandler.java b/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleHandler.java
index 9cae7450..c4745f77 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleHandler.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/handler/JRuleHandler.java
@@ -52,6 +52,7 @@
import org.openhab.core.items.events.ItemAddedEvent;
import org.openhab.core.items.events.ItemRemovedEvent;
import org.openhab.core.items.events.ItemUpdatedEvent;
+import org.openhab.core.scheduler.CronScheduler;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingManager;
import org.openhab.core.thing.ThingRegistry;
@@ -106,7 +107,7 @@ public class JRuleHandler implements PropertyChangeListener {
public JRuleHandler(JRuleConfig config, ItemRegistry itemRegistry, ThingRegistry thingRegistry,
ThingManager thingManager, EventPublisher eventPublisher, JRuleEventSubscriber eventSubscriber,
- VoiceManager voiceManager, BundleContext bundleContext) {
+ VoiceManager voiceManager, CronScheduler cronScheduler, BundleContext bundleContext) {
this.itemRegistry = itemRegistry;
this.thingRegistry = thingRegistry;
this.eventSubscriber = eventSubscriber;
@@ -197,6 +198,7 @@ public synchronized void dispose() {
delayedItemsCompiler.cancel();
delayedItemsCompiler.shutdown();
JRuleEngine.get().reset();
+ JRuleEngine.get().dispose();
if (directoryWatcher != null) {
directoryWatcher.removePropertyChangeListener(this);
}
@@ -301,7 +303,6 @@ private synchronized Boolean compileAndReloadRules() {
JRuleEngine.get().reset();
createRuleInstances();
logInfo("JRule Engine Rules Reloaded! {}", JRuleEngine.get().getRuleLoadingStatistics());
- eventSubscriber.registerSubscribedItemsAndChannels();
eventSubscriber.resumeEventDelivery();
return true;
}
diff --git a/src/main/java/org/openhab/automation/jrule/internal/test/JRuleMockedEventBus.java b/src/main/java/org/openhab/automation/jrule/internal/test/JRuleMockedEventBus.java
index edf62527..152a9e52 100644
--- a/src/main/java/org/openhab/automation/jrule/internal/test/JRuleMockedEventBus.java
+++ b/src/main/java/org/openhab/automation/jrule/internal/test/JRuleMockedEventBus.java
@@ -29,7 +29,6 @@ public JRuleMockedEventBus(String eventBusResourceName) {
super();
JRuleTestEventLogParser parser = new JRuleTestEventLogParser(eventBusResourceName);
eventList = parser.parse();
- registerSubscribedItemsAndChannels();
}
public void start() {
diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleDimmerItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleDimmerItem.java
index 50d3a564..405ea5cd 100644
--- a/src/main/java/org/openhab/automation/jrule/items/JRuleDimmerItem.java
+++ b/src/main/java/org/openhab/automation/jrule/items/JRuleDimmerItem.java
@@ -19,14 +19,14 @@
import org.openhab.automation.jrule.internal.handler.JRuleEventHandler;
import org.openhab.automation.jrule.rules.value.JRuleIncreaseDecreaseValue;
import org.openhab.automation.jrule.rules.value.JRuleOnOffValue;
-import org.openhab.automation.jrule.trigger.JRuleDimmerTrigger;
+import org.openhab.automation.jrule.trigger.JRuleSwitchTrigger;
/**
* The {@link JRuleDimmerItem} Items
*
* @author Joseph (Seaside) Hagberg - Initial contribution
*/
-public abstract class JRuleDimmerItem extends JRuleItem implements JRuleDimmerTrigger {
+public abstract class JRuleDimmerItem extends JRuleItem implements JRuleSwitchTrigger {
protected JRuleDimmerItem(String itemName) {
super(itemName);
diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleGroupDimmerItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleGroupDimmerItem.java
index 07f22d57..fe500538 100644
--- a/src/main/java/org/openhab/automation/jrule/items/JRuleGroupDimmerItem.java
+++ b/src/main/java/org/openhab/automation/jrule/items/JRuleGroupDimmerItem.java
@@ -21,7 +21,7 @@
import org.openhab.automation.jrule.internal.handler.JRuleEventHandler;
import org.openhab.automation.jrule.rules.value.JRuleIncreaseDecreaseValue;
import org.openhab.automation.jrule.rules.value.JRuleOnOffValue;
-import org.openhab.automation.jrule.trigger.JRuleDimmerTrigger;
+import org.openhab.automation.jrule.trigger.JRuleSwitchTrigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,7 +30,7 @@
*
* @author Arne Seime - Initial contribution
*/
-public abstract class JRuleGroupDimmerItem extends JRuleGroupItem implements JRuleDimmerTrigger {
+public abstract class JRuleGroupDimmerItem extends JRuleGroupItem implements JRuleSwitchTrigger {
private static final String LOG_NAME = "JRuleGroupDimmerItem";
private static final Logger logger = LoggerFactory.getLogger(JRuleGroupDimmerItem.class);
diff --git a/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java b/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java
index a757e7e5..f477641b 100644
--- a/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java
+++ b/src/main/java/org/openhab/automation/jrule/items/JRuleItem.java
@@ -15,14 +15,12 @@
import java.time.ZonedDateTime;
import java.util.Optional;
-import org.openhab.automation.jrule.trigger.JRuleCommonTrigger;
-
/**
* The {@link JRuleItem} Items
*
* @author Joseph (Seaside) Hagberg - Initial contribution
*/
-public abstract class JRuleItem implements JRuleCommonTrigger {
+public abstract class JRuleItem {
protected String itemName;
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleCondition.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleCondition.java
new file mode 100644
index 00000000..d0f52c3d
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleCondition.java
@@ -0,0 +1,32 @@
+/**
+ * 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 JRuleCondition}
+ *
+ * @author Robert Delbrück
+ */
+public @interface JRuleCondition {
+ double gt() default Double.MIN_VALUE;
+
+ double lt() default Double.MIN_VALUE;
+
+ double gte() default Double.MIN_VALUE;
+
+ double lte() default Double.MIN_VALUE;
+
+ String eq() default "";
+
+ String neq() default "";
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRulePrecondition.java b/src/main/java/org/openhab/automation/jrule/rules/JRulePrecondition.java
index 062906ff..4021be15 100644
--- a/src/main/java/org/openhab/automation/jrule/rules/JRulePrecondition.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRulePrecondition.java
@@ -29,15 +29,5 @@
public @interface JRulePrecondition {
String item() default "";
- double gt() default Double.MIN_VALUE;
-
- double lt() default Double.MIN_VALUE;
-
- double gte() default Double.MIN_VALUE;
-
- double lte() default Double.MIN_VALUE;
-
- String eq() default "";
-
- String neq() default "";
+ JRuleCondition condition() default @JRuleCondition;
}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTrigger.java
new file mode 100644
index 00000000..7945c2e2
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTrigger.java
@@ -0,0 +1,33 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenChannelTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenChannelTriggers.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenChannelTrigger {
+ String channel() default "";
+
+ String event() default "";
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTriggers.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTriggers.java
new file mode 100644
index 00000000..85cb09b4
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenChannelTriggers.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenChannelTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenChannelTriggers {
+ JRuleWhenChannelTrigger[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTrigger.java
new file mode 100644
index 00000000..7e792b66
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTrigger.java
@@ -0,0 +1,31 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenCronTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenCronTriggers.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenCronTrigger {
+ String cron() default "";
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTriggers.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTriggers.java
new file mode 100644
index 00000000..f8a1ced8
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenCronTriggers.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenCronTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenCronTriggers {
+ JRuleWhenCronTrigger[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhen.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChange.java
similarity index 55%
rename from src/main/java/org/openhab/automation/jrule/rules/JRuleWhen.java
rename to src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChange.java
index b602acfa..443c5575 100644
--- a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhen.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChange.java
@@ -19,45 +19,19 @@
import java.lang.annotation.Target;
/**
- * The {@link JRuleWhen}
+ * The {@link JRuleWhenItemChange}
*
- * @author Joseph (Seaside) Hagberg - Initial contribution
+ * @author Robert Delbrück
*/
-@Repeatable(JRuleWhens.class)
+@Repeatable(JRuleWhenItemChanges.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
-public @interface JRuleWhen {
- String cron() default "";
-
- int hours() default -1;
-
- int minutes() default -1;
-
- int seconds() default -1;
-
+public @interface JRuleWhenItemChange {
String item() default "";
- String channel() default "";
-
- String trigger() default "";
-
- String thing() default "";
-
- String update() default "";
-
String from() default "";
String to() default "";
- double gt() default Double.MIN_VALUE;
-
- double lt() default Double.MIN_VALUE;
-
- double gte() default Double.MIN_VALUE;
-
- double lte() default Double.MIN_VALUE;
-
- String eq() default "";
-
- String neq() default "";
+ JRuleCondition condition() default @JRuleCondition;
}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhens.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChanges.java
similarity index 82%
rename from src/main/java/org/openhab/automation/jrule/rules/JRuleWhens.java
rename to src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChanges.java
index 24bde33d..d3337fad 100644
--- a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhens.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemChanges.java
@@ -18,12 +18,12 @@
import java.lang.annotation.Target;
/**
- * The {@link JRuleWhen}
+ * The {@link JRuleWhenItemChanges}
*
- * @author Joseph (Seaside) Hagberg - Initial contribution
+ * @author Robert Delbrück
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
-public @interface JRuleWhens {
- JRuleWhen[] value();
+public @interface JRuleWhenItemChanges {
+ JRuleWhenItemChange[] value();
}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommand.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommand.java
new file mode 100644
index 00000000..2c5846f9
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommand.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenItemReceivedCommand}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenItemReceivedCommands.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenItemReceivedCommand {
+ String item() default "";
+
+ String command() default "";
+
+ JRuleCondition condition() default @JRuleCondition;
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommands.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommands.java
new file mode 100644
index 00000000..1ddbbf72
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedCommands.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenItemReceivedCommands}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenItemReceivedCommands {
+ JRuleWhenItemReceivedCommand[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdate.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdate.java
new file mode 100644
index 00000000..e93a7f57
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdate.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenItemReceivedUpdate}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenItemReceivedUpdates.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenItemReceivedUpdate {
+ String item() default "";
+
+ String state() default "";
+
+ JRuleCondition condition() default @JRuleCondition;
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdates.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdates.java
new file mode 100644
index 00000000..ddeee0e3
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenItemReceivedUpdates.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenItemReceivedUpdates}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenItemReceivedUpdates {
+ JRuleWhenItemReceivedUpdate[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTrigger.java
new file mode 100644
index 00000000..267f1d97
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTrigger.java
@@ -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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.openhab.automation.jrule.things.JRuleThingStatus;
+
+/**
+ * The {@link JRuleWhenThingTrigger}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenThingTriggers.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenThingTrigger {
+ String thing() default "";
+
+ JRuleThingStatus from() default JRuleThingStatus.THING_UNKNOWN;
+
+ JRuleThingStatus to() default JRuleThingStatus.THING_UNKNOWN;
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTriggers.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTriggers.java
new file mode 100644
index 00000000..0cbc77a0
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenThingTriggers.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenThingTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenThingTriggers {
+ JRuleWhenThingTrigger[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTrigger.java
new file mode 100644
index 00000000..8dbb1769
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTrigger.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenTimeTrigger}
+ *
+ * @author Robert Delbrück
+ */
+@Repeatable(JRuleWhenTimeTriggers.class)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenTimeTrigger {
+ int hours() default -1;
+
+ int minutes() default -1;
+
+ int seconds() default -1;
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTriggers.java b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTriggers.java
new file mode 100644
index 00000000..543200ef
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/JRuleWhenTimeTriggers.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The {@link JRuleWhenTimeTriggers}
+ *
+ * @author Robert Delbrück
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+public @interface JRuleWhenTimeTriggers {
+ JRuleWhenTimeTrigger[] value();
+}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/event/JRuleChannelEvent.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleChannelEvent.java
new file mode 100644
index 00000000..7f712f37
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleChannelEvent.java
@@ -0,0 +1,41 @@
+/**
+ * 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.event;
+
+/**
+ * The {@link JRuleChannelEvent}
+ *
+ * @author Robert Delbrück
+ */
+public class JRuleChannelEvent extends JRuleEvent {
+ private String channel;
+ private String event;
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public String getEvent() {
+ return event;
+ }
+
+ public JRuleChannelEvent(String channel, String event) {
+ this.channel = channel;
+ this.event = event;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("JRuleEvent [channel=%s]", channel);
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRuleThingStatusTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleEvent.java
similarity index 63%
rename from src/main/java/org/openhab/automation/jrule/trigger/JRuleThingStatusTrigger.java
rename to src/main/java/org/openhab/automation/jrule/rules/event/JRuleEvent.java
index 8a903ba4..c42ce91b 100644
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRuleThingStatusTrigger.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleEvent.java
@@ -10,13 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.automation.jrule.trigger;
+package org.openhab.automation.jrule.rules.event;
/**
- * The {@link JRuleThingStatusTrigger} Items
+ * The {@link JRuleEvent}
*
- * @author Gerhard Riegler - Initial contribution
+ * @author Joseph (Seaside) Hagberg - Initial contribution
*/
-public interface JRuleThingStatusTrigger {
- String TRIGGER_CHANGED = "Changed";
+public abstract class JRuleEvent {
+
}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/JRuleEvent.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleItemEvent.java
similarity index 62%
rename from src/main/java/org/openhab/automation/jrule/rules/JRuleEvent.java
rename to src/main/java/org/openhab/automation/jrule/rules/event/JRuleItemEvent.java
index 004c5919..236241f9 100644
--- a/src/main/java/org/openhab/automation/jrule/rules/JRuleEvent.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleItemEvent.java
@@ -10,45 +10,29 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.automation.jrule.rules;
+package org.openhab.automation.jrule.rules.event;
+import org.openhab.automation.jrule.rules.JRuleEventState;
import org.openhab.automation.jrule.rules.value.JRuleOnOffValue;
import org.openhab.automation.jrule.rules.value.JRuleOpenClosedValue;
import org.openhab.automation.jrule.rules.value.JRuleUpDownValue;
/**
- * The {@link JRuleEvent}
+ * The {@link JRuleItemEvent}
*
- * @author Joseph (Seaside) Hagberg - Initial contribution
+ * @author Robert Delbrück
*/
-public class JRuleEvent {
-
+public class JRuleItemEvent extends JRuleEvent {
+ private final String itemName;
+ private final String memberName;
private final JRuleEventState state;
private final JRuleEventState oldState;
- private String event;
-
- private String memberName;
-
- private String itemName;
-
- private String channel;
-
- public JRuleEvent(String value) {
- this(value, null, null, null);
- }
- public JRuleEvent(String value, String oldValue, String itemName, String memberName) {
+ public JRuleItemEvent(String itemName, String memberName, JRuleEventState state, JRuleEventState oldState) {
this.itemName = itemName;
- this.state = new JRuleEventState(value);
- this.oldState = new JRuleEventState(oldValue);
this.memberName = memberName;
- }
-
- public JRuleEvent(String value, String channel, String event) {
- this.state = new JRuleEventState(value);
- this.oldState = null;
- this.channel = channel;
- this.event = event;
+ this.state = state;
+ this.oldState = oldState;
}
public JRuleEventState getState() {
@@ -64,6 +48,10 @@ public String getValue() {
return state.getValue();
}
+ public String getMemberName() {
+ return memberName;
+ }
+
@Deprecated
public JRuleOnOffValue getValueAsOnOffValue() {
return state.getValueAsOnOffValue();
@@ -89,25 +77,12 @@ public Integer getValueAsInteger() {
return state.getValueAsInteger();
}
- public String getMemberName() {
- return memberName;
- }
-
public String getItemName() {
return itemName;
}
- public String getChannel() {
- return channel;
- }
-
- public String getThing() {
- return channel; // TODO must refactor JRuleEvent to support all types of events (item, channel, thing)
- }
-
@Override
public String toString() {
- return String.format("JRuleEvent [state=%s, oldState=%s, memberName=%s, itemName=%s, channel=%s, event=%s]",
- state, oldState, memberName, itemName, channel, event);
+ return String.format("JRuleEvent [state=%s, oldState=%s, itemName=%s]", state, oldState, itemName);
}
}
diff --git a/src/main/java/org/openhab/automation/jrule/rules/event/JRuleThingEvent.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleThingEvent.java
new file mode 100644
index 00000000..ccddecd3
--- /dev/null
+++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleThingEvent.java
@@ -0,0 +1,41 @@
+/**
+ * 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.event;
+
+/**
+ * The {@link JRuleThingEvent}
+ *
+ * @author Robert Delbrück
+ */
+public class JRuleThingEvent extends JRuleEvent {
+ private String thing;
+ private String status;
+
+ public String getThing() {
+ return thing;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public JRuleThingEvent(String thing, String status) {
+ this.thing = thing;
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("JRuleThingEvent [thing=%s, status=%s]", thing, status);
+ }
+}
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRuleCommonTrigger.java b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleTimerEvent.java
similarity index 54%
rename from src/main/java/org/openhab/automation/jrule/trigger/JRuleCommonTrigger.java
rename to src/main/java/org/openhab/automation/jrule/rules/event/JRuleTimerEvent.java
index 6858a033..ab7866fb 100644
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRuleCommonTrigger.java
+++ b/src/main/java/org/openhab/automation/jrule/rules/event/JRuleTimerEvent.java
@@ -10,15 +10,12 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.automation.jrule.trigger;
+package org.openhab.automation.jrule.rules.event;
/**
- * The {@link JRuleCommonTrigger} Items
+ * The {@link JRuleTimerEvent}
*
- * @author Gerhard Riegler - Initial contribution
+ * @author Robert Delbrück
*/
-public interface JRuleCommonTrigger {
- String TRIGGER_CHANGED = "Changed";
- String TRIGGER_RECEIVED_COMMAND = "received command";
- String TRIGGER_RECEIVED_UPDATE = "received update";
+public class JRuleTimerEvent extends JRuleEvent {
}
diff --git a/src/main/java/org/openhab/automation/jrule/things/JRuleAbstractThing.java b/src/main/java/org/openhab/automation/jrule/things/JRuleAbstractThing.java
index 2fd55b37..682da7f6 100644
--- a/src/main/java/org/openhab/automation/jrule/things/JRuleAbstractThing.java
+++ b/src/main/java/org/openhab/automation/jrule/things/JRuleAbstractThing.java
@@ -13,7 +13,6 @@
package org.openhab.automation.jrule.things;
import org.openhab.automation.jrule.internal.handler.JRuleThingHandler;
-import org.openhab.automation.jrule.trigger.JRuleThingStatusTrigger;
/**
* The {@link JRuleAbstractThing} represents a thing that is either a bridge, a bridged (sub thing of a bridge) or a
@@ -21,7 +20,7 @@
*
* @author Arne Seime - Initial contribution
*/
-public abstract class JRuleAbstractThing implements JRuleThingStatusTrigger {
+public abstract class JRuleAbstractThing {
private String thingUID;
protected JRuleAbstractThing(String thingUID) {
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRuleContactTrigger.java b/src/main/java/org/openhab/automation/jrule/trigger/JRuleContactTrigger.java
index 58efe860..2cc74c1d 100644
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRuleContactTrigger.java
+++ b/src/main/java/org/openhab/automation/jrule/trigger/JRuleContactTrigger.java
@@ -17,13 +17,7 @@
*
* @author Joseph (Seaside) Hagberg - Initial contribution
*/
-public interface JRuleContactTrigger extends JRuleCommonTrigger {
- String TRIGGER_RECEIVED_UPDATE_OPEN = "received update OPEN";
- String TRIGGER_RECEIVED_UPDATE_CLOSED = "received update CLOSED";
- String TRIGGER_CHANGED_FROM_OPEN_TO_CLOSED = "Changed from OPEN to CLOSED";
- String TRIGGER_CHANGED_FROM_OPEN = "Changed from OPEN";
- String TRIGGER_CHANGED_FROM_CLOSED = "Changed from CLOSED";
- String TRIGGER_CHANGED_TO_CLOSED = "Changed to CLOSED";
- String TRIGGER_CHANGED_TO_OPEN = "Changed to OPEN";
- String TRIGGER_CHANGED_FROM_CLOSED_TO_OPEN = "Changed from CLOSED to OPEN";
+public interface JRuleContactTrigger {
+ String OPEN = "OPEN";
+ String CLOSED = "CLOSED";
}
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRuleDimmerTrigger.java b/src/main/java/org/openhab/automation/jrule/trigger/JRuleDimmerTrigger.java
deleted file mode 100644
index 1b616f82..00000000
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRuleDimmerTrigger.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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.trigger;
-
-/**
- * The {@link JRuleDimmerTrigger} Items
- *
- * @author Gerhard Riegler - Initial contribution
- */
-public interface JRuleDimmerTrigger extends JRuleCommonTrigger {
- String TRIGGER_RECEIVED_UPDATE_ON = "received update ON";
- String TRIGGER_RECEIVED_UPDATE_OFF = "received update OFF";
- String TRIGGER_RECEIVED_COMMAND_ON = "received command ON";
- String TRIGGER_RECEIVED_COMMAND_OFF = "received command OFF";
- String TRIGGER_CHANGED_FROM_ON_TO_OFF = "Changed from ON to OFF";
- String TRIGGER_CHANGED_FROM_OFF_TO_ON = "Changed from OFF to ON";
- String TRIGGER_CHANGED_FROM_ON = "Changed from ON";
- String TRIGGER_CHANGED_FROM_OFF = "Changed from OFF";
- String TRIGGER_CHANGED_TO_OFF = "Changed to OFF";
- String TRIGGER_CHANGED_TO_ON = "Changed to ON";
-}
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRulePlayerTrigger.java b/src/main/java/org/openhab/automation/jrule/trigger/JRulePlayerTrigger.java
index 3b926516..87acc00b 100644
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRulePlayerTrigger.java
+++ b/src/main/java/org/openhab/automation/jrule/trigger/JRulePlayerTrigger.java
@@ -17,15 +17,7 @@
*
* @author Gerhard Riegler - Initial contribution
*/
-public interface JRulePlayerTrigger extends JRuleCommonTrigger {
- String TRIGGER_RECEIVED_UPDATE_ON = "received update PLAY";
- String TRIGGER_RECEIVED_UPDATE_OFF = "received update PAUSE";
- String TRIGGER_RECEIVED_COMMAND_ON = "received command PLAY";
- String TRIGGER_RECEIVED_COMMAND_OFF = "received command PAUSE";
- String TRIGGER_CHANGED_FROM_ON_TO_OFF = "Changed from PLAY to PAUSE";
- String TRIGGER_CHANGED_FROM_OFF_TO_ON = "Changed from PAUSE to PLAY";
- String TRIGGER_CHANGED_FROM_ON = "Changed from PLAY";
- String TRIGGER_CHANGED_FROM_OFF = "Changed from PAUSE";
- String TRIGGER_CHANGED_TO_OFF = "Changed to PAUSE";
- String TRIGGER_CHANGED_TO_ON = "Changed to PLAY";
+public interface JRulePlayerTrigger {
+ String PLAY = "PLAY";
+ String PAUSE = "PAUSE";
}
diff --git a/src/main/java/org/openhab/automation/jrule/trigger/JRuleSwitchTrigger.java b/src/main/java/org/openhab/automation/jrule/trigger/JRuleSwitchTrigger.java
index 37bc7b04..7a89fb13 100644
--- a/src/main/java/org/openhab/automation/jrule/trigger/JRuleSwitchTrigger.java
+++ b/src/main/java/org/openhab/automation/jrule/trigger/JRuleSwitchTrigger.java
@@ -17,15 +17,7 @@
*
* @author Gerhard Riegler - Initial contribution
*/
-public interface JRuleSwitchTrigger extends JRuleCommonTrigger {
- String TRIGGER_RECEIVED_UPDATE_ON = "received update ON";
- String TRIGGER_RECEIVED_UPDATE_OFF = "received update OFF";
- String TRIGGER_RECEIVED_COMMAND_ON = "received command ON";
- String TRIGGER_RECEIVED_COMMAND_OFF = "received command OFF";
- String TRIGGER_CHANGED_FROM_ON_TO_OFF = "Changed from ON to OFF";
- String TRIGGER_CHANGED_FROM_ON = "Changed from ON";
- String TRIGGER_CHANGED_FROM_OFF = "Changed from OFF";
- String TRIGGER_CHANGED_TO_OFF = "Changed to OFF";
- String TRIGGER_CHANGED_TO_ON = "Changed to ON";
- String TRIGGER_CHANGED_FROM_OFF_TO_ON = "Changed from OFF to ON";
+public interface JRuleSwitchTrigger {
+ String ON = "ON";
+ String OFF = "OFF";
}
diff --git a/src/test/java/org/openhab/binding/jrule/internal/cron/JRuleCronTest.java b/src/test/java/org/openhab/binding/jrule/internal/cron/JRuleCronTest.java
deleted file mode 100644
index 7e440c27..00000000
--- a/src/test/java/org/openhab/binding/jrule/internal/cron/JRuleCronTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * 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.binding.jrule.internal.cron;
-
-import java.time.ZonedDateTime;
-import java.util.Date;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.automation.jrule.internal.cron.JRuleCronExpression;
-import org.openhab.binding.jrule.internal.JRuleUtilTest;
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-
-/**
- * The {@link JRuleUtilTest}
- *
- * @author Joseph (Seaside) Hagberg - Initial contribution
- */
-public class JRuleCronTest {
-
- private static final Logger logger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
-
- @BeforeEach
- public void setUp() {
- Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
- rootLogger.setLevel(Level.ALL);
- }
-
- @Test
- public void testParseItemName() {
- // sec min hour day month DAY
- JRuleCronExpression expr = new JRuleCronExpression("4 10 21 6 8 *");
- ZonedDateTime nextTimeAfter = expr.nextTimeAfter(ZonedDateTime.now());
- Date futureTime = Date.from(nextTimeAfter.toInstant());
- long initialDelay = new Date(futureTime.getTime() - System.currentTimeMillis()).getTime();
- logger.debug("Schedule cron: {} initialDelay: {}", futureTime, initialDelay);
- }
-}