[ONOS-6142] Add geo coordinate & list ext addresses with unit test

Change-Id: I538009b8a0d86b2d9229eae382c094a66a9b137e
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispGcAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispGcAddress.java
index 8e796be..9920108 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispGcAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispGcAddress.java
@@ -16,12 +16,24 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.Maps;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.mapping.addresses.ASMappingAddress;
+import org.onosproject.mapping.addresses.DNMappingAddress;
+import org.onosproject.mapping.addresses.EthMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.IPMappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.store.serializers.KryoNamespaces;
 
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
-                        .ExtensionMappingAddressTypes.GEO_COORDINATE_ADDRESS;
+                            .ExtensionMappingAddressTypes.GEO_COORDINATE_ADDRESS;
 
 /**
  * Implementation of LISP Geo Coordinate (GC) address.
@@ -30,7 +42,166 @@
  * physical location information.
  */
 public class LispGcAddress extends AbstractExtension
-                                            implements ExtensionMappingAddress {
+        implements ExtensionMappingAddress {
+
+    private static final String NORTH = "north";
+    private static final String LATITUDE_DEGREE = "latitudeDegree";
+    private static final String LATITUDE_MINUTE = "latitudeMinute";
+    private static final String LATITUDE_SECOND = "latitudeSecond";
+    private static final String EAST = "east";
+    private static final String LONGITUDE_DEGREE = "longitudeDegree";
+    private static final String LONGITUDE_MINUTE = "longitudeMinute";
+    private static final String LONGITUDE_SECOND = "longitudeSecond";
+    private static final String ALTITUDE = "altitude";
+    private static final String ADDRESS = "address";
+
+    private boolean north;
+    private short latitudeDegree;
+    private byte latitudeMinute;
+    private byte latitudeSecond;
+    private boolean east;
+    private short longitudeDegree;
+    private byte longitudeMinute;
+    private byte longitudeSecond;
+    private int altitude;
+    private MappingAddress address;
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder()
+                                                .register(KryoNamespaces.API)
+                                                .register(MappingAddress.class)
+                                                .register(MappingAddress.Type.class)
+                                                .register(IPMappingAddress.class)
+                                                .register(ASMappingAddress.class)
+                                                .register(DNMappingAddress.class)
+                                                .register(EthMappingAddress.class)
+                                                .build();
+
+    /**
+     * Default constructor.
+     */
+    public LispGcAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param north           north flag
+     * @param latitudeDegree  latitude degree
+     * @param latitudeMinute  latitude minute
+     * @param latitudeSecond  latitude second
+     * @param east            east flag
+     * @param longitudeDegree longitude degree
+     * @param longitudeMinute longitude minute
+     * @param longitudeSecond longitude second
+     * @param altitude        altitude
+     * @param address         mapping address
+     */
+    private LispGcAddress(boolean north, short latitudeDegree, byte latitudeMinute,
+                          byte latitudeSecond, boolean east, short longitudeDegree,
+                          byte longitudeMinute, byte longitudeSecond, int altitude,
+                          MappingAddress address) {
+        this.north = north;
+        this.latitudeDegree = latitudeDegree;
+        this.latitudeMinute = latitudeMinute;
+        this.latitudeSecond = latitudeSecond;
+        this.east = east;
+        this.longitudeDegree = longitudeDegree;
+        this.longitudeMinute = longitudeMinute;
+        this.longitudeSecond = longitudeSecond;
+        this.altitude = altitude;
+        this.address = address;
+    }
+
+    /**
+     * Obtains north flag value.
+     *
+     * @return north flag value
+     */
+    public boolean isNorth() {
+        return north;
+    }
+
+    /**
+     * Obtains latitude degree.
+     *
+     * @return latitude degree
+     */
+    public short getLatitudeDegree() {
+        return latitudeDegree;
+    }
+
+    /**
+     * Obtains latitude minute.
+     *
+     * @return latitude minute
+     */
+    public byte getLatitudeMinute() {
+        return latitudeMinute;
+    }
+
+    /**
+     * Obtains latitude second.
+     *
+     * @return latitude second
+     */
+    public byte getLatitudeSecond() {
+        return latitudeSecond;
+    }
+
+    /**
+     * Obtains east flag value.
+     *
+     * @return east flag vlaue
+     */
+    public boolean isEast() {
+        return east;
+    }
+
+    /**
+     * Obtains longitude degree.
+     *
+     * @return longitude degree
+     */
+    public short getLongitudeDegree() {
+        return longitudeDegree;
+    }
+
+    /**
+     * Obtains longitude minute.
+     *
+     * @return longitude minute
+     */
+    public byte getLongitudeMinute() {
+        return longitudeMinute;
+    }
+
+    /**
+     * Obtains longitude second.
+     *
+     * @return longitude second
+     */
+    public byte getLongitudeSecond() {
+        return longitudeSecond;
+    }
+
+    /**
+     * Obtains altitude.
+     *
+     * @return altitude
+     */
+    public int getAltitude() {
+        return altitude;
+    }
+
+    /**
+     * Obtains mapping address.
+     *
+     * @return mapping address
+     */
+    public MappingAddress getAddress() {
+        return address;
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
         return GEO_COORDINATE_ADDRESS.type();
@@ -38,11 +209,218 @@
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(NORTH, north);
+        parameterMap.put(LATITUDE_DEGREE, latitudeDegree);
+        parameterMap.put(LATITUDE_MINUTE, latitudeMinute);
+        parameterMap.put(LATITUDE_SECOND, latitudeSecond);
+        parameterMap.put(EAST, east);
+        parameterMap.put(LONGITUDE_DEGREE, longitudeDegree);
+        parameterMap.put(LONGITUDE_MINUTE, longitudeMinute);
+        parameterMap.put(LONGITUDE_SECOND, longitudeSecond);
+        parameterMap.put(ALTITUDE, altitude);
+        parameterMap.put(ADDRESS, address);
+
+        return appKryo.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
+        Map<String, Object> parameterMap = appKryo.deserialize(data);
 
+        this.north = (boolean) parameterMap.get(NORTH);
+        this.latitudeDegree = (short) parameterMap.get(LATITUDE_DEGREE);
+        this.latitudeMinute = (byte) parameterMap.get(LATITUDE_MINUTE);
+        this.latitudeSecond = (byte) parameterMap.get(LATITUDE_SECOND);
+        this.east = (boolean) parameterMap.get(EAST);
+        this.longitudeDegree = (short) parameterMap.get(LONGITUDE_DEGREE);
+        this.longitudeMinute = (byte) parameterMap.get(LONGITUDE_MINUTE);
+        this.longitudeSecond = (byte) parameterMap.get(LONGITUDE_SECOND);
+        this.altitude = (int) parameterMap.get(ALTITUDE);
+        this.address = (MappingAddress) parameterMap.get(ADDRESS);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(north, latitudeDegree, latitudeMinute, latitudeSecond,
+                east, longitudeDegree, longitudeMinute, longitudeSecond,
+                altitude, address);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LispGcAddress) {
+            final LispGcAddress other = (LispGcAddress) obj;
+            return Objects.equals(this.north, other.north) &&
+                    Objects.equals(this.latitudeDegree, other.latitudeDegree) &&
+                    Objects.equals(this.latitudeMinute, other.latitudeMinute) &&
+                    Objects.equals(this.latitudeSecond, other.latitudeSecond) &&
+                    Objects.equals(this.east, other.east) &&
+                    Objects.equals(this.longitudeDegree, other.longitudeDegree) &&
+                    Objects.equals(this.longitudeMinute, other.longitudeMinute) &&
+                    Objects.equals(this.longitudeSecond, other.longitudeSecond) &&
+                    Objects.equals(this.altitude, other.altitude) &&
+                    Objects.equals(this.address, other.address);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("north", north)
+                .add("latitude degree", latitudeDegree)
+                .add("latitude minute", latitudeMinute)
+                .add("latitude second", latitudeSecond)
+                .add("east", east)
+                .add("longitude degree", longitudeDegree)
+                .add("longitude minute", longitudeMinute)
+                .add("longitude second", longitudeSecond)
+                .add("altitude", altitude)
+                .add("address", address)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispGcAddress.
+     */
+    public static final class Builder {
+        private boolean north;
+        private short latitudeDegree;
+        private byte latitudeMinute;
+        private byte latitudeSecond;
+        private boolean east;
+        private short longitudeDegree;
+        private byte longitudeMinute;
+        private byte longitudeSecond;
+        private int altitude;
+        private MappingAddress address;
+
+        /**
+         * Sets north flag value.
+         *
+         * @param north north flag value
+         * @return Builder object
+         */
+        public Builder withIsNorth(boolean north) {
+            this.north = north;
+            return this;
+        }
+
+        /**
+         * Sets latitude degree.
+         *
+         * @param latitudeDegree latitude degree
+         * @return Builder object
+         */
+        public Builder withLatitudeDegree(short latitudeDegree) {
+            this.latitudeDegree = latitudeDegree;
+            return this;
+        }
+
+        /**
+         * Sets latitude minute.
+         *
+         * @param latitudeMinute latitude minute
+         * @return Builder object
+         */
+        public Builder withLatitudeMinute(byte latitudeMinute) {
+            this.latitudeMinute = latitudeMinute;
+            return this;
+        }
+
+        /**
+         * Sets latitude second.
+         *
+         * @param latitudeSecond latitude second
+         * @return Builder object
+         */
+        public Builder withLatitudeSecond(byte latitudeSecond) {
+            this.latitudeSecond = latitudeSecond;
+            return this;
+        }
+
+        /**
+         * Sets east flag value.
+         *
+         * @param east east flag
+         * @return Builder object
+         */
+        public Builder withIsEast(boolean east) {
+            this.east = east;
+            return this;
+        }
+
+        /**
+         * Sets longitude degree.
+         *
+         * @param longitudeDegree longitude degree
+         * @return Builder object
+         */
+        public Builder withLongitudeDegree(short longitudeDegree) {
+            this.longitudeDegree = longitudeDegree;
+            return this;
+        }
+
+        /**
+         * Sets longitude minute.
+         *
+         * @param longitudeMinute longitude minute
+         * @return Builder object
+         */
+        public Builder withLongitudeMinute(byte longitudeMinute) {
+            this.longitudeMinute = longitudeMinute;
+            return this;
+        }
+
+        /**
+         * Sets longitude second.
+         *
+         * @param longitudeSecond longitude second
+         * @return Builder object
+         */
+        public Builder withLongitudeSecond(byte longitudeSecond) {
+            this.longitudeSecond = longitudeSecond;
+            return this;
+        }
+
+        /**
+         * Sets altitude.
+         *
+         * @param altitude altitude
+         * @return Builder object
+         */
+        public Builder withAltitude(int altitude) {
+            this.altitude = altitude;
+            return this;
+        }
+
+        /**
+         * Sets mapping address.
+         *
+         * @param address mapping addres
+         * @return Builder object
+         */
+        public Builder withAddress(MappingAddress address) {
+            this.address = address;
+            return this;
+        }
+
+        /**
+         * Builds LispGcAddress instance.
+         *
+         * @return LispGcAddress instance
+         */
+        public LispGcAddress build() {
+
+            return new LispGcAddress(north, latitudeDegree,
+                    latitudeMinute, latitudeSecond, east, longitudeDegree,
+                    longitudeMinute, longitudeSecond, altitude, address);
+        }
     }
 }
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispListAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispListAddress.java
index 77beeee..bba2c17 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispListAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispListAddress.java
@@ -16,10 +16,22 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.Maps;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.mapping.addresses.ASMappingAddress;
+import org.onosproject.mapping.addresses.DNMappingAddress;
+import org.onosproject.mapping.addresses.EthMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.IPMappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.store.serializers.KryoNamespaces;
 
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
                                 .ExtensionMappingAddressTypes.LIST_ADDRESS;
 
@@ -31,6 +43,58 @@
  */
 public class LispListAddress extends AbstractExtension
                                             implements ExtensionMappingAddress {
+
+    private static final String IPV4 = "ipv4";
+    private static final String IPV6 = "ipv6";
+
+    private MappingAddress ipv4;
+    private MappingAddress ipv6;
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder()
+                                                .register(KryoNamespaces.API)
+                                                .register(MappingAddress.class)
+                                                .register(MappingAddress.Type.class)
+                                                .register(IPMappingAddress.class)
+                                                .register(ASMappingAddress.class)
+                                                .register(DNMappingAddress.class)
+                                                .register(EthMappingAddress.class)
+                                                .build();
+
+    /**
+     * Default constructor.
+     */
+    public LispListAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param ipv4 IPv4 address
+     * @param ipv6 IPv6 address
+     */
+    private LispListAddress(MappingAddress ipv4, MappingAddress ipv6) {
+        this.ipv4 = ipv4;
+        this.ipv6 = ipv6;
+    }
+
+    /**
+     * Obtains IPv4 address.
+     *
+     * @return IPv4 address
+     */
+    public MappingAddress getIpv4() {
+        return ipv4;
+    }
+
+    /**
+     * Obtains IPv6 address.
+     *
+     * @return IPv6 address
+     */
+    public MappingAddress getIpv6() {
+        return ipv6;
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
         return LIST_ADDRESS.type();
@@ -38,11 +102,86 @@
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(IPV4, ipv4);
+        parameterMap.put(IPV6, ipv6);
+
+        return appKryo.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
 
+        Map<String, Object> parameterMap = appKryo.deserialize(data);
+
+        this.ipv4 = (MappingAddress) parameterMap.get(IPV4);
+        this.ipv6 = (MappingAddress) parameterMap.get(IPV6);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ipv4, ipv6);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof LispListAddress) {
+            LispListAddress that = (LispListAddress) obj;
+            return Objects.equals(ipv4, that.ipv4) &&
+                    Objects.equals(ipv6, that.ipv6);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(type().toString())
+                .add("ipv4", ipv4)
+                .add("ipv6", ipv6)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispListAddress.
+     */
+    public static final class Builder {
+        private MappingAddress ipv4;
+        private MappingAddress ipv6;
+
+        /**
+         * Sets IPv4 address.
+         *
+         * @param ipv4 IPv4 address
+         * @return Builder object
+         */
+        public Builder withIpv4(MappingAddress ipv4) {
+            this.ipv4 = ipv4;
+            return this;
+        }
+
+        /**
+         * Sets IPv6 address.
+         *
+         * @param ipv6 IPv6 address
+         * @return Builder object
+         */
+        public Builder withIpv6(MappingAddress ipv6) {
+            this.ipv6 = ipv6;
+            return this;
+        }
+
+        /**
+         * Builds LispListAddress instance.
+         *
+         * @return LispListAddress instance
+         */
+        public LispListAddress build() {
+            return new LispListAddress(ipv4, ipv6);
+        }
     }
 }