.
+*/
+package com.fluxtion.example.devworkflow.aot.generated;
+
+import com.fluxtion.runtime.StaticEventProcessor;
+import com.fluxtion.runtime.lifecycle.BatchHandler;
+import com.fluxtion.runtime.lifecycle.Lifecycle;
+import com.fluxtion.runtime.EventProcessor;
+import com.fluxtion.runtime.callback.InternalEventProcessor;
+import com.fluxtion.example.devworkflow.integrating.AdminCommand;
+import com.fluxtion.example.devworkflow.integrating.CommandAuthorizer;
+import com.fluxtion.example.devworkflow.integrating.CommandAuthorizerNode;
+import com.fluxtion.example.devworkflow.integrating.CommandExecutor;
+import com.fluxtion.runtime.EventProcessorContext;
+import com.fluxtion.runtime.audit.Auditor;
+import com.fluxtion.runtime.audit.EventLogManager;
+import com.fluxtion.runtime.audit.NodeNameAuditor;
+import com.fluxtion.runtime.callback.CallbackDispatcherImpl;
+import com.fluxtion.runtime.callback.ExportFunctionAuditEvent;
+import com.fluxtion.runtime.event.Event;
+import com.fluxtion.runtime.input.EventFeed;
+import com.fluxtion.runtime.input.SubscriptionManagerNode;
+import com.fluxtion.runtime.node.ForkedTriggerTask;
+import com.fluxtion.runtime.node.MutableEventProcessorContext;
+import com.fluxtion.runtime.time.Clock;
+import com.fluxtion.runtime.time.ClockStrategy.ClockStrategyEvent;
+import java.util.Map;
+
+import java.util.IdentityHashMap;
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+/**
+ *
+ *
+ *
+ * generation time : Not available
+ * eventProcessorGenerator version : 9.2.23
+ * api version : 9.2.23
+ *
+ *
+ * Event classes supported:
+ *
+ *
+ * com.fluxtion.compiler.generation.model.ExportFunctionMarker
+ * com.fluxtion.example.devworkflow.integrating.AdminCommand
+ * com.fluxtion.runtime.time.ClockStrategy.ClockStrategyEvent
+ *
+ *
+ * @author Greg Higgins
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class PermittedCommandProcessor
+ implements EventProcessor,
+ StaticEventProcessor,
+ InternalEventProcessor,
+ BatchHandler,
+ Lifecycle,
+ CommandAuthorizer {
+
+ //Node declarations
+ private final CallbackDispatcherImpl callbackDispatcher = new CallbackDispatcherImpl();
+ private final CommandAuthorizerNode commandAuthorizerNode_1 = new CommandAuthorizerNode();
+ private final CommandExecutor commandExecutor_0 = new CommandExecutor(commandAuthorizerNode_1);
+ public final NodeNameAuditor nodeNameLookup = new NodeNameAuditor();
+ private final SubscriptionManagerNode subscriptionManager = new SubscriptionManagerNode();
+ private final MutableEventProcessorContext context =
+ new MutableEventProcessorContext(
+ nodeNameLookup, callbackDispatcher, subscriptionManager, callbackDispatcher);
+ public final Clock clock = new Clock();
+ private final ExportFunctionAuditEvent functionAudit = new ExportFunctionAuditEvent();
+ //Dirty flags
+ private boolean initCalled = false;
+ private boolean processing = false;
+ private boolean buffering = false;
+ private final IdentityHashMap dirtyFlagSupplierMap =
+ new IdentityHashMap<>(0);
+ private final IdentityHashMap> dirtyFlagUpdateMap =
+ new IdentityHashMap<>(0);
+
+ //Forked declarations
+
+ //Filter constants
+
+ public PermittedCommandProcessor(Map contextMap) {
+ context.replaceMappings(contextMap);
+ //node auditors
+ initialiseAuditor(clock);
+ initialiseAuditor(nodeNameLookup);
+ subscriptionManager.setSubscribingEventProcessor(this);
+ context.setEventProcessorCallback(this);
+ }
+
+ public PermittedCommandProcessor() {
+ this(null);
+ }
+
+ @Override
+ public void init() {
+ initCalled = true;
+ auditEvent(Lifecycle.LifecycleEvent.Init);
+ //initialise dirty lookup map
+ isDirty("test");
+ clock.init();
+ afterEvent();
+ }
+
+ @Override
+ public void start() {
+ if (!initCalled) {
+ throw new RuntimeException("init() must be called before start()");
+ }
+ processing = true;
+ auditEvent(Lifecycle.LifecycleEvent.Start);
+
+ afterEvent();
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+
+ @Override
+ public void stop() {
+ if (!initCalled) {
+ throw new RuntimeException("init() must be called before stop()");
+ }
+ processing = true;
+ auditEvent(Lifecycle.LifecycleEvent.Stop);
+
+ afterEvent();
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+
+ @Override
+ public void tearDown() {
+ initCalled = false;
+ auditEvent(Lifecycle.LifecycleEvent.TearDown);
+ nodeNameLookup.tearDown();
+ clock.tearDown();
+ subscriptionManager.tearDown();
+ afterEvent();
+ }
+
+ @Override
+ public void setContextParameterMap(Map newContextMapping) {
+ context.replaceMappings(newContextMapping);
+ }
+
+ @Override
+ public void addContextParameter(Object key, Object value) {
+ context.addMapping(key, value);
+ }
+
+ //EVENT DISPATCH - START
+ @Override
+ public void onEvent(Object event) {
+ if (buffering) {
+ triggerCalculation();
+ }
+ if (processing) {
+ callbackDispatcher.processReentrantEvent(event);
+ } else {
+ processing = true;
+ onEventInternal(event);
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+ }
+
+ @Override
+ public void onEventInternal(Object event) {
+ if (event instanceof com.fluxtion.example.devworkflow.integrating.AdminCommand) {
+ AdminCommand typedEvent = (AdminCommand) event;
+ handleEvent(typedEvent);
+ } else if (event instanceof com.fluxtion.runtime.time.ClockStrategy.ClockStrategyEvent) {
+ ClockStrategyEvent typedEvent = (ClockStrategyEvent) event;
+ handleEvent(typedEvent);
+ }
+ }
+
+ public void handleEvent(AdminCommand typedEvent) {
+ auditEvent(typedEvent);
+ //Default, no filter methods
+ commandExecutor_0.executeCommand(typedEvent);
+ afterEvent();
+ }
+
+ public void handleEvent(ClockStrategyEvent typedEvent) {
+ auditEvent(typedEvent);
+ //Default, no filter methods
+ clock.setClockStrategy(typedEvent);
+ afterEvent();
+ }
+ //EVENT DISPATCH - END
+
+ //EXPORTED SERVICE FUNCTIONS - START
+ @Override
+ public boolean authorize(com.fluxtion.example.devworkflow.integrating.CommandPermission arg0) {
+ beforeServiceCall(
+ "public boolean com.fluxtion.example.devworkflow.integrating.CommandAuthorizerNode.authorize(com.fluxtion.example.devworkflow.integrating.CommandPermission)");
+ ExportFunctionAuditEvent typedEvent = functionAudit;
+ commandAuthorizerNode_1.authorize(arg0);
+ afterServiceCall();
+ return true;
+ }
+
+ @Override
+ public boolean removeAuthorized(
+ com.fluxtion.example.devworkflow.integrating.CommandPermission arg0) {
+ beforeServiceCall(
+ "public boolean com.fluxtion.example.devworkflow.integrating.CommandAuthorizerNode.removeAuthorized(com.fluxtion.example.devworkflow.integrating.CommandPermission)");
+ ExportFunctionAuditEvent typedEvent = functionAudit;
+ commandAuthorizerNode_1.removeAuthorized(arg0);
+ afterServiceCall();
+ return true;
+ }
+ //EXPORTED SERVICE FUNCTIONS - END
+
+ public void bufferEvent(Object event) {
+ buffering = true;
+ if (event instanceof com.fluxtion.example.devworkflow.integrating.AdminCommand) {
+ AdminCommand typedEvent = (AdminCommand) event;
+ auditEvent(typedEvent);
+ commandExecutor_0.executeCommand(typedEvent);
+ } else if (event instanceof com.fluxtion.runtime.time.ClockStrategy.ClockStrategyEvent) {
+ ClockStrategyEvent typedEvent = (ClockStrategyEvent) event;
+ auditEvent(typedEvent);
+ clock.setClockStrategy(typedEvent);
+ }
+ }
+
+ public void triggerCalculation() {
+ buffering = false;
+ String typedEvent = "No event information - buffered dispatch";
+ afterEvent();
+ }
+
+ private void auditEvent(Object typedEvent) {
+ clock.eventReceived(typedEvent);
+ nodeNameLookup.eventReceived(typedEvent);
+ }
+
+ private void auditEvent(Event typedEvent) {
+ clock.eventReceived(typedEvent);
+ nodeNameLookup.eventReceived(typedEvent);
+ }
+
+ private void initialiseAuditor(Auditor auditor) {
+ auditor.init();
+ auditor.nodeRegistered(commandAuthorizerNode_1, "commandAuthorizerNode_1");
+ auditor.nodeRegistered(commandExecutor_0, "commandExecutor_0");
+ auditor.nodeRegistered(callbackDispatcher, "callbackDispatcher");
+ auditor.nodeRegistered(subscriptionManager, "subscriptionManager");
+ auditor.nodeRegistered(context, "context");
+ }
+
+ private void beforeServiceCall(String functionDescription) {
+ functionAudit.setFunctionDescription(functionDescription);
+ auditEvent(functionAudit);
+ if (buffering) {
+ triggerCalculation();
+ }
+ processing = true;
+ }
+
+ private void afterServiceCall() {
+ afterEvent();
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+
+ private void afterEvent() {
+
+ clock.processingComplete();
+ nodeNameLookup.processingComplete();
+ }
+
+ @Override
+ public void batchPause() {
+ auditEvent(Lifecycle.LifecycleEvent.BatchPause);
+ processing = true;
+
+ afterEvent();
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+
+ @Override
+ public void batchEnd() {
+ auditEvent(Lifecycle.LifecycleEvent.BatchEnd);
+ processing = true;
+
+ afterEvent();
+ callbackDispatcher.dispatchQueuedCallbacks();
+ processing = false;
+ }
+
+ @Override
+ public boolean isDirty(Object node) {
+ return dirtySupplier(node).getAsBoolean();
+ }
+
+ @Override
+ public BooleanSupplier dirtySupplier(Object node) {
+ if (dirtyFlagSupplierMap.isEmpty()) {}
+
+ return dirtyFlagSupplierMap.getOrDefault(node, StaticEventProcessor.ALWAYS_FALSE);
+ }
+
+ @Override
+ public void setDirty(Object node, boolean dirtyFlag) {
+ if (dirtyFlagUpdateMap.isEmpty()) {}
+
+ dirtyFlagUpdateMap.get(node).accept(dirtyFlag);
+ }
+
+ @Override
+ public T getNodeById(String id) throws NoSuchFieldException {
+ return nodeNameLookup.getInstanceById(id);
+ }
+
+ @Override
+ public A getAuditorById(String id)
+ throws NoSuchFieldException, IllegalAccessException {
+ return (A) this.getClass().getField(id).get(this);
+ }
+
+ @Override
+ public void addEventFeed(EventFeed eventProcessorFeed) {
+ subscriptionManager.addEventProcessorFeed(eventProcessorFeed);
+ }
+
+ @Override
+ public void removeEventFeed(EventFeed eventProcessorFeed) {
+ subscriptionManager.removeEventProcessorFeed(eventProcessorFeed);
+ }
+
+ @Override
+ public PermittedCommandProcessor newInstance() {
+ return new PermittedCommandProcessor();
+ }
+
+ @Override
+ public PermittedCommandProcessor newInstance(Map contextMap) {
+ return new PermittedCommandProcessor();
+ }
+
+ @Override
+ public String getLastAuditLogRecord() {
+ try {
+ EventLogManager eventLogManager =
+ (EventLogManager) this.getClass().getField(EventLogManager.NODE_NAME).get(this);
+ return eventLogManager.lastRecordAsString();
+ } catch (Throwable e) {
+ return "";
+ }
+ }
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/experiment/MainExperiment.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/experiment/MainExperiment.java
new file mode 100644
index 0000000..df9c2a2
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/experiment/MainExperiment.java
@@ -0,0 +1,100 @@
+package com.fluxtion.example.devworkflow.experiment;
+
+import com.fluxtion.compiler.Fluxtion;
+import com.fluxtion.runtime.annotations.ExportService;
+import com.fluxtion.runtime.annotations.NoTriggerReference;
+import com.fluxtion.runtime.annotations.OnEventHandler;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import lombok.Data;
+
+public class MainExperiment {
+ public static void main(String[] args) {
+ var processor = Fluxtion.interpret(new CommandExecutor(new CommandAuthorizerNode()));
+ processor.init();
+
+ CommandAuthorizer commandAuthorizer = processor.getExportedService();
+ commandAuthorizer.authorize(new CommandPermission("admin", "shutdown"));
+ commandAuthorizer.authorize(new CommandPermission("admin", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Aslam", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Puck", "createMischief"));
+
+ commandAuthorizer.dumpMap();
+
+ processor.onEvent(new AdminCommand("admin", "shutdown", () -> System.out.println("executing shutdown command")));
+ processor.onEvent(new AdminCommand("Aslam", "listUser", () -> System.out.println("executing listUser command")));
+ processor.onEvent(new AdminCommand("Puck", "createMischief", () -> System.out.println("move the stool")));
+ processor.onEvent(new AdminCommand("Aslam", "shutdown", () -> System.out.println("executing shutdown command")));
+
+ commandAuthorizer.removeAuthorized(new CommandPermission("Puck", "createMischief"));
+ commandAuthorizer.dumpMap();
+ processor.onEvent(new AdminCommand("Puck", "createMischief", () -> System.out.println("move the stool")));
+ }
+
+ public interface CommandAuthorizer {
+ boolean authorize(CommandPermission commandPermission);
+
+ boolean removeAuthorized(CommandPermission commandPermission);
+
+ //used for testing
+ void dumpMap();
+ }
+
+ public static class CommandAuthorizerNode implements @ExportService CommandAuthorizer {
+ private transient final Multimap permissionMap = HashMultimap.create();
+
+ @Override
+ public boolean authorize(CommandPermission commandPermission) {
+ permissionMap.put(commandPermission.user, commandPermission.command);
+ return false;
+ }
+
+ @Override
+ public boolean removeAuthorized(CommandPermission commandPermission) {
+ permissionMap.remove(commandPermission.user, commandPermission.command);
+ return false;
+ }
+
+ @Override
+ public void dumpMap() {
+ System.out.println("""
+
+ Permission map
+ --------------------
+ %s
+ --------------------
+ """.formatted(permissionMap.toString()));
+ }
+
+ boolean isAuthorized(AdminCommand adminCommand) {
+ return permissionMap.containsEntry(adminCommand.user, adminCommand.command);
+ }
+ }
+
+ @Data
+ public static class CommandExecutor {
+ @NoTriggerReference
+ private final CommandAuthorizerNode commandAuthorizer;
+
+ @OnEventHandler
+ public boolean executeCommand(AdminCommand command) {
+ boolean authorized = commandAuthorizer.isAuthorized(command);
+ if (authorized) {
+ System.out.println("Executing command " + command);
+ command.commandToExecute().run();
+ } else {
+ System.out.println("FAILED authorization for command " + command);
+ }
+ return authorized;
+ }
+ }
+
+ public record CommandPermission(String user, String command) { }
+
+ public record AdminCommand(String user, String command, Runnable commandToExecute) {
+ @Override
+ public String toString() {
+ return "AdminCommand{user='" + user + '\'' + ", command='" + command + '\'' +'}';
+ }
+ }
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/AdminCommand.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/AdminCommand.java
new file mode 100644
index 0000000..40eb836
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/AdminCommand.java
@@ -0,0 +1,12 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+public record AdminCommand(String user, String command, Runnable commandToExecute) {
+
+ @Override
+ public String toString() {
+ return "AdminCommand{" +
+ "user='" + user + '\'' +
+ ", command='" + command + '\'' +
+ '}';
+ }
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizer.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizer.java
new file mode 100644
index 0000000..595e336
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizer.java
@@ -0,0 +1,7 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+public interface CommandAuthorizer {
+ boolean authorize(CommandPermission commandPermission);
+
+ boolean removeAuthorized(CommandPermission commandPermission);
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizerNode.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizerNode.java
new file mode 100644
index 0000000..4129c7c
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandAuthorizerNode.java
@@ -0,0 +1,25 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+import com.fluxtion.runtime.annotations.ExportService;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
+public class CommandAuthorizerNode implements @ExportService CommandAuthorizer {
+ private transient final Multimap permissionMap = HashMultimap.create();
+
+ @Override
+ public boolean authorize(CommandPermission commandPermission) {
+ permissionMap.put(commandPermission.user(), commandPermission.command());
+ return false;
+ }
+
+ @Override
+ public boolean removeAuthorized(CommandPermission commandPermission) {
+ permissionMap.remove(commandPermission.user(), commandPermission.command());
+ return false;
+ }
+
+ boolean isAuthorized(AdminCommand adminCommand) {
+ return permissionMap.containsEntry(adminCommand.user(), adminCommand.command());
+ }
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandExecutor.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandExecutor.java
new file mode 100644
index 0000000..2e2ba36
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandExecutor.java
@@ -0,0 +1,20 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+import com.fluxtion.runtime.annotations.NoTriggerReference;
+import com.fluxtion.runtime.annotations.OnEventHandler;
+import lombok.Data;
+
+@Data
+public class CommandExecutor {
+ @NoTriggerReference
+ private final CommandAuthorizerNode commandAuthorizer;
+
+ @OnEventHandler
+ public boolean executeCommand(AdminCommand command) {
+ boolean authorized = commandAuthorizer.isAuthorized(command);
+ if (authorized) {
+ command.commandToExecute().run();
+ }
+ return authorized;
+ }
+}
diff --git a/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandPermission.java b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandPermission.java
new file mode 100644
index 0000000..acf616b
--- /dev/null
+++ b/getting-started/developer-workflow/src/main/java/com/fluxtion/example/devworkflow/integrating/CommandPermission.java
@@ -0,0 +1,4 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+public record CommandPermission(String user, String command) {
+}
diff --git a/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/aot/CommandExecutorTest.java b/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/aot/CommandExecutorTest.java
new file mode 100644
index 0000000..83d4faf
--- /dev/null
+++ b/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/aot/CommandExecutorTest.java
@@ -0,0 +1,40 @@
+package com.fluxtion.example.devworkflow.aot;
+
+import com.fluxtion.example.devworkflow.aot.generated.PermittedCommandProcessor;
+import com.fluxtion.example.devworkflow.integrating.*;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.atomic.LongAdder;
+
+class CommandExecutorTest {
+
+ @Test
+ public void testPermission(){
+ var processor = new PermittedCommandProcessor();
+ processor.init();
+
+ CommandAuthorizer commandAuthorizer = processor.getExportedService();
+ commandAuthorizer.authorize(new CommandPermission("admin", "shutdown"));
+ commandAuthorizer.authorize(new CommandPermission("admin", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Aslam", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Puck", "createMischief"));
+
+ LongAdder longAdder = new LongAdder();
+ processor.onEvent(new AdminCommand("admin", "shutdown", longAdder::increment));
+ Assertions.assertEquals(1, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Aslam", "listUser", longAdder::increment));
+ Assertions.assertEquals(2, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Puck", "createMischief", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Aslam", "shutdown", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+
+ commandAuthorizer.removeAuthorized(new CommandPermission("Puck", "createMischief"));
+ processor.onEvent(new AdminCommand("Puck", "createMischief", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+ }
+}
\ No newline at end of file
diff --git a/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/integrating/CommandExecutorTest.java b/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/integrating/CommandExecutorTest.java
new file mode 100644
index 0000000..828c48a
--- /dev/null
+++ b/getting-started/developer-workflow/src/test/java/com/fluxtion/example/devworkflow/integrating/CommandExecutorTest.java
@@ -0,0 +1,39 @@
+package com.fluxtion.example.devworkflow.integrating;
+
+import com.fluxtion.compiler.Fluxtion;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.atomic.LongAdder;
+
+class CommandExecutorTest {
+
+ @Test
+ public void testPermission(){
+ var processor = Fluxtion.interpret(new CommandExecutor(new CommandAuthorizerNode()));
+ processor.init();
+
+ CommandAuthorizer commandAuthorizer = processor.getExportedService();
+ commandAuthorizer.authorize(new CommandPermission("admin", "shutdown"));
+ commandAuthorizer.authorize(new CommandPermission("admin", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Aslam", "listUser"));
+ commandAuthorizer.authorize(new CommandPermission("Puck", "createMischief"));
+
+ LongAdder longAdder = new LongAdder();
+ processor.onEvent(new AdminCommand("admin", "shutdown", longAdder::increment));
+ Assertions.assertEquals(1, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Aslam", "listUser", longAdder::increment));
+ Assertions.assertEquals(2, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Puck", "createMischief", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+
+ processor.onEvent(new AdminCommand("Aslam", "shutdown", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+
+ commandAuthorizer.removeAuthorized(new CommandPermission("Puck", "createMischief"));
+ processor.onEvent(new AdminCommand("Puck", "createMischief", longAdder::increment));
+ Assertions.assertEquals(3, longAdder.intValue());
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2efb96f..d061c47 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,7 @@ along with this program. If not, see
getting-started/tutorial6-lottery-nospring
reference-examples
service-helloworld
+ getting-started/developer-workflow