Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Namespace Members | Data Fields | Globals
reflect

object_visitor.cpp

Go to the documentation of this file.
00001 // See ../license.txt for license information.
00002 //
00003 // object_visitor.cpp
00004 //
00005 // 4-Jul-2003 phamilton Created
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  Concrete subclass of member_visitor used to dump the value of a member.
00028 */
00029 {
00030 public:
00031 dump_member_visitor(std::ostream *stream, int indent) :
00032 _stream(stream), _indent(indent)
00033 {};
00034 
00035 // member_visitor ovverides.
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 // use equal interface if one exists.
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 // pop the stack back out till it's empty.
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 // we have a new object.
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 // is the parent on the stack?
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 // pop the stack back till we get the parent.
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 // dump members.
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 // dump_member_visitor
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 // skip over name and type properties
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 // although we don't modify any of the objects we visit, we do
00218 // need to return the actual object at the end, so
00219 // we cast out const.
00220 _obj = const_cast<ph::common::object_base *>(obj);
00221 
00222 // We check for pretendable objects to make
00223 // sure that we get the actual object.
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 // although we don't modify any of the objects we visit, we do
00237 // need to return the actual object at the end, so
00238 // we cast out const.
00239 _obj = const_cast<ph::common::object_base *>(obj);
00240 
00241 // We check for pretendable objects to make
00242 // sure that we get the actual object.
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 // the order of these is very important. We often know the name of an object, but
00254 // not it's type, so if the name doesn't match, we don't want to even try to get it's 
00255 // type.
00256 if (name->name() == _name && name->type() == _type)
00257 {
00258 // although we don't modify any of the objects we visit, we do
00259 // need to return the actual object at the end, so
00260 // we cast out const.
00261 _obj = const_cast<ph::common::object_base *>(obj);
00262 
00263 // We check for pretendable objects to make
00264 // sure that we get the actual object.
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 // when the index is 0, return the object.
00276 if (_index == 0)
00277 {
00278 // although we don't modify any of the objects we visit, we do
00279 // need to return the actual object at the end, so
00280 // we cast out const.
00281 _obj = const_cast<ph::common::object_base *>(obj);
00282 
00283 // We check for pretendable objects to make
00284 // sure that we get the actual object.
00285 if (_obj->pretendable())
00286 _obj = _obj->pretendable()->realobject();
00287 
00288 return false;
00289 }
00290 _index--;
00291 return true;
00292 }

Generated on Wed Apr 5 22:03:25 2006 for cppxmlobj by doxygen 1.4.3

AltStyle によって変換されたページ (->オリジナル) /