00001
00002
00003
00004
00005
00006
00007
00008 #ifndef IMP_DECORATOR_H
00009 #define IMP_DECORATOR_H
00010
00011 #include "Object.h"
00012 #include "Pointer.h"
00013 #include "utility.h"
00014 #include "Particle.h"
00015 #include "Constraint.h"
00016 #include "Model.h"
00017 #include "internal/IndexingIterator.h"
00018
00019 IMP_BEGIN_NAMESPACE
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 class Decorator
00106 {
00107 private:
00108 Particle *particle_;
00109 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
00110 friend bool operator==(Decorator, Particle*);
00111 #endif
00112 protected:
00113 Decorator(Particle *p): particle_(p) {}
00114 Decorator() :particle_(NULL)
00115 {}
00116 public:
00117 #ifdef _MSC_VER
00118
00119 typedef Particle* ParticleP;
00120 #endif
00121
00122 IMP_NO_DOXYGEN(typedef Decorator This);
00123
00124 IMP_COMPARISONS_1(particle_);
00125
00126
00127
00128
00129
00130
00131
00132 Particle *get_particle() const {
00133 IMP_USAGE_CHECK(particle_,
00134 "You must give the decorator a particle to decorate.");
00135 IMP_CHECK_OBJECT(particle_);
00136 return particle_;
00137 }
00138
00139 #if !defined(IMP_DOXYGEN) && !defined(SWIG)
00140 operator Particle*() const {
00141 return particle_;
00142 }
00143 Particle* operator->() const {
00144 return particle_;
00145 }
00146 #endif
00147
00148
00149 Model *get_model() const {
00150 IMP_CHECK_OBJECT(particle_->get_model());
00151 return particle_->get_model();
00152 }
00153
00154 private:
00155 IMP_ONLY_DOXYGEN(int blah_;);
00156
00157 public:
00158 #ifdef IMP_DOXYGEN
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 static Decorator setup_particle(Particle *p, extra_arguments);
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 static bool particle_is_instance(Particle *p);
00197
00198
00199
00200
00201
00202
00203 Decorator(Particle *p);
00204
00205
00206
00207 Decorator();
00208
00209 #endif
00210 IMP_NO_DOXYGEN(bool is_null() const {return !particle_;});
00211 IMP_NO_DOXYGEN(typedef void (Decorator::*bool_type)() const);
00212 IMP_NO_DOXYGEN(void safe_bool_function() const {});
00213 };
00214
00215
00216 #ifndef IMP_DOXYGEN
00217 inline bool operator==(Decorator d, Particle *p) {
00218 return d.particle_==p;
00219 }
00220 inline bool operator==(Particle *p, Decorator d) {
00221 return d==p;
00222 }
00223
00224
00225 #if !defined(SWIG)
00226 #define IMP_DECORATORS_METHODS(test, on_add_decorator, on_add_particle, \
00227 swap) \
00228 struct Accessor { \
00229 typedef Accessor This; \
00230 typedef WrappedDecorator result_type; \
00231 typedef unsigned int argument_type; \
00232 result_type operator()(argument_type i) const { \
00233 return o_->operator[](i); \
00234 } \
00235 Accessor(ThisDecorators *pc): o_(pc){} \
00236 Accessor(): o_(NULL){} \
00237 IMP_COMPARISONS_1(o_); \
00238 private: \
00239
00240 \
00241 ThisDecorators* o_; \
00242 }; \
00243 void check(Particle *p) { \
00244 IMP_USAGE_CHECK(test, \
00245 "Particle \"" << (p)->get_name() \
00246 << "\" missing required attributes"); \
00247 } \
00248 template <class It> \
00249 void check(It b, It e) { \
00250 for (It c= b; c!= e; ++c) { \
00251 check(*c); \
00252 } \
00253 } \
00254 public: \
00255 typedef const WrappedDecorator const_reference; \
00256 typedef WrappedDecorator value_type; \
00257 typedef Proxy reference; \
00258 const ParticlesTemp &get_particles() const {return *this;} \
00259 void push_back(WrappedDecorator d) { \
00260 on_add_decorator; \
00261 ParentDecorators::push_back(d); \
00262 } \
00263 void push_back(Particle *p) { \
00264 check(p); \
00265 on_add_particle; \
00266 ParentDecorators::push_back(p); \
00267 } \
00268 void set(unsigned int i, WrappedDecorator d) { \
00269 ParentDecorators::operator[](i)= d; \
00270 } \
00271 WrappedDecorator back() const { \
00272 IMP_USAGE_CHECK(!ParentDecorators::empty(), \
00273 "Can't call back on empty Decorators"); \
00274 return WrappedDecorator(ParentDecorators::back()); \
00275 } \
00276 WrappedDecorator front() const { \
00277 IMP_USAGE_CHECK(!ParentDecorators::empty(), \
00278 "Can't call front on empty Decorators"); \
00279 return WrappedDecorator(ParentDecorators::front()); \
00280 } \
00281 typedef internal::IndexingIterator<Accessor> iterator; \
00282 typedef internal::IndexingIterator<Accessor> const_iterator; \
00283 iterator begin() const { \
00284 return iterator(Accessor(const_cast<ThisDecorators*>(this)), 0); \
00285 } \
00286 iterator end() const { \
00287 return iterator(Accessor(const_cast<ThisDecorators*>(this)), \
00288 ParentDecorators::size()); \
00289 } \
00290 template <class It> \
00291 void insert(iterator loc, It b, It e) { \
00292 check(b,e); \
00293 for (It c=b; c!= e; ++c) { \
00294 on_add_particle; \
00295 } \
00296 ParentDecorators::insert(ParentDecorators::begin()+(loc-begin()), \
00297 b, e); \
00298 } \
00299 void swap_with(ThisDecorators &o) { \
00300 swap; \
00301 ParentDecorators::swap_with(o); \
00302 } \
00303
00304 #else
00305 #define IMP_DECORATORS_METHODS(test, on_add_decorator, on_add_particle, \
00306 swap) \
00307 public: \
00308 const ParticlesTemp &get_particles() const; \
00309 void push_back(WrappedDecorator d); \
00310 void push_back(Particle *p); \
00311 WrappedDecorator back() const; \
00312 WrappedDecorator front() const;
00313
00314 #endif
00315
00316
00317 template <class WrappedDecorator, class ParentDecorators>
00318 class Decorators: public ParentDecorators {
00319 typedef Decorators<WrappedDecorator, ParentDecorators> ThisDecorators;
00320 struct Proxy: public WrappedDecorator {
00321 typedef typename ParentDecorators::reference Ref;
00322 Ref d_;
00323 Proxy(Ref t):
00324 WrappedDecorator(t), d_(t){
00325 }
00326 Proxy(Ref p, bool): WrappedDecorator(), d_(p){}
00327 void operator=(WrappedDecorator v) {
00328 WrappedDecorator::operator=(v);
00329 d_=v;
00330 }
00331 #ifdef _MSC_VER
00332
00333 operator Particle*() {
00334 if (WrappedDecorator()==*this) return NULL;
00335 else return WrappedDecorator::get_particle();
00336 }
00337 #endif
00338 };
00339 Proxy get_proxy(unsigned int i) {
00340 if (ParentDecorators::operator[](i)) {
00341 return Proxy(ParentDecorators::operator[](i));
00342 } else {
00343 return Proxy(ParentDecorators::operator[](i), false);
00344 }
00345 }
00346
00347 IMP_DECORATORS_METHODS(WrappedDecorator::particle_is_instance(p),,,);
00348 public:
00349 explicit Decorators(const Particles &ps): ParentDecorators(ps) {
00350 check(ps.begin(), ps.end());
00351 }
00352 explicit Decorators(const ParticlesTemp &ds): ParentDecorators(ds){
00353 check(ds.begin(), ds.end());
00354 }
00355 explicit Decorators(unsigned int i): ParentDecorators(i){}
00356 explicit Decorators(WrappedDecorator d): ParentDecorators(1, d){}
00357 explicit Decorators(unsigned int n,
00358 WrappedDecorator d): ParentDecorators(n, d){}
00359 Decorators(){}
00360 #ifndef SWIG
00361 Proxy
00362 operator[](unsigned int i) {
00363 return get_proxy(i);
00364 }
00365 #endif
00366
00367 #ifndef SWIG
00368 WrappedDecorator operator[](unsigned int i) const {
00369 return WrappedDecorator(ParentDecorators::operator[](i));
00370 }
00371 #endif
00372 };
00373
00374 IMP_SWAP_2(Decorators);
00375
00376 template <class WrappedDecorator, class ParentDecorators, class Traits>
00377 class DecoratorsWithTraits: public ParentDecorators {
00378 typedef DecoratorsWithTraits<WrappedDecorator, ParentDecorators,
00379 Traits> ThisDecorators;
00380
00381 struct Proxy: public WrappedDecorator {
00382 typedef typename ParentDecorators::reference Ref;
00383 Ref d_;
00384 Proxy(Ref t, Traits tr):
00385 WrappedDecorator(t, tr), d_(t){
00386 }
00387 Proxy(Ref p, bool): WrappedDecorator(), d_(p){}
00388 void operator=(WrappedDecorator v) {
00389
00390 WrappedDecorator::operator=(v);
00391 d_=v;
00392 }
00393 #ifdef _MSC_VER
00394
00395 operator Particle*() {
00396 if (WrappedDecorator()==*this) return NULL;
00397 else return WrappedDecorator::get_particle();
00398 }
00399 #endif
00400 };
00401 Proxy get_proxy(unsigned int i, Traits t) {
00402 if (ParentDecorators::operator[](i)) {
00403 return Proxy(ParentDecorators::operator[](i), t);
00404 } else {
00405 return Proxy(ParentDecorators::operator[](i), false);
00406 }
00407 }
00408 Traits tr_;
00409 bool has_traits_;
00410 IMP_DECORATORS_METHODS(WrappedDecorator::particle_is_instance(p, tr_),{
00411 if (!has_traits_) {
00412 tr_= d.get_traits();
00413 has_traits_=true;
00414 } else {
00415 IMP_USAGE_CHECK(tr_ == d.get_traits(),
00416 "Traits don't match");
00417 }
00418 },{
00419 IMP_USAGE_CHECK(has_traits_, "Need to add a decorator first to get "
00420 << "traits class.");
00421 }, {
00422 std::swap(tr_, o.tr_);
00423 std::swap(has_traits_, o.has_traits_);
00424 });
00425 public:
00426 explicit DecoratorsWithTraits(Traits tr): tr_(tr), has_traits_(true){}
00427 explicit DecoratorsWithTraits(WrappedDecorator d): ParentDecorators(1,d),
00428 tr_(d.get_traits()),
00429 has_traits_(true){}
00430 explicit DecoratorsWithTraits(unsigned int n, WrappedDecorator d):
00431 ParentDecorators(n, d),
00432 tr_(d.get_traits()),
00433 has_traits_(true) {}
00434 DecoratorsWithTraits(const Particles &ps,
00435 Traits tr): tr_(tr), has_traits_(true) {
00436 ParentDecorators::resize(ps.size());
00437 for (unsigned int i=0; i< ps.size(); ++i) {
00438 ParentDecorators::operator[](i)=WrappedDecorator(ps[i], tr);
00439 }
00440 }
00441 DecoratorsWithTraits(unsigned int i,
00442 Traits tr): ParentDecorators(i), tr_(tr),
00443 has_traits_(true){}
00444 DecoratorsWithTraits(): has_traits_(false){}
00445
00446 #ifndef SWIG
00447 Proxy
00448 operator[](unsigned int i) {
00449 IMP_USAGE_CHECK(has_traits_, "Can only use operator[] on a decorator "
00450 << "container "
00451 << "which is non-empty. This is a bug, but hard to fix.");
00452 return get_proxy(i, tr_);
00453 }
00454 WrappedDecorator operator[](unsigned int i) const {
00455 return WrappedDecorator(ParentDecorators::operator[](i), tr_);
00456 }
00457 #endif
00458 };
00459
00460
00461 IMP_SWAP_3(DecoratorsWithTraits);
00462
00463 template <class WrappedDecorator, class ParentDecorators>
00464 class DecoratorsWithImplicitTraits: public ParentDecorators {
00465 struct Proxy: public WrappedDecorator {
00466 typedef typename ParentDecorators::reference Ref;
00467 Ref d_;
00468 Proxy(Ref t):
00469 WrappedDecorator(t), d_(t){
00470 }
00471 Proxy(Ref p, bool): WrappedDecorator(), d_(p){}
00472 void operator=(WrappedDecorator v) {
00473
00474 WrappedDecorator::operator=(v);
00475 d_=v;
00476 }
00477 #ifdef _MSC_VER
00478
00479 operator Particle*() {
00480 if (WrappedDecorator()==*this) return NULL;
00481 else return WrappedDecorator::get_particle();
00482 }
00483 #endif
00484 };
00485 Proxy get_proxy(unsigned int i) {
00486 if (ParentDecorators::operator[](i)) {
00487 return Proxy(ParentDecorators::operator[](i));
00488 } else {
00489 return Proxy(ParentDecorators::operator[](i), false);
00490 }
00491 }
00492 typedef DecoratorsWithImplicitTraits<WrappedDecorator, ParentDecorators>
00493 ThisDecorators;
00494 IMP_DECORATORS_METHODS(WrappedDecorator::particle_is_instance(p),,,)
00495 public:
00496 explicit DecoratorsWithImplicitTraits():
00497 ParentDecorators(WrappedDecorator::get_traits()) {}
00498 explicit DecoratorsWithImplicitTraits(const Particles &ps):
00499 ParentDecorators(ps, WrappedDecorator::get_traits()){
00500 }
00501 explicit DecoratorsWithImplicitTraits(unsigned int i):
00502 ParentDecorators(i, WrappedDecorator::get_traits()){}
00503 explicit DecoratorsWithImplicitTraits(WrappedDecorator d):
00504 ParentDecorators(1,d){}
00505 explicit DecoratorsWithImplicitTraits(unsigned int n,WrappedDecorator d):
00506 ParentDecorators(n, d){}
00507 explicit DecoratorsWithImplicitTraits(const ParticlesTemp &ds):
00508 ParentDecorators(ds, WrappedDecorator::get_traits()){
00509 check(ds.begin(), ds.end());
00510 }
00511 #ifndef SWIG
00512 Proxy
00513 operator[](unsigned int i) {
00514 return get_proxy(i);
00515 }
00516 #endif
00517
00518 #ifndef SWIG
00519 WrappedDecorator operator[](unsigned int i) const {
00520 return WrappedDecorator(ParentDecorators::operator[](i));
00521 }
00522 #endif
00523 };
00524
00525 IMP_SWAP_2(DecoratorsWithImplicitTraits);
00526
00527
00528
00529 template <class D>
00530 class RefCountingDecorator: public D {
00531 public:
00532 RefCountingDecorator(){}
00533 RefCountingDecorator(const D &d): D(d){internal::ref(D::get_particle());}
00534 ~RefCountingDecorator(){ internal::unref(D::get_particle());}
00535 #ifndef SWIG
00536 void operator=(const D &d) {
00537 if (*this) {
00538 internal::unref(D::get_particle());
00539 }
00540 D::operator=(d);
00541 if (*this) {
00542 internal::ref(D::get_particle());
00543 }
00544 }
00545 const D&get_decorator() const {
00546 return static_cast<const D&>(*this);
00547 }
00548 D&get_decorator() {
00549 return static_cast<D&>(*this);
00550 }
00551 #endif
00552 };
00553
00554
00555 #define IMP_CONSTRAINT_DECORATOR_DECL(Name) \
00556 private: \
00557 static ObjectKey get_constraint_key(); \
00558 static void set_constraint(SingletonModifier* before, \
00559 SingletonModifier *after, Particle *p); \
00560 public: \
00561 Constraint *get_constraint() const { \
00562 return dynamic_cast<Constraint*>(get_particle() \
00563 ->get_value(get_constraint_key())); \
00564 }
00565
00566
00567 #define IMP_CONSTRAINT_DECORATOR_DEF(Name) \
00568 ObjectKey Name::get_constraint_key() { \
00569 static ObjectKey ret(#Name " score state"); \
00570 return ret; \
00571 } \
00572 void Name::set_constraint(SingletonModifier* before, \
00573 SingletonModifier *after, \
00574 Particle *p) { \
00575 Constraint *ss= new SingletonConstraint(before, \
00576 after, p, \
00577 std::string(#Name "updater for ")+p->get_name()); \
00578 p->add_attribute(get_constraint_key(), ss); \
00579 p->get_model()->add_score_state(ss); \
00580 } \
00581
00582 #endif
00583
00584 IMP_END_NAMESPACE
00585
00586 #endif