Enhancing the driver subsystem to allow retrieving originating data/handler contexts from the behaviours.

Change-Id: I973888190d569e7e147376b5ae4da9d2f2d9c620
diff --git a/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java b/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java
index 001c490..784e6c5 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/AbstractBehaviour.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.net.driver;
 
+import static com.google.common.base.Preconditions.checkState;
+
 /**
  * Base implementation of device driver behaviour.
  */
@@ -23,12 +25,13 @@
     private DriverData data;
 
     @Override
-    public void setData(DriverData data) {
-        this.data = data;
+    public DriverData data() {
+        return data;
     }
 
     @Override
-    public DriverData data() {
-        return data;
+    public void setData(DriverData data) {
+        checkState(this.data == null, "Driver data already set");
+        this.data = data;
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java b/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java
new file mode 100644
index 0000000..66b21ff
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/driver/AbstractHandlerBehaviour.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.net.driver;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Base implementation of device driver handler behaviour.
+ */
+public class AbstractHandlerBehaviour
+        extends AbstractBehaviour implements HandlerBehaviour {
+
+    private DriverHandler handler;
+
+    @Override
+    public DriverHandler handler() {
+        return handler;
+    }
+
+    @Override
+    public void setHandler(DriverHandler handler) {
+        checkState(this.handler == null, "Driver handler already set");
+        this.handler = handler;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java b/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java
index 208eef7..6e28aa8 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/Behaviour.java
@@ -23,17 +23,17 @@
 public interface Behaviour {
 
     /**
+     * Returns the driver data context.
+     *
+     * @return driver data
+     */
+    DriverData data();
+
+    /**
      * Sets the driver data context on this this behaviour should operate.
      *
      * @param data driver data
      */
     void setData(DriverData data);
 
-    /**
-     * Obtains the driver data.
-     *
-     * @return driver data
-     */
-    DriverData data();
-
 }
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
index 4a176d7..84da212 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
@@ -63,13 +63,6 @@
         this.properties = copyOf(checkNotNull(properties, "Properties cannot be null"));
     }
 
-    /**
-     * Merges the two drivers while giving preference to this driver when
-     * dealing with conflicts.
-     *
-     * @param other other driver
-     * @return new driver
-     */
     @Override
     public Driver merge(Driver other) {
         // Merge the behaviours.
@@ -121,19 +114,22 @@
         return behaviours.containsKey(behaviourClass);
     }
 
-    /**
-     * Creates an instance of behaviour primed with the specified driver data.
-     *
-     * @param data           driver data context
-     * @param behaviourClass driver behaviour class
-     * @param handler        indicates behaviour is intended for handler context
-     * @param <T>            type of behaviour
-     * @return behaviour instance
-     */
+    @Override
     public <T extends Behaviour> T createBehaviour(DriverData data,
-                                                   Class<T> behaviourClass,
-                                                   boolean handler) {
-        checkArgument(handler || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
+                                                   Class<T> behaviourClass) {
+        return createBehaviour(data, null, behaviourClass);
+    }
+
+    @Override
+    public <T extends Behaviour> T createBehaviour(DriverHandler handler,
+                                                   Class<T> behaviourClass) {
+        return createBehaviour(handler.data(), handler, behaviourClass);
+    }
+
+    // Creates an instance of behaviour primed with the specified driver data.
+    private <T extends Behaviour> T createBehaviour(DriverData data, DriverHandler handler,
+                                                    Class<T> behaviourClass) {
+        checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
                       "{} is applicable only to handler context", behaviourClass.getName());
 
         // Locate the implementation of the requested behaviour.
@@ -143,6 +139,11 @@
         // Create an instance of the behaviour and apply data as its context.
         T behaviour = createBehaviour(behaviourClass, implementation);
         behaviour.setData(data);
+
+        // If this is a handler behaviour, also apply handler as its context.
+        if (handler != null) {
+            ((HandlerBehaviour) behaviour).setHandler(handler);
+        }
         return behaviour;
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java
index 0d9ad9a..efa632d 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverData.java
@@ -49,7 +49,7 @@
 
     @Override
     public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
-        return driver.createBehaviour(this, behaviourClass, false);
+        return driver.createBehaviour(this, behaviourClass);
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java
index 38ee3d5..75ae8cd 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriverHandler.java
@@ -45,7 +45,7 @@
 
     @Override
     public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
-        return data.driver().createBehaviour(this.data, behaviourClass, true);
+        return data.driver().createBehaviour(this, behaviourClass);
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onosproject/net/driver/Driver.java b/core/api/src/main/java/org/onosproject/net/driver/Driver.java
index c8d6134..8c13f36 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/Driver.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/Driver.java
@@ -84,12 +84,20 @@
      *
      * @param data           driver data context
      * @param behaviourClass driver behaviour class
-     * @param handler        indicates behaviour is intended for handler context
      * @param <T>            type of behaviour
      * @return behaviour instance
      */
-    <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass,
-                                            boolean handler);
+    <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass);
+
+    /**
+     * Creates an instance of behaviour primed with the specified driver data.
+     *
+     * @param handler        driver handler context
+     * @param behaviourClass driver behaviour class
+     * @param <T>            type of behaviour
+     * @return behaviour instance
+     */
+    <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass);
 
     /**
      * Returns the set of annotations as map of key/value properties.
diff --git a/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java b/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java
index 7e3f78d..b5771ac 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/HandlerBehaviour.java
@@ -20,4 +20,19 @@
  * with a device (in context of {@link org.onosproject.net.driver.DriverHandler}).
  */
 public interface HandlerBehaviour extends Behaviour {
+
+    /**
+     * Returns the driver handler context on which this behaviour operates.
+     *
+     * @return driver handler context
+     */
+    DriverHandler handler();
+
+    /**
+     * Sets the driver handler context for this behaviour.
+     *
+     * @param handler driver handler
+     */
+    void setHandler(DriverHandler handler);
+
 }