initial implementation of triggers. issue 6
This commit is contained in:
parent
6a8040b529
commit
dd1bb75192
8 changed files with 283 additions and 11 deletions
|
|
@ -32,16 +32,17 @@ public class HalServer {
|
|||
// init logging
|
||||
LogUtil.readConfiguration("logging.properties");
|
||||
|
||||
// init DB and other configurations
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
// init Managers
|
||||
PluginManager pluginManager = new PluginManager("./");
|
||||
HalContext.initialize();
|
||||
ControllerManager.initialize(pluginManager);
|
||||
HalAlertManager.initialize();
|
||||
ControllerManager.initialize(pluginManager);
|
||||
TriggerManager.initialize(pluginManager);
|
||||
|
||||
|
||||
// init DB and other configurations
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
// Init sensors,events and controllers
|
||||
for(Sensor sensor : Sensor.getLocalSensors(db)){
|
||||
ControllerManager.getInstance().register(sensor);
|
||||
|
|
|
|||
90
src/se/hal/TriggerManager.java
Executable file
90
src/se/hal/TriggerManager.java
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
package se.hal;
|
||||
|
||||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import se.hal.struct.TriggerFlow;
|
||||
import zutil.log.LogUtil;
|
||||
import zutil.plugin.PluginManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* Handles all triggers registered on Hal
|
||||
*/
|
||||
public class TriggerManager {
|
||||
private static final Logger logger = LogUtil.getLogger();
|
||||
private static TriggerManager instance;
|
||||
|
||||
private ArrayList<Class<? extends HalTrigger>> availableTriggers = new ArrayList<>();
|
||||
private ArrayList<Class<? extends HalAction>> availableActions = new ArrayList<>();
|
||||
|
||||
private ArrayList<TriggerFlow> triggerFlows = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
public void addAvailableTrigger(Class<? extends HalTrigger> clazz) {
|
||||
if ( ! availableTriggers.contains(clazz))
|
||||
availableTriggers.add(clazz);
|
||||
}
|
||||
public List<Class<? extends HalTrigger>> getAvailableTriggers() {
|
||||
return availableTriggers;
|
||||
}
|
||||
|
||||
public void addAvailableAction(Class<? extends HalAction> clazz) {
|
||||
if ( ! availableActions.contains(clazz))
|
||||
availableActions.add(clazz);
|
||||
}
|
||||
public List<Class<? extends HalAction>> getAvailableActions() {
|
||||
return availableActions;
|
||||
}
|
||||
|
||||
public void register(TriggerFlow flow){
|
||||
if ( ! triggerFlows.contains(flow))
|
||||
triggerFlows.add(flow);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Main execution method.
|
||||
* This method will go through all flows and evaluate them. If the
|
||||
* evaluation of a trigger returns true then its execute method will be called.
|
||||
*/
|
||||
public synchronized void evaluateAndExecute() {
|
||||
for (int i = 0; i < triggerFlows.size(); i++) { // avoid foreach as triggerFlow can change while we are running
|
||||
TriggerFlow flow = triggerFlows.get(i);
|
||||
if (flow.evaluate()) {
|
||||
logger.fine("Flow "+ flow.getId() +" evaluated true, executing actions");
|
||||
flow.execute();
|
||||
flow.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void initialize(PluginManager pluginManager){
|
||||
TriggerManager manager = new TriggerManager();
|
||||
|
||||
for (Iterator<Class<? extends HalTrigger>> it = pluginManager.getClassIterator(HalTrigger.class);
|
||||
it.hasNext(); ){
|
||||
manager.addAvailableTrigger(it.next());
|
||||
}
|
||||
|
||||
for (Iterator<Class<? extends HalAction>> it = pluginManager.getClassIterator(HalAction.class);
|
||||
it.hasNext(); ){
|
||||
manager.addAvailableAction(it.next());
|
||||
}
|
||||
|
||||
instance = manager;
|
||||
}
|
||||
|
||||
public static TriggerManager getInstance(){
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
9
src/se/hal/intf/HalAction.java
Executable file
9
src/se/hal/intf/HalAction.java
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
package se.hal.intf;
|
||||
|
||||
/**
|
||||
* Defines a action that will be executed
|
||||
*/
|
||||
public interface HalAction {
|
||||
|
||||
void execute();
|
||||
}
|
||||
20
src/se/hal/intf/HalTrigger.java
Executable file
20
src/se/hal/intf/HalTrigger.java
Executable file
|
|
@ -0,0 +1,20 @@
|
|||
package se.hal.intf;
|
||||
|
||||
/**
|
||||
* A interfaces that declares a trigger/condition that
|
||||
* needs to be validated before an action can be run
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
boolean evaluate();
|
||||
|
||||
/**
|
||||
* Reset the evaluation to false.
|
||||
*/
|
||||
void reset();
|
||||
}
|
||||
|
|
@ -68,14 +68,16 @@ public class NetScanController implements HalEventController, HalAutoScannableCo
|
|||
public void run() {
|
||||
try(MultiCommandExecutor executor = new MultiCommandExecutor();){
|
||||
for (Map.Entry<LocalNetworkDevice,SwitchEventData> entry : devices.entrySet()) {
|
||||
LocalNetworkDevice device = entry.getKey();
|
||||
SwitchEventData data = entry.getValue();
|
||||
if (listener != null) {
|
||||
//logger.finest("Pinging IP "+entry.getKey().getHost());
|
||||
boolean online = InetScanner.isReachable(entry.getKey().getHost(), executor);
|
||||
if (entry.getValue() == null || entry.getValue().isOn() != online) {
|
||||
//logger.finest("Pinging IP "+ device.getHost());
|
||||
boolean online = InetScanner.isReachable(device.getHost(), executor);
|
||||
if (data == null || data.isOn() != online) {
|
||||
entry.setValue(
|
||||
new SwitchEventData(online, System.currentTimeMillis()));
|
||||
logger.fine("IP "+entry.getKey().getHost() +" state has changed to "+ entry.getValue());
|
||||
listener.reportReceived(entry.getKey(), entry.getValue());
|
||||
logger.fine("IP "+device.getHost() +" state has changed to "+ data);
|
||||
listener.reportReceived(device, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
{"se.hal.intf.HalHttpPage": "se.hal.page.PCOverviewHttpPage"},
|
||||
{"se.hal.intf.HalHttpPage": "se.hal.page.PCHeatMapHttpPage"},
|
||||
|
||||
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationClient"},
|
||||
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationDaemon"}
|
||||
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationClient"},
|
||||
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationDaemon"}
|
||||
]
|
||||
}
|
||||
55
src/se/hal/struct/TriggerFlow.java
Executable file
55
src/se/hal/struct/TriggerFlow.java
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
package se.hal.struct;
|
||||
|
||||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import zutil.db.bean.DBBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A class that encapsulates triggers and their actions.
|
||||
* TODO: Bad class name, should be renamed when we come up with a better one
|
||||
*/
|
||||
public class TriggerFlow extends DBBean {
|
||||
private ArrayList<HalTrigger> triggers = new ArrayList<>();
|
||||
private ArrayList<HalAction> actions = new ArrayList<>();
|
||||
|
||||
|
||||
public void addTrigger(HalTrigger trigger) {
|
||||
triggers.add(trigger);
|
||||
}
|
||||
public void addAction(HalAction action) {
|
||||
actions.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
|
||||
*/
|
||||
public boolean evaluate(){
|
||||
for(HalTrigger trigger : triggers){
|
||||
if (trigger.evaluate())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the associated actions in this flow
|
||||
*/
|
||||
public void execute(){
|
||||
for(HalAction action : actions){
|
||||
action.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all trigger evaluations
|
||||
*/
|
||||
public void reset() {
|
||||
for(HalTrigger trigger : triggers){
|
||||
trigger.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
95
test/se/hal/TriggerManagerTest.java
Executable file
95
test/se/hal/TriggerManagerTest.java
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
package se.hal;
|
||||
|
||||
import org.junit.Test;
|
||||
import se.hal.intf.HalAction;
|
||||
import se.hal.intf.HalTrigger;
|
||||
import se.hal.struct.TriggerFlow;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TriggerManagerTest {
|
||||
|
||||
private TriggerManager manager = new TriggerManager();
|
||||
|
||||
|
||||
@Test
|
||||
public void registerAvailableTrigger(){
|
||||
assertEquals(Collections.EMPTY_LIST, manager.getAvailableTriggers());
|
||||
|
||||
manager.addAvailableTrigger(TestTrigger.class);
|
||||
manager.addAvailableTrigger(TestTrigger.class);
|
||||
assertEquals(1, manager.getAvailableTriggers().size());
|
||||
assertTrue(manager.getAvailableTriggers().contains(TestTrigger.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerAvailableAction(){
|
||||
assertEquals(Collections.EMPTY_LIST, manager.getAvailableActions());
|
||||
|
||||
manager.addAvailableAction(TestAction.class);
|
||||
manager.addAvailableAction(TestAction.class);
|
||||
assertEquals(1, manager.getAvailableActions().size());
|
||||
assertTrue(manager.getAvailableActions().contains(TestAction.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void register(){
|
||||
registerAvailableTrigger();
|
||||
|
||||
TriggerFlow flow = new TriggerFlow();
|
||||
flow.addTrigger(new TestTrigger(true));
|
||||
TestAction action = new TestAction();
|
||||
flow.addAction(action);
|
||||
manager.register(flow);
|
||||
manager.evaluateAndExecute();
|
||||
assertEquals(1, action.nrOfExecutions);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void evaluateAndExecute(){
|
||||
registerAvailableTrigger();
|
||||
|
||||
TriggerFlow flow = new TriggerFlow();
|
||||
TestTrigger trigger = new TestTrigger(true);
|
||||
flow.addTrigger(trigger);
|
||||
TestAction action = new TestAction();
|
||||
flow.addAction(action);
|
||||
manager.register(flow);
|
||||
|
||||
manager.evaluateAndExecute();
|
||||
assertEquals("Action executed nr of times",
|
||||
1, action.nrOfExecutions);
|
||||
|
||||
manager.evaluateAndExecute();
|
||||
assertEquals("Action executed nr of times",
|
||||
1, action.nrOfExecutions);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private static class TestTrigger implements HalTrigger {
|
||||
boolean evaluation;
|
||||
TestTrigger(boolean b){ evaluation = b; }
|
||||
@Override
|
||||
public boolean evaluate() { return evaluation; }
|
||||
|
||||
@Override
|
||||
public void reset() { evaluation = false; }
|
||||
}
|
||||
|
||||
|
||||
private class TestAction implements HalAction {
|
||||
int nrOfExecutions;
|
||||
@Override
|
||||
public void execute() { nrOfExecutions++; }
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue