buddies/Sim2DocBuddy.hpp
Go to the documentation of this file.
00001 /*
00002 
00003   This file is part of OpenFLUID software
00004   Copyright(c) 2007, INRA - Montpellier SupAgro
00005 
00006 
00007  == GNU General Public License Usage ==
00008 
00009   OpenFLUID is free software: you can redistribute it and/or modify
00010   it under the terms of the GNU General Public License as published by
00011   the Free Software Foundation, either version 3 of the License, or
00012   (at your option) any later version.
00013 
00014   OpenFLUID is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017   GNU General Public License for more details.
00018 
00019   You should have received a copy of the GNU General Public License
00020   along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
00021 
00022 
00023  == Other Usage ==
00024 
00025   Other Usage means a use of OpenFLUID that is inconsistent with the GPL
00026   license, and requires a written agreement between You and INRA.
00027   Licensees for Other Usage of OpenFLUID may use this file in accordance
00028   with the terms contained in the written agreement between You and INRA.
00029   
00030 */
00031 
00032 
00033 
00034 /**
00035   @file
00036 
00037   @author Jean-Christophe FABRE <fabrejc@supagro.inra.fr>
00038  */
00039 
00040 
00041 #ifndef __SIM2DOCBUDDY_H___
00042 #define __SIM2DOCBUDDY_H___
00043 
00044 
00045 #ifndef __APPLE__
00046 
00047 // Disabled for compilation errors due to boost.spirit usage under MacOSX
00048 // TODO Should be re-enabled later
00049 
00050 
00051 #include <boost/filesystem/path.hpp>
00052 #include <map>
00053 #include <vector>
00054 
00055 #include <openfluid/dllexport.hpp>
00056 #include <openfluid/buddies/OpenFLUIDBuddy.hpp>
00057 #include <openfluid/ware/SimulatorSignature.hpp>
00058 
00059 #include <boost/spirit/include/classic_core.hpp>
00060 #include <boost/spirit/include/classic_file_iterator.hpp>
00061 #include <boost/bind.hpp>
00062 
00063 #include <openfluid/tools/ExternalProgram.hpp>
00064 
00065 using namespace BOOST_SPIRIT_CLASSIC_NS;
00066 
00067 namespace openfluid { namespace buddies {
00068 
00069 class BuddiesListener;
00070 
00071 
00072 class DLLEXPORT Sim2DocBuddy : public OpenFLUIDBuddy
00073 {
00074   private:
00075     typedef std::map< std::string,std::vector<std::string> > SignatureData_t;
00076 
00077     std::string m_CPPFile;
00078     std::string m_LatexOutFile;
00079 
00080     boost::filesystem::path m_InputDirPath;
00081     boost::filesystem::path m_OutputDirPath;
00082     boost::filesystem::path m_InputFilePath;
00083     boost::filesystem::path m_OutputLatexFilePath;
00084     boost::filesystem::path m_TplFilePath;
00085     boost::filesystem::path m_CProcessedFilePath;
00086 
00087     openfluid::tools::ExternalProgram m_PDFLatexProgram;
00088     openfluid::tools::ExternalProgram m_BibtexProgram;
00089     openfluid::tools::ExternalProgram m_Latex2HTMLProgram;
00090     openfluid::tools::ExternalProgram m_GCCProgram;
00091 
00092     std::string m_ExtractedLatexDoc;
00093 
00094     std::string m_Title;
00095     std::string m_NewCommands;
00096     std::string m_SimID;
00097     std::string m_SimName;
00098     std::string m_SimVersion;
00099     std::string m_SimStatus;
00100     std::vector<std::string> m_SimAuthorsNames;
00101     std::vector<std::string> m_SimAuthorsEmails;
00102     std::string m_SimDomain;
00103     std::string m_SimDescription;
00104     std::string m_SimData;
00105 
00106     std::string m_BeginSignatureTag;
00107     std::string m_EndSignatureTag;
00108     std::string m_BeginSim2DocTag;
00109     std::string m_EndSim2DocTag;
00110 
00111     std::string m_CurrentKeyValue;
00112     std::string m_CurrentBuiltParam;
00113 
00114     std::string m_HTMLPackageLatexCommand;
00115 
00116     SignatureData_t m_InVars;
00117     SignatureData_t m_OutVars;
00118     SignatureData_t m_ModVars;
00119     SignatureData_t m_InAttrs;
00120     SignatureData_t m_OutAttrs;
00121     SignatureData_t m_ParamsData;
00122     SignatureData_t m_Events;
00123     SignatureData_t m_ExtraFiles;
00124 
00125     openfluid::ware::SignatureHandledUnitsGraph m_UnitsGraph;
00126     openfluid::ware::SignatureTimeScheduling m_TimeScheduling;
00127 
00128     std::string extractBetweenTags(std::string Content, const std::string BeginTag, const std::string EndTag);
00129 
00130     std::string toLatexFriendly(std::string Content);
00131 
00132     void addLatexDataCatBegin(std::string& Content, const std::string Title, const std::string ColsFormat);
00133 
00134     void addLatexDataCatEnd(std::string& Content);
00135 
00136     std::string extractSignatureLines();
00137 
00138     std::vector<std::string> searchStringLitterals(std::string StrToParse);
00139 
00140     void copyDocDirectory();
00141 
00142     void extractLatexDocFromCPP();
00143 
00144     void cpreprocessCPP();
00145 
00146     /** Methods called by simulator signature parser **/
00147 
00148     /**
00149       Builds a signature parameter with parsed elements
00150       @param[in] First, Last Pointers to the beginning and the end of the parsed element
00151     */
00152     void buildParsedParam(const char* First, const char* Last);
00153 
00154     /**
00155       Clears the string containing the parameter built with parsing
00156     */
00157     void clearParsedParam();
00158 
00159     /**
00160       Stores data parsed in the string parameter
00161       @param[out] Str Pointer to the string receiving the value
00162     */
00163     void storeDataIntoString(std::string *Str);
00164 
00165     /**
00166       Adds data parsed in the list parameter
00167       @param[out] List Pointer to the vector receiving the value
00168      */
00169     void storeDataIntoVector(std::vector<std::string> *List);
00170 
00171     /**
00172       Stores the new key value parsed into SignatureData parameter
00173       @param[out] SignatureData Pointer to the map receiving the key value
00174       @param[in] State of the attribute or variable stored into the map
00175               (required, used, produced, updated)
00176     */
00177     void storeDataIntoKey(SignatureData_t *SignatureData, const std::string& State);
00178 
00179     /**
00180       Adds data parsed in the SignatureData attribute received as parameter
00181       @param[out] SignatureData Pointer to the map receiving the value
00182     */
00183     void storeDataIntoSignatureData(SignatureData_t *SignatureData);
00184 
00185     /**
00186       Checks data parsed and stores it into status attribute
00187     */
00188     void storeDataIntoStatus();
00189 
00190     /**
00191       Stores data parsed in a new UnitsClass item
00192       @param[out] UpdatedUnitsClass Vector of Units class
00193       @param[in] Attr Attribute of the new UnitsClass receiving the value
00194     */
00195     void storeDataIntoUnitsClass(std::vector<openfluid::ware::SignatureHandledUnitsClassItem> *UpdatedUnitsClass,
00196             int Attr);
00197 
00198     /**
00199       Sets fixed scheduling of TimeScheduling attribute
00200       @param[in] Val Value of scheduling
00201     */
00202     void setSchedulingFixed(double Val);
00203 
00204     /**
00205       Sets range scheduling of TimeScheduling attribute
00206       @param[in] Max Maximum value of the range
00207     */
00208     void setSchedulingRange(double Max);
00209 
00210     /** ********************************** **/
00211 
00212     /**
00213       Applies latex syntax to the attributes
00214     */
00215     void turnIntoLatexSyntax();
00216 
00217     void processSignature();
00218 
00219     void generateLatex();
00220 
00221     bool isErrorInPDFLatexLog();
00222 
00223     void buildPDF();
00224 
00225     void buildHTML();
00226 
00227   public:
00228 
00229     Sim2DocBuddy(openfluid::buddies::BuddiesListener* Listener);
00230 
00231     ~Sim2DocBuddy();
00232 
00233     bool run();
00234 
00235 
00236     /**
00237      * Grammar class used to parse simulator signature
00238     */
00239     struct SimSignatureGrammar : public grammar<SimSignatureGrammar>
00240     {
00241       Sim2DocBuddy *mp_Owner;       // Object of the class containing methods to be called
00242       SimSignatureGrammar(Sim2DocBuddy *Owner) : mp_Owner(Owner) {}
00243 
00244 
00245       template <typename ScannerT>
00246       struct definition
00247       {
00248         /** List of parsing rules **/
00249         rule<ScannerT> blank, linemarker, endLine, escapedQuote, string, varName, element, parameters, signature,
00250                         IDRule, NameRule, DescriptionRule, VersionRule, StatusRule, DomainRule, AuthorRule,
00251                         SimulatorParamRule, ProducedVarRule, UpdatedVarRule, RequiredVarRule, UsedVarRule,
00252                         ProducedAttributeRule, RequiredAttributeRule, UsedAttributeRule,
00253                         UsedEventsRule, UsedExtraFilesRule, RequiredExtraFilesRule,
00254                         UpdatedUnitsGraphRule, UpdatedUnitsClassRule;
00255 
00256         /**
00257          * Defines the different rules of content to parse or ignore
00258          *
00259          * boost::bind is used to execute a method after parsing of an element or a rule.
00260          * Its parameters are the method to call, the object with which the method is executed
00261          * and the different parameters of this method (_1 and _2 are used to send the parsed element).
00262          *
00263          * The different parsers which can be used :
00264          * http://www.boost.org/doc/libs/1_39_0/libs/spirit/classic/doc/quickref.html
00265         */
00266         definition(SimSignatureGrammar const& self)
00267         {
00268           /** Initial rule **/
00269 
00270           signature = str_p("BEGIN_SIMULATOR_SIGNATURE") >> *blank >> '(' >> IDRule >> ')' >> endLine
00271                 >> *(str_p("DECLARE_NAME") >> *blank >> '(' >> NameRule >> ')' >> endLine
00272                     | str_p("DECLARE_DESCRIPTION") >> *blank >> '(' >> DescriptionRule >> ')' >> endLine
00273                     | str_p("DECLARE_VERSION") >> *blank >> '(' >> VersionRule >> ')' >> endLine
00274                     | str_p("DECLARE_SDKVERSION") >> endLine
00275                     | str_p("DECLARE_STATUS") >> *blank >> '(' >> StatusRule >> ')' >> endLine
00276                     | str_p("DECLARE_DOMAIN") >> *blank >> '(' >> DomainRule >> ')' >> endLine
00277                     | str_p("DECLARE_PROCESS") >> *blank >> '(' >> parameters >> ')' >> endLine
00278                     | str_p("DECLARE_METHOD") >> *blank >> '(' >> parameters >> ')' >> endLine
00279                     | str_p("DECLARE_AUTHOR") >> *blank >> '(' >> AuthorRule >> ')' >> endLine
00280 
00281                     | str_p("DECLARE_SIMULATOR_PARAM") >> *blank >> '(' >> SimulatorParamRule >> ')' >> endLine
00282 
00283                     | str_p("DECLARE_PRODUCED_VAR") >> *blank >> '(' >> ProducedVarRule >> ')' >> endLine
00284                     | str_p("DECLARE_UPDATED_VAR") >> *blank >> '(' >> UpdatedVarRule >> ')' >> endLine
00285                     | str_p("DECLARE_REQUIRED_VAR") >> *blank >> '(' >> RequiredVarRule >> ')' >> endLine
00286                     | str_p("DECLARE_USED_VAR") >> *blank >> '(' >> UsedVarRule >> ')' >> endLine
00287 
00288                     | str_p("DECLARE_PRODUCED_ATTRIBUTE") >> *blank >> '(' >> ProducedAttributeRule >> ')' >> endLine
00289                     | str_p("DECLARE_REQUIRED_ATTRIBUTE") >> *blank >> '(' >> RequiredAttributeRule >> ')' >> endLine
00290                     | str_p("DECLARE_USED_ATTRIBUTE") >> *blank >> '(' >> UsedAttributeRule >> ')' >> endLine
00291 
00292                     | str_p("DECLARE_USED_EVENTS") >> *blank >> '(' >> UsedEventsRule >> ')' >> endLine
00293                     | str_p("DECLARE_USED_EXTRAFILE") >> *blank >> '(' >> UsedExtraFilesRule >> ')' >> endLine
00294                     | str_p("DECLARE_REQUIRED_EXTRAFILE") >> *blank >> '(' >> RequiredExtraFilesRule >> ')' >> endLine
00295 
00296                     | str_p("DECLARE_UPDATED_UNITSGRAPH") >> *blank >> '(' >> UpdatedUnitsGraphRule >> ')' >> endLine
00297                     | str_p("DECLARE_UPDATED_UNITSCLASS") >> *blank >> '(' >> UpdatedUnitsClassRule >> ')' >> endLine
00298 
00299                     | str_p("DECLARE_SCHEDULING_UNDEFINED")[boost::bind(&ware::SignatureTimeScheduling::setAsUndefined,
00300                         &self.mp_Owner->m_TimeScheduling)] >> endLine
00301                     | str_p("DECLARE_SCHEDULING_DEFAULT")[boost::bind(&ware::SignatureTimeScheduling::setAsDefaultDeltaT,
00302                         &self.mp_Owner->m_TimeScheduling)] >> endLine
00303                     | str_p("DECLARE_SCHEDULING_FIXED") >> *blank >> '(' >> *blank >> real_p[boost::bind(&Sim2DocBuddy::setSchedulingFixed, self.mp_Owner, _1)]
00304                             >> *blank >> ')' >> endLine
00305                     | str_p("DECLARE_SCHEDULING_RANGE") >> *blank >> '(' >> *blank >> real_p[boost::bind(&Sim2DocBuddy::setSchedulingFixed, self.mp_Owner, _1)]
00306                             >> *blank >> ',' >> *blank >> real_p[boost::bind(&Sim2DocBuddy::setSchedulingRange, self.mp_Owner, _1)] >> *blank >>  ')' >> endLine
00307 
00308                     | linemarker >> endLine
00309                   )
00310               >> str_p("END_SIMULATOR_SIGNATURE") >> endLine
00311           ;
00312 
00313           /** List of common rules **/
00314 
00315 
00316           /* Ignoring of inserted lines by the preprocessor which mean
00317            * the original position of lines in source file.
00318           */
00319           linemarker =  '#' >> *(anychar_p - eol_p) >> eol_p;
00320 
00321           blank = blank_p | eol_p;                        // Parse all spaces, tabs and newlines
00322           endLine = *(blank | ';');
00323           escapedQuote = str_p("\\\"");
00324 
00325           string = *(escapedQuote | (anychar_p - '"'));   // String content composed to all characters
00326 
00327           varName = *(print_p - ')');
00328 
00329           // Parameter of a method surrounded by quotes (string) or not (var name)
00330           element = (+(*blank >> '"' >> string[boost::bind(&Sim2DocBuddy::buildParsedParam, self.mp_Owner, _1, _2)] >> '"' >> *blank))
00331                       | (*blank >> varName[boost::bind(&Sim2DocBuddy::buildParsedParam, self.mp_Owner, _1, _2)] >> *blank);
00332 
00333           // List of parameters of a declaration (here not stored)
00334           parameters = element[boost::bind(&Sim2DocBuddy::clearParsedParam, self.mp_Owner)]
00335            >> *(',' >> element[boost::bind(&Sim2DocBuddy::clearParsedParam, self.mp_Owner)]);
00336 
00337 
00338 
00339           /** List of rules for the different lines of signature **/
00340 
00341           IDRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_SimID)];
00342           NameRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_SimName)];
00343           DescriptionRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_SimDescription)];
00344           VersionRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_SimVersion)];
00345 
00346           StatusRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoStatus, self.mp_Owner)];
00347 
00348           DomainRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_SimDomain)];
00349           AuthorRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoVector, self.mp_Owner, &self.mp_Owner->m_SimAuthorsNames)]
00350              >> ',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoVector, self.mp_Owner, &self.mp_Owner->m_SimAuthorsEmails)];
00351 
00352           SimulatorParamRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_ParamsData, "")]
00353                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_ParamsData)]);
00354 
00355           ProducedVarRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_OutVars, "produced")]
00356                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_OutVars)]);
00357           UpdatedVarRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_OutVars, "updated")]
00358                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_OutVars)]);
00359           RequiredVarRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_InVars, "required")]
00360                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_InVars)]);
00361           UsedVarRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_InVars, "used")]
00362                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_InVars)]);
00363 
00364           ProducedAttributeRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_OutAttrs, "produced")]
00365                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_OutAttrs)]);
00366           RequiredAttributeRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_InAttrs, "required")]
00367                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_InAttrs)]);
00368           UsedAttributeRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_InAttrs, "used")]
00369                    >> *(',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoSignatureData, self.mp_Owner, &self.mp_Owner->m_InAttrs)]);
00370 
00371           UsedEventsRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_Events, "")];
00372           UsedExtraFilesRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_ExtraFiles, "used")];
00373           RequiredExtraFilesRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoKey, self.mp_Owner, &self.mp_Owner->m_ExtraFiles, "required")];
00374 
00375           UpdatedUnitsGraphRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoString, self.mp_Owner, &self.mp_Owner->m_UnitsGraph.UpdatedUnitsGraph)];
00376           UpdatedUnitsClassRule = element[boost::bind(&Sim2DocBuddy::storeDataIntoUnitsClass, self.mp_Owner, &self.mp_Owner->m_UnitsGraph.UpdatedUnitsClass, 1)]
00377                   >> ',' >> element[boost::bind(&Sim2DocBuddy::storeDataIntoUnitsClass, self.mp_Owner, &self.mp_Owner->m_UnitsGraph.UpdatedUnitsClass, 2)];
00378         }
00379 
00380         /**
00381          * @return Main rule of parsing content
00382         */
00383         rule<ScannerT> const& start() const { return signature; }
00384       };
00385     };
00386 
00387 };
00388 
00389 
00390 } } //namespaces
00391 
00392 #endif /* __APPLE__ */
00393 
00394 #endif /* __SIM2DOCBUDDY_HPP__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines