00001 // 00002 // See license.txt for license information. 00003 // 00004 // persistable_object.hpp 00005 // 00006 // 17-Jul-2003 phamilton Created 00007 // 00008 00009 #ifndef incCOMMON_PERSISTABLE_OBJECT 00010 #define incCOMMON_PERSISTABLE_OBJECT 00011 00012 // forwards 00013 #include <string> 00014 #include "object.hpp" 00015 #include "boost/filesystem/path.hpp" 00016 00017 namespace ph { 00018 namespace common { 00019 00020 // forwards 00021 class persistable_object_context; 00022 class object_writer; 00023 00024 class persistable_object_base 00025 /** 00026 Abstract class representing the interface for an object to be persisted. 00027 00028 NOTE: This class is completely independant of reflection, although it is 00029 obvious that reflection combined with persistance is the perfect solution 00030 for complex objects. It is kept separate for the purposes 00031 of reusability. 00032 */ 00033 { 00034 public: 00035 virtual ~persistable_object_base() {} 00036 00037 virtual object_base *create( 00038 const std::string &type, 00039 const std::string &name, 00040 persistable_object_context *context) = 0; 00041 //!< Allow one object to create another. this is dependant 00042 //! on the way you want to build new objects, but usually 00043 //! it involves the Abstract Factory pattern. 00044 00045 virtual object_base *get_composite_object(const std::string &name) = 0; 00046 //!< return the object if it is a composite one. 00047 //! 00048 00049 virtual bool has(const std::string &name) const = 0; 00050 //!< Does this member name exist? 00051 //! 00052 00053 virtual void set(const std::string &name, const std::string &value) = 0; 00054 //!< Set the value of a member in the class with a particular name. 00055 //! 00056 virtual std::string get(const std::string &name) const = 0; 00057 //!< Get the value of a member in the class with a particular name. 00058 //! 00059 00060 virtual bool write(object_writer *writer) const 00061 { return true; } 00062 //!< Write out the object using the writer passed in. 00063 //! 00064 00065 virtual void set_file_path(const std::string &path) {} 00066 //!< This object is coming as the root object from a file. 00067 //! Allow it to receive the path to this file. 00068 }; 00069 00070 class persistable_object_context 00071 /** 00072 Abstract class representing a context that is passed when objects 00073 are created. 00074 */ 00075 { 00076 public: 00077 virtual ~persistable_object_context() {}; 00078 00079 virtual object_base *create( 00080 const std::string &type, 00081 const std::string &name) = 0; 00082 //!< Create an object of the appropriate type and name. Usually 00083 //! implemented with an Abstract Factory pattern. 00084 00085 virtual object_base *find_object( 00086 object_base *root, 00087 object_base *obj, 00088 const std::string &location) = 0; 00089 //!< Find the object and return it if it's Composite. 00090 //! "root" is the root object of the tree. 00091 //! "obj" is the current object for relative locations. 00092 //! "location" is the path location. 00093 //! 00094 00095 virtual object_base *find_composite_object( 00096 object_base *root, 00097 object_base *obj, 00098 const std::string &location) = 0; 00099 //!< Find the object and return it if it's Composite. 00100 //! "root" is the root object of the tree. 00101 //! "obj" is the current object for relative locations. 00102 //! "location" is the path location. 00103 //! 00104 00105 virtual bool delayed_import() { return false; } 00106 //!< The XML parser can do delayed importing. This means that instead of 00107 //! actually importing an external file, a placeholder object is created and 00108 //! then when this placeholder is referenced, the actual import is performed. 00109 //! This speeds up extremely large object systems, and you can enable this 00110 //! behaviour by returning true here. If your parser doesn't 00111 //! handle this type of importing, then throw an error if this is set to 00112 //! true (or something). 00113 00114 virtual ph::common::object_base *create_delayed( 00115 std::ostream *console, 00116 const boost::filesystem::path &url, 00117 const std::string &name, 00118 unsigned int debug) { return 0 ; } 00119 //!< Create an object to hold delayed import information. 00120 }; 00121 00122 class object_writer 00123 /** 00124 Abstract class used to write an object out. 00125 */ 00126 { 00127 public: 00128 virtual ~object_writer() {}; 00129 00130 virtual bool start(const std::string &tagname) = 0; 00131 //!< Start a new tag with the writer. 00132 //! 00133 virtual bool attr(const std::string &name, const std::string &value) = 0; 00134 //!< Write out name/value pairs for the tag. 00135 //! 00136 virtual bool data(const std::string &d) = 0; 00137 //!< Write out arbitrary data for the tag. 00138 //! 00139 virtual bool end(const std::string &tagname) = 0; 00140 //!< End the tag. Note that it is usually possible for the 00141 //! implementation of the writer to save away the tag name, 00142 //! but for keeping the writers simple, it is included again. 00143 }; 00144 00145 class object_writer_context 00146 /** 00147 A context used to start a tag, and then correctly end it 00148 upon destruction. 00149 00150 This allows code such as: 00151 00152 object_writer_context c(writer, "foo"); 00153 c.attr("name", "foo_1"); 00154 c.data("Hello World"); 00155 00156 To be used rather than explicitly starting and ending the tags. 00157 */ 00158 { 00159 public: 00160 object_writer_context(object_writer *writer, const std::string &tagname) : 00161 _writer(writer), _tagname(tagname) 00162 { _writer->start(_tagname); } 00163 ~object_writer_context() 00164 { _writer->end(_tagname); } 00165 void attr(const std::string &name, const std::string &value) 00166 { _writer->attr(name, value); } 00167 void data(const std::string &d) 00168 { _writer->data(d); } 00169 00170 private: 00171 object_writer *_writer; 00172 std::string _tagname; 00173 }; 00174 00175 inline bool get_persistable_obj_name(const object_base *obj, std::string *name) 00176 /** 00177 Function to return an objects name using the persistance scheme. 00178 */ 00179 { 00180 if (!obj->persistable()) 00181 return false; 00182 00183 *name = obj->persistable()->get("name"); 00184 return true; 00185 } 00186 00187 inline bool get_persistable_obj_type(const object_base *obj, std::string *type) 00188 /** 00189 Function to return an objects type using the persistance scheme. 00190 */ 00191 { 00192 if (!obj->persistable()) 00193 return false; 00194 00195 *type = obj->persistable()->get("type"); 00196 return true; 00197 } 00198 00199 inline bool set_persistable_obj_name(object_base *obj, const std::string &name) 00200 /** 00201 Function to set an objects name using the persistance scheme. 00202 */ 00203 { 00204 if (!obj->persistable()) 00205 return false; 00206 00207 obj->persistable()->set("name", name); 00208 return true; 00209 } 00210 00211 inline bool set_persistable_obj_type(object_base *obj, const std::string &type) 00212 /** 00213 Function to set an objects type using the persistance scheme. 00214 */ 00215 { 00216 if (!obj->persistable()) 00217 return false; 00218 00219 obj->persistable()->set("type", type); 00220 return true; 00221 } 00222 00223 }; // common 00224 }; // ph 00225 00226 #endif // incCOMMON_PERSISTABLE_OBJECT