Refactored storing logic of triggers and actions. issue 6
This commit is contained in:
parent
8d9354d845
commit
a1cb12f6ce
12 changed files with 227 additions and 201 deletions
|
|
@ -94,7 +94,7 @@
|
|||
|
||||
<target name="build-dependencies">
|
||||
<mkdir dir="${buildDir}" />
|
||||
<get src="http://ci.koc.se/jenkins/job/Zutil/119/artifact/build/release/Zutil.jar"
|
||||
<get src="http://ci.koc.se/jenkins/job/Zutil/131/artifact/build/release/Zutil.jar"
|
||||
dest="${libDir}" verbose="true" usetimestamp="true"/>
|
||||
</target>
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,53 @@
|
|||
|
||||
|
||||
<!-------------------------------- MODALS -------------------------------->
|
||||
<script>
|
||||
$(function(){
|
||||
initDynamicModalForm("trigger");
|
||||
initDynamicModalForm("action");
|
||||
});
|
||||
|
||||
|
||||
var dynamicConf = {};
|
||||
|
||||
function initDynamicModalForm(name){
|
||||
// read in all configurations into global variable (to skip naming issues)
|
||||
dynamicConf[name] = [];
|
||||
$("#"+name+"-data-conf-template div").each(function(){
|
||||
dynamicConf[name][$(this).attr("id")] = $(this).html();
|
||||
});
|
||||
// Update dynamic inputs
|
||||
$("#"+name+"Modal select[name=type]").change(function(){
|
||||
$("#"+name+"Modal #"+name+"-data-conf").html(dynamicConf[name][$(this).val()]);
|
||||
});
|
||||
// click event
|
||||
$("#"+name+"Modal").on('show.bs.modal', function (event) {
|
||||
var button = $(event.relatedTarget);
|
||||
var modal = $(this);
|
||||
modal.find("input[type=text]").val(""); // Reset all inputs
|
||||
if(button.data("id") >= 0){ // edit
|
||||
modal.find("input[name=action]").val("modify_"+name);
|
||||
}
|
||||
else{ // create
|
||||
modal.find("input[name=action]").val("create_"+name);
|
||||
modal.find("input[name=id]").val(-1);
|
||||
}
|
||||
// set dynamic form data
|
||||
modal.find("select[name=type]").val(button.data("type"));
|
||||
modal.find("select[name=type]").change(); // Update dynamic inputs
|
||||
$.each(button.attr(), function(fieldName, value) {
|
||||
if(fieldName.startsWith("data-")) {
|
||||
fieldName = fieldName.substring(5);
|
||||
console.log(fieldName, value);
|
||||
// case insensitive search
|
||||
modal.find("input").filter(function() {
|
||||
return this.name.toLowerCase() == fieldName;
|
||||
}).val(value);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="modal fade" id="triggerModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
|
|
@ -119,6 +166,10 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div id="trigger-data-conf">
|
||||
<!-- Dynamic form -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="reset" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
|
|
@ -150,6 +201,10 @@
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div id="action-data-conf">
|
||||
<!-- Dynamic form -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="reset" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
|
|
@ -158,4 +213,45 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="trigger-data-conf-template" class="hidden">
|
||||
{{#triggerConf}}
|
||||
<div id="{{.clazz.getName()}}">
|
||||
{{#.params}}
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{.getNiceName()}}:</label>
|
||||
{{#.isTypeString()}}<input type="text" class="form-control" name="{{.getName()}}">{{/#.isTypeString()}}
|
||||
{{#.isTypeInt()}}<input type="number" class="form-control" name="{{.getName()}}">{{/#.isTypeInt()}}
|
||||
{{#.isTypeBoolean()}}<input type="checkbox" name="{{.getName()}}">{{/#.isTypeBoolean()}}
|
||||
{{#.isTypeEnum()}}
|
||||
<select class="form-control" name="{{.getName()}}">
|
||||
{{#.getPossibleValues()}}<option>{{.}}</option>{{/.getPossibleValues()}}
|
||||
</select>
|
||||
{{/#.isTypeEnum()}}
|
||||
</div>
|
||||
{{/.params}}
|
||||
</div>
|
||||
{{/triggerConf}}
|
||||
</div>
|
||||
|
||||
<div id="sensor-data-conf-template" class="hidden">
|
||||
{{#actionConf}}
|
||||
<div id="{{.clazz.getName()}}">
|
||||
{{#.params}}
|
||||
<div class="form-group">
|
||||
<label class="control-label">{{.getNiceName()}}:</label>
|
||||
{{#.isTypeString()}}<input type="text" class="form-control" name="{{.getName()}}">{{/#.isTypeString()}}
|
||||
{{#.isTypeInt()}}<input type="number" class="form-control" name="{{.getName()}}">{{/#.isTypeInt()}}
|
||||
{{#.isTypeBoolean()}}<input type="checkbox" name="{{.getName()}}">{{/#.isTypeBoolean()}}
|
||||
{{#.isTypeEnum()}}
|
||||
<select class="form-control" name="{{.getName()}}">
|
||||
{{#.getPossibleValues()}}<option>{{.}}</option>{{/.getPossibleValues()}}
|
||||
</select>
|
||||
{{/#.isTypeEnum()}}
|
||||
</div>
|
||||
{{/.params}}
|
||||
</div>
|
||||
{{/actionConf}}
|
||||
</div>
|
||||
|
|
@ -1,49 +1,14 @@
|
|||
package se.hal.intf;
|
||||
|
||||
import se.hal.struct.TriggerFlow;
|
||||
import se.hal.struct.dso.ActionDSO;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBean;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines a action that will be executed
|
||||
*/
|
||||
public abstract class HalAction{
|
||||
private ActionDSO dso;
|
||||
|
||||
|
||||
public static HalAction getAction(DBConnection db, long id) throws SQLException {
|
||||
ActionDSO dso = DBBean.load(db, ActionDSO.class, id);
|
||||
dso.getObject().dso = dso;
|
||||
return dso.getObject();
|
||||
}
|
||||
public static List<HalAction> getActions(DBConnection db, TriggerFlow flow) {
|
||||
// TODO:
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Long getId(){
|
||||
return (dso!=null ? dso.getId() : null);
|
||||
}
|
||||
|
||||
public void save(DBConnection db) throws SQLException {
|
||||
if (dso == null)
|
||||
dso = new ActionDSO();
|
||||
dso.setObject(this);
|
||||
dso.save(db);
|
||||
}
|
||||
|
||||
public void delete(DBConnection db) throws SQLException {
|
||||
dso.delete(db);
|
||||
}
|
||||
|
||||
public interface HalAction{
|
||||
|
||||
/**
|
||||
* Executes this specific action
|
||||
*/
|
||||
public abstract void execute();
|
||||
void execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,58 +1,22 @@
|
|||
package se.hal.intf;
|
||||
|
||||
import se.hal.struct.TriggerFlow;
|
||||
import se.hal.struct.dso.TriggerDSO;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBean;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class that declares a trigger/condition that
|
||||
* A interface that declares a trigger/condition that
|
||||
* needs to be validated before an action can be run
|
||||
*/
|
||||
public abstract class HalTrigger{
|
||||
private TriggerDSO dso;
|
||||
|
||||
|
||||
public static HalTrigger getTrigger(DBConnection db, long id) throws SQLException {
|
||||
TriggerDSO dso = DBBean.load(db, TriggerDSO.class, id);
|
||||
dso.getObject().dso = dso;
|
||||
return dso.getObject();
|
||||
}
|
||||
public static List<HalTrigger> getTriggers(DBConnection db, TriggerFlow flow) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Long getId(){
|
||||
return (dso!=null ? dso.getId() : null);
|
||||
}
|
||||
|
||||
public void save(DBConnection db) throws SQLException {
|
||||
if (dso == null)
|
||||
dso = new TriggerDSO();
|
||||
dso.setObject(this);
|
||||
dso.save(db);
|
||||
}
|
||||
|
||||
public void delete(DBConnection db) throws SQLException {
|
||||
dso.delete(db);
|
||||
}
|
||||
|
||||
|
||||
public interface HalTrigger{
|
||||
|
||||
/**
|
||||
* Evaluates if this trigger has passed. If the trigger is
|
||||
* true then this method will return true until the {@link #reset()}
|
||||
* method is called.
|
||||
*/
|
||||
public abstract boolean evaluate();
|
||||
boolean evaluate();
|
||||
|
||||
/**
|
||||
* Reset the evaluation to false.
|
||||
*/
|
||||
public abstract void reset();
|
||||
void reset();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ import se.hal.TriggerManager;
|
|||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalHttpPage;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import se.hal.struct.Action;
|
||||
import se.hal.struct.ClassConfigurationData;
|
||||
import se.hal.struct.Trigger;
|
||||
import se.hal.struct.TriggerFlow;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.io.file.FileUtil;
|
||||
|
|
@ -46,12 +48,12 @@ public class TriggerHttpPage extends HalHttpPage {
|
|||
TriggerFlow flow = null;
|
||||
if (request.containsKey("flow_id"))
|
||||
flow = TriggerFlow.getTriggerFlow(db, Integer.parseInt(request.get("flow_id")));
|
||||
HalTrigger trigger = null;
|
||||
Trigger trigger = null;
|
||||
if (request.containsKey("trigger_id"))
|
||||
trigger = HalTrigger.getTrigger(db, Integer.parseInt(request.get("trigger_id")));
|
||||
HalAction action = null;
|
||||
trigger = Trigger.getTrigger(db, Integer.parseInt(request.get("trigger_id")));
|
||||
Action action = null;
|
||||
if (request.containsKey("action_id"))
|
||||
action = HalAction.getAction(db, Integer.parseInt(request.get("action_id")));
|
||||
action = Action.getAction(db, Integer.parseInt(request.get("action_id")));
|
||||
|
||||
|
||||
switch(request.get("action")) {
|
||||
|
|
@ -94,8 +96,8 @@ public class TriggerHttpPage extends HalHttpPage {
|
|||
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
||||
tmpl.set("triggerConfigurations", triggerConfigurators);
|
||||
tmpl.set("actionConfigurations", actionConfigurators);
|
||||
tmpl.set("triggerConf", triggerConfigurators);
|
||||
tmpl.set("actionConf", actionConfigurators);
|
||||
tmpl.set("availableTriggers", TriggerManager.getInstance().getAvailableTriggers());
|
||||
tmpl.set("availableActions", TriggerManager.getInstance().getAvailableActions());
|
||||
tmpl.set("flows", TriggerFlow.getTriggerFlows(db));
|
||||
|
|
|
|||
43
src/se/hal/struct/Action.java
Executable file
43
src/se/hal/struct/Action.java
Executable file
|
|
@ -0,0 +1,43 @@
|
|||
package se.hal.struct;
|
||||
|
||||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBean;
|
||||
import zutil.db.bean.DBBeanObjectDSO;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines a action that will be executed
|
||||
*/
|
||||
@DBBean.DBTable(value = "action", superBean = true)
|
||||
public class Action extends DBBeanObjectDSO<HalAction>{
|
||||
|
||||
|
||||
public static Action getAction(DBConnection db, long id) throws SQLException {
|
||||
return DBBean.load(db, Action.class, id);
|
||||
}
|
||||
public static List<Action> getActions(DBConnection db, TriggerFlow flow) {
|
||||
// TODO:
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Action() { }
|
||||
public Action(HalAction action) {
|
||||
this.setObject(action);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Executes this specific action
|
||||
*/
|
||||
public void execute(){
|
||||
if (getObject() != null)
|
||||
getObject().execute();
|
||||
}
|
||||
|
||||
}
|
||||
54
src/se/hal/struct/Trigger.java
Executable file
54
src/se/hal/struct/Trigger.java
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
package se.hal.struct;
|
||||
|
||||
import se.hal.intf.HalTrigger;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBean;
|
||||
import zutil.db.bean.DBBeanObjectDSO;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A class that declares a trigger/condition that
|
||||
* needs to be validated before an action can be run
|
||||
*/
|
||||
@DBBean.DBTable(value = "trigger", superBean = true)
|
||||
public class Trigger extends DBBeanObjectDSO<HalTrigger>{
|
||||
|
||||
|
||||
|
||||
public static Trigger getTrigger(DBConnection db, long id) throws SQLException {
|
||||
return DBBean.load(db, Trigger.class, id);
|
||||
}
|
||||
public static List<Trigger> getTriggers(DBConnection db, TriggerFlow flow) {
|
||||
// Todo:
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Trigger() { }
|
||||
public Trigger(HalTrigger trigger) {
|
||||
this.setObject(trigger);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluates if this trigger has passed. If the trigger is
|
||||
* true then this method will return true until the {@link #reset()}
|
||||
* method is called.
|
||||
*/
|
||||
public boolean evaluate(){
|
||||
if (getObject() != null)
|
||||
return getObject().evaluate();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the evaluation to false.
|
||||
*/
|
||||
public void reset(){
|
||||
if (getObject() != null)
|
||||
getObject().reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,8 +26,8 @@ import java.util.logging.Logger;
|
|||
public class TriggerFlow extends DBBean {
|
||||
private static final Logger logger = LogUtil.getLogger();
|
||||
|
||||
private transient List<HalTrigger> triggerList = new ArrayList<>();
|
||||
private transient List<HalAction> actionList = new ArrayList<>();
|
||||
private transient List<Trigger> triggerList = new ArrayList<>();
|
||||
private transient List<Action> actionList = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
|
|
@ -46,24 +46,24 @@ public class TriggerFlow extends DBBean {
|
|||
DBConnection db = HalContext.getDB();
|
||||
|
||||
triggerList.clear();
|
||||
triggerList = HalTrigger.getTriggers(db, this);
|
||||
triggerList = Trigger.getTriggers(db, this);
|
||||
|
||||
actionList.clear();
|
||||
actionList = HalAction.getActions(db, this);
|
||||
actionList = Action.getActions(db, this);
|
||||
}
|
||||
|
||||
|
||||
public void addTrigger(HalTrigger trigger) {
|
||||
public void addTrigger(Trigger trigger) {
|
||||
triggerList.add(trigger);
|
||||
}
|
||||
public void removeTrigger(HalTrigger trigger) {
|
||||
public void removeTrigger(Trigger trigger) {
|
||||
triggerList.remove(trigger);
|
||||
}
|
||||
|
||||
public void addAction(HalAction action) {
|
||||
public void addAction(Action action) {
|
||||
actionList.add(action);
|
||||
}
|
||||
public void removeAction(HalAction action) {
|
||||
public void removeAction(Action action) {
|
||||
actionList.remove(action);
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ public class TriggerFlow extends DBBean {
|
|||
* Note: this method will not execute any actionList
|
||||
*/
|
||||
public boolean evaluate(){
|
||||
for(HalTrigger trigger : triggerList){
|
||||
for(Trigger trigger : triggerList){
|
||||
if (trigger.evaluate())
|
||||
return true;
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ public class TriggerFlow extends DBBean {
|
|||
* Executes the associated actionList in this flow
|
||||
*/
|
||||
public void execute(){
|
||||
for(HalAction action : actionList){
|
||||
for(Action action : actionList){
|
||||
action.execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ public class TriggerFlow extends DBBean {
|
|||
* Resets all trigger evaluations
|
||||
*/
|
||||
public void reset() {
|
||||
for(HalTrigger trigger : triggerList){
|
||||
for(Trigger trigger : triggerList){
|
||||
trigger.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
package se.hal.struct.dso;
|
||||
|
||||
import se.hal.intf.HalAction;
|
||||
import zutil.db.bean.DBBean;
|
||||
|
||||
|
||||
/**
|
||||
* A intermediate class for loading HalAction objects from DB
|
||||
*/
|
||||
@DBBean.DBTable(value = "action", superBean = true)
|
||||
public class ActionDSO extends ObjectDSO<HalAction>{
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package se.hal.struct.dso;
|
||||
|
||||
import se.hal.intf.HalTrigger;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.db.bean.DBBean;
|
||||
import zutil.log.LogUtil;
|
||||
import zutil.parser.json.JSONParser;
|
||||
import zutil.parser.json.JSONWriter;
|
||||
import zutil.ui.Configurator;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* A intermediate class for loading HalTrigger objects from DB
|
||||
*/
|
||||
public abstract class ObjectDSO<T> extends DBBean{
|
||||
private static final Logger logger = LogUtil.getLogger();
|
||||
|
||||
// DB parameters
|
||||
private String type;
|
||||
private String config;
|
||||
|
||||
// Local parameters
|
||||
private transient T cachedObj;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void postUpdateAction() {
|
||||
if (type != null && !type.isEmpty()) {
|
||||
if (cachedObj == null) {
|
||||
try {
|
||||
Class clazz = Class.forName(type);
|
||||
cachedObj = (T) clazz.newInstance();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Unable instantiate class: " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (config != null && !config.isEmpty()) {
|
||||
Configurator<T> configurator = new Configurator<>(cachedObj);
|
||||
configurator.setValues(JSONParser.read(config));
|
||||
configurator.applyConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(DBConnection db) throws SQLException {
|
||||
if (cachedObj == null)
|
||||
this.config = null;
|
||||
else {
|
||||
Configurator<T> configurator = new Configurator<>(cachedObj);
|
||||
this.config = JSONWriter.toString(configurator.getValuesAsNode());
|
||||
}
|
||||
super.save(db);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public T getObject(){
|
||||
return cachedObj;
|
||||
}
|
||||
|
||||
public void setObject(T obj){
|
||||
this.cachedObj = obj;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
package se.hal.struct.dso;
|
||||
|
||||
import se.hal.intf.HalTrigger;
|
||||
import zutil.db.bean.DBBean;
|
||||
|
||||
|
||||
/**
|
||||
* A intermediate class for loading HalTrigger objects from DB
|
||||
*/
|
||||
@DBBean.DBTable(value = "trigger", superBean = true)
|
||||
public class TriggerDSO extends ObjectDSO<HalTrigger>{
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@ package se.hal;
|
|||
import org.junit.Test;
|
||||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import se.hal.struct.Action;
|
||||
import se.hal.struct.Trigger;
|
||||
import se.hal.struct.TriggerFlow;
|
||||
|
||||
import java.util.Collections;
|
||||
|
|
@ -43,9 +45,9 @@ public class TriggerManagerTest {
|
|||
registerAvailableTrigger();
|
||||
|
||||
TriggerFlow flow = new TriggerFlow();
|
||||
flow.addTrigger(new TestTrigger(true));
|
||||
flow.addTrigger(new Trigger(new TestTrigger(true)));
|
||||
TestAction action = new TestAction();
|
||||
flow.addAction(action);
|
||||
flow.addAction(new Action(action));
|
||||
manager.register(flow);
|
||||
manager.evaluateAndExecute();
|
||||
assertEquals(1, action.nrOfExecutions);
|
||||
|
|
@ -58,9 +60,9 @@ public class TriggerManagerTest {
|
|||
|
||||
TriggerFlow flow = new TriggerFlow();
|
||||
TestTrigger trigger = new TestTrigger(true);
|
||||
flow.addTrigger(trigger);
|
||||
flow.addTrigger(new Trigger(trigger));
|
||||
TestAction action = new TestAction();
|
||||
flow.addAction(action);
|
||||
flow.addAction(new Action(action));
|
||||
manager.register(flow);
|
||||
|
||||
manager.evaluateAndExecute();
|
||||
|
|
@ -75,7 +77,7 @@ public class TriggerManagerTest {
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static class TestTrigger extends HalTrigger {
|
||||
private static class TestTrigger implements HalTrigger {
|
||||
boolean evaluation;
|
||||
TestTrigger(boolean b){ evaluation = b; }
|
||||
@Override
|
||||
|
|
@ -86,7 +88,7 @@ public class TriggerManagerTest {
|
|||
}
|
||||
|
||||
|
||||
private class TestAction extends HalAction {
|
||||
private class TestAction implements HalAction {
|
||||
int nrOfExecutions;
|
||||
@Override
|
||||
public void execute() { nrOfExecutions++; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue