model: Adding exclude filter processing in all content store implementations

Although exclude filter is honored now by content stores, forwarding
strategy is completely ignoring them.  That is, if somebody replies to
an interest with a data packet that violates the filter, this data
packet will propagate back to the requester.  This "problem" may or may
not be addressed in future.

Refs #1009 (http://redmine.named-data.net/issues/1009)
diff --git a/apps/ndn-producer.cc b/apps/ndn-producer.cc
index e8a66aa..e224841 100644
--- a/apps/ndn-producer.cc
+++ b/apps/ndn-producer.cc
@@ -139,7 +139,7 @@
       data->SetKeyLocator (Create<Name> (m_keyLocator));
     }
 
-  NS_LOG_INFO ("node("<< GetNode()->GetId() <<") respodning with ContentObject:\n" << data->GetName ());
+  NS_LOG_INFO ("node("<< GetNode()->GetId() <<") respodning with ContentObject: " << data->GetName ());
 
   // Echo back FwHopCountTag if exists
   FwHopCountTag hopCountTag;
diff --git a/examples/custom-apps/ndn-api-app.cc b/examples/custom-apps/ndn-api-app.cc
index 3346b52..db55bb6 100644
--- a/examples/custom-apps/ndn-api-app.cc
+++ b/examples/custom-apps/ndn-api-app.cc
@@ -61,6 +61,10 @@
   Ptr<Interest> interest = Create<Interest> ();
   interest->SetName (m_name);
   interest->SetInterestLifetime (m_interestLifetime);
+
+  Ptr<Exclude> exclude = Create<Exclude> ();
+  exclude->excludeOne (name::Component ("unique"));
+  interest->SetExclude (exclude);
   
   m_face->ExpressInterest (interest,
                            MakeCallback (&ApiApp::GotData, this),
@@ -80,6 +84,7 @@
   m_face = CreateObject<ApiFace> (GetNode ());
   
   Simulator::Schedule (Seconds (1), &::ns3::ndn::ApiApp::RequestData, this);
+  Simulator::Schedule (Seconds (10), &::ns3::ndn::ApiApp::RequestData, this);
 }
 
 void
diff --git a/examples/ndn-simple-api.cc b/examples/ndn-simple-api.cc
index 5fb4dd9..6580fbe 100644
--- a/examples/ndn-simple-api.cc
+++ b/examples/ndn-simple-api.cc
@@ -77,7 +77,7 @@
   ndn::AppHelper consumerHelper ("ns3::ndn::ApiApp");
   consumerHelper.SetPrefix ("/prefix");
   ApplicationContainer app = consumerHelper.Install (nodes.Get (0)); // first node
-  app.Stop (Seconds (10.0));
+  app.Stop (Seconds (15.0));
 
   // Producer
   ndn::AppHelper producerHelper ("ns3::ndn::Producer");
diff --git a/model/cs/content-store-impl.h b/model/cs/content-store-impl.h
index 69fa00e..90d0c95 100644
--- a/model/cs/content-store-impl.h
+++ b/model/cs/content-store-impl.h
@@ -155,6 +155,24 @@
   return tid;
 }
 
+struct isNotExcluded
+{
+  inline
+  isNotExcluded (const Exclude &exclude)
+    : m_exclude (exclude)
+  {
+  }
+  
+  bool
+  operator () (const name::Component &comp) const
+  {
+    return !m_exclude.isExcluded (comp);
+  }
+
+private:
+  const Exclude &m_exclude;
+};
+
 template<class Policy>
 Ptr<ContentObject>
 ContentStoreImpl<Policy>::Lookup (Ptr<const Interest> interest)
@@ -162,7 +180,16 @@
   NS_LOG_FUNCTION (this << interest->GetName ());
 
   /// @todo Change to search with predicate
-  typename super::const_iterator node = this->deepest_prefix_match (interest->GetName ());
+  typename super::const_iterator node;
+  if (interest->GetExclude () == 0)
+    {
+      node = this->deepest_prefix_match (interest->GetName ());
+    }
+  else
+    {
+      node = this->deepest_prefix_match_if_next_level (interest->GetName (),
+                                                       isNotExcluded (*interest->GetExclude ()));
+    }
 
   if (node != this->end ())
     {
diff --git a/utils/trie/trie-with-policy.h b/utils/trie/trie-with-policy.h
index 2e1f883..8d95aff 100644
--- a/utils/trie/trie-with-policy.h
+++ b/utils/trie/trie-with-policy.h
@@ -210,7 +210,7 @@
    */
   template<class Predicate>
   inline iterator
-  deepest_prefix_match (const FullKey &key, Predicate pred)
+  deepest_prefix_match_if (const FullKey &key, Predicate pred)
   {
     iterator foundItem, lastItem;
     bool reachLast;
@@ -236,6 +236,40 @@
       }
   }
 
+  /**
+   * @brief Find a node that has prefix at least as the key
+   *
+   * This version of find checks predicate for the next level and if
+   * predicate is True, returns first deepest match available
+   */
+  template<class Predicate>
+  inline iterator
+  deepest_prefix_match_if_next_level (const FullKey &key, Predicate pred)
+  {
+    iterator foundItem, lastItem;
+    bool reachLast;
+    boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
+
+    // guard in case we don't have anything in the trie
+    if (lastItem == trie_.end ())
+      return trie_.end ();
+
+    if (reachLast)
+      {
+        foundItem = lastItem->find_if_next_level (pred); // may or may not find something
+        if (foundItem == trie_.end ())
+          {
+            return trie_.end ();
+          }
+        policy_.lookup (s_iterator_to (foundItem));
+        return foundItem;
+      }
+    else
+      { // couldn't find a node that has prefix at least as key
+        return trie_.end ();
+      }
+  }
+  
   iterator end () const
   {
     return 0;
diff --git a/utils/trie/trie.h b/utils/trie/trie.h
index 62411d6..4d5a884 100644
--- a/utils/trie/trie.h
+++ b/utils/trie/trie.h
@@ -415,6 +415,32 @@
     return 0;
   }
 
+  /**
+   * @brief Find next payload of the sub-trie satisfying the predicate
+   * @param pred predicate
+   *
+   * This version check predicate only for the next level children
+   *
+   * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
+   */
+  template<class Predicate>
+  inline const iterator
+  find_if_next_level (Predicate pred)
+  {
+    typedef trie<FullKey, PayloadTraits, PolicyHook> trie;
+    for (typename trie::unordered_set::iterator subnode = children_.begin ();
+         subnode != children_.end ();
+         subnode++ )
+      {
+        if (pred (subnode->key ()))
+          {
+            return subnode->find ();
+          }
+      }
+
+    return 0;
+  }
+
   iterator end ()
   {
     return 0;