Skip to content

Commit

Permalink
Initial commit of JSON rules (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
richturner committed Dec 23, 2018
1 parent 8aa3d82 commit 6baec89
Show file tree
Hide file tree
Showing 19 changed files with 1,275 additions and 1 deletion.

Large diffs are not rendered by default.

Expand Up @@ -31,15 +31,18 @@
import org.jeasy.rules.core.RuleBuilder;
import org.kohsuke.groovy.sandbox.GroovyValueFilter;
import org.kohsuke.groovy.sandbox.SandboxTransformer;
import org.openremote.container.Container;
import org.openremote.container.timer.TimerService;
import org.openremote.manager.asset.AssetStorageService;
import org.openremote.manager.rules.facade.NotificationsFacade;
import org.openremote.model.rules.Assets;
import org.openremote.model.rules.Ruleset;
import org.openremote.model.rules.RulesetStatus;
import org.openremote.model.rules.Users;
import org.openremote.model.rules.json.JsonRulesetDefinition;

import javax.script.*;
import java.io.IOException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -152,10 +155,26 @@ public boolean registerRules(Ruleset ruleset, Assets assetsFacade, Users usersFa
return registerRulesJavascript(ruleset, assetsFacade, usersFacade, notificationFacade);
case GROOVY:
return registerRulesGroovy(ruleset, assetsFacade, usersFacade, notificationFacade);
case JSON:
return registerRulesJson(ruleset);
}
return false;
}

private boolean registerRulesJson(Ruleset ruleset) {
try {
JsonRulesetDefinition simpleRulesetDefinition = Container.JSON.readValue(ruleset.getRules(), JsonRulesetDefinition.class);

JsonRulesBuilder simpleRulesBuilder = new JsonRulesBuilder(timerService, assetStorageService);
return true;

} catch (IOException e) {
RulesEngine.LOG.log(Level.SEVERE, "Error evaluating ruleset: " + ruleset, e);
setError(e);
return false;
}
}

public boolean registerRulesJavascript(Ruleset ruleset, Assets assetsFacade, Users usersFacade, NotificationsFacade consolesFacade) {
// TODO https://github.com/pfisterer/scripting-sandbox/blob/master/src/main/java/de/farberg/scripting/sandbox/ScriptingSandbox.java
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn");
Expand Down
28 changes: 27 additions & 1 deletion model/src/main/java/org/openremote/model/rules/Ruleset.java
Expand Up @@ -19,12 +19,14 @@
*/
package org.openremote.model.rules;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import java.util.Date;
import java.util.Optional;

Expand Down Expand Up @@ -98,7 +100,31 @@ public enum Lang {
" facts.updateAssetState(\n" +
" facts.bound(\"assetId\") as String, \"someAttribute\", \"bar\"\n" +
" )\n" +
" })");
" })"),
JSON(".json",
"locations: [],\n" +
"rules: [\n" +
" {\n" +
" name: \"Test Rule\",\n" +
" when: {\n" +
" operator: \"AND\",\n" +
" predicates: [\n" +
" {\n" +
" query: {\n" +
"\n" +
" }\n" +
" }\n" +
" ],\n" +
" conditions: []\n" +
" },\n" +
" then: {\n" +
" notifications: [],\n" +
" attributeEvents: []\n" +
" },\n" +
" reset: null // Only trigger once ever\n" +
" }\n" +
"]"
);

final String fileExtension;
final String emptyRulesExample;
Expand Down
@@ -0,0 +1,24 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

public class JsonRulesetDefinition {
protected Rule[] rules;
}
61 changes: 61 additions & 0 deletions model/src/main/java/org/openremote/model/rules/json/Rule.java
@@ -0,0 +1,61 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

import org.openremote.model.rules.json.predicate.AssetPredicate;

/**
* A declarative rule definition (a.k.a. JSON rules); consists of:
* <p>
* <h2>LHS</li>
* <p>
* {@link #when}* - This can be either a {@link RuleTrigger#timer} for time based rules or an {@link AssetPredicate}
* which will be used to filter {@link org.openremote.model.rules.AssetState}s currently available in the rule engine
* that this rule is loaded into. The {@link AssetPredicate} will evaluate to true when one or more
* {@link org.openremote.model.rules.AssetState}s are returned by applying the filter. The returned
* {@link org.openremote.model.rules.AssetState}s are then used as context for the RHS and also the
* {@link RuleTriggerReset} (if specified).
* <p>
* {@link #and} - Optional condition that can be used to further restrict the LHS but without affecting the
* {@link org.openremote.model.rules.AssetState}s that form the context for the RHS. If this is specified then the
* {@link #when} must evaluate to true and this condition must evaluate to true.
* <h2>RHS</h2>
* <p>
* {@link #then}* - Defines a series of {@link RuleAction}s to perform when the rule triggers.
* <h2>Reset</h2>
* <p>
* {@link #reset}* - Optional logic used to reset the rule, this is applied to each
* {@link org.openremote.model.rules.AssetState} that was returned by the {@link #when}. If no reset is specified then
* it is assumed that the rule is fire once per matched {@link org.openremote.model.rules.AssetState}.
* <b>NOTE: Rule trigger history is not persisted so on system restart this information is lost and a rule will be
* able to fire again.</b>
* <p>
* <b>* = Required</b>
*/
public class Rule {

public String name;
public String description;
public int priority = Integer.MAX_VALUE-1;
public RuleTrigger when;
public RuleCondition<AssetPredicate> and;
public RuleAction[] then;
public RuleTriggerReset reset;
}
@@ -0,0 +1,36 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonSubTypes({
@JsonSubTypes.Type(value = RuleActionWait.class, name = "wait"),
@JsonSubTypes.Type(value = RuleActionWriteAttribute.class, name = "write-attribute"),
@JsonSubTypes.Type(value = RuleActionNotification.class, name = "notification")
})
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "action"
)
public interface RuleAction {

}
@@ -0,0 +1,26 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

import org.openremote.model.notification.AbstractNotificationMessage;

public class RuleActionNotification extends RuleActionWithTarget {
protected AbstractNotificationMessage notification;
}
@@ -0,0 +1,24 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

public class RuleActionWait implements RuleAction {
protected long millis;
}
@@ -0,0 +1,34 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

import org.openremote.model.query.AssetQuery;
import org.openremote.model.query.UserQuery;

public abstract class RuleActionWithTarget implements RuleAction {

public static class Target {
protected boolean useAssetsFromWhen;
protected AssetQuery assets;
protected UserQuery users;
}

protected Target target;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

import org.openremote.model.value.Value;

public class RuleActionWriteAttribute extends RuleActionWithTarget {
protected String attributeName;
protected Value value;
}
@@ -0,0 +1,38 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

public class RuleCondition<T> {

/**
* If not specified then {@link RuleOperator#AND} is assumed.
*/
public RuleOperator operator;

/**
* Defines the predicates to apply using the {@link #operator}
*/
public T[] predicates;

/**
* Nested conditions allow for more complex logic with a mix of operators
*/
public RuleCondition<T>[] conditions;
}
@@ -0,0 +1,25 @@
/*
* Copyright 2018, OpenRemote Inc.
*
* See the CONTRIBUTORS.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.model.rules.json;

public enum RuleOperator {
AND,
OR
}

0 comments on commit 6baec89

Please sign in to comment.