Add REST API for query/update/delete/enable/disable telemetry config

1. Add unit test for newly added REST APIs
2. Add codec and unit tests for TelemetryConfig
3. Split web package out from app package due to dep conflict

Change-Id: I85f52b2a7d059622e98832843bc9613cb8befa98
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java
new file mode 100644
index 0000000..759dd5a
--- /dev/null
+++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaFlowInfoByteBufferCodec.java
@@ -0,0 +1,150 @@
+/*
+ * 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.openstacktelemetry.codec.bytebuffer;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpAddress.Version;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.openstacktelemetry.api.ByteBufferCodec;
+import org.onosproject.openstacktelemetry.api.FlowInfo;
+import org.onosproject.openstacktelemetry.api.StatsInfo;
+import org.onosproject.openstacktelemetry.api.DefaultFlowInfo;
+
+import java.nio.ByteBuffer;
+
+/**
+ * FlowInfo ByteBuffer Codec.
+ */
+public class TinaFlowInfoByteBufferCodec extends ByteBufferCodec<FlowInfo> {
+
+    private static final int NUM_RADIX = 16;
+    private static final int MESSAGE_SIZE = 88;
+    private static final String OF_PREFIX = "of:";
+
+    @Override
+    public ByteBuffer encode(FlowInfo flowInfo) {
+
+        ByteBuffer byteBuffer = ByteBuffer.allocate(MESSAGE_SIZE);
+        int srcPort = 0;
+        int dstPort = 0;
+
+        String  deviceId = flowInfo.deviceId().toString();
+        short switchId = (short) Integer.parseInt(deviceId.substring(3,
+                                      deviceId.length()), NUM_RADIX);
+
+        if (flowInfo.srcPort() != null) {
+            srcPort = flowInfo.srcPort().toInt();
+        }
+
+        if (flowInfo.dstPort() != null) {
+            dstPort = flowInfo.dstPort().toInt();
+        }
+
+        byteBuffer.put(flowInfo.flowType())
+                .putShort(switchId)
+                .putInt(flowInfo.inputInterfaceId())
+                .putInt(flowInfo.outputInterfaceId())
+                .putShort(flowInfo.vlanId().toShort())
+                .put(flowInfo.srcIp().address().toOctets())
+                .put((byte) flowInfo.srcIp().prefixLength())
+                .putShort((short) srcPort)
+                .put(flowInfo.dstIp().address().toOctets())
+                .put((byte) flowInfo.dstIp().prefixLength())
+                .putShort((short) dstPort)
+                .put(flowInfo.protocol())
+                .put(flowInfo.srcMac().toBytes())
+                .put(flowInfo.dstMac().toBytes());
+
+        TinaStatsInfoByteBufferCodec statsInfoByteBufferCodec =
+                new TinaStatsInfoByteBufferCodec();
+        byteBuffer.put(statsInfoByteBufferCodec.encode(flowInfo.statsInfo()).array());
+
+        return byteBuffer;
+    }
+
+    @Override
+    public FlowInfo decode(ByteBuffer byteBuffer) {
+
+        byte flowType = byteBuffer.get();
+        String deviceIdStr = String.format("%016x", byteBuffer.getShort());
+        DeviceId deviceId = DeviceId.deviceId(OF_PREFIX + deviceIdStr);
+        int inputInterfaceId = byteBuffer.getInt();
+        int outputInterfaceId = byteBuffer.getInt();
+        VlanId vlanId = VlanId.vlanId(byteBuffer.getShort());
+        IpAddress srcIp = IpAddress.valueOf(Version.INET, getIpv4Octets(byteBuffer));
+        int srcPrefixLen = byteBuffer.get();
+        TpPort srcPort = TpPort.tpPort((int) byteBuffer.getShort());
+        IpAddress dstIp = IpAddress.valueOf(Version.INET, getIpv4Octets(byteBuffer));
+        int dstPrefixLen = byteBuffer.get();
+        TpPort dstPort = TpPort.tpPort((int) byteBuffer.getShort());
+
+        byte protocol = byteBuffer.get();
+        MacAddress srcMac = MacAddress.valueOf(getMacByteArray(byteBuffer));
+        MacAddress dstMac = MacAddress.valueOf(getMacByteArray(byteBuffer));
+
+        TinaStatsInfoByteBufferCodec statsInfoByteBufferCodec =
+                new TinaStatsInfoByteBufferCodec();
+        StatsInfo statsInfo = statsInfoByteBufferCodec.decode(byteBuffer);
+
+        return new DefaultFlowInfo.DefaultBuilder()
+                .withFlowType(flowType)
+                .withDeviceId(deviceId)
+                .withInputInterfaceId(inputInterfaceId)
+                .withOutputInterfaceId(outputInterfaceId)
+                .withVlanId(vlanId)
+                .withSrcIp(IpPrefix.valueOf(srcIp, srcPrefixLen))
+                .withSrcPort(srcPort)
+                .withDstIp(IpPrefix.valueOf(dstIp, dstPrefixLen))
+                .withDstPort(dstPort)
+                .withProtocol(protocol)
+                .withSrcMac(srcMac)
+                .withDstMac(dstMac)
+                .withStatsInfo(statsInfo)
+                .build();
+    }
+
+    /**
+     * Obtains IPv4 Octets from ByteBuffer.
+     *
+     * @param buffer byte buffer
+     * @return Ipv4 Octets
+     */
+    private byte[] getIpv4Octets(ByteBuffer buffer) {
+        byte[] octets = new byte[4];
+        for (int i = 0; i < octets.length; i++) {
+            octets[i] = buffer.get();
+        }
+        return octets;
+    }
+
+    /**
+     * Obtains MAC address byte array from ByteBuffer.
+     *
+     * @param buffer byte buffer
+     * @return MAC address byte array
+     */
+    private byte[] getMacByteArray(ByteBuffer buffer) {
+        byte[] array = new byte[6];
+        for (int i = 0; i < array.length; i++) {
+            array[i] = buffer.get();
+        }
+        return array;
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java
new file mode 100644
index 0000000..514bc23
--- /dev/null
+++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaMessageByteBufferCodec.java
@@ -0,0 +1,69 @@
+/*
+ * 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.openstacktelemetry.codec.bytebuffer;
+
+import org.onosproject.openstacktelemetry.api.FlowInfo;
+import org.onosproject.openstacktelemetry.api.TelemetryCodec;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+
+/**
+ * Tina Message ByteBuffer Codec.
+ */
+public class TinaMessageByteBufferCodec implements TelemetryCodec {
+
+    private static final int HEADER_SIZE = 8;
+    private static final int ENTRY_SIZE = 88;
+    private static final int MILLISECONDS = 1000;
+    private static final short KAFKA_MESSAGE_TYPE = 1;
+
+    /**
+     * Encodes a collection flow infos into byte buffer.
+     *
+     * @param flowInfos a collection of flow info
+     * @return encoded byte buffer
+     */
+    @Override
+    public ByteBuffer encode(Set<FlowInfo> flowInfos) {
+        ByteBuffer byteBuffer =
+                ByteBuffer.allocate(HEADER_SIZE + flowInfos.size() * ENTRY_SIZE);
+
+        byteBuffer.put(buildMessageHeader(flowInfos));
+        byteBuffer.put(buildMessageBody(flowInfos));
+
+        return byteBuffer;
+    }
+
+    private byte[] buildMessageHeader(Set<FlowInfo> flowInfos) {
+        ByteBuffer byteBuffer = ByteBuffer.allocate(HEADER_SIZE);
+
+        byteBuffer.putShort((short) flowInfos.size());
+        byteBuffer.putShort(KAFKA_MESSAGE_TYPE);
+        byteBuffer.putInt((int) (System.currentTimeMillis() / MILLISECONDS));
+
+        return byteBuffer.array();
+    }
+
+    private byte[] buildMessageBody(Set<FlowInfo> flowInfos) {
+        ByteBuffer byteBuffer = ByteBuffer.allocate(flowInfos.size() * ENTRY_SIZE);
+
+        TinaFlowInfoByteBufferCodec codec = new TinaFlowInfoByteBufferCodec();
+        flowInfos.forEach(flowInfo -> byteBuffer.put(codec.encode(flowInfo).array()));
+
+        return byteBuffer.array();
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java
new file mode 100644
index 0000000..456dc72
--- /dev/null
+++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/TinaStatsInfoByteBufferCodec.java
@@ -0,0 +1,74 @@
+/*
+ * 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.openstacktelemetry.codec.bytebuffer;
+
+import org.onosproject.openstacktelemetry.api.ByteBufferCodec;
+import org.onosproject.openstacktelemetry.api.StatsInfo;
+import org.onosproject.openstacktelemetry.api.DefaultStatsInfo;
+
+import java.nio.ByteBuffer;
+
+/**
+ * StatsInfo ByteBuffer Codec.
+ */
+public class TinaStatsInfoByteBufferCodec extends ByteBufferCodec<StatsInfo> {
+
+    private static final int MESSAGE_SIZE = 48;
+
+    @Override
+    public ByteBuffer encode(StatsInfo statsInfo) {
+
+        ByteBuffer byteBuffer = ByteBuffer.allocate(MESSAGE_SIZE);
+
+        byteBuffer.putLong(statsInfo.startupTime())
+                .putLong(statsInfo.fstPktArrTime())
+                .putInt(statsInfo.lstPktOffset())
+                .putLong(statsInfo.prevAccBytes())
+                .putInt(statsInfo.prevAccPkts())
+                .putLong(statsInfo.currAccBytes())
+                .putInt(statsInfo.currAccPkts())
+                .putShort(statsInfo.errorPkts())
+                .putShort(statsInfo.dropPkts());
+
+        return byteBuffer;
+    }
+
+    @Override
+    public StatsInfo decode(ByteBuffer byteBuffer) {
+
+        long startupTime = byteBuffer.getLong();
+        long fstPktArrTime = byteBuffer.getLong();
+        int lstPktOffset = byteBuffer.getInt();
+        long prevAccBytes = byteBuffer.getLong();
+        int prevAccPkts = byteBuffer.getInt();
+        long currAccBytes = byteBuffer.getLong();
+        int currAccPkts = byteBuffer.getInt();
+        short errorPkts = byteBuffer.getShort();
+        short dropPkts = byteBuffer.getShort();
+
+        return new DefaultStatsInfo.DefaultBuilder()
+                .withStartupTime(startupTime)
+                .withFstPktArrTime(fstPktArrTime)
+                .withLstPktOffset(lstPktOffset)
+                .withPrevAccBytes(prevAccBytes)
+                .withPrevAccPkts(prevAccPkts)
+                .withCurrAccBytes(currAccBytes)
+                .withCurrAccPkts(currAccPkts)
+                .withErrorPkts(errorPkts)
+                .withDropPkts(dropPkts)
+                .build();
+    }
+}
diff --git a/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java
new file mode 100644
index 0000000..b8ef80a
--- /dev/null
+++ b/apps/openstacktelemetry/app/src/main/java/org/onosproject/openstacktelemetry/codec/bytebuffer/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementations of the codec broker and openstack telemetry entity codecs.
+ */
+package org.onosproject.openstacktelemetry.codec.bytebuffer;
\ No newline at end of file