LoaderGenerator.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright 2007, 2008, 2009, 2010, 2011 Instituto de Sistemas e Robotica, Instituto Superior Tecnico
00003 
00004 This file is part of MeRMaID.
00005 
00006 MeRMaID is free software: you can redistribute it and/or modify
00007 it under the terms of the GNU Lesser General Public License as published by
00008 the Free Software Foundation, either version 3 of the License, or
00009 (at your option) any later version.
00010 
00011 MeRMaID is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public License
00017 along with MeRMaID.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 
00021 
00022 /**
00023  * @Filename LoaderGenerator.cpp
00024  * @Description Implementation of the LoaderGenerator class for Ace-based mermaid implementation
00025  * @Status Implementing
00026  * @Version $Id: LoaderGenerator.cpp 1 2011-03-04 18:13:18Z jreis $
00027  * @Maintainer Marco Barbosa (mafb@isr.ist.utl.pt)
00028  */
00029 
00030 #include "config.h"
00031 
00032 #include "LoaderGenerator.hpp"
00033 
00034 #include <fstream>
00035 #include <iostream>
00036 #include <string>
00037 #include <sstream>
00038 #include <algorithm>
00039 
00040 
00041 
00042 #include <FilePathSearch.hpp>
00043 
00044 #include <XmlDocument.hpp>
00045 #include <XmlElement.hpp>
00046 #include <XmlElementVector.hpp>
00047 
00048 #include <DeploymentConfiguration.hpp>
00049 
00050 using namespace mermaid::mermaidloader;
00051 
00052 using std::cerr;
00053 using std::cerr;
00054 using std::endl;
00055 using std::ofstream;
00056 using std::string;
00057 using std::stringstream;
00058 
00059 using boost::shared_ptr;
00060 
00061 using mermaid::support::system::FilePathSearch;
00062 
00063 using mermaid::support::xml::XmlDocument;
00064 using mermaid::support::xml::XmlElement;
00065 using mermaid::support::xml::XmlElementVector;
00066 
00067 #include <iostream>
00068 
00069 int indent = 0;
00070 std::string getIndent()
00071 {
00072   stringstream s;
00073   for (int i = 0; i < indent; i++) {
00074     s << "    ";
00075   }
00076   return s.str();
00077 }
00078 
00079 int main (int argc, char **argv)
00080 {
00081 
00082   if (argc < 3) {
00083     cerr << "MermaidLoader generator for ACE-based systems" << endl;
00084     cerr << "Usage:" << endl;
00085     cerr << argv[0] << " <configuration file> <output file> <search paths>" << endl;
00086     exit (1);
00087   }
00088   
00089   //add user-defined search paths
00090   for (int i = 3; i < (argc); i++) {
00091     FilePathSearch::addSearchPath (argv[i]);
00092   }
00093   
00094   //add default search paths
00095   FilePathSearch::addSearchPath ("./config");
00096   FilePathSearch::addSearchPath ("./build/config");
00097   FilePathSearch::addSearchPath ("./");
00098   char * mermaid_dir = getenv ("MERMAID_DIR");
00099   if (mermaid_dir != 0) {
00100     FilePathSearch::addSearchPath (string (mermaid_dir) + "/config");
00101   }
00102   
00103   FilePathSearch::addSearchPath ("/");
00104   
00105   //configuration variables
00106   string configFileName = string (argv[1]);
00107   string outputFileName = string (argv[2]);
00108   
00109   //open output file
00110   ofstream outputFile;
00111   outputFile.open (outputFileName.c_str());
00112   
00113   if (outputFile.is_open() == false) {
00114     cerr << "Failed to open file: \"" << outputFileName << "\"" << endl;
00115     exit (1);
00116   }
00117   
00118   shared_ptr<XmlDocument> configXmlDoc = shared_ptr<XmlDocument> (new XmlDocument());
00119   configXmlDoc->parseFile (configFileName);
00120   
00121   DeploymentConfiguration configuration;
00122   configuration.loadConfiguration (configXmlDoc);
00123   
00124   FileSearchPathList fspl = configuration.getFileSearchPathList();
00125   DataDescriptionFileList ddfl = configuration.getDataDescriptionFileList();
00126   ServiceTypeDescriptionFileList stdfl = configuration.getServiceTypeDescriptionFileList();
00127   EntityDescriptionFileList edfl = configuration.getEntityDescriptionFileList();
00128   ActiveObjectConfigurationNameMap aocnm = configuration.getActiveObjectConfigurationNameMap();
00129   ActiveObjectConfigurationServiceMap aocsm = configuration.getActiveObjectConfigurationServiceMap();
00130   ServiceDeploymentConfigurationNameMap scnm = configuration.getServiceDeploymentConfigurationNameMap();
00131   
00132   /*ActiveObjectConfigurationNameMap::iterator aocit;
00133   
00134   for(aocit = aocnm.begin(); aocit != aocnm.end(); aocit++)
00135   {
00136       std::string aoName = (*aocit).first;
00137       cout << "ActiveObject name: " << aoName << endl;
00138   }*/
00139   
00140   
00141   // load XMl template file
00142   shared_ptr<XmlDocument> templateXmlDoc = shared_ptr<XmlDocument> (new XmlDocument());
00143   templateXmlDoc->parseFile ("loadergenerator-ace.xml");
00144   
00145   //build output file
00146   stringstream code;
00147   
00148   
00149   shared_ptr<XmlElement> templateRoot = templateXmlDoc->getRootElement();
00150   XmlElementVector templateChildren = templateRoot->getChildrenElements();
00151   shared_ptr<XmlElement> fileHeaderElement = templateChildren.getFirstElementWithName ("file-header");
00152   shared_ptr<XmlElement> includesElement = templateChildren.getFirstElementWithName ("includes");
00153   shared_ptr<XmlElement> serviceIncludeHeaderElement = templateChildren.getFirstElementWithName ("service-include-header");
00154   shared_ptr<XmlElement> serviceIncludeFooterElement = templateChildren.getFirstElementWithName ("service-include-footer");
00155   shared_ptr<XmlElement> usesElement = templateChildren.getFirstElementWithName ("uses");
00156   shared_ptr<XmlElement> serviceUsingHeaderElement = templateChildren.getFirstElementWithName ("service-using-header");
00157   shared_ptr<XmlElement> serviceUsingFooterElement = templateChildren.getFirstElementWithName ("service-using-footer");
00158   shared_ptr<XmlElement> mainHeaderElement = templateChildren.getFirstElementWithName ("main-header");
00159   shared_ptr<XmlElement> filePathHeaderElement = templateChildren.getFirstElementWithName ("file-path-header");
00160   shared_ptr<XmlElement> filePathFooterElement = templateChildren.getFirstElementWithName ("file-path-footer");
00161   shared_ptr<XmlElement> dataDescriptionLoadHeaderElement = templateChildren.getFirstElementWithName ("data-description-load-header");
00162   shared_ptr<XmlElement> dataDescriptionLoadFooterElement = templateChildren.getFirstElementWithName ("data-description-load-footer");
00163   shared_ptr<XmlElement> serviceTypeLoadHeaderElement = templateChildren.getFirstElementWithName ("service-type-load-header");
00164   shared_ptr<XmlElement> serviceTypeLoadFooterElement = templateChildren.getFirstElementWithName ("service-type-load-footer");
00165   shared_ptr<XmlElement> entityDescriptionLoadHeaderElement = templateChildren.getFirstElementWithName ("entity-description-load-header");
00166   shared_ptr<XmlElement> entityDescriptionLoadFooterElement = templateChildren.getFirstElementWithName ("entity-description-load-footer");
00167   shared_ptr<XmlElement> aoEntityRepositoryHeaderElement = templateChildren.getFirstElementWithName ("ao-entity-repository-header");
00168   shared_ptr<XmlElement> aoEntityRepositoryFooterElement = templateChildren.getFirstElementWithName ("ao-entity-repository-footer");
00169   shared_ptr<XmlElement> mainFooterElement = templateChildren.getFirstElementWithName ("main-footer");
00170   shared_ptr<XmlElement> fileFooterElement = templateChildren.getFirstElementWithName ("file-footer");
00171   
00172   //! @TODO All strings should be imported from the XML file.
00173   
00174   
00175   code << (string) (*fileHeaderElement->getFirstNonBlankCharData());
00176   code << (string) (*includesElement->getFirstNonBlankCharData());
00177   
00178   // Service includes
00179   {
00180     code << endl << getIndent() << "// Service Includes" << endl;
00181     
00182     ServiceDeploymentConfigurationNameMap::iterator siit;
00183     
00184     for (siit = scnm.begin(); siit != scnm.end(); siit++) {
00185       shared_ptr<ServiceDeploymentConfiguration> sc = (*siit).second;
00186       code << (string) (*serviceIncludeHeaderElement->getFirstNonBlankCharData());
00187       code << sc->getServiceHeaderFilename();
00188       code << (string) (*serviceIncludeFooterElement->getFirstNonBlankCharData());
00189     }
00190   }
00191   
00192   code << (string) (*usesElement->getFirstNonBlankCharData());
00193   
00194   // Services uses
00195   {
00196     code << endl << getIndent() << "// Service uses" << endl;
00197     
00198     ServiceDeploymentConfigurationNameMap::iterator siit;
00199     
00200     for (siit = scnm.begin(); siit != scnm.end(); siit++) {
00201       shared_ptr<ServiceDeploymentConfiguration> sc = (*siit).second;
00202       code << (string) (*serviceUsingHeaderElement->getFirstNonBlankCharData());
00203       code << sc->getServiceNamespace() << "::" << sc->getServiceClassName();
00204       code << (string) (*serviceUsingFooterElement->getFirstNonBlankCharData()) << std::endl;
00205     }
00206   }
00207   
00208   //main header
00209   code << (string) (*mainHeaderElement->getFirstNonBlankCharData());
00210   indent++;
00211   
00212   //set file search paths
00213   {
00214     FileSearchPathList::iterator fpit;
00215     
00216     code << endl << getIndent() << "//Setting file search paths" << endl;
00217     
00218     for (fpit = fspl.begin(); fpit != fspl.end(); fpit++) {
00219       std::string path = *fpit;
00220       code << getIndent() << (string) (*filePathHeaderElement->getFirstNonBlankCharData());
00221       code << path;
00222       code << (string) (*filePathFooterElement->getFirstNonBlankCharData()) << endl;
00223     }
00224     
00225     //set default path
00226     code << getIndent() << (string) (*filePathHeaderElement->getFirstNonBlankCharData());
00227     code << "./";
00228     code << (string) (*filePathFooterElement->getFirstNonBlankCharData()) << " //Default file search path" << endl;
00229   }
00230   
00231   //load data description files
00232   {
00233     DataDescriptionFileList::iterator ddit;
00234     vector<string> dddf;
00235     vector<string>::iterator sit;
00236     
00237     dddf.push_back ("ping-tool-data-description-file.xml");
00238 #ifdef USE_COMM
00239     dddf.push_back ("comm-service-data-description-file.xml");
00240 #endif
00241     
00242     code << endl << getIndent() << "//Load data description files" << endl;
00243     
00244     code << endl << getIndent() << "//Loading default data description files" << endl;
00245     for (sit = dddf.begin(); sit != dddf.end(); sit++) {
00246       code << getIndent() << (string) (*dataDescriptionLoadHeaderElement->getFirstNonBlankCharData());
00247       code << *sit;
00248       code << (string) (*dataDescriptionLoadFooterElement->getFirstNonBlankCharData()) << endl;
00249     }
00250     
00251     for (ddit = ddfl.begin(); ddit != ddfl.end(); ddit++) {
00252       std::string filename = *ddit;
00253       // only add a data description file if it hasn't been added yet
00254       if (std::find (dddf.begin(), dddf.end(), filename) == dddf.end()) {
00255         code << getIndent() << "//loading " << filename << endl;
00256         code << getIndent() << (string) (*dataDescriptionLoadHeaderElement->getFirstNonBlankCharData());
00257         code << filename;
00258         code << (string) (*dataDescriptionLoadFooterElement->getFirstNonBlankCharData()) << endl;
00259       }
00260     }
00261   }
00262   
00263   //load service type description files
00264   {
00265     ServiceTypeDescriptionFileList::iterator stit;
00266     vector<string> dsdf;
00267     vector<string>::iterator sit;
00268     
00269     dsdf.push_back ("ping-tool-service-type-description-file.xml");
00270 #ifdef USE_COMM
00271     dsdf.push_back ("comm-service-type-description-file.xml");
00272 #endif
00273     
00274     code << endl << getIndent() << "//Load service type description files" << endl;
00275     
00276     code << endl << getIndent() << "//Loading default service type description files" << endl;
00277     for (sit = dsdf.begin(); sit != dsdf.end(); sit++) {
00278       code << getIndent() << (string) (*serviceTypeLoadHeaderElement->getFirstNonBlankCharData());
00279       code << *sit;
00280       code << (string) (*serviceTypeLoadFooterElement->getFirstNonBlankCharData()) << endl;
00281     }
00282     
00283     for (stit = stdfl.begin(); stit != stdfl.end(); stit++) {
00284       std::string filename = *stit;
00285       // only add a service description file if it hasn't been added yet
00286       if (std::find (dsdf.begin(), dsdf.end(), filename) == dsdf.end()) {
00287         code << getIndent() << "//loading " << filename << endl;
00288         code << getIndent() << (string) (*serviceTypeLoadHeaderElement->getFirstNonBlankCharData());
00289         code << filename;
00290         code << (string) (*serviceTypeLoadFooterElement->getFirstNonBlankCharData()) << endl;
00291       }
00292     }
00293   }
00294   
00295   //load entity description files
00296   {
00297     EntityDescriptionFileList::iterator edit;
00298     
00299     code << endl << getIndent() << "//Load entity description files" << endl;
00300     
00301     for (edit = edfl.begin(); edit != edfl.end(); edit++) {
00302       std::string filename = *edit;
00303       code << getIndent() << "//loading " << filename << endl;
00304       code << getIndent() << (string) (*entityDescriptionLoadHeaderElement->getFirstNonBlankCharData());
00305       code << filename;
00306       code << (string) (*entityDescriptionLoadFooterElement->getFirstNonBlankCharData());
00307     }
00308   }
00309   
00310   //really load all description files
00311   //setup path
00312   
00313   code << getIndent() << "//setup search paths" << endl;
00314   code << getIndent() << "std::vector<std::string>::iterator pathIterator;" << endl;
00315   code << getIndent() << "for(pathIterator=pathVector.begin(); pathIterator!=pathVector.end(); pathIterator++)" << endl;
00316   code << getIndent() << "{" << endl;
00317   indent++;
00318   code << getIndent() << "std::string path = *pathIterator;" << endl;
00319   code << getIndent() << "std::cerr << \"Loading path: \" << path << std::endl;" << endl;
00320   code << getIndent() << "FilePathSearch::addSearchPath(path);" << endl;
00321   indent--;
00322   code << getIndent() << "}" << endl;
00323   
00324   //load data descriptions
00325   code << getIndent() << "//load data descriptions" << endl;
00326   code << getIndent() << "std::vector<std::string>::iterator dataDescriptionIterator;" << endl;
00327   code << getIndent() << "for(dataDescriptionIterator=dataDescriptionVector.begin(); dataDescriptionIterator!=dataDescriptionVector.end(); dataDescriptionIterator++)" << endl;
00328   code << getIndent() << "{" << endl;
00329   indent++;
00330   code << getIndent() << "std::string dataDescriptionFile = *dataDescriptionIterator;" << endl;
00331   code << getIndent() << "std::cerr << \"Loading data type description file: \" << dataDescriptionFile << std::endl;" << endl;
00332   code << getIndent() << "shared_ptr<XmlDocument>  dataDoc = shared_ptr<XmlDocument>(new XmlDocument());" << endl;
00333   code << getIndent() << "dataDoc->parseFile(dataDescriptionFile);" << endl;
00334   code << getIndent() << "DataFactory::loadDataDescription(dataDoc);" << endl;
00335   indent--;
00336   code << getIndent() << "}" << endl;
00337   
00338   //load service type descriptions
00339   code << getIndent() << "//load service type descriptions" << endl;
00340   code << getIndent() << "std::vector<std::string>::iterator serviceDescriptionIterator;" << endl;
00341   code << getIndent() << "for(serviceDescriptionIterator=serviceDescriptionVector.begin(); serviceDescriptionIterator!=serviceDescriptionVector.end(); serviceDescriptionIterator++)" << endl;
00342   code << getIndent() << "{" << endl;
00343   indent++;
00344   code << getIndent() << "std::string serviceDescriptionFile = *serviceDescriptionIterator;" << endl;
00345   code << getIndent() << "std::cerr << \"Loading service type description file: \" << serviceDescriptionFile << std::endl;" << endl;
00346   code << getIndent() << "shared_ptr<XmlDocument> docServiceType = shared_ptr<XmlDocument>(new XmlDocument());" << endl;
00347   code << getIndent() << "docServiceType->parseFile(serviceDescriptionFile);" << endl;
00348   code << getIndent() << "shared_ptr<XmlElement> serviceTypeDescriptionList = docServiceType->getRootElement();" << endl;
00349   code << getIndent() << "shared_ptr<ServiceTypeDescriptionRepository> serviceTypeDescriptionRepository = ServiceTypeDescriptionRepository::getInstance();" << endl;
00350   code << getIndent() << "ServiceTypeDescriptionFactory::populateServiceTypeDescriptionRepository(serviceTypeDescriptionRepository, serviceTypeDescriptionList);" << endl;
00351   indent--;
00352   code << getIndent() << "}" << endl;
00353   
00354   // load entity descriptions
00355   code << getIndent() << "//load entity descriptions" << endl;
00356   code << getIndent() << "std::vector<std::string>::iterator entityDescriptionIterator;" << endl;
00357   code << getIndent() << "for(entityDescriptionIterator=entityDescriptionVector.begin(); entityDescriptionIterator!=entityDescriptionVector.end(); entityDescriptionIterator++)" << endl;
00358   code << getIndent() << "{" << endl;
00359   indent++;
00360   code << getIndent() << "std::string entityDescriptionFile = *entityDescriptionIterator;" << endl;
00361   code << getIndent() << "std::cerr << \"Loading entity type description file: \" << entityDescriptionFile << std::endl;" << endl;
00362   code << getIndent() << "shared_ptr<XmlDocument> docEntityDescription = shared_ptr<XmlDocument>(new XmlDocument());" << endl;
00363   code << getIndent() << "docEntityDescription->parseFile(entityDescriptionFile);" << endl;
00364   code << getIndent() << "shared_ptr<XmlElement> entityDescriptionList = docEntityDescription->getRootElement();" << endl;
00365   code << getIndent() << "shared_ptr<EntityDescriptionRepository> entityDescriptionRepository = EntityDescriptionRepository::getInstance();" << endl;
00366   code << getIndent() << "shared_ptr<ServiceTypeDescriptionRepository> serviceTypeDescriptionRepository = ServiceTypeDescriptionRepository::getInstance();" << endl;
00367   code << getIndent() << "EntityDescriptionFactory::populateEntityDescriptionRepository(entityDescriptionRepository, entityDescriptionList, serviceTypeDescriptionRepository);" << endl;
00368   indent--;
00369   code << getIndent() << "}" << endl;
00370   
00371   // create ActiveObjects
00372   {
00373   
00374     ActiveObjectConfigurationNameMap::iterator aoit;
00375     
00376     code << endl << getIndent() << "// Create ActiveObjects" << endl;
00377     
00378     for (aoit = aocnm.begin(); aoit != aocnm.end(); aoit++) {
00379       shared_ptr<ActiveObjectConfiguration> aoc = (*aoit).second;
00380       code << getIndent() << "shared_ptr<ActiveObject> " << aoc->getName() << " = ActiveObjectManagerAce::getInstance()->createActiveObject();" << endl;
00381     }
00382     
00383   }
00384   
00385 //     // Run startup procedures on ActiveObjects
00386 //     {
00387 //         code << endl << getIndent() << "// Run StartUp procedures on ActiveObjects" << endl;
00388 //
00389 //         ActiveObjectConfigurationNameMap::iterator aoi;
00390 //
00391 //         for(aoi = aocnm.begin(); aoi != aocnm.end(); aoi++)
00392 //         {
00393 //             string aoName = (*aoi).first;
00394 //             code << getIndent() << aoName << "->doStartup();" << endl;
00395 //         }
00396 //     }
00397 
00398   // Do ActiveObjects start
00399   {
00400     code << endl << getIndent() << "// ActiveObjects start" << endl;
00401     
00402     ActiveObjectConfigurationNameMap::iterator aoi;
00403     
00404     for (aoi = aocnm.begin(); aoi != aocnm.end(); aoi++) {
00405       string aoName = (*aoi).first;
00406       code << getIndent() << aoName << "->start();" << endl;
00407     }
00408   }
00409   
00410   //create EntityRepository
00411   std::string entityRepositoryName = "aoEntityRepository";
00412   {
00413     code << endl << getIndent() << "// Create entity repository" << endl;
00414     code << getIndent() << (string) (*aoEntityRepositoryHeaderElement->getFirstNonBlankCharData());
00415     code << entityRepositoryName;
00416     code << (string) (*aoEntityRepositoryFooterElement->getFirstNonBlankCharData()) << endl;
00417     //! @TODO create one repository for each AO?
00418   }
00419   
00420   // create Services
00421   {
00422     ServiceDeploymentConfigurationNameMap::iterator sit;
00423     
00424     code << endl << getIndent() << "// Create Services" << endl;
00425     
00426     for (sit = scnm.begin(); sit != scnm.end(); sit++) {
00427       shared_ptr<ServiceDeploymentConfiguration> sc = (*sit).second;
00428       string serviceDescriptionXmlInstance = sc->getServiceInstanceName() + "Xml";
00429       
00430       code << getIndent() << "{" << endl;
00431       indent++;
00432       
00433       //create service configuration
00434       code << getIndent() << "shared_ptr<XmlDocument> serviceConfigurationDocument(new XmlDocument());" << endl;
00435       code << getIndent() << "serviceConfigurationDocument->parseFile(\"" << sc->getServiceConfigurationFilename() << "\");" << endl;
00436       code << getIndent() << "shared_ptr<ServiceConfiguration> serviceConfiguration(new ServiceConfiguration(serviceConfigurationDocument));" << endl;
00437       
00438       code << getIndent() << "shared_ptr<Task> build" << sc->getServiceClassName() << "((Task*)new ServiceBuildTask<" << sc->getServiceClassName() << ">(" << sc->getServiceActiveObjectName() << ", " << entityRepositoryName << ", \"" << sc->getServiceEntityName() << "\", \"" << sc->getServiceInstanceName() << "\", serviceConfiguration));" << endl;
00439       
00440       code << getIndent() << sc->getServiceActiveObjectName() << "->addTask(build" << sc->getServiceClassName() << ");" << endl;
00441       
00442       indent--;
00443       code << getIndent() << "}" << endl;
00444     }
00445     
00446   }
00447   
00448   
00449   // Wait for ActiveObjects to stop
00450   {
00451     code << endl << getIndent() << "// Wait for ActiveObjects to stop" << endl;
00452     code << getIndent() << "ActiveObjectManagerAce::getInstance()->waitForActiveObjectsToStop();" << endl;
00453     //code << getIndent() << "sleep(5); exit_program(0);" << endl;
00454   }
00455   
00456   
00457 //     //shutdown ActiveObjects
00458 //     {
00459 //         code << endl << getIndent() << "//Shutdown ActiveObjects" << endl;
00460 //
00461 //         ActiveObjectConfigurationNameMap::iterator aoi;
00462 //
00463 //         for(aoi = aocnm.begin(); aoi != aocnm.end(); aoi++)
00464 //         {
00465 //             string aoName = (*aoi).first;
00466 //             code << getIndent() << aoName << "->doShutdown();" << endl;
00467 //         }
00468 //
00469 //     }
00470 
00471 
00472   code << (string) (*mainFooterElement->getFirstNonBlankCharData());
00473   
00474   code << (string) (*fileFooterElement->getFirstNonBlankCharData());
00475   
00476   outputFile << code.str() << endl;
00477   outputFile.close();
00478   
00479 }; // main
00480 
Generated on Fri Mar 4 22:14:58 2011 for MeRMaID::support by  doxygen 1.6.3