Workflow life cycle management (WorkflowLcm)

In network automation, the workflow can be paused, resumed,
and terminated at any point in time.

Change-Id: I692cdb7d0ecf235d3945a6a149dfb7b60ff1c32f
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowExecutionService.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowExecutionService.java
index c5e00a7..058d050 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowExecutionService.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowExecutionService.java
@@ -54,4 +54,24 @@
      */
     void registerEventMap(Class<? extends Event> eventType, Set<String> eventHintSet,
                           String contextName, String programCounterString) throws WorkflowException;
+
+    /**
+     * Unregister workflow event map.
+     * @param contextName workflow context name
+     * @throws WorkflowException workflow exception
+     */
+    default void unregisterEventMap(String contextName) throws WorkflowException {
+       return;
+    }
+
+    /**
+     * Schedule handler task to be executed after some milli-seconds.
+     * @param afterMs the milli-second to execute handler task.
+     * @param task handler task to be executed after some milli-seconds.
+     */
+    default void scheduleHandlerTask(long afterMs, HandlerTask task) {
+        return;
+    }
+
+
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkplaceStore.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkplaceStore.java
index b73cd4f..e4430bf 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkplaceStore.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkplaceStore.java
@@ -17,6 +17,7 @@
 
 import org.onosproject.store.Store;
 import org.onosproject.store.service.StorageException;
+import org.onosproject.workflow.api.lcm.WorkflowLcm;
 
 import java.util.Collection;
 
@@ -115,4 +116,15 @@
      * @param workplaceName workplace name
      */
     void removeWorkplaceContexts(String workplaceName);
