00001
00002
00003
00004
00005
00006
00007
00008 #define REFLECT_IN_LIBRARY_SOURCE
00009
00010 #include "object_visitor.hpp"
00011 #include <iostream>
00012 #include "../common/object.hpp"
00013 #include "../common/comparable_object.hpp"
00014 #include "../common/outerable_object.hpp"
00015 #include "../common/visitable_object.hpp"
00016 #include "../common/nameable_object.hpp"
00017 #include "../common/pretendable_object.hpp"
00018 #include "member_visitor.hpp"
00019 #include "member.hpp"
00020 #include <boost/bind.hpp>
00021 #include <algorithm>
00022
00023 using namespace ph::reflect;
00024
00025 class dump_member_visitor : public ph::common::const_member_visitor
00026
00027
00028
00029 {
00030 public:
00031 dump_member_visitor(std::ostream *stream, int indent) :
00032 _stream(stream), _indent(indent)
00033 {};
00034
00035
00036 virtual bool visit(const ph::common::object_base *obj,
00037 const std::string &name, const ph::common::member_base *member);
00038
00039 private:
00040 std::ostream *_stream;
00041 int _indent;
00042 };
00043
00044 static std::string get_name(const ph::common::object_base *obj)
00045 {
00046 if (!obj->nameable())
00047 return "object has no nameable interface.";
00048 return obj->nameable()->name();
00049 }
00050
00051 static std::string get_type(const ph::common::object_base *obj)
00052 {
00053 if (!obj->nameable())
00054 return "object has no nameable interface.";
00055 return obj->nameable()->type();
00056 }
00057
00058 static bool obj_equal(const ph::common::object_base *o1, const ph::common::object_base *o2, std::ostream *debug)
00059 {
00060 if (debug)
00061 *debug << ">> comparing [" << get_name(o1) << "] to [" << get_name(o2) << "]" << std::endl;
00062
00063
00064 if (o1->comparable())
00065 return o1->comparable()->equal(o2);
00066 else
00067 return o1 == o2;
00068 }
00069
00070 void dump_object_visitor::obj_out(const std::string &msg, const ph::common::object_base *obj)
00071 {
00072 *_stream << ">> " << msg << " [" << get_name(obj) << "]" << std::endl;
00073 }
00074
00075 void dump_object_visitor::close_stack()
00076 {
00077 if (_debug)
00078 *_stream << ">> closing stack. " << std::endl;
00079
00080
00081 while (!_stack.empty())
00082 {
00083 _stack.pop_back();
00084 _indent--;
00085 indent();
00086 *_stream << "}" << std::endl;
00087 }
00088 if (_indent != 0)
00089 *_stream << ">> error after closing stack, indent is not 0?. " << std::endl;
00090 }
00091
00092 void dump_object_visitor::calc_indent(const ph::common::object_base *obj)
00093 {
00094 if (_debug)
00095 obj_out("calc_indent", obj);
00096
00097
00098 if (!obj->outerable())
00099 {
00100 if (_debug)
00101 obj_out("object has no parent interface. Can't calculate the indent.", obj);
00102 return;
00103 }
00104
00105 ph::common::object_base *parent = obj->outerable()->outer();
00106 if (parent)
00107 {
00108 if (_debug)
00109 obj_out("parent.", parent);
00110
00111
00112 if (std::find_if(_stack.rbegin(), _stack.rend(),
00113 boost::bind(obj_equal, _1, parent, _debug ? _stream : 0)) != _stack.rend())
00114 {
00115 if (_debug)
00116 obj_out("found parent on stack.", parent);
00117
00118
00119 while (!obj_equal(_stack.back(), parent, _debug ? _stream : 0))
00120 {
00121 if (_debug)
00122 obj_out("popping.", _stack.back());
00123 _stack.pop_back();
00124 _indent--;
00125 indent();
00126 *_stream << "}" << std::endl;
00127 }
00128
00129 if (_debug)
00130 obj_out("pushing.", obj);
00131 _stack.push_back(obj);
00132 }
00133 else
00134 {
00135 if (_debug)
00136 obj_out("not found on stack. pushing.", obj);
00137 _stack.push_back(obj);
00138 _indent++;
00139 }
00140 }
00141 else
00142 {
00143 if (_debug)
00144 obj_out("no parent. pushing.", obj);
00145 close_stack();
00146 _stack.push_back(obj);
00147 }
00148 }
00149
00150 void dump_object_visitor::indent()
00151 {
00152 for (int i=0; i<_indent; i++)
00153 *_stream << " ";
00154 }
00155
00156 dump_object_visitor::~dump_object_visitor()
00157 {
00158 close_stack();
00159 }
00160
00161 bool dump_object_visitor::visit(const ph::common::object_base *obj)
00162 {
00163 if (_debug)
00164 obj_out("visit", obj);
00165
00166 calc_indent(obj);
00167
00168 indent();
00169 *_stream << get_type(obj) << "(name=" << get_name(obj) << ") { " << std::endl;
00170
00171 _indent++;
00172
00173
00174 dump_member_visitor v(_stream, _indent);
00175 if (obj->visitable())
00176 obj->visitable()->accept(&v);
00177 else
00178 obj_out("object can't be reflected.", obj);
00179
00180 return true;
00181 }
00182
00183 bool dump_object_visitor::visit_composite(const ph::common::object_base *obj)
00184 {
00185 if (_debug)
00186 obj_out("visit_composite", obj);
00187
00188 calc_indent(obj);
00189
00190 indent();
00191 *_stream << get_name(obj) << " { " << std::endl;
00192
00193 _indent++;
00194
00195 return true;
00196 }
00197
00198
00199 bool dump_member_visitor::visit(const ph::common::object_base *obj, const std::string &name,
00200 const ph::common::member_base *member)
00201 {
00202
00203 if (name != "name" && name != "type")
00204 {
00205 for (int i=0; i<_indent; i++)
00206 *_stream << " ";
00207 *_stream << name << "=" << member->get() << std::endl;
00208 }
00209
00210 return true;
00211 }
00212
00213 bool get_composite_object_visitor::visit_composite(const ph::common::object_base *obj, const ph::common::nameable_object_base *name)
00214 {
00215 if (name->name() == _name)
00216 {
00217
00218
00219
00220 _obj = const_cast<ph::common::object_base *>(obj);
00221
00222
00223
00224 if (_obj->pretendable())
00225 _obj = _obj->pretendable()->realobject();
00226
00227 return false;
00228 }
00229 return true;
00230 }
00231
00232 bool get_object_visitor::visit(const ph::common::object_base *obj, const ph::common::nameable_object_base *name)
00233 {
00234 if (name->name() == _name)
00235 {
00236
00237
00238
00239 _obj = const_cast<ph::common::object_base *>(obj);
00240
00241
00242
00243 if (_obj->pretendable())
00244 _obj = _obj->pretendable()->realobject();
00245
00246 return false;
00247 }
00248 return true;
00249 }
00250
00251 bool get_object_with_type_visitor::visit(const ph::common::object_base *obj, const ph::common::nameable_object_base *name)
00252 {
00253
00254
00255
00256 if (name->name() == _name && name->type() == _type)
00257 {
00258
00259
00260
00261 _obj = const_cast<ph::common::object_base *>(obj);
00262
00263
00264
00265 if (_obj->pretendable())
00266 _obj = _obj->pretendable()->realobject();
00267
00268 return false;
00269 }
00270 return true;
00271 }
00272
00273 bool get_nth_object_visitor::visit(const ph::common::object_base *obj, const ph::common::nameable_object_base *name)
00274 {
00275
00276 if (_index == 0)
00277 {
00278
00279
00280
00281 _obj = const_cast<ph::common::object_base *>(obj);
00282
00283
00284
00285 if (_obj->pretendable())
00286 _obj = _obj->pretendable()->realobject();
00287
00288 return false;
00289 }
00290 _index--;
00291 return true;
00292 }