00001 /* 00002 * The information in this file is 00003 * Copyright(c) 2007 Ball Aerospace & Technologies Corporation 00004 * and is subject to the terms and conditions of the 00005 * GNU Lesser General Public License Version 2.1 00006 * The license text is available from 00007 * http://www.gnu.org/licenses/lgpl.html 00008 */ 00009 00010 #ifndef DYNAMICOBJECT_H 00011 #define DYNAMICOBJECT_H 00012 00013 #include "DataVariant.h" 00014 #include "DataVariantValidator.h" 00015 #include "Serializable.h" 00016 #include "Subject.h" 00017 00018 #include <string> 00019 #include <vector> 00020 00021 class DataVariant; 00022 class QRegExp; 00023 00024 /** 00025 * Dynamic extension of class attributes 00026 * 00027 * Dynamic Object refers to a class that allows attributes to be 00028 * added during runtime. Many classes extend the Dynamic Object 00029 * to provide future support for new attributes without changing 00030 * the class specification. 00031 * 00032 * This subclass of Subject will notify upon the following conditions: 00033 * - The following methods are called: setAttribute(), setAttributeByPath(), 00034 * adoptAttribute(), adoptAttributeByPath(), merge(), removeAttribute(), 00035 * removeAttributeByPath(), clear(). 00036 * - %Any of the objects within the DynamicObject post a notification. 00037 * These notifications will be passed on to any observers of the 00038 * DynamicObject 00039 * - Everything else documented in Subject. 00040 */ 00041 class DynamicObject : public Subject, public Serializable 00042 { 00043 public: 00044 /** 00045 * Emitted just after a new attribute is added with 00046 * boost::any<std::pair<std::string, DataVariant*> > containing the 00047 * attribute name and value. 00048 */ 00049 SIGNAL_METHOD(DynamicObject, AttributeAdded) 00050 00051 /** 00052 * Emitted just after an existing attribute is modified with 00053 * boost::any<std::pair<std::string, DataVariant*> > containing the 00054 * attribute name and the new value. 00055 */ 00056 SIGNAL_METHOD(DynamicObject, AttributeModified) 00057 00058 /** 00059 * Emitted just before an existing attribute is removed with 00060 * boost::any<std::pair<std::string, DataVariant*> > containing the 00061 * name and value of the attribute that will be removed.\ The attribute 00062 * value is guaranteed to be valid when the signal is emitted. 00063 */ 00064 SIGNAL_METHOD(DynamicObject, AttributeRemoved) 00065 00066 /** 00067 * Emitted just before the dynamic object is cleared.\ All existing 00068 * attribute values are guaranteed to be valid when the signal is emitted. 00069 */ 00070 SIGNAL_METHOD(DynamicObject, Cleared) 00071 00072 /** 00073 * Sets attributes from those of another dynamic object. 00074 * 00075 * This method parses the given object's attributes, adding them to or 00076 * setting them in this object. Any existing attributes that are not 00077 * contained in the given object are not removed. 00078 * 00079 * @param pObject 00080 * The object from which to set this object's attributes. 00081 * Cannot be \c NULL. 00082 * 00083 * @notify This method will notify Subject::signalModified once for each 00084 * attribute which gets merged. The parameters will depend on 00085 * the attribute modified. 00086 * 00087 * @see setAttribute() 00088 */ 00089 virtual void merge(const DynamicObject* pObject) = 0; 00090 00091 /** 00092 * Sets attributes from those of another dynamic object. 00093 * 00094 * This method parses the given object's attributes, adopting them into 00095 * the destination object. Any existing attributes that are not 00096 * contained in the given object are not removed. The attributes of 00097 * the given dynamic object will be modified in an undefined manner. 00098 * 00099 * This method is intended for use when the given object will be discarded 00100 * after being merged into the destination object and can be much faster 00101 * than using the merge() method which sets the attributes rather than 00102 * adopting them. 00103 * 00104 * @param pObject 00105 * The object from which to adopt into this object's attributes. 00106 * Cannot be \c NULL. 00107 * 00108 * @notify This method will notify Subject::signalModified once for each 00109 * attribute which gets adopted. The parameters will depend on 00110 * the attribute modified. 00111 * 00112 * @see adoptAttribute() 00113 */ 00114 virtual void adoptiveMerge(DynamicObject* pObject) = 0; 00115 00116 /** 00117 * Creates a new attribute or sets an existing dynamic attribute. 00118 * 00119 * This method is preferred to adoptAttribute() unless 00120 * you are passing an already constructed DataVariant in 00121 * which case, adoptAttribute() will be faster because 00122 * it avoids a deep copy. 00123 * 00124 * @param name 00125 * The name of the attribute to set the value. If an attribute 00126 * with the given name does not exist, an attribute is added. 00127 * @param value 00128 * The attribute's value. 00129 * 00130 * @return Returns \c true if the attributes was successfully created or set, 00131 * otherwise \c false. 00132 * 00133 * @notify This method will notify Subject::signalModified. 00134 * 00135 * @see adoptAttribute() 00136 */ 00137 template<class T> 00138 bool setAttribute(const std::string& name, const T& value) 00139 { 00140 DataVariant temp(value); 00141 return adoptAttribute(name, temp); 00142 } 00143 00144 /** 00145 * Creates a new attribute or sets an existing dynamic attribute. 00146 * 00147 * This method should not be used; generally setAttribute() is 00148 * preferred. This method and setAttribute() have identical 00149 * performance characteristics and setAttribute() is easier to 00150 * call. This method is faster than setAttribute() though if 00151 * you have an already constructed DataVariant and is 00152 * preferred to setAttribute() in this case. 00153 * 00154 * @param name 00155 * The name of the attribute to set the value. If an attribute 00156 * with the given name does not exist, an attribute is added. 00157 * @param value 00158 * A variant holding the attribute's value. On return, this will 00159 * contain the value previously stored in the DynamicObject. 00160 * If the value did not previously exist in the DynamicObject, 00161 * then this will contain an invalid DataVariant. 00162 * 00163 * @return Returns \c true if the attributes was successfully created or set, 00164 * otherwise \c false. 00165 * 00166 * @notify This method will notify Subject::signalModified. 00167 * 00168 * @see setAttribute() 00169 */ 00170 virtual bool adoptAttribute(const std::string& name, DataVariant& value) = 0; 00171 00172 /** 00173 * Sets the value within the DynamicObject hierarchy as described in the path. 00174 * 00175 * This method will create DynamicObjects as needed to set the value. 00176 * This method is preferred to adoptAttributeByPath() unless 00177 * you are passing an already constructed DataVariant in 00178 * which case, adoptAttributeByPath() will be faster because 00179 * it avoids a deep copy. 00180 * 00181 * @param path 00182 * The path of names within names for the DynamicObjects, 00183 * separated by '/'. A slash in the name can be represented by 00184 * escaping the slash with another slash (e.g. '//'). If the path 00185 * ends in a single slash, it will be ignored. 00186 * @param value 00187 * The value to set into the DynamicObject. 00188 * 00189 * @return Returns \c true if the operation was a success, \c false otherwise. 00190 * This method will fail if any object along the path already exists 00191 * but is not a DynamicObject. 00192 * 00193 * @notify This method will notify Subject::signalModified. 00194 * 00195 * @see adoptAttributeByPath() 00196 */ 00197 template<class T> 00198 bool setAttributeByPath(const std::string& path, const T& value) 00199 { 00200 DataVariant temp(value); 00201 return adoptAttributeByPath(path, temp); 00202 } 00203 00204 /** 00205 * Sets the value within the DynamicObject hierarchy as described in the path. 00206 * 00207 * This method should not be used; generally setAttributeByPath() is 00208 * preferred. This method and setAttributeByPath() have identical 00209 * performance characteristics and setAttributeByPath() is easier to 00210 * call. This method is faster than setAttributeByPath() though if 00211 * you have an already constructed DataVariant and is 00212 * preferred to setAttributeByPath() in this case. 00213 * 00214 * @param path 00215 * The path of names within names for the DynamicObjects, 00216 * separated by '/'. A slash in the name can be represented by 00217 * escaping the slash with another slash (e.g. '//'). If the path 00218 * ends in a single slash, it will be ignored. 00219 * @param value 00220 * The value to set into the DynamicObject. On return, this will 00221 * contain the value previously stored in the DynamicObject. If 00222 * the value did not previously exist in the DynamicObject, then 00223 * this will contain an invalid DataVariant. 00224 * 00225 * @return Returns \c true if the operation was a success, \c false otherwise. 00226 * This method will fail if any object along the path already exists 00227 * but is not a DynamicObject. 00228 * 00229 * @notify This method will notify Subject::signalModified. 00230 * 00231 * @see setAttributeByPath() 00232 */ 00233 virtual bool adoptAttributeByPath(const std::string& path, DataVariant& value) = 0; 00234 00235 /** 00236 * Sets the value within the DynamicObject hierarchy as described in the path. 00237 * 00238 * This method will create DynamicObjects as needed to set the value. 00239 * This method is preferred to adoptAttributeByPath() unless 00240 * you are passing an already constructed DataVariant in 00241 * which case, adoptAttributeByPath() will be faster because 00242 * it avoids a deep copy. 00243 * 00244 * @param pComponents 00245 * An array of path components to the desired object as std::strings. Must end with 00246 * END_METADATA_NAME. 00247 * 00248 * @param value 00249 * The value to set into the DynamicObject. 00250 * 00251 * @return Returns \c true if the operation was a success, \c false otherwise. 00252 * This method will fail if any object along the path already exists 00253 * but is not a DynamicObject. 00254 * 00255 * @notify This method will notify Subject::signalModified. 00256 * 00257 * @see adoptAttributeByPath() 00258 */ 00259 template<class T> 00260 bool setAttributeByPath(const std::string pComponents[], const T& value) 00261 { 00262 DataVariant temp(value); 00263 return adoptAttributeByPath(pComponents, temp); 00264 } 00265 00266 /** 00267 * Sets the value within the DynamicObject hierarchy as described in the path. 00268 * 00269 * This method should not be used; generally setAttributeByPath() is 00270 * preferred. This method and setAttributeByPath() have identical 00271 * performance characteristics and setAttributeByPath() is easier to 00272 * call. This method is faster than setAttributeByPath() though if 00273 * you have an already constructed DataVariant and is 00274 * preferred to setAttributeByPath() in this case. 00275 * 00276 * @param pComponents 00277 * An array of path components to the desired object as std::strings. Must end with 00278 * END_METADATA_NAME. 00279 * 00280 * @param value 00281 * The value to set into the DynamicObject. On return, this will contain the value previously stored in the DynamicObject. 00282 * If the value did not previously exist in the DynamicObject, then this will contain an invalid DataVariant. 00283 * 00284 * @return Returns \c true if the operation was a success, \c false otherwise. 00285 * This method will fail if any object along the path already exists 00286 * but is not a DynamicObject. 00287 * 00288 * @notify This method will notify Subject::signalModified. 00289 * 00290 * @see setAttributeByPath() 00291 */ 00292 virtual bool adoptAttributeByPath(const std::string pComponents[], DataVariant& value) = 0; 00293 00294 /** 00295 * Returns an attribute value. 00296 * 00297 * @param name 00298 * The name of the attribute for which to get the value. 00299 * 00300 * @return A variant holding the attributes value. The variant will be 00301 * invalid if the attribute did not exist. 00302 * 00303 * @see DataVariant::isValid() 00304 */ 00305 virtual const DataVariant& getAttribute(const std::string& name) const = 0; 00306 00307 /** 00308 * Returns an attribute value. 00309 * 00310 * @param name 00311 * The name of the attribute for which to get the value. 00312 * 00313 * @return A variant holding the attributes value. The variant will be 00314 * invalid if the attribute did not exist. 00315 * 00316 * @see DataVariant::isValid() 00317 */ 00318 virtual DataVariant& getAttribute(const std::string& name) = 0; 00319 00320 /** 00321 * Get the value within the DynamicObject hierarchy 00322 * as described in the path. 00323 * 00324 * @param path 00325 * The path of names within names for the DynamicObjects, 00326 * separated by '/'. A slash in the name can be represented by 00327 * escaping the slash with another slash (e.g. '//'). If the path 00328 * ends in a single slash, it will be ignored. 00329 * 00330 * @return A variant holding the attributes value. The variant will be 00331 * empty if the attribute did not exist. 00332 */ 00333 virtual const DataVariant& getAttributeByPath(const std::string& path) const = 0; 00334 00335 /** 00336 * Get the value within the DynamicObject hierarchy 00337 * as described in the path. 00338 * 00339 * @param path 00340 * The path of names within names for the DynamicObjects, 00341 * separated by '/'. A slash in the name can be represented by 00342 * escaping the slash with another slash (e.g. '//'). If the path 00343 * ends in a single slash, it will be ignored. 00344 * 00345 * @return A variant holding the attributes value. The variant will be 00346 * empty if the attribute did not exist. 00347 */ 00348 virtual DataVariant& getAttributeByPath(const std::string& path) = 0; 00349 00350 /** 00351 * Get the value within the DynamicObject hierarchy 00352 * as described in the path. 00353 * 00354 * @param pComponents 00355 * An array of path components to the desired object as std::strings. Must end with 00356 * END_METADATA_NAME. 00357 * 00358 * @return A variant holding the attributes value. The variant will be 00359 * empty if the attribute did not exist. 00360 */ 00361 virtual const DataVariant& getAttributeByPath(const std::string pComponents[]) const = 0; 00362 00363 /** 00364 * Get the value within the DynamicObject hierarchy 00365 * as described in the path. 00366 * 00367 * @param pComponents 00368 * An array of path components to the desired object as std::strings. Must end with 00369 * END_METADATA_NAME. 00370 * 00371 * @return A variant holding the attributes value. The variant will be 00372 * empty if the attribute did not exist. 00373 */ 00374 virtual DataVariant& getAttributeByPath(const std::string pComponents[]) = 0; 00375 00376 /** 00377 * Retrieves the names of all attributes in the object. 00378 * 00379 * @param attributeNames 00380 * A vector of strings that is populated with the attribute names. 00381 * 00382 * @see getNumAttributes() 00383 * @see getAttribute() 00384 */ 00385 virtual void getAttributeNames(std::vector<std::string>& attributeNames) const = 0; 00386 00387 /** 00388 * Retrieves the total number of attributes in the object. 00389 * 00390 * @return The number of attributes in the object. 00391 * 00392 * @see getAttributeNames() 00393 */ 00394 virtual unsigned int getNumAttributes() const = 0; 00395 00396 /** 00397 * Searches the object for an attribute with a given name and/or value. 00398 * 00399 * @warning This method only searches this object's attributes and not 00400 * any attributes of a child DynamicObject. 00401 * 00402 * @param name 00403 * The name of the attribute for which to search, which can be a 00404 * fixed string or any regular expression supported by QRegExp. If 00405 * \em name is empty, then the first attribute found with the given 00406 * value is returned. 00407 * @param value 00408 * The value of the attribute for which to search, which can be a 00409 * fixed string or any regular expression supported by QRegExp. If 00410 * \em value is empty, then the first attribute found with the given 00411 * name is returned. 00412 * 00413 * @return Returns a const reference to the first attribute found with the 00414 * given name and/or value. A const reference to an invalid value 00415 * is returned if both \em name and \em value are empty, or if this 00416 * object does not have an attribute with the given name and/or 00417 * value. 00418 * 00419 * @see findFirstOf(const QRegExp&, const QRegExp&) 00420 */ 00421 virtual const DataVariant& findFirstOf(const QRegExp& name, const QRegExp& value) const = 0; 00422 00423 /** 00424 * Searches the object for an attribute with a given name and/or value. 00425 * 00426 * @warning This method only searches this object's attributes and not 00427 * any attributes of a child DynamicObject. 00428 * 00429 * @param name 00430 * The name of the attribute for which to search, which can be a 00431 * fixed string or any regular expression supported by QRegExp. If 00432 * \em name is empty, then the first attribute found with the given 00433 * value is returned. 00434 * @param value 00435 * The value of the attribute for which to search, which can be a 00436 * fixed string or any regular expression supported by QRegExp. If 00437 * \em value is empty, then the first attribute found with the given 00438 * name is returned. 00439 * 00440 * @return Returns a non-const reference to the first attribute found with 00441 * the given name and/or value. A non-const reference to an invalid 00442 * value is returned if both \em name and \em value are empty, or if 00443 * this object does not have an attribute with the given name and/or 00444 * value. 00445 * 00446 * @see findFirstOf(const QRegExp&, const QRegExp&) const 00447 */ 00448 virtual DataVariant& findFirstOf(const QRegExp& name, const QRegExp& value) = 0; 00449 00450 /** 00451 * Removes an attribute from the object. 00452 * 00453 * @param name 00454 * The name of the attribute to remove. 00455 * 00456 * @return Returns \c true if the attribute was was successfully removed from the object, 00457 * otherwise \c false. 00458 * 00459 * @notify This method will notify Subject::signalModified. 00460 * 00461 * @see clear() 00462 */ 00463 virtual bool removeAttribute(const std::string& name) = 0; 00464 00465 /** 00466 * Removes an attribute from the object. 00467 * 00468 * @param pComponents 00469 * An array of path components to the desired object as std::strings. Must end with 00470 * END_METADATA_NAME. 00471 * 00472 * @return Returns \c true if the attribute was was successfully removed from the object, 00473 * otherwise \c false. 00474 * 00475 * @notify This method will notify Subject::signalModified. 00476 * 00477 * @see clear() 00478 */ 00479 virtual bool removeAttributeByPath(const std::string pComponents[]) = 0; 00480 00481 /** 00482 * Removes an attribute from the object. 00483 * 00484 * @param path 00485 * The path of names within names for the DynamicObjects, 00486 * separated by '/'. A slash in the name can be represented by 00487 * escaping the slash with another slash (e.g. '//'). If the path 00488 * ends in a single slash, it will be ignored. 00489 * 00490 * @return Returns \c true if the attribute was was successfully removed from the object, 00491 * otherwise \c false. 00492 * 00493 * @notify This method will notify Subject::signalModified. 00494 * 00495 * @see clear() 00496 */ 00497 virtual bool removeAttributeByPath(const std::string& path) = 0; 00498 00499 /** 00500 * Compares all attributes in this DynamicObject with those of another 00501 * DynamicObject. 00502 * 00503 * @warning Based on the number of attributes present in the DynamicObject, 00504 * calling this method could be time intensive. 00505 * 00506 * @param pObject 00507 * The DynamicObject with which to compare attributes in this 00508 * DynamicObject. This method does nothing and returns \c false if 00509 * \c NULL is passed in. 00510 * 00511 * @return Returns \c true if all attributes in \em pObject are present and 00512 * have the same values as the attributes in this DynamicObject; 00513 * otherwise returns \c false. 00514 */ 00515 virtual bool compare(const DynamicObject* pObject) const = 0; 00516 00517 /** 00518 * Erases all attributes in the object. 00519 * 00520 * @notify This method will notify Subject::signalModified. 00521 * 00522 * @see remove() 00523 */ 00524 virtual void clear() = 0; 00525 00526 protected: 00527 /** 00528 * This should be destroyed by calling ObjectFactory::destroyObject. 00529 */ 00530 virtual ~DynamicObject() {} 00531 }; 00532 00533 /** 00534 * \cond INTERNAL 00535 * These template specialization are required to allow these types to be put into a DataVariant. 00536 */ 00537 template <> class VariantTypeValidator<DynamicObject> {}; 00538 template <> class VariantTypeValidator<const DynamicObject> {}; 00539 /// \endcond 00540 00541 #endif // DYNAMICOBJECT_H