[CORD-1675]Bug fix and encode, decode implementation for Ofdpa3 extensions

Change-Id: Idbace6d58fdcff5573b250319f02fe31d09b8467
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
index 34d9757..4b50700 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
@@ -142,6 +142,8 @@
                         (L2ModificationInstruction.ModVlanHeaderInstruction) l2Instruction;
                 result.put(InstructionCodec.ETHERNET_TYPE, pushVlanInstruction.ethernetType().toString());
                 break;
+            case VLAN_POP:
+                break;
             case MPLS_LABEL:
                 final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
                         (L2ModificationInstruction.ModMplsLabelInstruction) l2Instruction;
@@ -162,11 +164,13 @@
                 final L2ModificationInstruction.ModMplsBosInstruction modMplsBosInstruction =
                         (L2ModificationInstruction.ModMplsBosInstruction) l2Instruction;
                 result.put(InstructionCodec.MPLS_BOS, modMplsBosInstruction.mplsBos());
+                break;
             case MPLS_POP:
                 final L2ModificationInstruction.ModMplsHeaderInstruction popHeaderInstruction =
                         (L2ModificationInstruction.ModMplsHeaderInstruction) l2Instruction;
                 result.put(InstructionCodec.ETHERNET_TYPE,
                         toHexWithPrefix(popHeaderInstruction.ethernetType().toShort()));
+                break;
             case DEC_MPLS_TTL:
                 break;
             default:
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionSelectorInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionSelectorInterpreter.java
index a76cc7d..5ac9cf3 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionSelectorInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionSelectorInterpreter.java
@@ -16,7 +16,9 @@
 
 package org.onosproject.driver.extensions;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
 import org.onosproject.net.behaviour.ExtensionSelectorResolver;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
@@ -30,6 +32,9 @@
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaOvid;
 import org.projectfloodlight.openflow.types.U16;
 import org.projectfloodlight.openflow.types.U32;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Interpreter for OFDPA3 OpenFlow selector extensions.
@@ -37,6 +42,8 @@
 public class Ofdpa3ExtensionSelectorInterpreter extends AbstractHandlerBehaviour
         implements ExtensionSelectorInterpreter, ExtensionSelectorResolver {
 
+    private final Logger log = getLogger(getClass());
+
     @Override
     public boolean supported(ExtensionSelectorType extensionSelectorType) {
         if (extensionSelectorType.equals(ExtensionSelectorTypes.OFDPA_MATCH_OVID.type())) {
@@ -131,4 +138,18 @@
         throw new UnsupportedOperationException(
                 "Driver does not support extension type " + type.toString());
     }
+
+    @Override
+    public ObjectNode encode(ExtensionSelector extensionSelector, CodecContext context) {
+        // TODO
+        log.warn("The encode method of Ofdpa3ExtensionSelectorInterpreter hasn't been implemented");
+        return null;
+    }
+
+    @Override
+    public ExtensionSelector decode(ObjectNode json, CodecContext context) {
+        // TODO
+        log.warn("The decode method of Ofdpa3ExtensionSelectorInterpreter hasn't been implemented");
+        return null;
+    }
 }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
index c906f60..2a89b26 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
@@ -16,7 +16,9 @@
 
 package org.onosproject.driver.extensions;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
 import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.flow.instructions.ExtensionTreatment;
@@ -39,6 +41,9 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
 /**
  * Interpreter for OFDPA3 OpenFlow treatment extensions.
  */
@@ -51,6 +56,11 @@
     private static final int SUB_TYPE_PUSH_CW = 3;
     private static final int SUB_TYPE_POP_CW = 4;
 
+    private static final String TYPE = "type";
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in Ofdpa3ExtensionTreatmentInterpreter";
+    private static final String MISSING_TREATMENT_MESSAGE = "Extension treatment cannot be null";
+    private static final String NOT_SUPPORTED_MESSAGE = "Driver does not support extension type of ";
+
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     @Override
@@ -214,7 +224,70 @@
         } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
             return new Ofdpa3PopCw();
         }
-        throw new UnsupportedOperationException(
-                "Driver does not support extension type " + type.toString());
+        throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE + type.toString());
+    }
+
+    @Override
+    public ObjectNode encode(ExtensionTreatment extensionTreatment, CodecContext context) {
+        checkNotNull(extensionTreatment, MISSING_TREATMENT_MESSAGE);
+        ExtensionTreatmentType type = extensionTreatment.type();
+        ObjectNode root = context.mapper().createObjectNode();
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.type())) {
+            Ofdpa3SetMplsType setMplsType = (Ofdpa3SetMplsType) extensionTreatment;
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.name());
+            root.setAll(context.codec(Ofdpa3SetMplsType.class).encode(setMplsType, context));
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.type())) {
+            Ofdpa3SetOvid setOvid = (Ofdpa3SetOvid) extensionTreatment;
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.name());
+            root.setAll(context.codec(Ofdpa3SetOvid.class).encode(setOvid, context));
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
+            Ofdpa3SetMplsL2Port setMplsL2Port = (Ofdpa3SetMplsL2Port) extensionTreatment;
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.name());
+            root.setAll(context.codec(Ofdpa3SetMplsL2Port.class).encode(setMplsL2Port, context));
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
+            Ofdpa3SetQosIndex setQosIndex = (Ofdpa3SetQosIndex) extensionTreatment;
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.name());
+            root.setAll(context.codec(Ofdpa3SetQosIndex.class).encode(setQosIndex, context));
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.type())) {
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.name());
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.type())) {
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.name());
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.type())) {
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.name());
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
+            root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.name());
+        }
+
+        return root;
+    }
+
+    @Override
+    public ExtensionTreatment decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        String type = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText();
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.name())) {
+            return context.codec(Ofdpa3SetMplsType.class).decode(json, context);
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.name())) {
+            return context.codec(Ofdpa3SetOvid.class).decode(json, context);
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.name())) {
+            return context.codec(Ofdpa3SetMplsL2Port.class).decode(json, context);
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.name())) {
+            return context.codec(Ofdpa3SetQosIndex.class).decode(json, context);
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.name())) {
+            return new Ofdpa3PushL2Header();
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.name())) {
+            return new Ofdpa3PushCw();
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.name())) {
+            return new Ofdpa3PopL2Header();
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.name())) {
+            return new Ofdpa3PopCw();
+        } else {
+            throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE + type.toString());
+        }
     }
 }
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index aae4266..2f646d5 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -88,6 +88,10 @@
                    impl="org.onosproject.driver.extensions.Ofdpa3ExtensionSelectorInterpreter" />
         <behaviour api="org.onosproject.net.behaviour.ExtensionSelectorResolver"
                    impl="org.onosproject.driver.extensions.Ofdpa3ExtensionSelectorInterpreter" />
+        <behaviour api="org.onosproject.net.flow.ExtensionTreatmentCodec"
+                   impl="org.onosproject.driver.extensions.Ofdpa3ExtensionTreatmentInterpreter" />
+        <behaviour api="org.onosproject.net.flow.ExtensionSelectorCodec"
+                   impl="org.onosproject.driver.extensions.Ofdpa3ExtensionSelectorInterpreter" />
     </driver>
 
     <!--  Driver for OFDPA 3.0 EA* for Qumran based switches.