management: replace FaceFlags with individual fields

refs #1992

Change-Id: I2b8e999fcf27444b8f3805f23da9f8ef9bcb5624
diff --git a/src/management/nfd-face-event-notification.cpp b/src/management/nfd-face-event-notification.cpp
new file mode 100644
index 0000000..d459de4
--- /dev/null
+++ b/src/management/nfd-face-event-notification.cpp
@@ -0,0 +1,186 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that 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.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "nfd-face-event-notification.hpp"
+
+namespace ndn {
+namespace nfd {
+FaceEventNotification::FaceEventNotification()
+  : FaceTraits()
+  , m_kind(static_cast<FaceEventKind>(0))
+{
+}
+
+FaceEventNotification::FaceEventNotification(const Block& block)
+{
+  this->wireDecode(block);
+}
+
+template<bool T>
+size_t
+FaceEventNotification::wireEncode(EncodingImpl<T>& encoder) const
+{
+  size_t totalLength = 0;
+
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::LinkType, m_linkType);
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FacePersistency, m_facePersistency);
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FaceScope, m_faceScope);
+  totalLength += prependByteArrayBlock(encoder, tlv::nfd::LocalUri,
+                 reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+  totalLength += prependByteArrayBlock(encoder, tlv::nfd::Uri,
+                 reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FaceId, m_faceId);
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FaceEventKind, m_kind);
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::nfd::FaceEventNotification);
+  return totalLength;
+}
+
+const Block&
+FaceEventNotification::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+  return m_wire;
+}
+
+void
+FaceEventNotification::wireDecode(const Block& block)
+{
+  if (block.type() != tlv::nfd::FaceEventNotification) {
+    throw Error("expecting FaceEventNotification block");
+  }
+  m_wire = block;
+  m_wire.parse();
+  Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceEventKind) {
+    m_kind = static_cast<FaceEventKind>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required FaceEventKind field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+    m_faceId = readNonNegativeInteger(*val);
+    ++val;
+  }
+  else {
+    throw Error("missing required FaceId field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
+    m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+    ++val;
+  }
+  else {
+    throw Error("missing required Uri field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+    m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+    ++val;
+  }
+  else {
+    throw Error("missing required LocalUri field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+    m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required FaceScope field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+    m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required FacePersistency field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+    m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required LinkType field");
+  }
+}
+
+FaceEventNotification&
+FaceEventNotification::setKind(FaceEventKind kind)
+{
+  m_wire.reset();
+  m_kind = kind;
+  return *this;
+}
+
+void
+FaceEventNotification::wireReset() const
+{
+  m_wire.reset();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceEventNotification& notification)
+{
+  os << "FaceEventNotification(";
+
+  switch (notification.getKind())
+    {
+    case FACE_EVENT_CREATED:
+      os << "Kind: created, ";
+      break;
+    case FACE_EVENT_DESTROYED:
+      os << "Kind: destroyed, ";
+      break;
+    }
+
+  os << "FaceID: " << notification.getFaceId() << ", "
+     << "RemoteUri: " << notification.getRemoteUri() << ", "
+     << "LocalUri: " << notification.getLocalUri() << ", "
+     << "FaceScope: " << notification.getFaceScope() << ", "
+     << "FacePersistency: " << notification.getFacePersistency() << ", "
+     << "LinkType: " << notification.getLinkType()
+     << ")";
+  return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/management/nfd-face-event-notification.hpp b/src/management/nfd-face-event-notification.hpp
index a455e57..94870d9 100644
--- a/src/management/nfd-face-event-notification.hpp
+++ b/src/management/nfd-face-event-notification.hpp
@@ -23,11 +23,7 @@
 #define NDN_MANAGEMENT_NFD_FACE_EVENT_NOTIFICATION_HPP
 
 // This include must be kept as the first one, to ensure nfd-face-flags.hpp compiles on its own.
-#include "nfd-face-flags.hpp"
-
-#include "../encoding/tlv-nfd.hpp"
-#include "../encoding/encoding-buffer.hpp"
-#include "../encoding/block-helpers.hpp"
+#include "nfd-face-traits.hpp"
 
 namespace ndn {
 namespace nfd {
@@ -45,26 +41,13 @@
  * \brief represents a Face status change notification
  * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Status-Change-Notification
  */
-class FaceEventNotification : public FaceFlagsTraits<FaceEventNotification>
+class FaceEventNotification : public FaceTraits<FaceEventNotification>
 {
 public:
-  class Error : public tlv::Error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : tlv::Error(what)
-    {
-    }
-  };
-
   FaceEventNotification();
 
   explicit
-  FaceEventNotification(const Block& block)
-  {
-    this->wireDecode(block);
-  }
+  FaceEventNotification(const Block& block);
 
   /** \brief prepend FaceEventNotification to the encoder
    */
@@ -90,198 +73,20 @@
   }
 
   FaceEventNotification&
-  setKind(FaceEventKind kind)
-  {
-    m_wire.reset();
-    m_kind = kind;
-    return *this;
-  }
+  setKind(FaceEventKind kind);
 
-  uint64_t
-  getFaceId() const
-  {
-    return m_faceId;
-  }
-
-  FaceEventNotification&
-  setFaceId(uint64_t faceId)
-  {
-    m_wire.reset();
-    m_faceId = faceId;
-    return *this;
-  }
-
-  const std::string&
-  getRemoteUri() const
-  {
-    return m_remoteUri;
-  }
-
-  FaceEventNotification&
-  setRemoteUri(const std::string& remoteUri)
-  {
-    m_wire.reset();
-    m_remoteUri = remoteUri;
-    return *this;
-  }
-
-  const std::string&
-  getLocalUri() const
-  {
-    return m_localUri;
-  }
-
-  FaceEventNotification&
-  setLocalUri(const std::string& localUri)
-  {
-    m_wire.reset();
-    m_localUri = localUri;
-    return *this;
-  }
-
-  uint64_t
-  getFlags() const
-  {
-    return m_flags;
-  }
-
-  FaceEventNotification&
-  setFlags(uint64_t flags)
-  {
-    m_wire.reset();
-    m_flags = flags;
-    return *this;
-  }
+protected:
+  void
+  wireReset() const;
 
 private:
   FaceEventKind m_kind;
-  uint64_t m_faceId;
-  std::string m_remoteUri;
-  std::string m_localUri;
-  uint64_t m_flags;
 
   mutable Block m_wire;
 };
 
-inline
-FaceEventNotification::FaceEventNotification()
-  : m_kind(static_cast<FaceEventKind>(0))
-  , m_faceId(0)
-  , m_flags(0)
-{
-}
-
-template<bool T>
-inline size_t
-FaceEventNotification::wireEncode(EncodingImpl<T>& encoder) const
-{
-  size_t totalLength = 0;
-
-  totalLength += prependNonNegativeIntegerBlock(encoder,
-                 tlv::nfd::FaceFlags, m_flags);
-  totalLength += prependByteArrayBlock(encoder, tlv::nfd::LocalUri,
-                 reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
-  totalLength += prependByteArrayBlock(encoder, tlv::nfd::Uri,
-                 reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
-  totalLength += prependNonNegativeIntegerBlock(encoder,
-                 tlv::nfd::FaceId, m_faceId);
-  totalLength += prependNonNegativeIntegerBlock(encoder,
-                 tlv::nfd::FaceEventKind, m_kind);
-
-  totalLength += encoder.prependVarNumber(totalLength);
-  totalLength += encoder.prependVarNumber(tlv::nfd::FaceEventNotification);
-  return totalLength;
-}
-
-inline const Block&
-FaceEventNotification::wireEncode() const
-{
-  if (m_wire.hasWire())
-    return m_wire;
-
-  EncodingEstimator estimator;
-  size_t estimatedSize = wireEncode(estimator);
-
-  EncodingBuffer buffer(estimatedSize, 0);
-  wireEncode(buffer);
-
-  m_wire = buffer.block();
-  return m_wire;
-}
-
-inline void
-FaceEventNotification::wireDecode(const Block& block)
-{
-  if (block.type() != tlv::nfd::FaceEventNotification) {
-    throw Error("expecting FaceEventNotification block");
-  }
-  m_wire = block;
-  m_wire.parse();
-  Block::element_const_iterator val = m_wire.elements_begin();
-
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceEventKind) {
-    m_kind = static_cast<FaceEventKind>(readNonNegativeInteger(*val));
-    ++val;
-  }
-  else {
-    throw Error("missing required FaceEventKind field");
-  }
-
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
-    m_faceId = static_cast<uint64_t>(readNonNegativeInteger(*val));
-    ++val;
-  }
-  else {
-    throw Error("missing required FaceId field");
-  }
-
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
-    m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
-    ++val;
-  }
-  else {
-    throw Error("missing required Uri field");
-  }
-
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
-    m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
-    ++val;
-  }
-  else {
-    throw Error("missing required LocalUri field");
-  }
-
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceFlags) {
-    m_flags = static_cast<uint64_t>(readNonNegativeInteger(*val));
-    ++val;
-  }
-  else {
-    throw Error("missing required FaceFlags field");
-  }
-}
-
-inline std::ostream&
-operator<<(std::ostream& os, const FaceEventNotification& notification)
-{
-  os << "FaceEventNotification(";
-
-  switch (notification.getKind())
-    {
-    case FACE_EVENT_CREATED:
-      os << "Kind: created, ";
-      break;
-    case FACE_EVENT_DESTROYED:
-      os << "Kind: destroyed, ";
-      break;
-    }
-
-  os << "FaceID: " << notification.getFaceId() << ", "
-     << "RemoteUri: " << notification.getRemoteUri() << ", "
-     << "LocalUri: " << notification.getLocalUri() << ", "
-     << "Flags: " << notification.getFlags()
-     << ")";
-  return os;
-}
+std::ostream&
+operator<<(std::ostream& os, const FaceEventNotification& notification);
 
 } // namespace nfd
 } // namespace ndn
