Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

ObjectInterface.h

Go to the documentation of this file.
00001 /* SimData: Data Infrastructure for Simulations
00002  * Copyright (C) 2002 Mark Rose <tm2@stm.lbl.gov>
00003  * 
00004  * This file is part of SimData.
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019  */
00020 
00021 
00027 #ifndef __SIMDATA_OBJECTINTERFACE_H__
00028 #define __SIMDATA_OBJECTINTERFACE_H__
00029 
00030 
00031 #include <string>
00032 #include <vector>
00033 
00034 #include <SimData/hash_map.h>
00035 #include <SimData/TypeAdapter.h>
00036 #include <SimData/Namespace.h>
00037 #include <SimData/Archive.h>
00038 
00039 /*
00040  * Simulated Partial Template Specialization
00041  *
00042  * Adapted from: metactrl.h
00043  * by Krzysztof Czarnecki & Ulrich Eisenecker
00044  */
00045 #include <SimData/PTS.h>
00046 
00047 
00048 
00049 NAMESPACE_SIMDATA
00050 
00051 
00052 class Object;
00053 
00054 
00055 SIMDATA_EXCEPTION(InterfaceError)
00056 
00057 
00058 
00059 
00064 class MemberAccessorBase 
00065 {
00066 public:
00067         virtual ~MemberAccessorBase() {}
00068 
00069         typedef HASH_MAPS<std::string, MemberAccessorBase *, hashstring, eqstring>::Type map;
00070 
00071         
00072         virtual void set(Object *, TypeAdapter const &) throw(TypeMismatch) { 
00073                 throw TypeMismatch("Cannot set vector<> '" + name + "' directly, use push_back() instead."); 
00074         }
00075         virtual void push_back(Object *, TypeAdapter const &) throw(TypeMismatch) { 
00076                 throw TypeMismatch("Cannot call push_back() on non-vector<> variable '" + name + "'.");
00077         }
00078         virtual void clear(Object *) throw(TypeMismatch) { 
00079                 throw TypeMismatch("Cannot call clear() on non-vector<> variable '" + name + "'.");
00080         }
00081         virtual TypeAdapter const get(Object *) const throw(TypeMismatch) {
00082                 throw TypeMismatch("get() '" + name + "': not supported for variables of type vector<>.");
00083         }
00084         bool isRequired() const { return required; };
00085         std::string getName() const { return name; }
00086         virtual void pack(Object *, Packer &) const {
00087                 assert(0);
00088         }
00089         virtual void unpack(Object *, UnPacker &) {
00090                 assert(0);
00091         }
00092         std::string getType() const { return type; }
00093         virtual unsigned int getMask() const { return 0; }
00094 protected:
00095         void setType(BaseType &x) { type = x.typeString(); }
00096         void setType(double &x) { type = "builtin::double"; }
00097         void setType(float &x) { type = "builtin::float"; }
00098         void setType(unsigned int &x) { type = "builtin::uint"; }
00099         void setType(int &x) { type = "builtin::int"; }
00100         void setType(unsigned char &x) { type = "builtin::uint8"; }
00101         void setType(char &x) { type = "builtin::int8"; }
00102         void setType(unsigned short &x) { type = "builtin::uint16"; }
00103         void setType(short &x) { type = "builtin::int16"; }
00104         void setType(bool &x) { type = "builtin::bool"; }
00105         void setType(std::string const &x) { type = "builtin::string"; }
00106         MemberAccessorBase(): type("none") {}
00107         std::string name;
00108         std::string help;
00109         std::string type;
00110         bool required;
00111 };
00112 
00113 
00119 template <class C, typename T> 
00120 class MemberMaskAccessor: public MemberAccessorBase 
00121 {
00122         T C::* member;
00123         T mask;
00124 public:
00125         MemberMaskAccessor(T C::*pm, std::string name_, int mask_, bool required_) {
00126                 member = pm;
00127                 name = name_;
00128                 mask = mask_;
00129                 required = required_;
00130                 {
00131                         T prototype;
00132                         setType(prototype);
00133                 }
00134         }
00135         virtual TypeAdapter const get(Object *o) const throw(TypeMismatch) {
00136                 C * object = dynamic_cast<C *>(o);
00137                 if (object == NULL) {
00138                         throw TypeMismatch("get(\"" + name + "\"): Object class does not match interface.");
00139                 }
00140                 return TypeAdapter(object->*member);
00141         }
00142         virtual void set(Object *o, TypeAdapter const &v) throw(TypeMismatch) {
00143                 C * object = dynamic_cast<C *>(o);
00144                 if (object == NULL) {
00145                         throw TypeMismatch("set(\"" + name + "\"): Object class does not match interface.");
00146                 }
00147                 try {
00148                         if (mask != 0) {
00149                                 T value;
00150                                 v.set(value);
00151                                 if (value != 0) {
00152                                         object->*member |= mask;
00153                                 } else {
00154                                         object->*member &= ~mask;
00155                                 }
00156                         } else {
00157                                 v.set(object->*member);
00158                         }
00159                 } catch (Exception &e) {
00160                         e.addMessage("MemberMaskAccessor::set(" + name + "):");
00161                         throw;
00162                 }
00163         }
00164         virtual void pack(Object *o, Packer &p) const {
00165                 C * object = dynamic_cast<C *>(o);
00166                 p(object->*member);
00167         }
00168         virtual void unpack(Object *o, UnPacker &p) {
00169                 C * object = dynamic_cast<C *>(o);
00170                 p(object->*member);
00171         }
00172         virtual unsigned int getMask() const { return static_cast<unsigned int>(mask); }
00173 };
00174 
00175 
00181 template <class C, typename T> 
00182 class MemberAccessor: public MemberAccessorBase 
00183 {
00184         T C::* member;
00185 public:
00186         MemberAccessor(T C::*pm, std::string name_, bool required_) {
00187                 member = pm;
00188                 name = name_;
00189                 required = required_;
00190                 {
00191                         T prototype;
00192                         setType(prototype);
00193                 }
00194         }
00195         virtual TypeAdapter const get(Object *o) const throw(TypeMismatch) {
00196                 C * object = dynamic_cast<C *>(o);
00197                 if (object == NULL) {
00198                         throw TypeMismatch("get(\"" + name + "\"): Object class does not match interface.");
00199                 }
00200                 return TypeAdapter(object->*member);
00201         }
00202         virtual void set(Object *o, TypeAdapter const &v) throw(TypeMismatch) {
00203                 C * object = dynamic_cast<C *>(o);
00204                 if (object == NULL) {
00205                         throw TypeMismatch("set(\"" + name + "\"): Object class does not match interface.");
00206                 }
00207                 try {
00208                         v.set(object->*member);
00209                 } catch (Exception &e) {
00210                         e.addMessage("MemberAccessor::set(" + name + "):");
00211                         throw;
00212                 }
00213         }
00214         virtual void pack(Object *o, Packer &p) const {
00215                 C * object = dynamic_cast<C *>(o);
00216                 p(object->*member);
00217         }
00218         virtual void unpack(Object *o, UnPacker &p) {
00219                 C * object = dynamic_cast<C *>(o);
00220                 p(object->*member);
00221         }
00222 };
00223 
00224 
00230 #ifdef __SIMDATA_PTS_SIM
00231 template <class C, typename T> 
00232 class VectorMemberAccessor: public MemberAccessorBase 
00233 {
00234         T C::* member;
00235 public:
00236         VectorMemberAccessor(T C::*pm, std::string name_, bool required_) {
00237                 member = pm;
00238                 name = name_;
00239                 required = required_;
00240                 {
00241                         T prototype;
00242                         setType(prototype);
00243                         type = "vector::" + type;
00244                 }
00245         }
00246         virtual void push_back(Object *o, TypeAdapter const &v) throw(TypeMismatch) {
00247                 C * object = dynamic_cast<C *>(o);
00248                 if (object == NULL) {
00249                         throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface.");
00250                 }
00251                 typename T::value_type value;
00252                 try {
00253                         v.set(value);
00254                 } catch (Exception &e) {
00255                         e.addMessage("VectorMemberAccessor::push_back(" + name + "):");
00256                         throw;
00257                 }
00258                 (object->*member).push_back(value);
00259         }
00260         virtual void clear(Object *o) throw(TypeMismatch) {
00261                 C * object = dynamic_cast<C *>(o);
00262                 if (object == NULL) {
00263                         throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface.");
00264                 }
00265                 (object->*member).clear();
00266         }
00267         virtual void pack(Object *o, Packer &p) const {
00268                 C * object = dynamic_cast<C *>(o);
00269                 T &m = object->*member;
00270                 int n = static_cast<int>(m.size());
00271                 p(n);
00272                 typename T::iterator idx;
00273                 for (idx = m.begin(); idx != m.end(); idx++) {
00274                         p(*idx);
00275                 }
00276         }
00277         virtual void unpack(Object *o, UnPacker &p) {
00278                 C * object = dynamic_cast<C *>(o);
00279                 T &m = object->*member;
00280                 typename T::value_type temp;
00281                 int n;
00282                 p(n);
00283                 while (--n >= 0) {
00284                         p(temp);
00285                         m.push_back(temp);
00286                 }
00287         }
00288 };
00289 
00290 #else // #if !defined(__SIMDATA_PTS_SIM)
00291 template <class C, typename T> 
00292 class MemberAccessor< C, std::vector<T> >: public MemberAccessorBase 
00293 {
00294         std::vector<T> C::* member;
00295 public:
00296         MemberAccessor(std::vector<T> C::*pm, std::string name_, bool required_) {
00297                 member = pm;
00298                 name = name_;
00299                 required = required_;
00300                 {
00301                         T prototype;
00302                         setType(prototype);
00303                         type = "vector::" + type;
00304                 }
00305         }
00306         virtual void push_back(Object *o, TypeAdapter const &v) throw(TypeMismatch) {
00307                 C * object = dynamic_cast<C *>(o);
00308                 if (object == NULL) {
00309                         throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface.");
00310                 }
00311                 T value;
00312                 try {
00313                         v.set(value);
00314                 } catch (Exception &e) {
00315                         e.addMessage("MemberAccessor::push_back(" + name + "):");
00316                         throw;
00317                 }
00318                 (object->*member).push_back(value);
00319         }
00320         virtual void clear(Object *o) throw(TypeMismatch) {
00321                 C * object = dynamic_cast<C *>(o);
00322                 if (object == NULL) {
00323                         throw TypeMismatch("push_back(\"" + name + "\"): Object class does not match interface.");
00324                 }
00325                 (object->*member).clear();
00326         }
00327         virtual void pack(Object *o, Packer &p) const {
00328                 C * object = dynamic_cast<C *>(o);
00329                 std::vector<T> &m = object->*member;
00330                 int n = static_cast<int>(m.size());
00331                 p(n);
00332                 typename std::vector<T>::iterator idx;
00333                 for (idx = m.begin(); idx != m.end(); ++idx) {
00334                         p(*idx);
00335                 }
00336         }
00337         virtual void unpack(Object *o, UnPacker &p) {
00338                 C * object = dynamic_cast<C *>(o);
00339                 std::vector<T> &m = object->*member;
00340                 T temp;
00341                 int n;
00342                 p(n);
00343                 m.reserve(n);
00344                 while (--n >= 0) {
00345                         p(temp);
00346                         m.push_back(temp);
00347                 }
00348         }
00349 };
00350 
00356 template <class C> 
00357 class MemberAccessor< C, int >: public MemberMaskAccessor<C, int> {
00358 public:
00359         MemberAccessor(int C::*pm, std::string name_, bool required_):
00360                 MemberMaskAccessor<C, int>(pm, name_, 0, required_) { }
00361         MemberAccessor(int C::*pm, std::string name_, int mask_, bool required_):
00362                 MemberMaskAccessor<C, int>(pm, name_, mask_, required_) { }
00363 };
00364 
00370 template <class C> 
00371 class MemberAccessor< C, short >: public MemberMaskAccessor<C, short> {
00372 public:
00373         MemberAccessor(short C::*pm, std::string name_, bool required_):
00374                 MemberMaskAccessor<C, short>(pm, name_, 0, required_) { }
00375         MemberAccessor(short C::*pm, std::string name_, int mask_, bool required_):
00376                 MemberMaskAccessor<C, short>(pm, name_, mask_, required_) { }
00377 };
00378 
00384 template <class C> 
00385 class MemberAccessor< C, char >: public MemberMaskAccessor<C, char> {
00386 public:
00387         MemberAccessor(char C::*pm, std::string name_, bool required_):
00388                 MemberMaskAccessor<C, char>(pm, name_, 0, required_) { }
00389         MemberAccessor(char C::*pm, std::string name_, int mask_, bool required_):
00390                 MemberMaskAccessor<C, char>(pm, name_, mask_, required_) { }
00391 };
00392 
00393 #endif // !defined(__SIMDATA_PTS_SIM)
00394 
00395 
00396 #ifdef __SIMDATA_PTS_SIM
00397 
00413 namespace PTS {
00414 
00415         template <typename T>
00416         char IsVector(std::vector<T> const *);  // no implementation is required
00417 
00418         int IsVector(BaseType const *); // no implementation is required
00419         int IsVector(float const *);    // no implementation is required
00420         int IsVector(double const *);   // no implementation is required
00421         int IsVector(int const *);      // no implementation is required
00422         int IsVector(bool const*);      // no implementation is required
00423         int IsVector(char const*);      // no implementation is required
00424         int IsVector(short const*);     // no implementation is required
00425         int IsVector(std::string const*);// no implementation is required
00426         int IsVector(TypeAdapter const *);// no implementation is required
00427 
00428         template <typename T>
00429         struct ISVECTOR {
00430                 enum { RET = (sizeof(IsVector((T*)0)) == 1) };
00431         };
00432         
00433         template <class C, typename T>
00434         struct SELECT_ACCESSOR {
00435                 typedef typename meta::IF<ISVECTOR<T>::RET, 
00436                         simdata::VectorMemberAccessor<C, T>, simdata::MemberAccessor<C, T> >::RET ACCESSOR;
00437         };
00438 }
00439 
00440 #endif // __SIMDATA_PTS_SIM
00441 
00442 
00448 class ObjectInterfaceBase {
00449 public:
00450         virtual ~ObjectInterfaceBase() {}
00451 
00457         virtual bool variableExists(std::string const &name) const = 0;
00458 
00464         virtual bool variableRequired(std::string const &name) const = 0;
00465 
00470         virtual std::string variableType(std::string const &name) const = 0;
00471 
00474         virtual std::vector<std::string> getVariableNames() const = 0;
00475         
00478         virtual std::vector<std::string> getRequiredNames() const = 0;
00479 
00482         virtual const TypeAdapter get(Object *o, std::string const &name) const = 0;
00483         
00486         virtual void set(Object *o, std::string const &name, const TypeAdapter &v) const = 0;
00487         
00490         virtual void push_back(Object *o, std::string const &name, const TypeAdapter &v) const = 0;
00491         
00494         virtual void clear(Object *o, std::string const &name) const = 0;
00495 };
00496 
00497 
00503 template <class C>
00504 class ObjectInterface: public ObjectInterfaceBase {
00505         
00506         typedef ObjectInterface<C> Self;
00507         MemberAccessorBase::map table;
00508 
00509         void __not_found(std::string const &name) const throw (InterfaceError) {
00510                 throw InterfaceError("Variable '"+name+"' not found in interface to class '" + C::_getClassName()+"'");
00511         }
00512 
00513         MemberAccessorBase *getAccessor(std::string const &name) const {
00514                 MemberAccessorBase::map::const_iterator idx = table.find(name);
00515                 if (idx == table.end()) return 0;
00516                 return idx->second;
00517         }
00518 
00519 public:
00520         ObjectInterface() {}
00521         virtual ~ObjectInterface() {}
00522 
00529         template<typename T>
00530         Self& def(std::string const &name, T C::*pm, bool required) throw(InterfaceError) {
00531                 if (variableExists(name)) throw InterfaceError("interface variable \"" + std::string(name) + "\" multiply defined in class '" + C::_getClassName() + "'.");
00532 #ifdef __SIMDATA_PTS_SIM
00533                 table[name] = new typename PTS::SELECT_ACCESSOR<C, T>::ACCESSOR(pm, name, required);
00534 #else
00535                 table[name] = new MemberAccessor<C, T>(pm, name, required);
00536 #endif
00537                 return *this;
00538         }
00539         template<typename T>
00540         Self& def(std::string const &name, T C::*pm, int mask, bool required) throw(InterfaceError) {
00541                 if (variableExists(name)) throw InterfaceError("interface variable \"" + std::string(name) + "\" multiply defined in class '" + C::_getClassName() + "'.");
00542 #ifdef __SIMDATA_PTS_SIM
00543                 table[name] = new typename PTS::SELECT_ACCESSOR<C, T>::ACCESSOR(pm, name, required);
00544 #else
00545                 table[name] = new MemberAccessor<C, T>(pm, name, mask, required);
00546 #endif
00547                 return *this;
00548         }
00549 
00550         inline Self& pass() { return *this; }
00551 
00557         virtual bool variableExists(std::string const &name) const {
00558                 return table.find(name) != table.end();
00559         }
00560 
00566         virtual bool variableRequired(std::string const &name) const {
00567                 MemberAccessorBase::map::const_iterator idx = table.find(name);
00568                 if (idx == table.end()) return false;
00569                 return idx->second->isRequired();
00570         }
00571 
00576         virtual std::string variableType(std::string const &name) const {
00577                 MemberAccessorBase::map::const_iterator idx = table.find(name);
00578                 if (idx == table.end()) __not_found(name);
00579                 return idx->second->getType();
00580         }
00581 
00584         virtual std::vector<std::string> getVariableNames() const {
00585                 std::vector<std::string> names;
00586                 MemberAccessorBase::map::const_iterator idx;
00587                 for (idx = table.begin(); idx != table.end(); idx++) {
00588                         names.push_back(idx->first);
00589                 }
00590                 return names;
00591         }
00592 
00595         virtual std::vector<std::string> getRequiredNames() const {
00596                 std::vector<std::string> names;
00597                 MemberAccessorBase::map::const_iterator idx;
00598                 for (idx = table.begin(); idx != table.end(); idx++) {
00599                         if (idx->second->isRequired()) {
00600                                 names.push_back(idx->first);
00601                         }
00602                 }
00603                 return names;
00604         }
00605 
00608         virtual const TypeAdapter get(Object *o, std::string const &name) const {
00609                 return getAccessor(name)->get(o);
00610         }
00611         
00614         virtual void set(Object *o, std::string const &name, const TypeAdapter &v) const {
00615                 getAccessor(name)->set(o, v);
00616         }
00617         
00620         virtual void push_back(Object *o, std::string const &name, const TypeAdapter &v) const {
00621                 getAccessor(name)->push_back(o, v);
00622         }
00623         
00626         virtual void clear(Object *o, std::string const &name) const {
00627                 getAccessor(name)->clear(o);
00628         }
00629 
00630 private:
00631         // These methods are currently in limbo.  Minimally they should be
00632         // updated to use serialize(Archive&), but the usefulness of this
00633         // feature is still in doubt.
00634         virtual void pack(Object *o, Packer &p) const {
00635                 MemberAccessorBase::map::const_iterator idx;
00636                 for (idx = table.begin(); idx != table.end(); ++idx) {
00637                         idx->second->pack(o, p);
00638                 }
00639         }
00640 
00641         virtual void unpack(Object *o, UnPacker &p) const {
00642                 MemberAccessorBase::map::const_iterator idx;
00643                 for (idx = table.begin(); idx != table.end(); ++idx) {
00644                         idx->second->unpack(o, p);
00645                 }
00646         }
00647 };
00648 
00649 
00650 NAMESPACE_SIMDATA_END
00651 
00652 
00653 #endif // __SIMDATA_OBJECTINTERFACE_H__
00654 

SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage.

Generated on Tue Oct 14 12:06:39 2003, using Doxygen 1.2.18.

[SF.net]