ONOS-7963 workflow invocation trigger on ONOS event

Change-Id: Ie9014bfa77f5514c3580042f9ff2add8e42f25f6
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/AbstractWorkflow.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/AbstractWorkflow.java
index 5fb8943..30e50db 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/AbstractWorkflow.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/AbstractWorkflow.java
@@ -57,4 +57,5 @@
                 .data(data)
                 .build();
     }
+
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ContextEventMapStore.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ContextEventMapStore.java
index 4b54cf3..389352c 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ContextEventMapStore.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ContextEventMapStore.java
@@ -33,11 +33,21 @@
      * @param eventType the class name of event
      * @param eventHintSet Set of event hint string value of the event
      * @param contextName workflow context name
-     * @param programCounterString the program counter of workflow
+     * @param programCounter the program counter of workflow
      * @throws WorkflowException workflow exception
      */
     void registerEventMap(String eventType, Set<String> eventHintSet,
-                          String contextName, String programCounterString) throws WorkflowException;
+                          String contextName, ProgramCounter programCounter) throws WorkflowException;
+
+    /**
+     * Registers workflow trigger flag.
+     * @param eventType the class name of event
+     * @param eventHintSet Set of event hint string value of the event
+     * @param contextName workflow context name
+     * @throws WorkflowException workflow exception
+     */
+    void registerTriggerFlag(String eventType, Set<String> eventHintSet,
+                                    String contextName) throws WorkflowException;
 
     /**
      * Unregisters workflow context event mapping.
@@ -52,10 +62,10 @@
      * Returns workflow context event mapping.
      * @param eventType the class name of event
      * @param eventHint vent hint string value of the event
-     * @return Map of workflow context and value (program counter)
+     * @return Map of workflow context and value (WorkflowEventMetaData)
      * @throws WorkflowException workflow exception
      */
-    Map<String, String> getEventMapByHint(String eventType,
+    Map<String, WorkflowEventMetaData> getEventMapByHint(String eventType,
                                           String eventHint) throws WorkflowException;
 
     /**
@@ -66,12 +76,23 @@
     boolean isEventMapPresent(String contextName);
 
     /**
+     * Returns true or false depending on trigger flag for the workflow.
+     * @param eventType the class name of event
+     * @param eventHint vent hint string value of the event
+     * @param contextName name of workflow context
+     * @return Boolean true or false depending on trigger flag for the workflow
+     * @throws WorkflowException workflow exception
+     */
+    boolean isTriggerSet(String eventType, String eventHint,
+                         String contextName) throws WorkflowException;
+
+    /**
      * Returns child nodes on document tree path.
      * @param path document tree path including eventType and Hint
      * @return children under document tree path
      * @throws WorkflowException workflow exception
      */
-    Map<String, Versioned<String>> getChildren(String path) throws WorkflowException;
+    Map<String, Versioned<WorkflowEventMetaData>> getChildren(String path) throws WorkflowException;
 
     /**
      * Returns document path.
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkflowContext.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkflowContext.java
index 8f5d3c7..977a978 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkflowContext.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkflowContext.java
@@ -92,6 +92,12 @@
     private transient WorkplaceStore workplaceStore;
 
     /**
+     * Service reference for eventMap store.
+     */
+    private transient ContextEventMapStore eventMapStore;
+
+
+    /**
      * Constructor of DefaultWorkflowContext.
      * @param builder default workflow context builder
      */
@@ -214,6 +220,11 @@
     }
 
     @Override
+    public void registerTriggerEvent(Class<? extends Event> event, Set<String> eventHintSet) throws WorkflowException {
+        eventMapStore.registerTriggerFlag(event.getName(), eventHintSet, this.name());
+    }
+
+    @Override
     public void setWorkflowExecutionService(WorkflowExecutionService workflowExecutionService) {
         this.workflowExecutionService = workflowExecutionService;
     }
@@ -243,6 +254,17 @@
         return workplaceStore;
     }
 