diff --git a/src/management/nfd-face-flags.hpp b/src/management/nfd-face-flags.hpp
deleted file mode 100644
index 39c85cb..0000000
--- a/src/management/nfd-face-flags.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2014 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that 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.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#ifndef NDN_MANAGEMENT_NFD_FACE_FLAGS_HPP
-#define NDN_MANAGEMENT_NFD_FACE_FLAGS_HPP
-
-namespace ndn {
-namespace nfd {
-
-/**
- * \ingroup management
- * \brief provides additional information about a face
- */
-enum FaceFlags {
-  /** \brief face is local (for scope control purpose)
-   */
-  FACE_IS_LOCAL = 1,
-  /** \brief face is created on demand (accepted incoming connection,
-   *         not initiated outgoing connection)
-   */
-  FACE_IS_ON_DEMAND = 2
-  // FACE_? = 4
-  // FACE_? = 8
-};
-
-/**
- * \ingroup management
- * \brief implements getters to each face flag
- *
- * \tparam T class containing a FaceFlags field and implements
- *           `FaceFlags getFlags() const` method
- */
-template<typename T>
-class FaceFlagsTraits
-{
-public:
-  bool
-  isLocal() const
-  {
-    return static_cast<const T*>(this)->getFlags() & FACE_IS_LOCAL;
-  }
-
-  bool
-  isOnDemand() const
-  {
-    return static_cast<const T*>(this)->getFlags() & FACE_IS_ON_DEMAND;
-  }
-};
-
-} // namespace nfd
-} // namespace ndn
-
-#endif // NDN_MANAGEMENT_NFD_FACE_FLAGS_HPP
diff --git a/src/management/nfd-face-status.cpp b/src/management/nfd-face-status.cpp
index adf29c2..17145bd 100644
--- a/src/management/nfd-face-status.cpp
+++ b/src/management/nfd-face-status.cpp
@@ -25,9 +25,8 @@
 namespace nfd {
 
 FaceStatus::FaceStatus()
-  : m_faceId(0)
+  : FaceTraits()
   , m_hasExpirationPeriod(false)
-  , m_flags(0)
   , m_nInInterests(0)
   , m_nInDatas(0)
   , m_nOutInterests(0)
@@ -37,6 +36,11 @@
 {
 }
 
+FaceStatus::FaceStatus(const Block& block)
+{
+  this->wireDecode(block);
+}
+
 template<bool T>
 size_t
 FaceStatus::wireEncode(EncodingImpl<T>& encoder) const
@@ -56,7 +60,11 @@
   totalLength += prependNonNegativeIntegerBlock(encoder,
                  tlv::nfd::NInInterests, m_nInInterests);
   totalLength += prependNonNegativeIntegerBlock(encoder,
-                 tlv::nfd::FaceFlags, m_flags);
+                 tlv::nfd::LinkType, m_linkType);
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FacePersistency, m_facePersistency);
+  totalLength += prependNonNegativeIntegerBlock(encoder,
+                 tlv::nfd::FaceScope, m_faceScope);
   if (m_hasExpirationPeriod) {
     totalLength += prependNonNegativeIntegerBlock(encoder,
                    tlv::nfd::ExpirationPeriod, m_expirationPeriod.count());
@@ -139,12 +147,28 @@
     // ExpirationPeriod is optional
   }
 