+
+     /**
+     * Gets LCM of workflow context.
+     * @param name name of workflow context
+     * @return Current LCM operation of workflow context
+     * @throws StorageException storage exception
+     */
+    default WorkflowLcm getLcm(String name) throws StorageException {
+        return WorkflowLcm.RUN;
+    }
+
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/PostProcessing.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/PostProcessing.java
new file mode 100644
index 0000000..031740c
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/PostProcessing.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.workflow.api.lcm;
+
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.event.Event;
+import org.onosproject.workflow.api.EventTimeoutTask;
+import org.onosproject.workflow.api.TimeoutTask;
+import org.onosproject.workflow.api.WorkExecutor;
+import org.onosproject.workflow.api.Workflow;
+import org.onosproject.workflow.api.WorkflowContext;
+import org.onosproject.workflow.api.WorkflowException;
+import org.onosproject.workflow.api.WorkflowExecutionService;
+import org.onosproject.workflow.api.WorkflowState;
+import org.slf4j.Logger;
+
+import java.util.Set;
+
+import static org.onosproject.workflow.api.CheckCondition.check;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Class for data for post-processing.
+ */
+public abstract class PostProcessing {
+
+    /**
+     * Processes post job of work-let execution.
+     * @param context workflow context
+     * @param workflow workflow
+     * @throws WorkflowException workflow exception
+     */
+    public abstract void process(WorkflowContext context, Workflow workflow) throws WorkflowException;
+
+    /**
+     * Returns whether ths context LCM is PAUSE or not.
+     * @param context workflow context
+     * @return whether ths context LCM is PAUSE or not
+     */
+    protected boolean isPause(WorkflowContext context) {
+        return context.workplaceStore().getLcm(context.name()) == WorkflowLcm.PAUSE;
+    }
+
+    /**
+     * Returns whether ths context LCM is TERMINATE or not.
+     * @param context workflow context
+     * @return whether ths context LCM is TERMINATE or not
+     */
+    protected boolean isTerminate(WorkflowContext context) {
+        return context.workplaceStore().getLcm(context.name()) == WorkflowLcm.TERMINATE;
+    }
+
+    /**
+     * Class for data for wait completed post-processing.
+     */
+    public static final class WaitCompletion extends PostProcessing {
+
+        private static final Logger log = getLogger(WaitCompletion.class);
+
+        /**
+         * Completion event type.
+         */
+        public transient Class<? extends Event> eventType;
+
+        /**
+         * Completion event hint Set.
+         */
+        public transient Set<String> eventHintSet;
+
+        /**
+         * Completion event generator method reference.
+         */
+        public transient WorkExecutor eventGenerator;
+
+        /**
+         * Completion event timeout milliseconds.
+         */
+        public transient long eventTimeoutMs;
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(getClass())
+                    .add("eventType", eventType)
+                    .add("eventHintSet", eventHintSet)
+                    .add("eventGenerator", eventGenerator)
+                    .add("eventTimeoutMs", eventTimeoutMs)
+                    .toString();
+        }
+
+        @Override
+        public void process(WorkflowContext context, Workflow workflow) throws WorkflowException {
+
+            if (isPause(context) || isTerminate(context)) {
+                // if LCM operation is pause, it does not execute event generator, and
+                // does not schedule vent timeout task
+                context.setTriggerNext(false);
+                context.setState(WorkflowState.IDLE);
+                return;
+            }
+
+            WorkflowExecutionService executionService = context.workflowService();
+
+            executionService.registerEventMap(
+                    eventType, eventHintSet, context.name(), context.current().toString());
+
+            check(eventGenerator != null, "invalid event generator in " + context);
+
+            eventGenerator.apply();
+
+            if (eventTimeoutMs != 0L) {
+
+                final EventTimeoutTask eventTimeoutTask = EventTimeoutTask.builder()
+                        .context(context)
+                        .programCounter(context.current())
+                        .eventType(eventType.getName())
+                        .eventHintSet(eventHintSet)
+                        .build();
+
+                executionService.scheduleHandlerTask(eventTimeoutMs, eventTimeoutTask);
+            }
+        }
+    }
+
+    /**
+     * Class for data for wait for post-processing.
+     */
+    public static final class WaitFor extends PostProcessing {
+
+        private static final Logger log = getLogger(WaitFor.class);
+
+        /**
+         * timeout milliseconds.
+         */
+        public transient long timeoutMs;
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(getClass())
+                    .add("timeoutMs", timeoutMs)
+                    .toString();
+        }
+
+        @Override
+        public void process(WorkflowContext context, Workflow workflow) throws WorkflowException {
+
+            if (isPause(context) || isTerminate(context)) {
+                // if LCM operation is pause, it does not schedule vent timeout task
+                context.setTriggerNext(false);
+                context.setState(WorkflowState.IDLE);
+                return;
+            }
+
+            final TimeoutTask timeoutTask = TimeoutTask.builder()
+                    .context(context)
+                    .programCounter(context.current())
+                    .build();
+
+            context.workflowService().scheduleHandlerTask(timeoutMs, timeoutTask);
+        }
+    }
+
+    /**
+     * Class for data for completed for post processing.
+     */
+    public static final class Completed extends PostProcessing {
+
+        private static final Logger log = getLogger(Completed.class);
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(getClass())
+                    .toString();
+        }
+
+        @Override
+        public void process(WorkflowContext context, Workflow workflow) throws WorkflowException {
+
+            context.workflowService().unregisterEventMap(context.name());
+            context.setCurrent(workflow.increased(context.current()));
+
+            if (isPause(context) || isTerminate(context)) {
+                // if LCM operation is pause, it does not schedule vent timeout task
+                context.setTriggerNext(false);
+                context.setState(WorkflowState.IDLE);
+                return;
+            }
+
+            context.setTriggerNext(true);
+        }
+    }
+}
+
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/WorkflowLcm.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/WorkflowLcm.java
new file mode 100644
index 0000000..882ea8b
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/WorkflowLcm.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.workflow.api.lcm;
+
+/**
+ * LCM(Life Cycle Management) operation of workflow.
+ */
+public enum WorkflowLcm {
+
+    /**
+     * Makes workflow to run.
+     */
+    RUN,
+
+    /**
+     * Makes workflow to be paused.
+     */
+    PAUSE,
+
+    /**
+     * Workflow is exception state.
+     */
+    TERMINATE
+
+}
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/package-info.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/package-info.java
new file mode 100644
index 0000000..3b1830a
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/lcm/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2024-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Package for workflow LCM APIs.
+ */
+package org.onosproject.workflow.api.lcm;
\ No newline at end of file