Add ChannelStatus

Change-Id: I14495cb211f71df6abec599738d5af97ee3a023a
diff --git a/src/main/java/com/intel/jndn/management/Nfdc.java b/src/main/java/com/intel/jndn/management/Nfdc.java
index aba6c4f..f8a780d 100644
--- a/src/main/java/com/intel/jndn/management/Nfdc.java
+++ b/src/main/java/com/intel/jndn/management/Nfdc.java
@@ -17,6 +17,7 @@
 import com.intel.jndn.management.enums.RouteOrigin;
 import com.intel.jndn.management.helpers.FetchHelper;
 import com.intel.jndn.management.helpers.StatusDatasetHelper;
+import com.intel.jndn.management.types.ChannelStatus;
 import com.intel.jndn.management.types.FaceStatus;
 import com.intel.jndn.management.types.FibEntry;
 import com.intel.jndn.management.types.ForwarderStatus;
@@ -151,6 +152,25 @@
   }
 
   /**
+   * Retrieve the list of channel status entries from the NFD; calls
+   * /localhost/nfd/faces/channels which requires a local Face (all non-local packets
+   * are dropped).
+   *
+   * @param face only a localhost Face
+   * @return a list of channel status entries
+   * @throws ManagementException if the network request failed, the NFD response could not be decoded, or
+   *                             the NFD rejected the request
+   * @see <a href="http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset">Face Management</a>
+   */
+  public static List<ChannelStatus> getChannelStatusList(final Face face) throws ManagementException {
+    try {
+      List<Data> segments = FetchHelper.getSegmentedData(face, new Name("/localhost/nfd/faces/channels"));
+      return StatusDatasetHelper.wireDecode(segments, ChannelStatus.class);
+    } catch (IOException e) {
+      throw new ManagementException(e.getMessage(), e);
+    }
+  }
+  /**
    * Retrieve the {@link KeyLocator} for an NFD.
    *
    * @param face only a localhost {@link Face}
diff --git a/src/main/java/com/intel/jndn/management/types/ChannelStatus.java b/src/main/java/com/intel/jndn/management/types/ChannelStatus.java
new file mode 100644
index 0000000..8f30d07
--- /dev/null
+++ b/src/main/java/com/intel/jndn/management/types/ChannelStatus.java
@@ -0,0 +1,117 @@
+/*
+ * jndn-management
+ * Copyright (c) 2016, Regents of the University of California.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 3, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ */
+package com.intel.jndn.management.types;
+
+import com.intel.jndn.management.enums.NfdTlv;
+import com.intel.jndn.management.helpers.EncodingHelper;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.encoding.tlv.TlvEncoder;
+import net.named_data.jndn.util.Blob;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Represent a ChannelStatus object.
+ *
+ * @see <a href="http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset">Face Management</a>
+ */
+public class ChannelStatus implements Decodable {
+  private String localUri = "";
+  /////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Default constructor.
+   */
+  public ChannelStatus() {
+    // nothing to do
+  }
+
+  /**
+   * Constructor from wire format.
+   *
+   * @param input wire format
+   * @throws EncodingException when decoding fails
+   */
+  public ChannelStatus(final ByteBuffer input) throws EncodingException {
+    wireDecode(input);
+  }
+
+  /**
+   * Encode using a new TLV encoder.
+   *
+   * @return The encoded buffer
+   */
+  public final Blob wireEncode() {
+    TlvEncoder encoder = new TlvEncoder();
+    wireEncode(encoder);
+    return new Blob(encoder.getOutput(), false);
+  }
+
+  /**
+   * Encode as part of an existing encode context.
+   *
+   * @param encoder TlvEncoder instance
+   */
+  public final void wireEncode(final TlvEncoder encoder) {
+    int saveLength = encoder.getLength();
+    encoder.writeBlobTlv(NfdTlv.LocalUri, new Blob(localUri).buf());
+    encoder.writeTypeAndLength(NfdTlv.ChannelStatus, encoder.getLength() - saveLength);
+  }
+
+  /**
+   * Decode the input from its TLV format.
+   *
+   * @param input The input buffer to decode. This reads from position() to
+   *              limit(), but does not change the position.
+   * @throws EncodingException when decoding fails
+   */
+  public final void wireDecode(final ByteBuffer input) throws EncodingException {
+    TlvDecoder decoder = new TlvDecoder(input);
+    wireDecode(decoder);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void wireDecode(final TlvDecoder decoder) throws EncodingException {
+    int endOffset = decoder.readNestedTlvsStart(NfdTlv.ChannelStatus);
+    this.localUri = EncodingHelper.toString(decoder.readBlobTlv(NfdTlv.LocalUri));
+    decoder.finishNestedTlvs(endOffset);
+  }
+
+  /**
+   * @return channel URI
+   */
+  public String getLocalUri() {
+    return localUri;
+  }
+
+  /**
+   * Set channel URI.
+   *
+   * @param localUri channel URI
+   * @return this
+   */
+  public ChannelStatus setLocalUri(final String localUri) {
+    this.localUri = localUri;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    return "ChannelStatus(" + getLocalUri() + ")";
+  }
+}