/** @page libsbml-howto-implement-extension.html How to implement a package extension

This section describes the summary of how to implement a package extension for libSBML-5.
(Note that since libSBML-5 is currently in development stage the API described in this
documentation may be changed in the future.)

<tr><td>
<ol>
<li>
<a href="#i1">Implement an SBMLExtension derived class</a>
</li>
<li>
<a href="#i2">Implement SBase derived classes of the package extension</a>
</li>
<li>
<a href="#i3">Implement SBasePlugin derived classes</a>
</li>
<li>
<a href="#i4">Implement a forward declaration file</a>
</li>
<li>
<a href="#i5">Implement a header file which includes all SBML types defined in the extension</a>
</li>
<li>
<a href="#i6">Defines a macro value of the package extension</a>
</li>
<li>
<a href="#i7">How to import a source tree of a package extension into the source tree of libSBML-5</a>
</li>
</ol>
</td>
</tr>


<h2><a class="anchor" name="i1">1. Implement an SBMLExtension derived class</a></h2>

Firstly, an SBMLExtension derived class for your package needs to be implemented 
based on the steps described in SBMLExtension class.


<h2><a class="anchor" name="i2">2. Implement SBase derived classes of the package extension</a></h2>

  Secondly, SBase derived classes for your package need to be implemented
  based on the following steps:
  
  <h3><a class="anchor" name="i2-1">2-1. Identify elements defined in the package extension</a></h3>
  
  <p>
     For example, the following elements are defined in the groups package:
  </p>
  
  <ol>
   <li> Group
   <li> Member
   <li> ListOfMembers
  </ol>
  
  
  <h3><a class="anchor" name="i2-2">2-2. Identify which subelements and/or attributes are defined in each element</a></h3>
  
  <p>
     For example, the following subelements and attributes are defined in 
     the Group element in the groups package.
  </p>   
  
  <ul>
   <li> <p>subelements</p>
        <ol>
         <li> ListOfMembers  mMembers  ('listOfMembers' element)
        </ol>
   <li> <p>attributes</p>
        <ol>
         <li> std::string         mId  ('id'   attribute)
         <li> std::string       mName  ('name' attribute) 
        </ol>
  </ul>

  <h3><a class="anchor" name="i2-3">2-3. Implement each SBase derived class</a></h3>

  <h4><a class="anchor" name="i2-3-1">2-3-1. Define protected data members that store identified subelements and/or attributes </a></h4>

  <p>
       For example, the following protected data members are defined in
       Group class ('src/packages/groups/sbml/Group.h'):
  </p>
@verbatim
          class LIBSBML_EXTERN Group : public SBase
          {
          protected:
            std::string   mId;
            std::string   mName;
            ListOfMembers mMembers;

            ....
                             
          };    
@endverbatim

  <p>
     Basically, the attribute data will have one of the types "std::string", 
     "double", "int", or "bool", and the type of the element data will be 
     ListOf derived classes or SBase derived classes.

     The data members must be properly initialized in the constructor, and must 
     be properly copied in the copy constructor and assignment operator.
  </p>

  <h4><a class="anchor" name="i2-3-2">2-3-2. Define the following two constructors</a></h4>

<ol>
  <li> <p> a constructor that accepts three arguments: </p>
    <ol>
      <li>SBML Level</li>
      <li>SBML Version</li>
      <li>Package Version</li>
    </ol>     

  <p>
     For example, this type of constructor of Group class is implemented 
     in 'src/packages/groups/sbml/Group.cpp' as follows:
  </p>     

@verbatim
               Group::Group (unsigned int level, unsigned int version, 
                             unsigned int pkgVersion)
                 : SBase (level,version)   // <-- invokes parent's constructor
                  ,mId("")
                  ,mName("")
                  ,mMembers(level,version,pkgVersion)
               {
                 // set an SBMLNamespaces derived object (GroupsPkgNamespaces) of 
                 //this package.
                 setSBMLNamespacesAndOwn(new GroupsPkgNamespaces(level,version,
                                                                 pkgVersion));
                  
                 // connects child elements to this element.
                 connectToChild(); 
               }
@endverbatim

   <p><em>NOTE</em></p>
   <ul>
      <li>
             default level, default version, and default pacakge version
             should be given as default arguments.
             (This may change in the future release).

      <li>  the corresponding constructor of the parent class must be properly 
            invoked by using initializer of the constructor.
         
      <li>  setSBMLNamespacesAndOwn() function must be invoked with a newly
	    created SBMLNamespaces derived object with the given level, version,
            and package version.

      <li>  connectToChild() function must be invoked if the element has one
            or more child elements.
    </ul>	       

    <p>
           For example, an instance of the SBase derived object is created by this
           constructor as follows:
    </p>

@verbatim   
               Layout layout(3,1,1);
@endverbatim

   <li><p> a constructor that accepts an SBMLNamespaces derived object </p>

     <p>
           For example, this type of constructor of Group class is implemented 
           in 'src/packages/groups/sbml/Group.cpp' as follows:
           (GroupsPkgNamespaces is the type of SBMLNamespaces derived class for
            groups package)
     </p>

@verbatim
               Group::Group(GroupsPkgNamespaces* groupsns)
                : SBase(groupsns)
                 ,mId("")
                 ,mName("")
                 ,mMembers(groupsns)
               {
                 // set the element namespace of this object
                 setElementNamespace(groupsns->getURI());

                 // connect child elements to this element
                 connectToChild();

                 // load pacakge extensions bound with this object (if any)
                 loadPlugins(groupsns);
               }
@endverbatim

   <p><em>NOTE</em></p>
   <ul>
      <li>
             SBMLNamespaces and its derived class throws an SBMLExtensionException
             if the given combination is invalid (undefined).

      <li>
             the corresponding constructor of the parent class must be properly 
             invoked by initializer.
         
      <li>
             setElementNamespace() function must be invoked with the URI
             of the package in the constructor.

      <li>
             connectToChild() function must be invoked if the element has one
             or more child elements.

      <li>
             loadPlugins() function should be invoked if the element can be
             extended by other package extensions.
   </ul>

   <p>
           For example, an instance of the SBase derived object is created by 
           this constructor as follows:
   </p>
   
@verbatim   
               try
               {
                 LayputPkgNamespaces layoutns(3,1,1);
                 Layout              layout(&layoutns); 
               }
               catch (SBMLExtensionException e)
               {
                 cerr << "Caught " << e.what() << endl;
               }
@endverbatim

  </ol> 


  <p>
       <em>NOTE</em>
 
       In the layout extension, additional constructors that accept one or more 
       attributes of the element have been implemented for backward compatibility
       (support for L2 model).
       (validation check of the given arguments of attributes are not performed.)
  </p>



  <h4><a class="anchor" name="i2-3-3">2-3-3. Override the following functions in the SBase class</a></h4>
    <ul>
      <li>
          Copy Constructor
      <li>
          Assignment operator (operator=)
      <li>
          clone() function
          (basically implemented by using the copy constructor)
    </ul>

  <h4><a class="anchor" name="i2-3-4">2-3-4. Override the following virtual functions if one or more attributes (except for those defined in its ancestors) are defined in this element
</a></h4>

    <ul>
      <li>
          addExpectedAttributes()
      <li>	  
          readAttributes()
      <li>	  
          hasRequiredAttributes()
    </ul>	  

    <p>
          <em>NOTE</em>

	  <ul>
	    <li>
	      <p>
                corresponding function of the parent class must be invoked
	        in  addExpectedAttributes() and readAttributes() functions
                as follows:
	      </p>
	      
@verbatim
                Group::addExpectedAttributes(ExpectedAttributes& attributes)
                {
                   SBase::addExpectedAttributes(attributes);
                   ....
                }
@endverbatim

@verbatim
               void
               Group::readAttributes (const XMLAttributes& attributes,
                                      const ExpectedAttributes& expectedAttributes)
               {
                 SBase::readAttributes(attributes,expectedAttributes);
                  ...
               }
@endverbatim
         
                (SBase class is a parent of Group class.)


            <li>
	      <p>
	      the following attributes don't need to be added in 
              the addExpectedAttributes() function because they are added
              in SBase::addExpectedAttributes() function.
	      </p>
	      
	      <ol>
                <li>metaid  (L2V1 or later)
                <li>sboTerm (L2V3 or later)
	      </ol>


            <li> "src/packages/groups/sbml/{Group,Member}.{h,cpp}" are simple example
                 files in which these functions are implemented.
          </ul> 		 


  <h4><a class="anchor" name="i2-3-5">2.3.5. Override the following virtual functions if one or more subelements are defined in this element</a></h4>
    <ul>
          <li> createObject()

          <li> writeElements()

          <li> hasRequiredElements()

          <li> setSBMLDocument()

          <li> enablePackageInternal()
	   
          <li> connectToChild()
    </ul>	  


      <p><em>NOTE</em></p>
      <ul>          

            <li> corresponding function of the parent class must be invoked
	         in writeElements(), setSBMLDocument(), and enablePackageInternal()
                 functions

            <li> "src/packages/groups/sbml/{Group,Member}.{h,cpp}" are simple example
                 files in which these functions are implemented.

      </ul>          


  <h4><a class="anchor" name="i2-3-6">2.3.6. Override the following virtual functions if the element is a top-level element of the package</a></h4>

  <ul>
      <li>writeXMLNS()
  </ul>      
      
	  <p><em>NOTE</em></p> 

	  <p>
           For example, this function is implemented in the following top-level
              elements:
	  </p>

	  <ol>
             <li> SBMLDocument   (SBML Core)
             <li> ListOfLayouts  (Layout extension)
             <li> ListOfGroups   (Groups extension)
	  </ol>



	  <ul>
            <li> In package extensions, writeXMLNS() function writes an xmlns="..."
                 attribute if the top-level element of the package extension 
                 belongs to default XML namespace.
                 This behaviour can be enabled/disabled by the following function:
@verbatim
    SBMLDocument::enableDefaultNS(const std::string& package, bool flag)
@endverbatim
	  </ul>


  <h4><a class="anchor" name="i2-3-7">2.3.7. Override the following virtual functions if 'id' attribute is defined in the element</a></h4>

      <ol>
           <li> setId()

           <li> getId()

           <li> isSetId()

           <li> unsetId()
      </ol>


	  <p><em>NOTE</em></p> 

      <ul>	  
           <li> Basically, implementation of these functions are almost the same
                between elements defining the 'id' attribute

           </li> setId() function can be easily implemented as follows (one line):
      </ul>	  

@verbatim
                 return SyntaxChecker::checkAndSetSId(id,mId);
@endverbatim

  <h4><a class="anchor" name="i2-3-8">2.3.8. Override the following virtual functions if 'name' attribute is defined in the element</a></h4>

    <ol>
          <li> setName()

          <li> getName()

          <li> isSetName()

          <li> unsetName()
    </ol>
    

	  <p><em>NOTE</em></p> 

      <ul>
           <li> Basically, implementation of these functions are almost the same
                between elements defining the 'id' attribute
      </ul>


  <h4><a class="anchor" name="i2-3-9">2.3.9. Add function calls of loadPlugins() in the constructor which accepts an SBMLNamespaces derived class for supporting package extensions.</a></h4>

    <p>
          loadPlugins() doesn't need to be invoked in an abstract class.
    </p>

  <h4><a class="anchor" name="i2-3-10">2.3.10. Add function calls of connectToChild() in constructor, copy constructor, and assignment operator.</a></h4>

  <h4><a class="anchor" name="i2-3-11">2.3.11. Implement additional (package developer-defined) functions for manipulating the attributes and/or subelements.</a></h4>

    <p>
        For example, getMember(), addMember(), getNumMembers(), createMember(),
        removeMember() and etc. are implemented in Group class of the groups package.
    </p>

	  <p><em>NOTE</em></p> 

	  <ul>

           <li><p> when implementing setXXXX(const XXXX&) / addXXXX(const XXXX&) 
             functions that set/add the given SBase derived object, the following
             check should be done for the given object:
	     </p>

	     <ol>

	       <li> check if the given object is not NULL

               <li> check if the SBML Level, Version, and Package Version 
                    of the given object matches those of target element

               <li> check if an object with the id of the given object
                    already exists (i.e. checks an error of duplicated object id
	     </ol>

           <li> <p>one of status codes, which is defined in "src/common/operationReturnValues.h"
                should be returned based on the result of functions except for
	        getter functions and functions returning a bool value


           <li> <p>In setXXXX(const XXXX&) function,  connectToParent() function 
                must be invoked if the given object is valid.

               (for detail, please check existing implementation such as
                setKineticLaw() function in  "src/sbml/Reaction.cpp")

	  </ul>


  <h3><a class="anchor" name="i3">3. Implement SBasePlugin derived classes</a></h3>

  <p>
Thirdly, SBasePlugin derived classes for the pacakge needs to be implemented.

  <h4><a class="anchor" name="i3-1">3-1. Identify which core SBML elements (e.g. Model, Reaction,..) to be extended (i.e. adding attributes and/or elements) for your package extensions.</a></h4>
  <p>
    For example, the following SBML elementes are extended by groups and layout
    packages, respectively:
  </p>

  <ol>
      <li> groups package

        <ol>
          <li> SBMLDocument
	    <ul>
              <li> Add 'required' attribute
	    </ul>
          <li>  Model
	    <ul>
              <li> Add 'listOfGroups' element 
	    </ul>
        </ol>
      </li>

      <li> layout package
        <ol>
          <li> SBMLDocument
	    <ul>
              <li> Add 'required' attribute
	    </ul>

          <li> Model
	    <ul>
              <li> Add 'listOfLayouts' element 
	    </ul>

          <li> SpeciesReferences (only for L2V1 for backward compatibility)
	    <ul>
              <li> Add 'id' attribute
	    </ul>
        </ol>
      </li>
     
  </ol>

    <h4><a class="anchor" name="i3-2">3-2. Implement SBasePlugin derived objects for each identified core SBML element based on the following policy:</a></h4>

    <p>
       For example, to extend the identified classes, the following SBasePlugin 
       derived classes are newly implemnted in the groups and layout packages:
    </p>

    <ol>
          <li> groups

	    <ul>
              <li> LayoutModelPlugin 
              <li> LayoutSpeciesReferencesPlugin
	    </ul>
	    
          <li> groups
            <ul>	  
              <li> GroupsModelPlugin
            </ul>
    </ol>
    

         <p><em>NOTE</em></p>

	 <p>
	        Package developers can use existing SBMLDocumentPlugin class
                as-is for extending the SBMLDocument class if only 'required' 
                attribute is added the class in their packages, otherwise package 
                developers must implement a new SBMLDocumentPlugin derived class 
                for extending the SBMLDocument class.

                Since the both of groups and layout packages require only 
                'required' attribute for extending the SBMLDocument class, 
                the SBMLDocumentPlugin is used as-is for the packages.
	 </p>


    <h4><a class="anchor" name="i3-2-1">3-2-1. Define additional protected data members that store additional elements and/or attributes if one ore more elemnets and/or attributes are added to the target core element.</a></h4>

      <p>
         
         Basically, the attribute data will have one of the types "std::string", 
         "double", "int", or "bool", and the type of the element data will be 
         ListOf derived classes or SBase derived classes.
 
         The additional data members must be properly initialized in the constructor,
         and must be properly copied in the copy constructor and assignment operator.
      </p>

      <p>
         For example, the following data member is defined in the GroupsModelPlugin 
         class (in GroupsModelPlugin.h):
      </p>

@verbatim
             ListOfGroups mGroups;
@endverbatim

  <h4><a class="anchor" name="i3-2-2">3-2-2. Override the following functions in the SBasePlugin class</a></h4>

    <ul>
           <li> Constructor

	     <p>
                SBasePlugin(const std::string& uri, const std::string &prefix)
	     </p>

           <li> Copy Constructor

	     <p>
                SBasePlugin(const SBasePlugin&)
	     </p>

           <li> Assignment operator 

           <li> clone() function
	     <p>
                Basically, clone() function is implemented by using the copy constructor.
	     </p>
    </ul>


          <p><em>NOTE</em></p>

	  <p>
	  'src/extension/SBMLDocumentPlugin.{h,cpp} is a simple example
           files in which these functions are implemented.
	   </p>

  <h4><a class="anchor" name="i3-2-3">3-2-3. Override the following virtual functions if one or more attributes are added to the target core element</a></h4>

    <ul>
        <li> addExpectedAttributes()
        <li> readAttributes()
        <li> hasRequiredAttributes()
    </ul>

  <h4><a class="anchor" name="i3-2-4">3-2-4. Override the following virtual functions if one or more top-level elements are added to the target core element</a></h4>    

    <ul>
      <li> createObject()
      <li> writeElements()
      <li> hasRequiredElements()
      <li> setSBMLDocument()
      <li> connectToParent() 
      <li> enablePackageInternal()
    </ul>


        <p><em>NOTE</em></p>
	<p>
	'src/packages/groups/extension/GroupsModelPlugin.{h,cpp}' and
        'src/packages/layout/extension/LayoutModelPlugin.{h,cpp}'
         are example files in which the functions are implemented.
	</p>

  <h4><a class="anchor" name="i3-2-5">3-2-5. The following virtual functions must be overridden if one or more additional xmlns attributes need to be added to the target element</a></h4>

    <ul>
      <li> writeXMLNS() </li>
    </ul>          
      

	  <p><em>NOTE</em></p>
	  <p>
          Currently, no example files implementing this function
	  </p>

  <h4><a class="anchor" name="i3-2-6">3-2-6. Implement additional (package developer-defined) functions for manipulating the additional attributes and/or top-level elements</a></h4>

    <p>
          For example, the following manipulation functions are implemented in 
          LayoutModelPlugin class (a class for the extension of the model element 
          in layout package) for manipulating the additional &lt;listOfLayouts&gt; element
          in the list element:
    </p>

    <ol>
              <li>const ListOfLayouts* getListOfLayouts() const
	      </li>
              <li>ListOfLayouts*       getListOfLayouts()
	      </li>
              <li>Layout*              getLayout(unsigned int index)
	      </li>
              <li>Layout*              getLayout(const std::string &sid)
	      </li>
              <li>int                  addLayout(const Layout* layout)
	      </li>
              <li>Layout*              createLayout()
	      </li>
              <li>Layout*              removeLayout(unsigned int n)
	      </li>
              <li>int                  getNumLayouts() const
	      </li>
    </ol>

    <p>
          Similarly, the following manipulation functions are implemented in 
          GroupsModelPlugin class (a class for the extension of the model element 
          in groups package) for manipulating the additional &lt;listOfGroups&gt; element
          in the list element:
    </p>

    <ol>
              <li> const ListOfGroups* getListOfGroups() const
	      </li>
              <li> ListOfGroups*       getListOfGroups()
	      </li>
              <li> Group*              getGroup(unsigned int index)
	      </li>
              <li> Group*              getGroup(const std::string &sid)
	      </li>
              <li> int                 addGroup(const Group* group)
	      </li>
              <li> Group*              createGroup()
	      </li>
              <li> Group*              removeGroup(unsigned int n)
	      </li>
              <li> int                 getNumGroups() const
	      </li>
    </ol>

<h2><a class="anchor" name="i4">4. Implement a forward declaration file</a></h2>    

<p>
A header file in which forward declarations for all classes defined in the
package extension should be implemented.
</p>

<p>
For example, please see "src/common/sbmlfwd.h" (forward declaration of SBML Core),  
"src/packages/groups/common/groupsfwd.h" (forward declaration of Groups package), 
and "src/packages/layout/common/layoutfwd.h" (forward declaration of Layout package)
</p>


<h2><a class="anchor" name="i5">5. Implement a header file which includes all SBML types defined in the extension</a></h2>    

<p>
A header file in which all SBML types defined in the extension should be implemented.
For example, please see "src/packages/groups/common/GroupsExtensionTypes.h" of the
groups extension and "src/packages/layout/common/LayoutExtensionTypes.h" of the
layout extension.
</p>

<h2><a class="anchor" name="i6">6. Defines a macro vaule of the package extension</a></h2>    

   <p><em>NOTE</em></p> 

   <p>
       A new package extension can be implemented and built outside the 
       source tree of libSBML. So, this step is not mandatory if you don't
       want to import your package extension into the source tree of libSBML.
   </p>

   <p>
USE_\%%PACKAGE_NAME%% macro variable needs to be defined in the following files:
   </p>

   <ol>
    <li> "src/common/libsbml-config-unix.h.in"
    <li> "src/common/libsbml-config-win.h"
   </ol>
   
   <p>
       (\%%PACKAGE_NAME%% is a place holder of the package name.
        For example, USE_LAYOUT is defined for the layout package.)
   </p>	


<h2><a class="anchor" name="i7">7. How to import a source tree of a package extension into the source tree of libSBML-5</a></h2>    

   <p><em>NOTE</em></p>

   <p>
   A new package extension can be implemented and built outside the 
   source tree of libSBML. So, this step is not mandatory if you don't 
   want to import your package extension into the source tree of libSBML.
   </p>	  

  <h3><a class="anchor" name="i7-1">7-1. Override the following virtual functions if one or more top-level elements are added to the target core element</a></h3>

    (The following example configuration is that of groups extension)

      <h4><a class="anchor" name="i7-1-1">7-1-1. configure.ac</a></h4>

      <ol>
        <li> Add --enable-XXXX 

@verbatim
          dnl -------------------------------------------------------
          dnl Groups extension
          dnl -------------------------------------------------------
  
          AC_ARG_ENABLE([groups],
          AC_HELP_STRING([--enable-groups@<:@=ARG@:>@],
                         [Build the SBML groups extension (default=no)]),
            [enable_groups=$enableval],
            [enable_groups=no])
  
          if test "$enable_group" != no; then
            AC_DEFINE([USE_GROUPS], 1, [Define to 1 to build the SBML groups extension.])
            AC_SUBST(USE_GROUPS, 1)
          fi
@endverbatim


        <li> Add AC_CONFIG_FILES for additional Makefile.in files


@verbatim
          AC_CONFIG_FILES([src/packages/groups/Makefile])
          AC_CONFIG_FILES([src/packages/groups/common/Makefile])
          AC_CONFIG_FILES([src/packages/groups/extension/Makefile])
          AC_CONFIG_FILES([src/packages/groups/sbml/Makefile])
@endverbatim

  
        <li> Add the code for noticing the enabled package

@verbatim
           if test "$enable_groups" != "no" ; then
             echo "  Using groups extension  = yes"
           fi
@endverbatim


        <li> Run a shell script "autogen.sh" in the top directory of the libsbml-5
             as follows (for updating configure script):

@verbatim
              % ./autogen.sh
@endverbatim
      </ol>

      <h4><a class="anchor" name="i7-1-2">7-1-2. src/packages/Makefile.in</a></h4>

        Add the name of package to 'subdirs' variable based on existing code.

  <h3><a class="anchor" name="i7-2">7-2. Create a directory tree of the package</a></h3>

      <h4><a class="anchor" name="i7-2-1">7-2-1. Create a top directory of the package in "src/packages/"</a></h4>

        <p>
        Currently, "src/packages/groups" (groups package) and 
        "src/packages/layout" (layout package) exist in the directory.
        </p>

      <h4><a class="anchor" name="i7-2-2">7-2-2. Create the following sub directories in the "src/packages/PKGNAME"</a></h4>

      <ol>

        <li> common

           <p>common header and/or class files (e.g. sbmlfwd.h) are located

        <li> extension

           <p>SBMLExtension and SBasePlugin derived classes of the package 
           extension are located

        <li> sbml

           <p>SBase derived classes of the package extension are located.

        <li> util (if needed)

           <p>Utility class files are located (e.g. LayoutAnnotation.{h,cpp} in
           layout package).

        <li> <p>other directories (if needed)

      </ol>

  <h3><a class="anchor" name="i7-3">7-3. Create Makefile.in in each sub directory based on existing 
  Makefile.in in layout or groups extensions
  </a></h3>

*/
