m2etis  0.4
AttributeDecisionTreeNode.h
Go to the documentation of this file.
1 /*
2  Copyright (2016) Michael Baer, Daniel Bonrath, All rights reserved.
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16 
22 #ifndef __M2ETIS_PUBSUB_FILTER_DECISIONTREE_ATTRIBUTEDECISIONTREENODE_H__
23 #define __M2ETIS_PUBSUB_FILTER_DECISIONTREE_ATTRIBUTEDECISIONTREENODE_H__
24 
25 #include <set>
26 #include <string>
27 
29 
30 #include "boost/shared_ptr.hpp"
31 
32 namespace m2etis {
33 namespace pubsub {
34 
35  M2ETIS_API extern std::map<filter::AttributeName, std::shared_ptr<filter::AttributeAccessor_Basic> > attributes_accessor_map;
36 
37 namespace filter {
38 
39  template<typename EventType, typename NetworkType> class DecisionTreePreProcessVisitor;
40  template<typename EventType, typename NetworkType> class AttributeTypeInformation;
41 
42  typedef int AttributeName; // TODO: (Roland) already defined in AttributeTypeInformation
43 
44  template<typename EventType, typename NetworkType, typename AttributeType>
45  class AttributeDecisionTreeNode : public DecisionTreeNode<EventType, NetworkType> {
46  public:
47  explicit AttributeDecisionTreeNode(AttributeName attribute_id) : attribute_id_(attribute_id) {
48  }
49  AttributeDecisionTreeNode() : attribute_id_() {
50  }
51 
52  // equivalent to match algorithm in Aguilera
53  virtual void visit(const EventType & event, std::set<typename NetworkType::Key> & matching_subscribers) override {
54  // perform test prescribed by v on event (i.e. determine attribute value)
55  auto attribute_value_iterator = attributes_accessor_map.find(attribute_id_);
56 
57  if (attribute_value_iterator == attributes_accessor_map.end()) {
58  M2ETIS_THROW_API("AttributeDecisionTreeNode function visit", "Attribute not found in attribute map.");
59  }
60 
61  // look for edge with value of attribute
62 
63  auto result_subnode_iterator = result_subnodes_.find((dynamic_cast<AttributeAccessor<EventType, AttributeType> *>(attribute_value_iterator->second.get()))->getAttributeValue(event));
64 
65  if (result_subnode_iterator != result_subnodes_.end()) {
66  // v has an edge e with the result of test (i.e. attribute value)
67  result_subnode_iterator->second->visit(event, matching_subscribers);
68  }
69 
70  if (dont_care_subnode_ptr_) {
71  dont_care_subnode_ptr_->visit(event, matching_subscribers);
72  }
73  }
74 
75  // merges with another subscription tree received by subscriptions from subscribes
76  virtual void merge(boost::shared_ptr<DecisionTreeNode<EventType, NetworkType> > & other_tree, typename NetworkType::Key subscriber) override {
77  auto other_tree_node = boost::dynamic_pointer_cast<AttributeDecisionTreeNode<EventType, NetworkType, AttributeType> >(other_tree);
78 
79  if (other_tree_node->dont_care_subnode_ptr_) {
80  if (dont_care_subnode_ptr_) {
81  // dont care edge already exists in both trees about to be merged
82  dont_care_subnode_ptr_->merge(other_tree_node->dont_care_subnode_ptr_, subscriber);
83  } else {
84  dont_care_subnode_ptr_ = other_tree_node->dont_care_subnode_ptr_;
85  dont_care_subnode_ptr_->changeSubscriber(subscriber);
86  // newly inserted nodes belong to the subscriber that sent the filter
87  }
88  }
89 
90  for (auto other_tree_node_subnodes : other_tree_node->result_subnodes_) {
91  if (result_subnodes_.find(other_tree_node_subnodes.first) != result_subnodes_.end()) {
92  // edge existing in both trees
93 
94  result_subnodes_[other_tree_node_subnodes.first]->merge(other_tree_node_subnodes.second, subscriber);
95  } else {
96  result_subnodes_[other_tree_node_subnodes.first] = other_tree_node_subnodes.second;
97  result_subnodes_[other_tree_node_subnodes.first]->changeSubscriber(subscriber);
98  }
99  }
100  } // merge
101 
102  virtual void changeSubscriber(typename NetworkType::Key subscriber) override {
103  for (auto subnodes : result_subnodes_) {
104  subnodes.second->changeSubscriber(subscriber);
105  }
106 
107  if (dont_care_subnode_ptr_) {
108  dont_care_subnode_ptr_->changeSubscriber(subscriber);
109  }
110  } // changeSubscriber
111 
112  // Removes the node from the tree; returns number of children left
113  virtual void removeSubscriber(const typename NetworkType::Key & subscriber) override {
114  for (auto subnodes : result_subnodes_) {
115  subnodes.second->removeSubscriber(subscriber);
116  }
117 
118  if (dont_care_subnode_ptr_) {
119  dont_care_subnode_ptr_->removeSubscriber(subscriber);
120  }
121  }
122 
123  // Testing whether there are subscriptions to the subscriber
124  virtual bool hasSubscription(typename NetworkType::Key subscriber) override {
125  bool hasSubscriptionResult = false;
126  for (auto subnodes : result_subnodes_) {
127  hasSubscriptionResult = hasSubscriptionResult
128  || subnodes.second->hasSubscription(subscriber);
129  }
130 
131  if (dont_care_subnode_ptr_) {
132  hasSubscriptionResult = hasSubscriptionResult
133  || dont_care_subnode_ptr_->hasSubscription(subscriber);
134  }
135 
136  return hasSubscriptionResult;
137  }
138 
139  virtual operator std::string() const {
140  std::string temp = "attribute node with attribute_id: " + std::to_string(attribute_id_) + "subnodes:";
141  for (auto subnodes : result_subnodes_) {
142  temp += "edge: with value (not computable) next node:" + std::string(*(subnodes.second));
143  }
144  return temp;
145  }
146 
148  }
149 
150  friend class DecisionTreePreProcessVisitor<EventType, NetworkType>;
151  friend class AttributeTypeInformation<EventType, NetworkType>;
152 
153  private:
154  std::map<AttributeType, boost::shared_ptr<DecisionTreeNode<EventType, NetworkType> > > result_subnodes_; // maps each value to the corresponding subnode in the decision tree.
155 
156  /* -edge (does not fit into result_subnode_map), for subscriptions that donĀ“t care about the
157  * value of this attribute
158  */
159  boost::shared_ptr<DecisionTreeNode<EventType, NetworkType> > dont_care_subnode_ptr_;
160 
161  AttributeName attribute_id_;
162 
164  template<typename Archive>
165  void serialize(Archive & ar, const unsigned int version) {
166  ar & boost::serialization::base_object<DecisionTreeNode<EventType, NetworkType> >(*this);
167  ar & result_subnodes_;
168  ar & dont_care_subnode_ptr_;
169  ar & attribute_id_;
170  }
171  };
172  // AttributeDecisionTreeNode
173 
174 } /* namespace filter */
175 } /* namespace pubsub */
176 } /* namespace m2etis */
177 
178 #endif /* __M2ETIS_PUBSUB_FILTER_DECISIONTREE_ATTRIBUTEDECISIONTREENODE_H__ */
179 
#define M2ETIS_API
virtual void merge(boost::shared_ptr< DecisionTreeNode< EventType, NetworkType > > &other_tree, typename NetworkType::Key subscriber) override
virtual void changeSubscriber(typename NetworkType::Key subscriber) override
M2ETIS_API std::map< filter::AttributeName, std::shared_ptr< filter::AttributeAccessor_Basic > > attributes_accessor_map
virtual void visit(const EventType &event, std::set< typename NetworkType::Key > &matching_subscribers) override
virtual bool hasSubscription(typename NetworkType::Key subscriber) override
virtual void removeSubscriber(const typename NetworkType::Key &subscriber) override
#define M2ETIS_THROW_API(module, message)
throws on wrong API usage
Definition: Exceptions.h:40