BSON C++ API  2.5.1
uma::bson
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ODMObject.h
Go to the documentation of this file.
1 #ifndef UMA_BSON_ODMOBJECT_H
2 #define UMA_BSON_ODMOBJECT_H
3 
4 #include <uma/bson/Object.h>
5 
6 #include <Poco/SharedPtr.h>
7 
8 #include <map>
9 #include <typeinfo>
10 
11 namespace uma
12 {
13  namespace bson
14  {
15 
36  template <typename Model>
37  class ODMObject : public Object
38  {
39  public:
41  virtual ~ODMObject() {}
42 
51  const FieldNames getFieldNames() const
52  {
53  Object::FieldNames names;
54 
55  const Model* model = static_cast<const Model*>( this );
56  for ( typename MetaFieldMap::const_iterator iter = getMetaFields( model ).begin();
57  iter != getMetaFields( model ).end(); ++iter )
58  {
59  names.push_back( iter->first );
60  }
61 
62  return names;
63  }
64 
65  Value& getValue( const std::string& name )
66  {
67  Model* model = static_cast<Model*>( this );
68  typename MetaFieldMap::iterator iter = getMetaFields( model ).find( name );
69  if ( iter == getMetaFields( model ).end() ) throw Poco::NotFoundException( "No field with name: " + name );
70 
71  return ( iter->second->getValue( model ) );
72  }
73 
74  void setValue( const std::string& name, const Value& value )
75  {
76  Model* model = static_cast<Model*>( this );
77  typename MetaFieldMap::iterator iter = getMetaFields( model ).find( name );
78  if ( iter == getMetaFields( model ).end() ) throw Poco::NotFoundException( "No field with name: " + name );
79 
80  iter->second->setValue( model, value );
81  }
82 
83  protected:
92  class MetaField
93  {
94  public:
101  MetaField( const std::string& field ) : name( field ) {}
102 
104  virtual ~MetaField() {}
105 
113  virtual Value& getValue( Model* model ) = 0;
114 
122  virtual void setValue( Model* model, const Value& value ) = 0;
123 
130  const std::string& getName() const { return name; }
131 
132  private:
134  std::string name;
135  };
136 
138  typedef Poco::SharedPtr<MetaField> MetaFieldPtr;
139 
151  template <typename DataType>
152  class MetaFieldImpl : public MetaField
153  {
154  public:
156  typedef DataType& (Model::*Accessor)();
157 
159  typedef void (Model::*Mutator)( const DataType& );
160 
169  MetaFieldImpl( const std::string& field, Accessor get, Mutator set ) :
170  MetaField( field ), accessor( get ), mutator( set ) {}
171 
172  Value& getValue( Model* model )
173  {
174  return ( model->*accessor )();
175  }
176 
177  void setValue( Model* model, const Value& value )
178  {
179  const DataType& dt = dynamic_cast<const DataType&>( value );
180  ( model->*mutator )( dt );
181  }
182 
183  private:
185  Accessor accessor;
186 
188  Mutator mutator;
189  };
190 
199  void registerField( const MetaFieldPtr mo )
200  {
201  const std::string& name = mo->getName();
202  getMetaFields( static_cast<Model*>( this ) ).insert(
203  std::pair<std::string,MetaFieldPtr>( name, mo ) );
204  }
205 
213  MetaFieldPtr getMetaField( const std::string& name )
214  {
215  typename MetaFieldMap::iterator iter = getMetaFields( this ).find( name );
216  if ( iter == getMetaFields( this ).end() ) throw Poco::NotFoundException( "No field with name: " + name );
217 
218  return iter->second;
219  }
220 
229  static bool registered( Model* model )
230  {
231  std::string cls( typeid( model ).name() );
232  typename ClassMetaFields::const_iterator iter = getClassMetaFields().find( cls );
233  return ( iter != getClassMetaFields().end() );
234  }
235 
236  private:
238  typedef std::map<std::string,MetaFieldPtr> MetaFieldMap;
239 
241  typedef std::map<std::string,MetaFieldMap> ClassMetaFields;
242 
243  static ClassMetaFields& getClassMetaFields()
244  {
245  static ClassMetaFields cmf;
246  return cmf;
247  }
248 
249  static MetaFieldMap& getMetaFields( Model* model )
250  {
251  std::string cls( typeid( model ).name() );
252  ClassMetaFields& cmf = getClassMetaFields();
253  MetaFieldMap& mm = cmf[cls];
254  return mm;
255  }
256 
257  static MetaFieldMap& getMetaFields( const Model* model )
258  {
259  // typeid returns different value without casting away const-ness
260  return getMetaFields( const_cast<Model*>( model ) );
261  }
262  };
263 
264  } // namespace bson
265 } // namespace uma
266 
267 #endif // UMA_BSON_ODMOBJECT_H