faif
Value.hpp
1 #ifndef FAIF_VALUE_HPP_
2 #define FAIF_VALUE_HPP_
3 
4 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
5 //msvc9.0 warnings for boost::concept_check
6 #pragma warning(disable:4100)
7 #endif
8 
9 #include <ostream>
10 #include <string>
11 #include <list>
12 #include <iterator>
13 #include <algorithm>
14 
15 #include <boost/bind.hpp>
16 #include <boost/concept_check.hpp>
17 #include <boost/serialization/serialization.hpp>
18 #include <boost/serialization/list.hpp>
19 #include <boost/serialization/nvp.hpp>
20 
21 #include "ExceptionsFaif.hpp"
22 
23 namespace faif {
24 
25  /** \brief nominal attribute trait (equality comparable), modeled as element in unordered set */
26  struct nominal_tag {};
27 
28  /** \brief ordered attribute trait (equality comparable, less than comparable) , modeled as element in ordered set */
29  struct ordinal_tag : public nominal_tag {};
30 
31  /** \brief interval attribute trait (equality comparable, less than comparable, distance), integer numbers */
32  struct interval_tag : public ordinal_tag {};
33 
34  /** \brief nominal attribute trait (equality comparable, less than comparable, distance, continuous), real numbers */
35  struct ratio_tag : public interval_tag {};
36 
37  /**
38  \brief the value concept
39  */
40  template<typename Val>
41  struct ValueConcept
42  : boost::EqualityComparable<Val>, boost::DefaultConstructible<Val>,
43  boost::CopyConstructible<Val>, boost::Assignable<Val> {
44 
45  typedef typename Val::ValueTag ValueTag; //the ValueType is required
46  typedef typename Val::Value Value; //the Value is required
47  typedef typename Val::DomainType DomainType; //the DomainType is required
48 
49  BOOST_CONCEPT_USAGE(ValueConcept)
50  {
51  Val v; //default constructable is required
52  v.get(); //the get() method is required
53  v.getDomain(); //the getDomain() method is required
54  v.isUnknown(); //the isUnknown() method is required
55  }
56 
57  };
58 
59  /** \brief forward declaration */
60  template <typename Val> class DomainEnumerate;
61 
62  /**
63  \brief nominal attribute template (equality comparable)
64  */
65  template <typename Val> class ValueNominal {
66  public:
67  BOOST_CONCEPT_ASSERT(( boost::EqualityComparable<Val> ));
68  BOOST_CONCEPT_ASSERT(( boost::DefaultConstructible<Val> ));
69  BOOST_CONCEPT_ASSERT(( boost::CopyConstructible<Val> ));
70  BOOST_CONCEPT_ASSERT(( boost::Assignable<Val> ));
71 
72  /** \brief the attribute trait */
74 
75  typedef Val Value;
76 
78 
79  /** \brief c-tor. Create UNKNOWN Value */
80  ValueNominal() : val_(), domain_(0L) {}
81 
82  /** \brief c-tor */
83  ValueNominal(const Value& val, DomainType* d) : val_(val), domain_(d) {}
84 
85  /** \brief c-tor */
86  ValueNominal(const ValueNominal& a) : val_(a.val_), domain_(a.domain_) {}
87 
88  /** \brief assign operator */
90  val_ = a.val_;
91  domain_ = a.domain_;
92  return *this;
93  }
94 
95  /** \brief d-tor */
97 
98  /** \brief accessor */
99  Value& get() { return val_; }
100 
101  /** \brief accessor */
102  const Value& get() const { return val_; }
103 
104  /** \brief accessor */
105  bool isUnknown() const { return domain_ == 0L; }
106 
107  /** \brief accessor - domain */
108  const DomainType* getDomain() const { return domain_; }
109 
110  /** \brief the equality comparison */
111  bool operator==(const ValueNominal& v) const { return val_ == v.val_ && domain_ == v.domain_; }
112 
113  /** \brief the equality comparison */
114  bool operator!=(const ValueNominal& v) const { return val_ != v.val_ || domain_ != v.domain_; }
115 
116  /** \brief return the unknown value object */
118  static ValueNominal unknown;
119  return unknown;
120  }
121 
122  /** \brief serialization using boost::serialization */
123  template<class Archive>
124  void serialize(Archive & ar, const unsigned int /* file_version */){
125  ar & boost::serialization::make_nvp("ValueVal", val_ );
126  ar & boost::serialization::make_nvp("ValueDomain", domain_ );
127  }
128  private:
129  Value val_;
130  DomainType* domain_;
131  };
132 
135 
136  /**
137  \brief the domain concept
138  */
139  template<typename Dom>
140  struct DomainConcept : boost::EqualityComparable<Dom>, boost::DefaultConstructible<Dom>,
141  boost::CopyConstructible<Dom>, boost::Assignable<Dom> {
142 
143  typedef typename Dom::ValueTag ValueTag; //the ValueTag is required
144  typedef typename Dom::Value Value; //the type of Value is required
145  typedef typename Dom::ValueId ValueId; //the ValueId is required
146  typedef typename Dom::iterator iterator; //the iterator is required
147  typedef typename Dom::const_iterator const_iterator; //the const_iterator is required
148 
149  BOOST_CONCEPT_USAGE(DomainConcept)
150  {
151  Dom d; //default constructable is required
152  d.getId(); //the getId() method is required
153  }
154  };
155 
156  /** \breif the domain of nominal attributes.
157 
158  Finite set of unique equally comparable values. No erase/remove operations on this set is available.
159  */
160  template <typename Val>
161  class DomainEnumerate {
162  public:
163  BOOST_CONCEPT_ASSERT((ValueConcept<Val>));
164 
165  typedef typename Val::ValueTag ValueTag;
166  typedef Val Value;
167  typedef const Val* ValueId; //value identifier
168  typedef Val* ValueIdSerialize; //value identifier for serialization
169  typedef ValueNominalString* AttrIddSerialize; // !< \brief for serialization the const not works correctly
170 
171  typedef std::list<Val> Container;
172  typedef typename Container::iterator iterator;
173  typedef typename Container::const_iterator const_iterator;
174 
175  DomainEnumerate(const std::string& id = "") : id_(id) {}
176 
177  /** \brief copy c-tor (transform the parent pointers) */
179 
180  /** \brief assignment (transform the parent pointers) */
181  DomainEnumerate& operator=(const DomainEnumerate&);
182 
183  ~DomainEnumerate() {}
184 
185  /** \brief accessor */
186  std::string getId() const { return id_; }
187 
188  /** \brief return the value id for given value iterator */
189  static ValueId getValueId(const_iterator it) {
190  return &(*it);
191  }
192 
193  /** \brief return the value id for unknown value */
194  static ValueId getUnknownId() {
195  return &(Value::getUnknown());
196  }
197 
198  /** \brief accessor */
199  int getSize() const { return static_cast<int>(values_.size()); }
200 
201  /** the domain equality operator (the id is compared, not all attributes) */
202  bool operator==(const DomainEnumerate& d) const { return id_ == d.id_; }
203 
204  /** the domain not equality operator (the id is compared, not all attributes) */
205  bool operator!=(const DomainEnumerate& d) const { return id_ != d.id_;}
206 
207  /** \brief accessor */
208  iterator begin() { return values_.begin(); }
209  /** \brief accessor */
210  iterator end() { return values_.end(); }
211 
212  /** \brief accessor */
213  const_iterator begin() const { return values_.begin(); }
214  /** \brief accessor */
215  const_iterator end() const { return values_.end(); }
216 
217  /** \brief search for value equal to given, if found return the value identifier,
218  otherwise insert new into collection and return the inserted value identifier */
219  ValueId insert(const typename Val::Value& value);
220 
221  /** \brief return the first iterator to attribute equal to given */
222  ValueId find(const typename Val::Value& value) const;
223 
224  /** \brief serialization using boost::serialization */
225  template<class Archive>
226  void serialize(Archive & ar, const unsigned int /* file_version */){
227  ar & boost::serialization::make_nvp("DomainId", id_ );
228  ar & boost::serialization::make_nvp("DomainValues", values_ );
229  }
230  private:
231  std::string id_; //!< the domain id
232  Container values_;
233  };
234 
235  /** \brief create the domain with attributes.
236  \return the new domain
237  */
238  template <typename T>
239  DomainEnumerate< ValueNominal<T> > createDomain(const std::string& id, T* begin, T* end) {
241  for(T* i = begin; i != end; ++i) {
242  domain.insert(*i);
243  }
244  return domain;
245  }
246 
247  /** the ostream operator for attribute, defined here because it uses the domain method */
248  template <typename Value> std::ostream& operator<<(std::ostream& os, const ValueNominal<Value>& a) {
249  if(a.getDomain() == 0L)
250  os << "Unknown";
251  else
252  os << a.getDomain()->getId() << "=" << a.get(); // << " addr:" << &a << ' ';
253  return os;
254  }
255 
256  /** the ostream operator for pointer to attribute, defined here because it uses the domain method */
257  template <typename Value> std::ostream& operator<<(std::ostream& os, const ValueNominal<Value>* a) {
258  if(a) {
259  return operator<<(os, *a);
260  } else {
261  return os << "Null";
262  }
263  }
264 
265  /** \brief the ostream operator for domain */
266  template <typename Val>
267  std::ostream& operator<<(std::ostream& os, const DomainEnumerate<Val>& domain) {
268  std::copy(domain.begin(), domain.end(), std::ostream_iterator<Val>(os,","));
269  return os << ';';
270  }
271 
272  namespace {
273 
274  template <typename Val>
275  Val TransformFunction(const Val& a, typename Val::DomainType* d) {
276  return Val(a.get(),d);
277  }
278 
279  } //namespace
280 
281 
282  /** \brief copy c-tor (transform the parent pointers */
283  template <typename Val>
285  : id_(d.id_) {
286 
287  std::transform(d.values_.begin(), d.values_.end(), std::back_inserter<Container>(values_),
288  boost::bind(&TransformFunction<Val>, _1, this) );
289  }
290 
291  /** \brief assignment (transform the parent pointers */
292  template <typename Val>
295  if(&d == this)
296  return *this;
297 
298  id_ = d.id_;
299  values_.clear();
300 
301  std::transform(d.values_.begin(), d.values_.end(), std::back_inserter<Container>(values_),
302  boost::bind(&TransformFunction<Val>, _1, this) );
303  return *this;
304  }
305 
306  /** search for attribute equal to given. If found return the iterator,
307  otherwise insert new into collection and return the inserted attribute */
308  template< typename Val>
309  typename DomainEnumerate<Val>::ValueId
310  DomainEnumerate<Val>::insert(const typename Val::Value& value) {
311  Val attr(value, this);
312  const_iterator found = std::find( values_.begin(), values_.end(), attr );
313  if( found != values_.end() )
314  return getValueId(found);
315  //inserts element on the end (if not found)
316  return getValueId( values_.insert( values_.end(), Val(value, this) ) );
317  }
318 
319  /** return the first iterator to attribute equal to given
320  // \throws NotFoundException
321  */
322  template<typename Val>
323  typename DomainEnumerate<Val>::ValueId
324  DomainEnumerate<Val>::find(const typename Val::Value& value) const {
325  Val attr(value, const_cast<DomainEnumerate<Val>*>(this)); //ValueNominal requires non-const pointer to domain
326  const_iterator found = std::find( values_.begin(), values_.end(), attr );
327  if( found != values_.end() ) {
328  return getValueId( found);
329  }
330  throw NotFoundException( getId().c_str() );
331  }
332 
333 } //namespace faif
334 
335 #endif //FAIF_VALUE_HPP_
DomainEnumerate & operator=(const DomainEnumerate &)
assignment (transform the parent pointers)
Definition: Value.hpp:294
bool operator!=(const ValueNominal &v) const
the equality comparison
Definition: Value.hpp:114
~ValueNominal()
d-tor
Definition: Value.hpp:96
ValueNominal & operator=(const ValueNominal &a)
assign operator
Definition: Value.hpp:89
Definition: Chain.h:17
std::string getId() const
accessor
Definition: Value.hpp:186
bool operator!=(const DomainEnumerate &d) const
Definition: Value.hpp:205
iterator begin()
accessor
Definition: Value.hpp:208
bool operator==(const ValueNominal &v) const
the equality comparison
Definition: Value.hpp:111
void serialize(Archive &ar, const unsigned int)
serialization using boost::serialization
Definition: Value.hpp:226
the domain concept
Definition: Value.hpp:140
nominal_tag ValueTag
the attribute trait
Definition: Value.hpp:73
iterator end()
accessor
Definition: Value.hpp:210
ordered attribute trait (equality comparable, less than comparable) , modeled as element in ordered s...
Definition: Value.hpp:29
int getSize() const
accessor
Definition: Value.hpp:199
const DomainType * getDomain() const
accessor - domain
Definition: Value.hpp:108
nominal attribute trait (equality comparable), modeled as element in unordered set ...
Definition: Value.hpp:26
const_iterator end() const
accessor
Definition: Value.hpp:215
forward declaration
Definition: Value.hpp:60
const_iterator begin() const
accessor
Definition: Value.hpp:213
the value concept
Definition: Value.hpp:41
interval attribute trait (equality comparable, less than comparable, distance), integer numbers ...
Definition: Value.hpp:32
static ValueId getValueId(const_iterator it)
return the value id for given value iterator
Definition: Value.hpp:189
bool operator==(const DomainEnumerate &d) const
Definition: Value.hpp:202
nominal attribute trait (equality comparable, less than comparable, distance, continuous), real numbers
Definition: Value.hpp:35
bool isUnknown() const
accessor
Definition: Value.hpp:105
ValueNominal()
c-tor. Create UNKNOWN Value
Definition: Value.hpp:80
ValueId find(const typename Val::Value &value) const
return the first iterator to attribute equal to given
Definition: Value.hpp:324
static ValueNominal & getUnknown()
return the unknown value object
Definition: Value.hpp:117
ValueId insert(const typename Val::Value &value)
search for value equal to given, if found return the value identifier, otherwise insert new into coll...
Definition: Value.hpp:310
ValueNominal(const Value &val, DomainType *d)
c-tor
Definition: Value.hpp:83
static ValueId getUnknownId()
return the value id for unknown value
Definition: Value.hpp:194
nominal attribute template (equality comparable)
Definition: Value.hpp:65
void serialize(Archive &ar, const unsigned int)
serialization using boost::serialization
Definition: Value.hpp:124
ValueNominal(const ValueNominal &a)
c-tor
Definition: Value.hpp:86
the exception thrown when the value for given attribute is not found
Definition: ExceptionsFaif.hpp:32