m2etis  0.4
AttributeFilter.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__FILTEREXPRESSIONS_ATTRIBUTEFILTER_H__
23 #define __M2ETIS_PUBSUB_FILTER__FILTEREXPRESSIONS_ATTRIBUTEFILTER_H__
24 
25 #include <functional>
26 
29 
30 #include "boost/serialization/string.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; // TODO: (Roland) make non-static, defined where?
36 
37 namespace filter {
38 
39  template<typename EventType, typename AttributeType>
40  class AttributeFilter : public Predicate<EventType> {
41  public:
42  AttributeFilter() : attribute_id_(-1) {}
43  AttributeFilter(const AttributeName attribute_id, const std::vector<AttributeType> & constants): attribute_id_(attribute_id), constants_(constants) {}
44 
45  virtual ~AttributeFilter() {}
46 
47  virtual void getAttributeType(FilterVisitor<EventType> & visitor) const override {
48  visitor.getAttributeType(this);
49  }
50 
51  virtual bool match(const EventType & event) const override {
52  auto attribute_value_iterator = attributes_accessor_map.find(attribute_id_);
53 
54  if (attribute_value_iterator == attributes_accessor_map.end()) {
55  M2ETIS_THROW_API("AttributeFilter function match", "Attribute not found in attribute map.");
56  }
57 
58  return matchAttribute((dynamic_cast<AttributeAccessor<EventType, AttributeType> *>(attribute_value_iterator->second.get()))->getAttributeValue(event));
59  }
60 
61  virtual bool matchAttribute(const AttributeType & attribute_value) const = 0;
62 
63  // tests, whether 2 attribute filters overlap. needed to determine the trees to subscribe to by comparing dynamic and static predicates
64  virtual bool overlaps(const Predicate<EventType> * other_predicate) const override {
65  const AttributeFilter * other_attribute_filter = dynamic_cast<const AttributeFilter *>(other_predicate);
66 
67  if (other_attribute_filter == nullptr) {
68  return true; // AttributeFilters for different attributes overlap
69  }
70  return overlaps(other_attribute_filter);
71  };
72 
73  virtual bool overlaps(const AttributeFilter *) const = 0;
74 
75  template<typename OtherAttributeType>
77  return true; // filters with different attribute types overlap
78  }
79 
80  const std::vector<AttributeType> get_constants() const { return constants_; }
81 
82  AttributeName get_attribute_id() const { return attribute_id_; } // needed for overlap calculation for filter attributes
83 
84  private:
85  virtual bool doCompare(const FilterExp<EventType> & other_filter) const override {
86  const AttributeFilter<EventType, AttributeType> * other_AttributeFilter = dynamic_cast<const AttributeFilter<EventType, AttributeType> *>(&other_filter);
87 
88  if (other_AttributeFilter) {
89  return (typeid(*this) == typeid(*other_AttributeFilter) && attribute_id_ == other_AttributeFilter->attribute_id_ && constants_ == other_AttributeFilter->constants_);
90  } else {
91  return false;
92  }
93  }
94 
95  virtual size_t doHash() const {
96  // hash function should be improved:
97  if (constants_.empty()) {
98  return (std::hash<AttributeName>()(attribute_id_) ^ std::hash<std::string>()(std::string(typeid(*this).name())));
99  } else {
100  return ((std::hash<AttributeName>()(attribute_id_) ^ std::hash<AttributeType>()(*(constants_.begin()))) ^ std::hash<std::string>()(std::string(typeid(*this).name())));
101  }
102  }
103 
104  AttributeName attribute_id_;
105  std::vector<AttributeType> constants_;
106 
107  friend class boost::serialization::access; // not sure if necessary
108  template<typename Archive>
109  void serialize(Archive & ar, const unsigned int) {
110  ar & boost::serialization::base_object<Predicate<EventType>>(*this);
111  ar & attribute_id_;
112  ar & constants_;
113  }
114  }; // class AttributeFilter
115 
116 } /* namespace filter */
117 } /* namespace pubsub */
118 } /* namespace m2etis */
119 
120 #endif /* __M2ETIS_PUBSUB_FILTER__FILTEREXPRESSIONS_ATTRIBUTEFILTER_H__ */
121 
#define M2ETIS_API
bool overlaps(const AttributeFilter< EventType, OtherAttributeType > *) const
virtual bool matchAttribute(const AttributeType &attribute_value) const =0
virtual bool overlaps(const Predicate< EventType > *other_predicate) const override
virtual void getAttributeType(const GreaterThanAttributeFilter< EventType, std::string > *)
Definition: FilterVisitor.h:49
const std::vector< AttributeType > get_constants() const
AttributeFilter(const AttributeName attribute_id, const std::vector< AttributeType > &constants)
M2ETIS_API std::map< filter::AttributeName, std::shared_ptr< filter::AttributeAccessor_Basic > > attributes_accessor_map
friend class boost::serialization::access
virtual void getAttributeType(FilterVisitor< EventType > &visitor) const override
virtual bool match(const EventType &event) const override
#define M2ETIS_THROW_API(module, message)
throws on wrong API usage
Definition: Exceptions.h:40