generateDoc.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include "generateDoc.h"
00028 
00029 #include <fstream>
00030 
00031 #include <sofa/core/ObjectFactory.h>
00032 #include <sofa/core/objectmodel/Context.h>
00033 #include <sofa/simulation/common/Colors.h>
00034 
00035 namespace projects
00036 {
00037 
00038 bool generateFactoryHTMLDoc(const std::string& filename)
00039 {
00040     //sofa::core::ObjectFactory::getInstance()->dump();
00041     std::ofstream ofile(filename.c_str());
00042     ofile << "<html><body>\n";
00043     sofa::core::ObjectFactory::getInstance()->dumpHTML(ofile);
00044     ofile << "</body></html>\n";
00045 
00046     return true;
00047 }
00048 
00049 static std::string xmlencode(const std::string& str)
00050 {
00051     std::string res;
00052     for (unsigned int i=0; i<str.length(); ++i)
00053     {
00054         switch(str[i])
00055         {
00056         case '<': res += "&lt;"; break;
00057         case '>': res += "&gt;"; break;
00058         case '&': res += "&amp;"; break;
00059         case '"': res += "&quot;"; break;
00060         case '\'': res += "&apos;"; break;
00061         default:  res += str[i];
00062         }
00063     }
00064     return res;
00065 }
00066 
00067 //bool generateClassPHPDoc(const std::string& filename, sofa::core::ObjectFactory::ClassEntry* entry)
00068 //{
00069 //    return true;
00070 //}
00071 
00072 static const char* baseClasses[] =
00073 {
00074 //"BaseNode",
00075 //"BaseObject",
00076 "BehaviorModel",
00077 "CollisionModel",
00078 "VisualModel",
00079 "Mapping",
00080 "MechanicalState",
00081 "MechanicalMapping",
00082 "MasterSolver",
00083 "OdeSolver",
00084 "Mass",
00085 "ForceField",
00086 "InteractionForceField",
00087 "Constraint",
00088 //"CollisionPipeline",
00089 "Topology",
00090 "ContextObject",
00091 NULL
00092 };
00093 
00094 #if 0
00095 class DummyObjectDescription : public sofa::core::objectmodel::BaseObjectDescription
00096 {
00097 protected:
00098     std::string name;
00099     AttributeMap attributes;
00100     sofa::core::objectmodel::BaseObjectDescription* parent;
00101 public:
00102     DummyObjectDescription()
00103     : name ("dummy")
00104     {
00105     parent = this;
00106     }
00107     
00109     virtual sofa::core::objectmodel::Base* getObject() { return NULL; }
00110     
00112     virtual const std::string& getName() const { return name; }
00113     
00115     virtual sofa::core::objectmodel::BaseObjectDescription* getParent() const { return parent; }
00116     
00118     virtual const AttributeMap& getAttributeMap() const { return attributes; }
00119     
00121     virtual sofa::core::objectmodel::BaseObjectDescription* find(const char* /*nodeName*/, bool /*absolute*/=false) { return this; }
00122     
00123     virtual std::string getFullName() { return name; }
00124     
00126     virtual sofa::core::objectmodel::Base* findObject(const char* /*nodeName*/) { return NULL; }
00127 
00128 };
00129 #endif
00130 
00131 bool generateFactoryPHPDoc(const std::string& filename, const std::string& url)
00132 {
00133     //sofa::core::ObjectFactory::getInstance()->dump();
00134     std::ofstream out(filename.c_str());
00135 
00136     out << "<html><body>\n";
00137 
00138     std::vector<std::string> templates;
00139     std::set<std::string> templateSet;
00140 
00141     sofa::core::ObjectFactory::ClassEntry* mobject = sofa::core::ObjectFactory::getInstance()->getEntry("MechanicalObject");
00142     if (mobject)
00143     {
00144             for (std::list< std::pair< std::string, sofa::core::ObjectFactory::Creator* > >::iterator itc = mobject->creatorList.begin(), itcend = mobject->creatorList.end(); itc != itcend; ++itc)
00145             {
00146         if (itc->first.length() < 10) // only put short templates
00147         {
00148             templates.push_back(itc->first);
00149             templateSet.insert(itc->first);
00150         }
00151         }
00152     }
00153 
00154     std::vector<sofa::core::ObjectFactory::ClassEntry*> classes;
00155     sofa::core::ObjectFactory::getInstance()->getAllEntries(classes);
00156 
00157     // re-order classes depending on namespaces
00158 
00159     std::map<std::string, std::vector<sofa::core::ObjectFactory::ClassEntry*> > sortedClasses;
00160     for (std::vector<sofa::core::ObjectFactory::ClassEntry*>::iterator it = classes.begin(), itend = classes.end(); it != itend; ++it)
00161     {
00162         sofa::core::ObjectFactory::ClassEntry* entry = *it;
00163     std::string nameSpace = sofa::core::objectmodel::Base::decodeNamespaceName(entry->creatorList.begin()->second->type());
00164     sortedClasses[nameSpace].push_back(entry);
00165     }
00166 
00167     out << "<?php $show=$_REQUEST['show']; ?>\n";
00168 
00169     out << "<?php $desc=$_REQUEST['desc']; ?>\n";
00170 
00171     out << "<?php $base=0; \n";
00172     for (const char** c = baseClasses; *c; ++c)
00173     out << " if ($show == '" << xmlencode(*c) << "') $base=1;\n";
00174     out << " if (!$show) $base=1; ?>\n";
00175 
00176     out << "<h1><?php if (!$base) echo 'Component : '.$show; else if ($show) echo 'Registered Components : '.$show; else echo 'Registered Components' ?></h1>\n";
00177 
00178     out << "<?php if ($base) { ?>";
00179 
00180     out << "<p> <b>Filter by Base Class :</b> ";
00181 
00182     out << "<?php if ($show) { echo '<a href=\""<<url<<"'.($desc?'?desc='.$desc:'').'\">'; ?>";
00183     out << "ALL";
00184     out << "<?php } if ($show) echo '</a>'; ?>";
00185     for (const char** c = baseClasses; *c; ++c)
00186     {
00187     out << " <span class=\"class-base-name\" style=\"background-color: " << sofa::simulation::Colors::getColor(*c) << ";\">";
00188     out << "<?php if ($show != '"<<xmlencode(*c)<<"') echo '<a href=\""<<url<<"?show="<<xmlencode(*c)<<"'.($desc?'&desc='.$desc:'').'\">'; ?>";
00189     out << *c;
00190     out << "<?php if ($show != '"<<xmlencode(*c)<<"') echo '</a>'; ?>";
00191     out << "</span>";
00192     }
00193     out << "</p>\n";
00194     out << "<p><?php if ($desc) echo '<a href=\""<<url<<"'.($show? ('?show='.$show) : '').'\">Hide Descriptions<a>'; else echo '<a href=\""<<url<<"'.($show? ('?show='.$show).'&desc=1' : '?desc=1').'\">Show Descriptions<a>'; ?></p>";
00195     out << "<?php } ?>";
00196 
00197     out << "<table class=\"sofa-classes\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n";
00198 
00199     int nbcol = 2 + templates.size() + 2;
00200 
00201     // header
00202     out << "<tr class=\"sofa-header\">";
00203     out << "<td class=\"sofa-base-header\">Base&nbsp;Class</td>";
00204     out << "<td class=\"sofa-name-header\">Class&nbsp;Name</td>";
00205     for (std::vector<std::string>::iterator itt = templates.begin(), ittend = templates.end(); itt != ittend; ++itt)
00206     out << "<td class=\"sofa-template-header\">"<<xmlencode(*itt)<<"</td>";
00207     out << "<td class=\"sofa-template-header\">Other</td>";
00208     out << "<td class=\"sofa-namespace-header\">Namespace</td>";
00209     out << "</tr>\n";
00210 
00211     for (std::map< std::string, std::vector<sofa::core::ObjectFactory::ClassEntry*> >::iterator it1 = sortedClasses.begin(), it1end = sortedClasses.end(); it1 != it1end; ++it1)
00212     for (std::vector<sofa::core::ObjectFactory::ClassEntry*>::iterator it = it1->second.begin(), itend = it1->second.end(); it != itend; ++it)
00213     {
00214         sofa::core::ObjectFactory::ClassEntry* entry = *it;
00215 
00216     out << "<?php if (!$show || $show=='"<<xmlencode(entry->className)<<"'";
00217     for (std::set<std::string>::iterator it = entry->baseClasses.begin(), itend = entry->baseClasses.end(); it != itend; ++it)
00218         if (entry->baseClasses.size()==1 || *it != "VisualModel") // VisualModel matters only if it is the only base class
00219         out << " || $show == '"<<xmlencode(*it)<<"'";
00220     out << ") { ?>\n";
00221 
00222 
00223     out << "<tr class=\"sofa-class\">";
00224     out << "<td class=\"sofa-base\" valign=\"top\">";
00225     for (std::set<std::string>::iterator it = entry->baseClasses.begin(), itend = entry->baseClasses.end(); it != itend; ++it)
00226         out << "<span class=\"class-base\" style=\"background-color: " << sofa::simulation::Colors::getColor((*it).c_str()) << ";\" alt=\"" << xmlencode(*it) << "\" title=\"" << xmlencode(*it) << "\">&nbsp;</span>";
00227     out << "</td>";
00228     
00229         out << "<td class=\"sofa-name\" valign=\"top\"><?php if ($base) echo '<a href=\""<<url<<"?show="<<xmlencode(entry->className)<<"'.($desc?'&desc='.$desc:'').'\" class=\"class-name\">'; else echo '<span class=\"class-name\">'; ?>" << xmlencode(entry->className) <<"<?php if ($base) echo '</a>'; else echo '</span>'; ?>\n";
00230         if (!entry->aliases.empty())
00231         {
00232             for (std::set<std::string>::iterator it = entry->aliases.begin(), itend = entry->aliases.end(); it != itend; ++it)
00233         out << "<br/><span class=\"class-alias\">" << xmlencode(*it) <<"</span>\n";
00234         }
00235     out << "</td>";
00236     
00237     for (std::vector<std::string>::iterator itt = templates.begin(), ittend = templates.end(); itt != ittend; ++itt)
00238     {
00239         out << "<td class=\"sofa-template\" align=\"center\" valign=\"top\">";
00240         if (entry->defaultTemplate == *itt)
00241 //      out << "<img src=\"images/classes/default-template.png\" alt=\""<<xmlencode(*itt)<<" (default)\" title=\""<<xmlencode(*itt)<<" (default)\" />";
00242             out << "<span class=\"class-template-default\" alt=\""<<xmlencode(*itt)<<" (default)\" title=\""<<xmlencode(*itt)<<" (default)\">*</span>";
00243         else if (entry->creatorMap.find(*itt)!=entry->creatorMap.end())
00244 //      out << "<img src=\"images/classes/template.png\" alt=\""<<xmlencode(*itt)<<"\" title=\""<<xmlencode(*itt)<<"\" />";
00245             out << "<span class=\"class-template\" alt=\""<<xmlencode(*itt)<<"\" title=\""<<xmlencode(*itt)<<"\">*</span>";
00246         else
00247             out << "<span class=\"class-no-template\">&nbsp;<span>";
00248         out << "</td>";
00249     }
00250     std::string others;
00251     for (std::list< std::pair< std::string, sofa::core::ObjectFactory::Creator* > >::iterator itc = entry->creatorList.begin(), itcend = entry->creatorList.end(); itc != itcend; ++itc)
00252     {
00253         if (!itc->first.empty() && templateSet.find(itc->first)==templateSet.end())
00254         {
00255         if (!others.empty())
00256             others += ", ";
00257         others += xmlencode(itc->first);
00258         if (itc->first == entry->defaultTemplate)
00259             others += " (default)";
00260         }
00261     }
00262     out << "<td class=\"sofa-template\" align=\"center\" valign=\"top\">";
00263     if (!others.empty())
00264 //      out << "<img src=\"images/classes/template.png\" alt=\"...\" title=\""<<others<<"\" />";
00265         out << "<span class=\"class-template-others\" alt=\""<<others<<"\" title=\""<<others<<"\">*</span>";
00266     else
00267         out << "<span class=\"class-no-template\">&nbsp;<span>";
00268     out << "</td>";
00269     std::string nameSpace = it1->first; //sofa::core::objectmodel::Base::decodeNamespaceName(entry->creatorList.begin()->second->type());
00270     out << "<td class=\"sofa-namespace\" valign=\"top\">";
00271     out << "<span class=\"class-namespace\">"<< xmlencode(nameSpace) <<"</span>";
00272     out << "</td>";
00273     out << "</tr>\n";
00274     if ((!entry->description.empty() && entry->description.substr(0,4)!="TODO") || !entry->authors.empty() || !entry->license.empty())
00275         out << "<?php if ($desc || !$base) { ?>";
00276     else
00277         out << "<?php if (!$base) { ?>";
00278     out << "<tr class=\"sofa-description\">";
00279     out << "<td>";
00280     out << "</td>";
00281     out << "<td class=\"sofa-description\" colspan=\""<< nbcol-1 <<"\" >";
00282         if (!entry->description.empty() && entry->description.substr(0,4)!="TODO")
00283             out << "<div class=\"class-description\">"<<entry->description<<"</div>";
00284         if (!entry->authors.empty())
00285             out << "<div class=\"class-authors\">Authors: "<<entry->authors<<"</div>";
00286         if (!entry->license.empty())
00287             out << "<div class=\"class-license\">License: "<<entry->license<<"</div>";
00288     out << "<?php if (!$base) { echo '<a href=\"api?class="<<xmlencode(nameSpace)<<"::"<<xmlencode(entry->className)<<"\">Doxygen class documentation</a>'; } ?>";
00289     out << "</td>";
00290     out << "</tr>\n";
00291     out << "<?php if (!$base) { ?>";
00292     // Write Fields
00293     out << "<tr class=\"sofa-fields-header\">";
00294     out << "<td></td>";
00295         out << "<td class=\"sofa-field-name-header\">Field Name</td>";
00296         out << "<td class=\"sofa-field-type-header\" colspan=\""<<templates.size() + 1<<"\">Type</td>";
00297         out << "<td class=\"sofa-field-value-header\">Value</td>";
00298     out << "</tr>\n";
00299 
00300     // Take the first creator for now
00301     try {
00302         std::cerr << "Trying to instantiate "<<entry->className<<std::endl;
00303         sofa::core::ObjectFactory::Creator* creator = entry->creatorList.begin()->second;
00304         //DummyObjectDescription arg;
00305         //sofa::core::objectmodel::Context ctx;
00306         sofa::core::objectmodel::BaseObject* object = creator->createInstance(NULL, NULL); //&ctx, &arg);
00307         if (object == NULL)
00308         {
00309         std::cerr << "ERROR: Failed to instantiate "<<entry->className<<std::endl;
00310         }
00311         else
00312         {
00313           std::vector< std::pair<std::string, sofa::core::objectmodel::BaseData* > > fields = object->getFields();
00314           for (std::vector< std::pair< std::string, sofa::core::objectmodel::BaseData*>  >::iterator itf = fields.begin(), itfend = fields.end(); itf != itfend; ++itf)
00315         {
00316             sofa::core::objectmodel::BaseData* f = itf->second;
00317             out << "<tr class=\"sofa-field\">";
00318             out << "<td></td>";
00319             out << "<td class=\"sofa-field-name\">";
00320             out << "<span class=\"field-name\">"<<xmlencode(itf->first)<<"</span>";
00321             out << "</td>";
00322             out << "<td class=\"sofa-field-type\" colspan=\""<<templates.size() + 1<<"\">";
00323             out << "<span class=\"field-type\">"<<xmlencode(f->getValueTypeString())<<"</span>";
00324             out << "</td>";
00325             out << "<td class=\"sofa-field-value\">";
00326             out << "<span class=\"field-value\">"<<xmlencode(f->getValueString())<<"</span>";
00327             out << "</td>";
00328             out << "</tr>\n";
00329             if (f->help && *f->help && strncmp(f->help,"TODO",4))
00330             {
00331             out << "<tr class=\"sofa-field-description\">";
00332             out << "<td></td>";
00333             out << "<td class=\"sofa-field-description\" colspan=\""<<nbcol - 1<<"\">";
00334             out << "<div class=\"field-description\">"<<f->help<<"</div>";
00335             out << "</td>";
00336             out << "</tr>\n";
00337             }
00338         }
00339         delete object;
00340         }
00341     } catch(...)
00342     {
00343         std::cerr << "ERROR: Exception raised while trying to instantiate "<<entry->className<<std::endl;
00344     }
00345     out << "</tr>\n";
00346     out << "<?php } ?>\n";
00347     out << "<?php } ?>\n";
00348     out << "<?php } ?>\n";
00349 
00350     }
00351     out << "</table>\n";
00352 
00353     out << "</body></html>\n";
00354 
00355     return true;
00356 }
00357 
00358 }

Generated on Sun Nov 23 02:28:26 2008 for Sofa by  doxygen 1.5.7.1