[ONOS-6142] Add multicast & NAT extension addresses with unit test

Change-Id: I40f31e42de99bd9dbe28dd6418502f34b80013b0
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMulticastAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMulticastAddress.java
index 5bbda74..b47d36c 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMulticastAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispMulticastAddress.java
@@ -16,12 +16,18 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.Maps;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
 
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
-                            .ExtensionMappingAddressTypes.MULTICAST_ADDRESS;
+                                .ExtensionMappingAddressTypes.MULTICAST_ADDRESS;
 
 /**
  * Implementation of LISP multicast address.
@@ -29,7 +35,90 @@
  * multiple ETRs at receiver LISP multicast sites.
  */
 public class LispMulticastAddress extends AbstractExtension
-                                            implements ExtensionMappingAddress {
+        implements ExtensionMappingAddress {
+
+    private static final String INSTANCE_ID = "instanceId";
+    private static final String SRC_MASK_LENGTH = "srcMaskLength";
+    private static final String GRP_MASK_LENGTH = "grpMaskLength";
+    private static final String SRC_ADDRESS = "srcAddress";
+    private static final String GRP_ADDRESS = "grpAddress";
+
+    private int instanceId;
+    private byte srcMaskLength;
+    private byte grpMaskLength;
+    private MappingAddress srcAddress;
+    private MappingAddress grpAddress;
+
+    /**
+     * Default constructor.
+     */
+    public LispMulticastAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param instanceId    instance identifier
+     * @param srcMaskLength source mask length
+     * @param grpMaskLength group mask length
+     * @param srcAddress    source address
+     * @param grpAddress    group address
+     */
+    private LispMulticastAddress(int instanceId, byte srcMaskLength,
+                                 byte grpMaskLength, MappingAddress srcAddress,
+                                 MappingAddress grpAddress) {
+        this.instanceId = instanceId;
+        this.srcMaskLength = srcMaskLength;
+        this.grpMaskLength = grpMaskLength;
+        this.srcAddress = srcAddress;
+        this.grpAddress = grpAddress;
+    }
+
+    /**
+     * Obtains instance identifier.
+     *
+     * @return instance identifier
+     */
+    public int getInstanceId() {
+        return instanceId;
+    }
+
+    /**
+     * Obtains source mask length.
+     *
+     * @return source mask length
+     */
+    public byte getSrcMaskLength() {
+        return srcMaskLength;
+    }
+
+    /**
+     * Obtains group mask length.
+     *
+     * @return group mask length
+     */
+    public byte getGrpMaskLength() {
+        return grpMaskLength;
+    }
+
+    /**
+     * Obtains source address.
+     *
+     * @return source address
+     */
+    public MappingAddress getSrcAddress() {
+        return srcAddress;
+    }
+
+    /**
+     * Obtains group address.
+     *
+     * @return group address
+     */
+    public MappingAddress getGrpAddress() {
+        return grpAddress;
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
         return MULTICAST_ADDRESS.type();
@@ -37,11 +126,137 @@
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(INSTANCE_ID, instanceId);
+        parameterMap.put(SRC_MASK_LENGTH, srcMaskLength);
+        parameterMap.put(GRP_MASK_LENGTH, grpMaskLength);
+        parameterMap.put(SRC_ADDRESS, srcAddress);
+        parameterMap.put(GRP_ADDRESS, grpAddress);
+
+        return APP_KRYO.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
+        Map<String, Object> parameterMap = APP_KRYO.deserialize(data);
 
+        this.instanceId = (int) parameterMap.get(INSTANCE_ID);
+        this.srcMaskLength = (byte) parameterMap.get(SRC_MASK_LENGTH);
+        this.grpMaskLength = (byte) parameterMap.get(GRP_MASK_LENGTH);
+        this.srcAddress = (MappingAddress) parameterMap.get(SRC_ADDRESS);
+        this.grpAddress = (MappingAddress) parameterMap.get(GRP_ADDRESS);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(instanceId, srcMaskLength, grpMaskLength,
+                srcAddress, grpAddress);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LispMulticastAddress) {
+            final LispMulticastAddress other = (LispMulticastAddress) obj;
+            return Objects.equals(this.instanceId, other.instanceId) &&
+                    Objects.equals(this.srcMaskLength, other.srcMaskLength) &&
+                    Objects.equals(this.grpMaskLength, other.grpMaskLength) &&
+                    Objects.equals(this.srcAddress, other.srcAddress) &&
+                    Objects.equals(this.grpAddress, other.grpAddress);
+
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("instance ID", instanceId)
+                .add("source mask length", srcMaskLength)
+                .add("group mask length", grpMaskLength)
+                .add("source address", srcAddress)
+                .add("group address", grpAddress)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispMulticastAddress.
+     */
+    public static final class Builder {
+        private int instanceId;
+        private byte srcMaskLength;
+        private byte grpMaskLength;
+        private MappingAddress srcAddress;
+        private MappingAddress grpAddress;
+
+        /**
+         * Sets instance identifier.
+         *
+         * @param instanceId instance identifier
+         * @return Builder object
+         */
+        public Builder withInstanceId(int instanceId) {
+            this.instanceId = instanceId;
+            return this;
+        }
+
+        /**
+         * Sets source mask length.
+         *
+         * @param srcMaskLength source mask length
+         * @return Builder object
+         */
+        public Builder withSrcMaskLength(byte srcMaskLength) {
+            this.srcMaskLength = srcMaskLength;
+            return this;
+        }
+
+        /**
+         * Sets group mask length.
+         *
+         * @param grpMaskLength group mask length
+         * @return Builder object
+         */
+        public Builder withGrpMaskLength(byte grpMaskLength) {
+            this.grpMaskLength = grpMaskLength;
+            return this;
+        }
+
+        /**
+         * Sets source address.
+         *
+         * @param srcAddress source address
+         * @return Builder object
+         */
+        public Builder withSrcAddress(MappingAddress srcAddress) {
+            this.srcAddress = srcAddress;
+            return this;
+        }
+
+        /**
+         * Sets group address.
+         *
+         * @param grpAddress group address
+         * @return Builder object
+         */
+        public Builder withGrpAddress(MappingAddress grpAddress) {
+            this.grpAddress = grpAddress;
+            return this;
+        }
+
+        /**
+         * Builds LispMulticastAddress instance.
+         *
+         * @return LispMulticastAddress instance
+         */
+        public LispMulticastAddress build() {
+
+            return new LispMulticastAddress(instanceId, srcMaskLength,
+                    grpMaskLength, srcAddress, grpAddress);
+        }
     }
 }
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNatAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNatAddress.java
index a71b684..1687eb9 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNatAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNatAddress.java
@@ -16,10 +16,18 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
 
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
                                 .ExtensionMappingAddressTypes.NAT_ADDRESS;
 
@@ -30,6 +38,104 @@
  */
 public class LispNatAddress extends AbstractExtension
                                             implements ExtensionMappingAddress {
+
+    private static final String MS_UDP_PORT_NUMBER = "msUdpPortNumber";
+    private static final String ETR_UDP_PORT_NUMBER = "etrUdpPortNumber";
+    private static final String GLOBAL_ETR_RLOC_ADDRESS = "globalEtrRlocAddress";
+    private static final String MS_RLOC_ADDRESS = "msRlocAddress";
+    private static final String PRIVATE_ETR_RLOC_ADDRESS = "privateEtrRlocAddress";
+    private static final String RTR_RLOC_ADDRESSES = "rtrRlocAddresses";
+
+    private short msUdpPortNumber;
+    private short etrUdpPortNumber;
+    private MappingAddress globalEtrRlocAddress;
+    private MappingAddress msRlocAddress;
+    private MappingAddress privateEtrRlocAddress;
+    private List<MappingAddress> rtrRlocAddresses;
+
+    /**
+     * Default constructor.
+     */
+    public LispNatAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param msUdpPortNumber       Map Server (MS) UDP port number
+     * @param etrUdpPortNumber      ETR UDP port number
+     * @param globalEtrRlocAddress  global ETR RLOC address
+     * @param msRlocAddress         Map Server (MS) RLOC address
+     * @param privateEtrRlocAddress private ETR RLOC address
+     * @param rtrRlocAddresses      a collection of RTR RLOC addresses
+     */
+    private LispNatAddress(short msUdpPortNumber, short etrUdpPortNumber,
+                           MappingAddress globalEtrRlocAddress,
+                           MappingAddress msRlocAddress,
+                           MappingAddress privateEtrRlocAddress,
+                           List<MappingAddress> rtrRlocAddresses) {
+        this.msUdpPortNumber = msUdpPortNumber;
+        this.etrUdpPortNumber = etrUdpPortNumber;
+        this.globalEtrRlocAddress = globalEtrRlocAddress;
+        this.msRlocAddress = msRlocAddress;
+        this.privateEtrRlocAddress = privateEtrRlocAddress;
+        this.rtrRlocAddresses = ImmutableList.copyOf(rtrRlocAddresses);
+    }
+
+    /**
+     * Obtains Map Server UDP port number.
+     *
+     * @return Map Server UDP port number
+     */
+    public short getMsUdpPortNumber() {
+        return msUdpPortNumber;
+    }
+
+    /**
+     * Obtains ETR UDP port number.
+     *
+     * @return ETR UDP port number
+     */
+    public short getEtrUdpPortNumber() {
+        return etrUdpPortNumber;
+    }
+
+    /**
+     * Obtains global ETR RLOC address.
+     *
+     * @return global ETR
+     */
+    public MappingAddress getGlobalEtrRlocAddress() {
+        return globalEtrRlocAddress;
+    }
+
+    /**
+     * Obtains Map Server RLOC address.
+     *
+     * @return Map Server RLOC address
+     */
+    public MappingAddress getMsRlocAddress() {
+        return msRlocAddress;
+    }
+
+    /**
+     * Obtains private ETR RLOC address.
+     *
+     * @return private ETR RLOC address
+     */
+    public MappingAddress getPrivateEtrRlocAddress() {
+        return privateEtrRlocAddress;
+    }
+
+    /**
+     * Obtains a collection of RTR RLOC addresses.
+     *
+     * @return a collection of RTR RLOC addresses
+     */
+    public List<MappingAddress> getRtrRlocAddresses() {
+        return ImmutableList.copyOf(rtrRlocAddresses);
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
         return NAT_ADDRESS.type();
@@ -37,11 +143,155 @@
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(MS_UDP_PORT_NUMBER, msUdpPortNumber);
+        parameterMap.put(ETR_UDP_PORT_NUMBER, etrUdpPortNumber);
+        parameterMap.put(GLOBAL_ETR_RLOC_ADDRESS, globalEtrRlocAddress);
+        parameterMap.put(MS_RLOC_ADDRESS, msRlocAddress);
+        parameterMap.put(PRIVATE_ETR_RLOC_ADDRESS, privateEtrRlocAddress);
+        parameterMap.put(RTR_RLOC_ADDRESSES, rtrRlocAddresses);
+
+        return APP_KRYO.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
+        Map<String, Object> parameterMap = APP_KRYO.deserialize(data);
 
+        this.msUdpPortNumber = (short) parameterMap.get(MS_UDP_PORT_NUMBER);
+        this.etrUdpPortNumber = (short) parameterMap.get(ETR_UDP_PORT_NUMBER);
+        this.globalEtrRlocAddress = (MappingAddress) parameterMap.get(GLOBAL_ETR_RLOC_ADDRESS);
+        this.msRlocAddress = (MappingAddress) parameterMap.get(MS_RLOC_ADDRESS);
+        this.privateEtrRlocAddress = (MappingAddress) parameterMap.get(PRIVATE_ETR_RLOC_ADDRESS);
+        this.rtrRlocAddresses = (List<MappingAddress>) parameterMap.get(RTR_RLOC_ADDRESSES);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(msUdpPortNumber, etrUdpPortNumber,
+                globalEtrRlocAddress, msRlocAddress, privateEtrRlocAddress);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LispNatAddress) {
+            final LispNatAddress other = (LispNatAddress) obj;
+            return Objects.equals(this.msUdpPortNumber, other.msUdpPortNumber) &&
+                    Objects.equals(this.etrUdpPortNumber, other.etrUdpPortNumber) &&
+                    Objects.equals(this.globalEtrRlocAddress, other.globalEtrRlocAddress) &&
+                    Objects.equals(this.msRlocAddress, other.msRlocAddress) &&
+                    Objects.equals(this.privateEtrRlocAddress, other.privateEtrRlocAddress) &&
+                    Objects.equals(this.rtrRlocAddresses, other.rtrRlocAddresses);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("Map Server UDP port number", msUdpPortNumber)
+                .add("ETR UDP port number", etrUdpPortNumber)
+                .add("global ETR RLOC address", globalEtrRlocAddress)
+                .add("Map Server RLOC address", msRlocAddress)
+                .add("private ETR RLOC address", privateEtrRlocAddress)
+                .add("RTR RLOC addresses", rtrRlocAddresses)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispNatAddress.
+     */
+    public static final class Builder {
+        private short msUdpPortNumber;
+        private short etrUdpPortNumber;
+        private MappingAddress globalEtrRlocAddress;
+        private MappingAddress msRlocAddress;
+        private MappingAddress privateEtrRlocAddress;
+        private List<MappingAddress> rtrRlocAddresses;
+
+        /**
+         * Sets Map Server UDP port number.
+         *
+         * @param msUdpPortNumber Map Server UDP port number
+         * @return Builder object
+         */
+        public Builder withMsUdpPortNumber(short msUdpPortNumber) {
+            this.msUdpPortNumber = msUdpPortNumber;
+            return this;
+        }
+
+        /**
+         * Sets ETR UDP port number.
+         *
+         * @param etrUdpPortNumber ETR UDP port number
+         * @return Builder object
+         */
+        public Builder withEtrUdpPortNumber(short etrUdpPortNumber) {
+            this.etrUdpPortNumber = etrUdpPortNumber;
+            return this;
+        }
+
+        /**
+         * Sets global ETR RLOC address.
+         *
+         * @param globalEtrRlocAddress global ETR RLOC address
+         * @return Builder object
+         */
+        public Builder withGlobalEtrRlocAddress(MappingAddress globalEtrRlocAddress) {
+            this.globalEtrRlocAddress = globalEtrRlocAddress;
+            return this;
+        }
+
+        /**
+         * Sets Map Server RLOC address.
+         *
+         * @param msRlocAddress Map Server RLOC address
+         * @return Builder object
+         */
+        public Builder withMsRlocAddress(MappingAddress msRlocAddress) {
+            this.msRlocAddress = msRlocAddress;
+            return this;
+        }
+
+        /**
+         * Sets private ETR RLOC address.
+         *
+         * @param privateEtrRlocAddress private ETR RLOC address
+         * @return Builder object
+         */
+        public Builder withPrivateEtrRlocAddress(MappingAddress privateEtrRlocAddress) {
+            this.privateEtrRlocAddress = privateEtrRlocAddress;
+            return this;
+        }
+
+        /**
+         * Sets RTR RLOC addresses.
+         *
+         * @param rtrRlocAddresses a collection of RTR RLOC addresses
+         * @return Builder object
+         */
+        public Builder withRtrRlocAddresses(List<MappingAddress> rtrRlocAddresses) {
+            if (rtrRlocAddresses != null) {
+                this.rtrRlocAddresses = ImmutableList.copyOf(rtrRlocAddresses);
+            }
+            return this;
+        }
+
+        /**
+         * Builds LispNatAddress instance.
+         *
+         * @return LispNatAddress instance
+         */
+        public LispNatAddress build() {
+
+            return new LispNatAddress(msUdpPortNumber, etrUdpPortNumber,
+                                        globalEtrRlocAddress, msRlocAddress,
+                                        privateEtrRlocAddress, rtrRlocAddresses);
+        }
     }
 }