-  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceFlags) {
-    m_flags = readNonNegativeInteger(*val);
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+    m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
     ++val;
   }
   else {
-    throw Error("missing required FaceFlags field");
+    throw Error("missing required FaceScope field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+    m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required FacePersistency field");
+  }
+
+  if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+    m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+    ++val;
+  }
+  else {
+    throw Error("missing required LinkType field");
   }
 
   if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInInterests) {
@@ -196,6 +220,69 @@
   }
 }
 
+FaceStatus&
+FaceStatus::setExpirationPeriod(const time::milliseconds& expirationPeriod)
+{
+  m_wire.reset();
+  m_expirationPeriod = expirationPeriod;
+  m_hasExpirationPeriod = true;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInInterests(uint64_t nInInterests)
+{
+  m_wire.reset();
+  m_nInInterests = nInInterests;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInDatas(uint64_t nInDatas)
+{
+  m_wire.reset();
+  m_nInDatas = nInDatas;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutInterests(uint64_t nOutInterests)
+{
+  m_wire.reset();
+  m_nOutInterests = nOutInterests;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutDatas(uint64_t nOutDatas)
+{
+  m_wire.reset();
+  m_nOutDatas = nOutDatas;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInBytes(uint64_t nInBytes)
+{
+  m_wire.reset();
+  m_nInBytes = nInBytes;
+  return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutBytes(uint64_t nOutBytes)
+{
+  m_wire.reset();
+  m_nOutBytes = nOutBytes;
+  return *this;
+}
+
+void
+FaceStatus::wireReset() const
+{
+  m_wire.reset();
+}
+
 std::ostream&
 operator<<(std::ostream& os, const FaceStatus& status)
 {
@@ -211,7 +298,9 @@
     os << "ExpirationPeriod: infinite,\n";
   }
 
-  os << "Flags: " << status.getFlags() << ",\n"
+  os << "FaceScope: " << status.getFaceScope() << ",\n"
+     << "FacePersistency: " << status.getFacePersistency() << ",\n"
+     << "LinkType: " << status.getLinkType() << ",\n"
      << "Counters: { Interests: {in: " << status.getNInInterests() << ", "
      << "out: " << status.getNOutInterests() << "},\n"
      << "            Data: {in: " << status.getNInDatas() << ", "
diff --git a/src/management/nfd-face-status.hpp b/src/management/nfd-face-status.hpp
index eff9c83..237b3f1 100644
--- a/src/management/nfd-face-status.hpp
+++ b/src/management/nfd-face-status.hpp
@@ -23,11 +23,8 @@
 #define NDN_MANAGEMENT_NFD_FACE_STATUS_HPP
 
 // This include must be kept as the first one, to ensure nfd-face-flags.hpp compiles on its own.
-#include "nfd-face-flags.hpp"
+#include "nfd-face-traits.hpp"
 
-#include "../encoding/tlv-nfd.hpp"
-#include "../encoding/encoding-buffer.hpp"
-#include "../encoding/block-helpers.hpp"
 #include "../util/time.hpp"
 
 namespace ndn {
@@ -38,26 +35,13 @@
  * \brief represents Face status
  * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset
  */
-class FaceStatus : public FaceFlagsTraits<FaceStatus>
+class FaceStatus : public FaceTraits<FaceStatus>
 {
 public:
-  class Error : public tlv::Error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : tlv::Error(what)
-    {
-    }
-  };
-
   FaceStatus();
 
   explicit
-  FaceStatus(const Block& block)
-  {
-    this->wireDecode(block);
-  }
+  FaceStatus(const Block& block);
 
   /** \brief prepend FaceStatus to the encoder
    */
@@ -76,48 +60,6 @@
   wireDecode(const Block& wire);
 
 public: // getters & setters
-  uint64_t
-  getFaceId() const
-  {
-    return m_faceId;
-  }
-
-  FaceStatus&
-  setFaceId(uint64_t faceId)
-  {
-    m_wire.reset();
-    m_faceId = faceId;
-    return *this;
-  }
-
-  const std::string&
-  getRemoteUri() const
-  {
-    return m_remoteUri;
-  }
-
-  FaceStatus&
-  setRemoteUri(const std::string& remoteUri)
-  {
-    m_wire.reset();
-    m_remoteUri = remoteUri;
-    return *this;
-  }
-
-  const std::string&
-  getLocalUri() const
-  {
-    return m_localUri;
-  }
-
-  FaceStatus&
-  setLocalUri(const std::string& localUri)
-  {
-    m_wire.reset();
-    m_localUri = localUri;
-    return *this;
-  }
-
   bool
   hasExpirationPeriod() const
   {
@@ -132,26 +74,7 @@
   }
 
   FaceStatus&
-  setExpirationPeriod(const time::milliseconds& expirationPeriod)
-  {
-    m_expirationPeriod = expirationPeriod;
-    m_hasExpirationPeriod = true;
-    return *this;
-  }
-
-  uint64_t
-  getFlags() const
-  {
-    return m_flags;
-  }
-
-  FaceStatus&
-  setFlags(uint64_t flags)
-  {
-    m_wire.reset();
-    m_flags = flags;
-    return *this;
-  }
+  setExpirationPeriod(const time::milliseconds& expirationPeriod);
 
   uint64_t
   getNInInterests() const
@@ -160,12 +83,7 @@
   }
 
   FaceStatus&
-  setNInInterests(uint64_t nInInterests)
-  {
-    m_wire.reset();
-    m_nInInterests = nInInterests;
-    return *this;
-  }
+  setNInInterests(uint64_t nInInterests);
 
   uint64_t
   getNInDatas() const
@@ -174,12 +92,7 @@
   }
 
   FaceStatus&
-  setNInDatas(uint64_t nInDatas)
-  {
-    m_wire.reset();
-    m_nInDatas = nInDatas;
-    return *this;
-  }
+  setNInDatas(uint64_t nInDatas);
 
   uint64_t
   getNOutInterests() const
@@ -188,12 +101,7 @@
   }
 
   FaceStatus&
-  setNOutInterests(uint64_t nOutInterests)
-  {
-    m_wire.reset();
-    m_nOutInterests = nOutInterests;
-    return *this;
-  }
+  setNOutInterests(uint64_t nOutInterests);
 
   uint64_t
   getNOutDatas() const
@@ -202,12 +110,7 @@
   }
 
   FaceStatus&
-  setNOutDatas(uint64_t nOutDatas)
-  {
-    m_wire.reset();
-    m_nOutDatas = nOutDatas;
-    return *this;
-  }
+  setNOutDatas(uint64_t nOutDatas);
 
   uint64_t
   getNInBytes() const
@@ -216,12 +119,7 @@
   }
 
   FaceStatus&
-  setNInBytes(uint64_t nInBytes)
-  {
-    m_wire.reset();
-    m_nInBytes = nInBytes;
-    return *this;
-  }
+  setNInBytes(uint64_t nInBytes);
 
   uint64_t
   getNOutBytes() const
@@ -230,20 +128,15 @@
   }
 
   FaceStatus&
-  setNOutBytes(uint64_t nOutBytes)
-  {
-    m_wire.reset();
-    m_nOutBytes = nOutBytes;
-    return *this;
-  }
+  setNOutBytes(uint64_t nOutBytes);
+
+protected:
+  void
+  wireReset() const;
 
 private:
-  uint64_t m_faceId;
-  std::string m_remoteUri;
-  std::string m_localUri;
   time::milliseconds m_expirationPeriod;
   bool m_hasExpirationPeriod;
-  uint64_t m_flags;
   uint64_t m_nInInterests;
   uint64_t m_nInDatas;
   uint64_t m_nOutInterests;
diff --git a/src/management/nfd-face-traits.cpp b/src/management/nfd-face-traits.cpp
new file mode 100644
index 0000000..5556046
--- /dev/null
+++ b/src/management/nfd-face-traits.cpp
@@ -0,0 +1,82 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that 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.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "nfd-face-traits.hpp"
+
+namespace ndn {
+namespace nfd {
+
+std::ostream&
+operator<<(std::ostream& os, FaceScope faceScope)
+{
+  switch (faceScope) {
+  case FACE_SCOPE_NON_LOCAL:
+    os << "non-local";
+    break;
+  case FACE_SCOPE_LOCAL:
+    os << "local";
+    break;
+  default:
+    os << "unknown";
+    break;
+  }
+  return os;
+}
+
+std::ostream&
+operator<<(std::ostream& os, FacePersistency facePersistency)
+{
+  switch (facePersistency) {
+  case FACE_PERSISTENCY_PERSISTENT:
+    os << "persistent";
+    break;
+  case FACE_PERSISTENCY_ON_DEMAND:
+    os << "on-demand";
+    break;
+  case FACE_PERSISTENCY_PERMANENT:
+    os << "permanent";
+    break;
+  default:
+    os << "unknown";
+    break;
+  }
+  return os;
+}
+
+std::ostream&
+operator<<(std::ostream& os, LinkType linkType)
+{
+  switch (linkType) {
+  case LINK_TYPE_POINT_TO_POINT:
+    os << "point-to-point";
+    break;
+  case LINK_TYPE_MULTI_ACCESS:
+    os << "multi-access";
+    break;
+  default:
+    os << "unknown";
+    break;
+  }
+  return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/management/nfd-face-traits.hpp b/src/management/nfd-face-traits.hpp
new file mode 100644
index 0000000..db4aef4
--- /dev/null
+++ b/src/management/nfd-face-traits.hpp
@@ -0,0 +1,274 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that 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.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_FACE_TRAITS_HPP
+#define NDN_MANAGEMENT_NFD_FACE_TRAITS_HPP
+
+#include "../encoding/tlv-nfd.hpp"
+#include "../encoding/encoding-buffer.hpp"
+#include "../encoding/block-helpers.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \deprecated provides additional information about a face
+ */
+enum FaceFlags {
+  /** \deprecated face is local (for scope control purpose)
+   */
+  FACE_IS_LOCAL = 1,
+  /** \deprecated face is created on demand (accepted incoming connection,
+   *              not initiated outgoing connection)
+   */
+  FACE_IS_ON_DEMAND = 2
+};
+
+/**
+ * \ingroup management
+ * \brief provides additional information about a faceScope
+ */
+enum FaceScope {
+  /** \brief face is non-local
+   */
+  FACE_SCOPE_NON_LOCAL = 0,
+  /** \brief face is local
+   */
+  FACE_SCOPE_LOCAL = 1
+};
+
+std::ostream&
+operator<<(std::ostream& os, FaceScope faceScope);
+
+/**
+ * \ingroup management
+ * \brief provides additional information about a facePersistency
+ */
+enum FacePersistency {
+  /** \brief face is persistent
+   */
+  FACE_PERSISTENCY_PERSISTENT = 0,
+  /** \brief face is on-demand
+   */
+  FACE_PERSISTENCY_ON_DEMAND = 1,
+  /** \brief face is permanent
+   */
+  FACE_PERSISTENCY_PERMANENT = 2
+};
+
+std::ostream&
+operator<<(std::ostream& os, FacePersistency facePersistency);
+
+/**
+ * \ingroup management
+ * \brief provides additional information about a linkType
+ */
+enum LinkType {
+  /** \brief link is point-to-point
+   */
+  LINK_TYPE_POINT_TO_POINT = 0,
+  /** \brief link is multi-access
+   */
+  LINK_TYPE_MULTI_ACCESS = 1
+};
+
+std::ostream&
+operator<<(std::ostream& os, LinkType linkType);
+
+/** \ingroup management
+ *  \brief providers getters and setters of face information fields
+ *  \tparam C the concrete class; it must provide .wireReset() method
+            to clear wire encoding when a field changes
+ */
+template<class C>
+class FaceTraits
+{
+public:
+  class Error : public tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : tlv::Error(what)
+    {
+    }
+  };
+
+  FaceTraits()
+    : m_faceId(0)
+    , m_faceScope(FACE_SCOPE_NON_LOCAL)
+    , m_facePersistency(FACE_PERSISTENCY_PERSISTENT)
+    , m_linkType(LINK_TYPE_POINT_TO_POINT)
+  {
+  }
+
+  uint64_t
+  getFaceId() const
+  {
+    return m_faceId;
+  }
+
+  C&
+  setFaceId(uint64_t faceId)
+  {
+    wireReset();
+    m_faceId = faceId;
+    return static_cast<C&>(*this);
+  }
+
+  const std::string&
+  getRemoteUri() const
+  {
+    return m_remoteUri;
+  }
+
+  C&
+  setRemoteUri(const std::string& remoteUri)
+  {
+    wireReset();
+    m_remoteUri = remoteUri;
+    return static_cast<C&>(*this);
+  }
+
+  const std::string&
+  getLocalUri() const
+  {
+    return m_localUri;
+  }
+
+  C&
+  setLocalUri(const std::string& localUri)
+  {
+    wireReset();
+    m_localUri = localUri;
+    return static_cast<C&>(*this);
+  }
+
+  FaceScope
+  getFaceScope() const
+  {
+    return m_faceScope;
+  }
+
+  C&
+  setFaceScope(FaceScope faceScope)
+  {
+    wireReset();
+    m_faceScope = faceScope;
+    return static_cast<C&>(*this);
+  }
+
+  FacePersistency
+  getFacePersistency() const
+  {
+    return m_facePersistency;
+  }
+
+  C&
+  setFacePersistency(FacePersistency facePersistency)
+  {
+    wireReset();
+    m_facePersistency = facePersistency;
+    return static_cast<C&>(*this);
+  }
+
+  LinkType
+  getLinkType() const
+  {
+    return m_linkType;
+  }
+
+  C&
+  setLinkType(LinkType linkType)
+  {
+    wireReset();
+    m_linkType = linkType;
+    return static_cast<C&>(*this);
+  }
+
+  /**
+   * \deprecated Use getFaceScope instead
+   */
+  bool
+  isLocal() const
+  {
+    return getFlags() & FACE_IS_LOCAL;
+  }
+
+  /**
+   * \deprecated Use getFacePersistency instead
+   */
+  bool
+  isOnDemand() const
+  {
+    return getFlags() & FACE_IS_ON_DEMAND;
+  }
+
+  /**
+   * \deprecated Use getFaceScope, and getFacePersistency instead
+   */
+  uint64_t
+  getFlags() const
+  {
+    uint64_t flags = 0;
+    if (m_faceScope == FACE_SCOPE_LOCAL)
+      flags |= FACE_IS_LOCAL;
+    if (m_facePersistency == FACE_PERSISTENCY_ON_DEMAND)
+      flags |= FACE_IS_ON_DEMAND;
+    return flags;
+  }
+
+  /**
+   * \deprecated Use setFaceScope, and setFacePersistency instead
+   */
+  C&
+  setFlags(uint64_t flags)
+  {
+    wireReset();
+    if ((flags & FACE_IS_LOCAL) != 0)
+      m_faceScope = FACE_SCOPE_LOCAL;
+    else
+      m_faceScope = FACE_SCOPE_NON_LOCAL;
+    if ((flags & FACE_IS_ON_DEMAND) != 0)
+      m_facePersistency = FACE_PERSISTENCY_ON_DEMAND;
+    else
+      m_facePersistency = FACE_PERSISTENCY_PERSISTENT;
+    return static_cast<C&>(*this);
+  }
+
+protected:
+  virtual void
+  wireReset() const = 0;
+
+protected:
+  uint64_t m_faceId;
+  std::string m_remoteUri;
+  std::string m_localUri;
+  FaceScope m_faceScope;
+  FacePersistency  m_facePersistency;
+  LinkType m_linkType;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_FACE_TRAITS_HPP