[Debian-astro-commits] [gyoto] 136/221: Document Object class

Thibaut Jean-Claude Paumard thibaut at moszumanska.debian.org
Fri May 22 20:52:40 UTC 2015


This is an automated email from the git hooks/post-receive script.

thibaut pushed a commit to branch master
in repository gyoto.

commit bca056121fdfa7d741fa2ef84fc8a61c1c63dda8
Author: Thibaut Paumard <paumard at users.sourceforge.net>
Date:   Tue Dec 9 14:27:56 2014 +0100

    Document Object class
---
 doc/doxyfile.in       |   6 +-
 include/GyotoObject.h | 239 +++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 211 insertions(+), 34 deletions(-)

diff --git a/doc/doxyfile.in b/doc/doxyfile.in
index 3860d5f..abe596a 100644
--- a/doc/doxyfile.in
+++ b/doc/doxyfile.in
@@ -1210,13 +1210,13 @@ ENABLE_PREPROCESSING   = YES
 # compilation will be performed. Macro expansion can be done in a controlled 
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
-MACRO_EXPANSION        = NO
+MACRO_EXPANSION        = YES
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
 # PREDEFINED and EXPAND_AS_DEFINED tags.
 
-EXPAND_ONLY_PREDEF     = NO
+EXPAND_ONLY_PREDEF     = YES
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
@@ -1251,7 +1251,7 @@ PREDEFINED             = DOXYGEN_RUN
 # The macro definition that is found in the sources will be used. 
 # Use the PREDEFINED tag if you want to use a different macro definition.
 
-EXPAND_AS_DEFINED      = 
+EXPAND_AS_DEFINED      = GYOTO_OBJECT
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
 # doxygen's preprocessor will remove all function-like macros that are alone 
diff --git a/include/GyotoObject.h b/include/GyotoObject.h
index fec7ff9..02c3f31 100644
--- a/include/GyotoObject.h
+++ b/include/GyotoObject.h
@@ -1,6 +1,6 @@
 /**
  * \file GyotoObject.h
- * \brief Introspectbale objects 
+ * \brief Introspectable objects 
  */
 
 /*
@@ -38,48 +38,177 @@ namespace Gyoto {
 }
 
 /// Declare  class::properties and class::getProperties()
+/**
+ * Any derived class that does define Properties (i.e. the macro
+ * GYOTO_PROPERTY_START() is called somewhere in the .C file) must
+ * call the GYOTO_OBJECT macro in a "public:" section of the class
+ * declaration. Else, the property list is inherited from the direct
+ * parent, and calling GYOTO_PROPERTY_START() in the .C file leads to
+ * a compile-time error.
+ */
 #define GYOTO_OBJECT \
   static Property const  properties[];		\
   virtual Property const * getProperties() const
 
