Implementation of DB read and store procedures for Actions and triggers(not tested). issue 6

This commit is contained in:
Ziver Koc 2017-01-16 17:10:11 +01:00
parent 44d5fa0227
commit 4b24615f4f
11 changed files with 249 additions and 22 deletions

Binary file not shown.

View file

@ -7,6 +7,7 @@ import se.hal.intf.HalJsonPage;
import se.hal.page.*;
import se.hal.struct.Event;
import se.hal.struct.Sensor;
import se.hal.struct.TriggerFlow;
import zutil.db.DBConnection;
import zutil.io.file.FileUtil;
import zutil.log.LogUtil;
@ -47,16 +48,20 @@ public class HalServer {
TriggerManager.initialize(pluginManager);
// Init sensors,events and controllers
// Import sensors,events and controllers
for(Sensor sensor : Sensor.getLocalSensors(db)){
ControllerManager.getInstance().register(sensor);
}
for(Event event : Event.getLocalEvents(db)){
ControllerManager.getInstance().register(event);
}
// Import triggers
for(TriggerFlow flow : TriggerFlow.getTriggerFlows(db)){
TriggerManager.getInstance().register(flow);
}
// init daemons
// Init daemons
// We set only one thread for easier troubleshooting
daemonExecutor = Executors.newScheduledThreadPool(1);
for (Iterator<HalDaemon> it=pluginManager.getObjectIterator(HalDaemon.class); it.hasNext(); )

View file

@ -6,12 +6,14 @@ import se.hal.struct.TriggerFlow;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -30,6 +32,7 @@ public class TriggerManager {
private ScheduledExecutorService executor;
public void setEvaluationInterval(long interval) {
if (executor != null)
executor.shutdownNow();

View file

@ -1,9 +1,40 @@
package se.hal.intf;
import se.hal.struct.dso.ActionDSO;
import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
import java.sql.SQLException;
/**
* Defines a action that will be executed
*/
public interface HalAction {
public abstract class HalAction{
private ActionDSO dso;
void execute();
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 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);
}
/**
* Executes this specific action
*/
public abstract void execute();
}

View file

@ -1,20 +1,47 @@
package se.hal.intf;
import se.hal.struct.dso.TriggerDSO;
import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
import java.sql.SQLException;
/**
* A interfaces that declares a trigger/condition that
* A class that declares a trigger/condition that
* needs to be validated before an action can be run
*/
public interface HalTrigger {
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 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);
}
/**
* Evaluates if this trigger has passed. If the trigger is
* true then this method will return true until the {@link #reset()}
* method is called.
*/
boolean evaluate();
public abstract boolean evaluate();
/**
* Reset the evaluation to false.
*/
void reset();
public abstract void reset();
}

View file

@ -85,6 +85,7 @@ public abstract class AbstractDevice<T,D> extends DBBean {
}
}
@Override
public void save(DBConnection db) throws SQLException {
if (deviceConfig != null)
updateConfigString();

View file

@ -1,34 +1,94 @@
package se.hal.struct;
import se.hal.HalContext;
import se.hal.intf.HalAction;
import se.hal.intf.HalTrigger;
import zutil.db.DBConnection;
import zutil.db.bean.DBBean;
import zutil.db.bean.DBBeanSQLResultHandler;
import zutil.log.LogUtil;
import zutil.parser.DataNode;
import zutil.parser.json.JSONParser;
import zutil.parser.json.JSONWriter;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A class that encapsulates triggers and their actions.
* A class that encapsulates triggerList and their actionList.
* TODO: Bad class name, should be renamed when we come up with a better one
*/
@DBBean.DBTable("trigger_flow")
public class TriggerFlow extends DBBean {
private ArrayList<HalTrigger> triggers = new ArrayList<>();
private ArrayList<HalAction> actions = new ArrayList<>();
private static final Logger logger = LogUtil.getLogger();
private String triggers; // only used for flat DB storage
private transient ArrayList<HalTrigger> triggerList = new ArrayList<>();
private String actions; // only used for flat DB storage
private transient ArrayList<HalAction> actionList = new ArrayList<>();
public static List<TriggerFlow> getTriggerFlows(DBConnection db) throws SQLException {
PreparedStatement stmt = db.getPreparedStatement("SELECT * FROM trigger_flow");
return DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(TriggerFlow.class, db));
}
@Override
public void save(DBConnection db) throws SQLException {
DataNode root = new DataNode(DataNode.DataType.List);
for (HalTrigger t : triggerList)
root.add(t.getId());
triggers = JSONWriter.toString(root);
for (HalAction a : actionList)
root.add(a.getId());
actions = JSONWriter.toString(root);
super.save(db);
}
@Override
protected void postUpdateAction() {
DBConnection db = HalContext.getDB();
triggerList.clear();
for (DataNode tId : JSONParser.read(triggers))
try {
triggerList.add(HalTrigger.getTrigger(db, tId.getInt()));
} catch (SQLException e) {
logger.log(Level.SEVERE, null, e);
}
actionList.clear();
for (DataNode aId : JSONParser.read(actions))
try {
actionList.add(HalAction.getAction(db, aId.getInt()));
} catch (SQLException e) {
logger.log(Level.SEVERE, null, e);
}
}
public void addTrigger(HalTrigger trigger) {
triggers.add(trigger);
triggerList.add(trigger);
}
public void addAction(HalAction action) {
actions.add(action);
actionList.add(action);
}
/**
* @return true if any one of the triggers evaluate to true,
* false if there are no triggers added.
* Note: this method will not execute any actions
* @return true if any one of the triggerList evaluate to true,
* false if there are no triggerList added.
* Note: this method will not execute any actionList
*/
public boolean evaluate(){
for(HalTrigger trigger : triggers){
for(HalTrigger trigger : triggerList){
if (trigger.evaluate())
return true;
}
@ -36,10 +96,10 @@ public class TriggerFlow extends DBBean {
}
/**
* Executes the associated actions in this flow
* Executes the associated actionList in this flow
*/
public void execute(){
for(HalAction action : actions){
for(HalAction action : actionList){
action.execute();
}
}
@ -48,7 +108,7 @@ public class TriggerFlow extends DBBean {
* Resets all trigger evaluations
*/
public void reset() {
for(HalTrigger trigger : triggers){
for(HalTrigger trigger : triggerList){
trigger.reset();
}
}

View file

@ -0,0 +1,14 @@
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>{
}

View file

@ -0,0 +1,72 @@
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;
}
}

View file

@ -0,0 +1,14 @@
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>{
}

View file

@ -75,7 +75,7 @@ public class TriggerManagerTest {
/////////////////////////////////////////////////////////////////////////////
private static class TestTrigger implements HalTrigger {
private static class TestTrigger extends HalTrigger {
boolean evaluation;
TestTrigger(boolean b){ evaluation = b; }
@Override
@ -86,7 +86,7 @@ public class TriggerManagerTest {
}
private class TestAction implements HalAction {
private class TestAction extends HalAction {
int nrOfExecutions;
@Override
public void execute() { nrOfExecutions++; }