+
+    @Override
+    public void setEventMapStore(ContextEventMapStore contextEventMapStore) {
+        this.eventMapStore = contextEventMapStore;
+    }
+
+    @Override
+    public ContextEventMapStore eventMapStore() {
+        return eventMapStore;
+    }
+
     public <T> T getService(Class<T> serviceClass) throws WorkflowException {
         T service;
         try {
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
index 5819f11..f167b94 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 
 import static org.onosproject.workflow.api.CheckCondition.check;
@@ -55,6 +56,8 @@
     private static JsonDataModelInjector dataModelInjector = new JsonDataModelInjector();
     private static StaticDataModelInjector staticDataModelInjector = new StaticDataModelInjector();
 
+    private Optional<String> triggerWorkletClassName = Optional.empty();
+
     /**
      * Constructor of ImmutableListWorkflow.
      *
@@ -62,12 +65,18 @@
      */
     private ImmutableListWorkflow(Builder builder) {
         super(builder.id);
+        triggerWorkletClassName = builder.triggerWorkletClassName;
         this.initWorkletType = builder.initWorkletType;
         program = ImmutableList.copyOf(builder.workletDescList);
         attributes = ImmutableSet.copyOf(builder.attributes);
     }
 
     @Override
+    public Optional<String> getTriggerWorkletClassName() {
+        return triggerWorkletClassName;
+    }
+
+    @Override
     public Worklet init(WorkflowContext context) throws WorkflowException {
         if (Objects.isNull(initWorkletType)) {
             return null;
@@ -209,6 +218,12 @@
     }
 
     @Override
+    public Worklet getTriggerWorkletInstance(String workletType) throws WorkflowException {
+        return getWorkletInstance(workletType);
+    }
+
+
+    @Override
     public WorkletDescription getWorkletDesc(ProgramCounter pc) {
 
         WorkletDescription workletDescription = program.get(pc.workletIndex());
@@ -297,6 +312,7 @@
     public static class Builder {
 
         private URI id;
+        private Optional<String> triggerWorkletClassName = Optional.empty();
         private String initWorkletType;
         private final List<WorkletDescription> workletDescList = Lists.newArrayList();
         private final Set<WorkflowAttribute> attributes = Sets.newHashSet();
@@ -314,6 +330,17 @@
         }
 
         /**
+         * Sets trigger flag of immutable list workflow.
+         *
+         * @param triggerWorkletClassName name of trigger worklet class
+         * @return builder
+         */
+        public Builder trigger(String triggerWorkletClassName) {
+            this.triggerWorkletClassName = Optional.of(triggerWorkletClassName);
+            return this;
+        }
+
+        /**
          * Sets init worklet class name of immutable list workflow.
          *
          * @param workletClassName class name of worklet
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/TriggerWorklet.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/TriggerWorklet.java
new file mode 100644
index 0000000..3931693
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/TriggerWorklet.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019-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;
+
+
+import org.onosproject.event.Event;
+
+/**
+ * Abstract class for Trigger worklet.
+ */
+public abstract class TriggerWorklet implements Worklet {
+
+    @Override
+    public String tag() {
+        return this.getClass().getName();
+    }
+
+    /**
+     * Registers trigger event for a workflow under the workflow context.
+     * @param context workflow context
+     * @throws WorkflowException workflow exception
+     */
+    public abstract void register(WorkflowContext context) throws WorkflowException;
+
+    /**
+     * Validates trigger event for a given workflow context.
+     * @param context workflow context
+     * @param event trigger event
+     * @return true/false based on trigger event's validity
+     * @throws WorkflowException workflow exception
+     */
+    public abstract boolean isTriggerValid(WorkflowContext context, Event event) throws WorkflowException;
+
+    @Override
+    public boolean isCompleted(WorkflowContext context, Event event)throws WorkflowException {
+        throw new WorkflowException("(" + tag() + ").isCompleted should not be called");
+    }
+
+    @Override
+    public boolean isNext(WorkflowContext context) throws WorkflowException {
+        throw new WorkflowException("(" + tag() + ").isNext should not be called");
+    }
+
+    @Override
+    public void timeout(WorkflowContext context) throws WorkflowException {
+        throw new WorkflowException("(" + tag() + ").timeout should not be called");
+    }
+
+    @Override
+    public void process(WorkflowContext context) throws WorkflowException {
+        throw new WorkflowException("(" + tag() + ").process should not be called");
+    }
+}
+
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WfTriggerEventTask.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WfTriggerEventTask.java
new file mode 100644
index 0000000..8febd38
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WfTriggerEventTask.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018-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;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.event.Event;
+
+import java.util.Objects;
+
+import static org.onosproject.workflow.api.CheckCondition.check;
+
+/**
+ * Class for WorkFlow Trigger event task.
+ */
+public final class WfTriggerEventTask extends HandlerTask {
+
+    /**
+     * Event triggering event task.
+     */
+    private final Event event;
+
+    /**
+     * Constructor of event task.
+     * @param builder builder of event task
+     */
+    private WfTriggerEventTask(Builder builder) {
+        super(builder);
+        this.event = builder.event;
+    }
+
+
+    /**
+     * Gets event of event task.
+     * @return event triggering event task
+     */
+    public Event event() {
+        return event;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(this.toString());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (!(obj instanceof EventTask)) {
+            return false;
+        }
+        return Objects.equals(this.event(),
+                              ((WfTriggerEventTask) obj).event());
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("context", context())
+                .add("event", event())
+                .toString();
+    }
+
+    /**
+     * Gets a instance of builder.
+     * @return instance of builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder of WfTriggerEventTask.
+     */
+    public static class Builder extends HandlerTask.Builder {
+
+        /**
+         * Event triggering event task.
+         */
+        private Event event;
+
+
+        /**
+         * Sets event.
+         * @param event event triggering event task
+         * @return Builder of WfTriggerEventTask
+         */
+        public Builder event(Event event) {
+            this.event = event;
+            return this;
+        }
+
+        @Override
+        public Builder context(WorkflowContext context) {
+            super.context(context);
+            return this;
+        }
+
+        /**
+         * Builds WfTriggerEventTask.
+         * @return instance of WfTriggerEventTask
+         * @throws WorkflowException workflow exception
+         */
+        public WfTriggerEventTask build() throws WorkflowException {
+            check(context != null, "context is invalid");
+            check(event != null, "event is invalid");
+            return new WfTriggerEventTask(this);
+        }
+    }
+}
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
index 3849afe..01fb92d 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
@@ -17,6 +17,7 @@
 
 import java.net.URI;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 /**
@@ -102,10 +103,25 @@
     List<ProgramCounter> getProgram();
 
     /**
+     * Returns worklet instance with given worklet Name.
+     * @param workletType worklet name
+     * @return Worklet
+     * @throws WorkflowException workflow exception
+     */
+
+    Worklet getTriggerWorkletInstance(String workletType) throws WorkflowException;
+
+    /**
      * Returns worklet description.
      * @param pc program counter
      * @return worklet description list
      */
     WorkletDescription getWorkletDesc(ProgramCounter pc);
 
-}
+    /**
+     * Returns trigger worklet class name if any.
+     * @return trigger worklet class name
+     */
+    Optional<String> getTriggerWorkletClassName();
+
+    }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowContext.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowContext.java
index 836524d..2398b09 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowContext.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowContext.java
@@ -144,6 +144,29 @@
     public abstract long completionEventTimeout();
 
     /**
+     * Sets event map store.
+     * @param contextEventMapStore event map store
+     */
+    public abstract void setEventMapStore(ContextEventMapStore contextEventMapStore);
+
+    /**
+     * Returns the event map store.
+     * @return ContextEventMapStore
+     */
+    public abstract ContextEventMapStore eventMapStore();
+
+
+    /**
+     * Registers an trigger event which has 'eventHint'.
+     * If the event happens, Workflow would be resatrted.
+     * @param event event when trigger happens
+     * @param eventHintSet Set of hint for the event
+     * @throws WorkflowException exception in case any
+     */
+    public abstract void registerTriggerEvent(Class<? extends Event> event,
+                                              Set<String> eventHintSet) throws WorkflowException;
+
+    /**
      * Sets workflow service.
      * @param workflowExecutionService workflow service
      */
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowEventMetaData.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowEventMetaData.java
new file mode 100644
index 0000000..24a485c
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowEventMetaData.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019-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;
+
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * A class representing meta data for workflow event.
+ */
+public class WorkflowEventMetaData {
+
+    private boolean isTriggerSet = false;
+    private ProgramCounter programCounter;
+
+    /**
+     * Constructor of workflow event meta data.
+     * @param isTriggerSet trigger event set for the the workflow
+     * @param programCounter program counter representing worklet type for registered event
+     */
+    public WorkflowEventMetaData(boolean isTriggerSet, ProgramCounter programCounter) {
+        this.isTriggerSet = isTriggerSet;
+        this.programCounter = programCounter;
+    }
+
+    /**
+     * Copy constructor of workflow event meta data.
+     * @param workflowEventMetaData object of WorkflowEventMetaData
+     */
+    public WorkflowEventMetaData(WorkflowEventMetaData workflowEventMetaData) {
+        this.isTriggerSet = workflowEventMetaData.getTriggerFlag();
+        this.programCounter = workflowEventMetaData.getProgramCounter().clone();
+    }
+
+    /**
+     * Returns program counter value related to worflow event.
+     * @return programCounter
+     */
+    public ProgramCounter getProgramCounter() {
+        return programCounter;
+    }
+
+    /**
+     * Returns trigger flag for the workflow.
+     * @return triggerFlag
+     */
+    public boolean getTriggerFlag() {
+        return isTriggerSet;
+    }
+
+
+    /**
+     * Sets true or false for triggerFlag of the workflow.
+     * @param triggerFlag flag to indicate trigger event set for the workflow
+     */
+    public void setTriggerFlag(boolean triggerFlag) {
+        this.isTriggerSet = triggerFlag;
+    }
+
+    /**
+     * Sets program counter representing worklet type for registered event of the workflow.
+     * @param programCounter program counter representing worklet type for registered event
+     */
+    public void setProgramCounterString(ProgramCounter programCounter) {
+        this.programCounter = programCounter;
+    }
+
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("trigger-flag", getTriggerFlag())
+                .add("program-counter", getProgramCounter())
+                .toString();
+    }
+
+}
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..3a41a60 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
@@ -49,9 +49,9 @@
      * @param eventType event type (class name of event)
      * @param eventHintSet Set of event hint value
      * @param contextName workflow context name to be called by this event map
-     * @param programCounterString worklet type to be called by this event map
+     * @param programCounter worklet type to be called by this event map
      * @throws WorkflowException workflow exception
      */
     void registerEventMap(Class<? extends Event> eventType, Set<String> eventHintSet,
-                          String contextName, String programCounterString) throws WorkflowException;
+                          String contextName, ProgramCounter programCounter) throws WorkflowException;
 }