+/// Object with properties
 /**
- * \brief Object with properties
+ * The Object API allows declaring a list of Properties that can be
+ * set and retrieved using a common, text-based interface. This
+ * interface simplifies a lot how to read and write XML, as well as
+ * writing bindings for interpreted langages (e.g. the Yorick
+ * interface).
+ *
+ * In fact, any class member that has an interface implemented as a
+ * Property can be readily read and written from/to XML as well as
+ * from the Yorick plug-in, without the need for any additional code.
+ *
+ * To declare a Property list:
+ *   1. declare (in the class declaration, .h file) and define (.C
+ *      file) the pair or quadruplet of accessors for your Property
+ *      (see Property class documentation;
+ *   2. call the GYOTO_OBJECT macro in in a public section of the
+ *      class declaration (in the .h file):
+ *      \code
+ *      class A: public Object {
+ *        public:
+ *          GYOTO_OBJECT;
+ *          A();
+ *          virtual ~A();
+ *        ...
+ *      };
+ *      \endcode
+ *   3. call the various GYOTO_PROPERTY_* macros in the corresponding
+ *      .C file (see the documentation of the Property class).
+ *
+ * It is possible to get a Property by name (Assume \a A is a class
+ * deriving from Object):
+ * \code
+ * A myobj();
+ * Property const *prop=NULL;
+ * prop = myobj.property("PropertyName");
+ * if (!prop) throwError("No Property by that name in this object");
+ * \endcode
+ * It then becomes possible to set or get the Property from or to a
+ * Value:
+ * \code
+ * myobj.set(*prop, size_t(12));
+ * size_t val = myobj.get(*prop);
+ * \endcode
+ * Of course the type of the Value instance and of the Property
+ * instance must match. Refer to the documentation of these to classes
+ * for details.
+ * 
  */
 class Gyoto::Object
 {
  protected:
+  /// The "kind" that is output in the XML entity
+  /**
+   * E.g. for an Astrobj, fillElement() will ensure
+   * \code
+   *   <Astrobj kind="kind_">...</Astrobj>
+   * \endcode
+   * is written.
+   */
   std::string kind_;
  public:
   GYOTO_OBJECT;
+
+  /// Constructor setting kind
   Object (std::string const &kind) ;
+
+  /// Default constructor
   Object () ;
+
+  /// Deep copy constructor
   Object (Object const &orig) ;
+
+  /// Virtual destructor
   virtual ~Object();
+
+  /// Set Value of a Property
   void set(Property const &p, Value val);
+
+  /// Set Value (expressed in unit) of a Property
   void set(Property const &p, Value val, std::string const &unit);
 
+  /// Get Value of a Property
   Value get(Property const &p) const;
+
+  /// Get Value of a Property, converted to unit
   Value get(Property const &p, std::string const &unit) const;
 
+  /// Find property by name
+  /**
+   * Look into the Property list for a Property whose \a name (or
+   * \a name_false, for a boolean Property) is \a pname. Return a const
+   * pointer to the first such property found, or NULL if none is
+   * found.
+   */
   Property const * property(std::string const pname) const;
 
 #ifdef GYOTO_USE_XERCES
-  virtual void fillProperty(Gyoto::FactoryMessenger *fmp, Property const &p) const ;
+  /// Output a single Property to XML
+  /**
+   * The base implementation decides what to do based on the \a
+   * p.type. The format matches how setParameters() an setParameter()
+   * would interpret the XML descition.
+   *
+   * Overriding this method should be avoided, but makes sense in some
+   * cases (for instance Screen::fillProperty() selects a different
+   * unit for \a Distance based on its magnitude, so that stellar
+   * sizes are expressed in solar radii while smaller sizes can be
+   * expressed in meters and larger sizes in parsecs).
+   *
+   * Overriding implementation should fall-back on calling the
+   * implementation in the direct parent class:
+   * \code
+   * class A: public Object {};
+   * class B: public A { 
+   *  using B::setParameter;
+   *  virtual void fillProperty(Gyoto::FactoryMessenger *fmp,
+   *     			Property const &p) const ;
+   * };
+   * void B::fillProperty(Gyoto::FactoryMessenger *fmp,
+   *     			Property const &p) const {
+   *   if (name=="Duff") fmp->doSomething();
+   *   else A::fillProperty(fmp, p);
+   * }
+   * \endcode
+   */
+  virtual void fillProperty(Gyoto::FactoryMessenger *fmp,
+			    Property const &p) const ;
 
-  /// Called from Factory
+  /// Fill the XML element for this Object
   /**
-   * Object implementations should impement fillElement to save their
-   * parameters to XML and call the Metric::fillElement(fmp) for the
-   * shared properties
+   * The base implementation simply calls fillProperty() for each
+   * Property defined for the Object.
+   *
+   * Derived classes should avoid overriding fillElement(). It may
+   * make sense occasionally, e.g. to make sure that the metric is
+   * output first.
+   * 
+   * To customize how a given Property is rendered, it is better to
+   * override fillProperty().
+   *
+   * If this method is overriden, the implementation should in general
+   * call fillElement() on the direct base.
    */
   virtual void fillElement(Gyoto::FactoryMessenger *fmp) const ;
 
+  
+  /// \brief Main loop for parsing Properties from XML description
   /**
-   * \brief Main loop in Subcontractor_t function
+   * This function queries the FactoryMessenger for elements to parse,
+   * and tries to matche each element to a Property to set it
+   * accordingly.
+   *
+   * Any class that tries to be buildable from XML must supply a
+   * subcontractor (for base classes such as Metric, Astrobj, Spectrum
+   * and Spectrometer, it is done as a template that must be
+   * specialized for each class).
    *
-   * The Subcontractor_t function for each Metric kind should look
-   * somewhat like this (templated as
-   * Gyoto::Metric::Subcontractor<MyKind>):
+   * This subcontractor typically looks somewhat like this:
 \code
 SmartPointer<Metric::Generic>
 Gyoto::Metric::MyKind::Subcontractor(FactoryMessenger* fmp) {
@@ -89,32 +218,48 @@ Gyoto::Metric::MyKind::Subcontractor(FactoryMessenger* fmp) {
 }
 \endcode
    *
-   * Each metric kind should implement setParameter(string name,
-   * string content, string unit) to interpret the individual XML
-   * elements. setParameters() can be overloaded in case the specific
-   * Metric class needs low level access to the FactoryMessenger. See
-   * Gyoto::Astrobj::UniformSphere::setParameters().
+   * Although this is discouraged, it is possible to override the
+   * following functions to customize how XML entities are parsed:
+   *   - setParameters() if low-level access to the
+   *     FactoryMessenger is required;
+   *   - setParameter(std::string name,
+   *		      std::string content,
+   *		      std::string unit)
+   *     to interpret an entity that does not match a Property
+   *     (e.g. alternative name);
+   *   - setParameter(Gyoto::Property const &p,
+   *		      std::string const &name,
+   *		      std::string const &content,
+   *		      std::string const &unit)
+   *     to change how a Property is interpreted.
    */
   virtual void setParameters(Gyoto::FactoryMessenger *fmp) ;
 #endif
   /**
    * \brief Set parameter by name
    *
-   * Assume MyKind is a subclass of Metric::Generic which has two
-   * members (a string StringMember and a double DoubleMember):
-\code
-int MyKind::setParameter(std::string name, std::string content, std::string unit) {
- if      (name=="StringMember") setStringMember(content);
- else if (name=="DoubleMember") setDoubleMemeber(atof(content.c_str()), unit);
- else return Generic::setParameter(name, content, unit);
- return 0;
-}
-\endcode
-   * If MyKind is not a direct subclass of Generic, it should call the
-   * corresponding setParameter() implementation instead of
-   * Generic::setParameter().
+   * This function is used when parsing an XML description, if no
+   * Property of this \a name is found. Overriding implementation should
+   * fall-back on calling the direct's parent implementation:
+   *
+   * \code
+   * class A: public Object {};
+   * class B: public A { 
+   *  using B::setParameter;
+   *  virtual int setParameter(std::string name,
+   *			    std::string content,
+   *			    std::string unit);
+   * };
+   * int B::setParameter(std::string name,
+   *			    std::string content,
+   *			    std::string unit) {
+   *   if (name=="Duff") doSomething(content, unit);
+   *   else return A::setParameter(name, content, unit);
+   *   return 0;  // name was known
+   * }
+   * \endcode
    *
-   * \param name XML name of the parameter
+   * \param name XML name of the parameter (XML entity)
    * \param content string representation of the value
    * \param unit string representation of the unit
    * \return 0 if this parameter is known, 1 if it is not.
@@ -123,7 +268,39 @@ int MyKind::setParameter(std::string name, std::string content, std::string unit
 			    std::string content,
 			    std::string unit);
 
-  virtual void setParameter(Gyoto::Property const &p,
+  /**
+   * \brief Set parameter by Property (and name)
+   *
+   * This function is used when parsing an XML description, if
+   * Property (\a p) of this \a name is found (i.e. either \a p.name or
+   * \a p.name_false is equal to \a name). Implementation should fall-back
+   * on calling the direct's parent implementation:
+   *
+   * \code
+   * class A: public Object {};
+   * class B: public A { 
+   *  using B::setParameter;
+   *  virtual void setParameter(Gyoto::Property const &p,
+   *                            std::string name,
+   *			        std::string content,
+   *			        std::string unit);
+   * };
+   * void B::setParameter(Gyoto::Property const &p,
+   *  			  std::string name,
+   *			  std::string content,
+   *			  std::string unit) {
+   *   if (name=="Duff") doSomething(content, unit);
+   *   else A::setParameter(p, name, content, unit);
+   * }
+   * \endcode
+   *
+   * \param p Property that matches \a name (\a p.name == \a name or
+   *            \a p.name_false == \a name)
+   * \param name XML name of the parameter (XML entity)
+   * \param content string representation of the value
+   * \param unit string representation of the unit
+   */
+   virtual void setParameter(Gyoto::Property const &p,
 			    std::string const &name,
 			    std::string const &content,
 			    std::string const &unit);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-astro/packages/gyoto.git



More information about the Debian-astro-commits mailing list