# XmlParser.cc

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // CERTI - HLA RunTime Infrastructure
    00003 // Copyright (C) 2003-2006  ONERA
    00004 //
    00005 // This file is part of CERTI-libCERTI
    00006 //
    00007 // CERTI-libCERTI is free software ; you can redistribute it and/or
    00008 // modify it under the terms of the GNU Lesser General Public License
    00009 // as published by the Free Software Foundation ; either version 2 of
    00010 // the License, or (at your option) any later version.
    00011 //
    00012 // CERTI-libCERTI is distributed in the hope that it will be useful, but
    00013 // WITHOUT ANY WARRANTY ; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    00015 // Lesser General Public License for more details.
    00016 //
    00017 // You should have received a copy of the GNU Lesser General Public
    00018 // License along with this program ; if not, write to the Free Software
    00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    00020 // ----------------------------------------------------------------------------
    00021
    00022 #include "XmlParser.hh"
    00023 #include "ObjectClassSet.hh"
    00024 #include "InteractionSet.hh"
    00025 #include "ObjectClassAttribute.hh"
    00026 #include "RoutingSpace.hh"
    00027 #include "PrettyDebug.hh"
    00028
    00029 using std::string ;
    00030 using std::cerr ;
    00031 using std::endl ;
    00032
    00033 #ifdef HAVE_XML
    00034
    00035 #define NODE_OBJECT_MODEL (const xmlChar*) "objectModel"
    00036 #define NODE_OBJECTS (const xmlChar*) "objects"
    00037 #define NODE_OBJECT_CLASS (const xmlChar*) "objectClass"
    00038 #define NODE_INTERACTIONS (const xmlChar*) "interactions"
    00039 #define NODE_INTERACTION_CLASS (const xmlChar*) "interactionClass"
    00040 #define NODE_ATTRIBUTE (const xmlChar*) "attribute"
    00041 #define NODE_PARAMETER (const xmlChar*) "parameter"
    00042 #define NODE_ROUTING_SPACE (const xmlChar*) "routingSpace"
    00043 #define NODE_DIMENSIONS (const xmlChar*) "dimensions"
    00044 #define NODE_DIMENSION (const xmlChar*) "dimension"
    00045
    00046 #define ATTRIBUTE_NAME (const xmlChar*) "name"
    00047 #define ATTRIBUTE_TRANSPORTATION (const xmlChar*) "transportation"
    00048 #define ATTRIBUTE_ORDER (const xmlChar*) "order"
    00049 #define ATTRIBUTE_SPACE (const xmlChar*) "space"
    00050
    00051 #define VALUE_RELIABLE (const xmlChar*) "HLAreliable"
    00052 #define VALUE_BESTEFFORT (const xmlChar*) "HLAbestEffort"
    00053 #define VALUE_TSO (const xmlChar*) "TimeStamp"
    00054 #define VALUE_RO (const xmlChar*) "Receive"
    00055
    00056 namespace certi {
    00057
    00058 static pdCDebug D("XMLPARSER", "(XmlParser) ");
    00059
    00060 XmlParser::XmlParser(RootObject* r)
    00061 {
    00062     root = r ;
    00063
    00064     freeObjectClassHandle = 1 ;
    00065     freeInteractionClassHandle = 1 ;
    00066     freeAttributeHandle = 1 ;
    00067     freeParameterHandle = 1 ;
    00068     freeSpaceHandle = 1 ;
    00069 }
    00070
    00071 // ----------------------------------------------------------------------------
    00072 RootObject*
    00073 XmlParser::parse(string pathToXmlFile)
    00074 {
    00075     D.Out(pdTrace, "Starting to parse XML file");
    00076     filename = pathToXmlFile;
    00077
    00078     // transportation = HLAreliable
    00079     // order = TimeStamp
    00080
    00081     doc = xmlParseFile(filename.c_str());
    00082
    00083     // Did libXML manage to parse the file ?
    00084     if (doc == 0) {
    00085         cerr << "XML file not parsed successfully" << endl ;
    00086         xmlFreeDoc(doc);
    00087         return 0 ;
    00088     }
    00089
    00090     // Is there a root element ?
    00091     cur = xmlDocGetRootElement(doc);
    00092     if (cur == 0) {
    00093         cerr << "XML file is empty" << endl ;
    00094         xmlFreeDoc(doc);
    00095         return 0 ;
    00096     }
    00097
    00098     // Is this root element an objectModel ?
    00099     if (xmlStrcmp(cur->name, (const xmlChar *) NODE_OBJECT_MODEL)) {
    00100         cerr << "Wrong XML file: not the expected root node" << endl ;
    00101         return 0 ;
    00102     }
    00103     D.Out(pdTrace, "XML file looks ok, starting main loop");
    00104
    00105     // First Loop (Routing Spaces)
    00106     cur = xmlDocGetRootElement(doc);
    00107     cur = cur->xmlChildrenNode ;
    00108     while (cur != NULL) {
    00109         if ((!xmlStrcmp(cur->name, NODE_ROUTING_SPACE))) {
    00110             D.Out(pdTrace, "Found a routing space");
    00111             xmlNodePtr prev = cur ;
    00112             this->parseRoutingSpace();
    00113             cur = prev ;
    00114         }
    00115         cur = cur->next ;
    00116     }
    00117
    00118     // Second Loop (Object and Interaction classes)
    00119     cur = xmlDocGetRootElement(doc);
    00120     cur = cur->xmlChildrenNode ;
    00121     while (cur != NULL) {
    00122         if ((!xmlStrcmp(cur->name, NODE_OBJECTS))) {
    00123             D.Out(pdTrace, "Found a group of object classes");
    00124             xmlNodePtr prev = cur ;
    00125             cur = cur->xmlChildrenNode ;
    00126             while (cur != NULL) {
    00127                 if ((!xmlStrcmp(cur->name, NODE_OBJECT_CLASS))) {
    00128                     this->parseClass(0);
    00129                 }
    00130                 cur = cur->next ;
    00131             }
    00132             cur = prev ;
    00133         }
    00134         if ((!xmlStrcmp(cur->name, NODE_INTERACTIONS))) {
    00135             D.Out(pdTrace, "Found a group of interaction classes");
    00136             xmlNodePtr prev = cur ;
    00137             cur = cur->xmlChildrenNode ;
    00138             while (cur != NULL) {
    00139                 if ((!xmlStrcmp(cur->name, NODE_INTERACTION_CLASS))) {
    00140                     this->parseInteraction(0);
    00141                 }
    00142                 cur = cur->next ;
    00143             }
    00144             cur = prev ;
    00145         }
    00146         cur = cur->next ;
    00147     }
    00148
    00149     xmlFreeDoc(doc);
    00150
    00151     D[pdTrace] << "XmlParser: finished parsing" << endl ;
    00152     return root ;
    00153 }
    00154
    00155 // ----------------------------------------------------------------------------
    00156 void
    00157 XmlParser::parseClass(ObjectClass* parent)
    00158 {
    00159     D[pdTrace] << "New Object Class" << endl ;
    00160
    00161     xmlNodePtr prev = cur ;
    00162     /* note how objectHandle counter is incremented */
    00163     ObjectClass* current = new ObjectClass(std::string(CleanXmlGetProp(cur,ATTRIBUTE_NAME)),freeObjectClassHandle++);
    00164
    00165     root->addObjectClass(current, parent);
    00166     cur = cur->xmlChildrenNode ;
    00167     while (cur != NULL) {
    00168         // Attributes
    00169         if ((!xmlStrcmp(cur->name, NODE_ATTRIBUTE))) {
    00170             std::string name = std::string(CleanXmlGetProp(cur,ATTRIBUTE_NAME));
    00171             TransportType transport;
    00172             OrderType order;
    00173
    00174             // Transportation
    00175             xmlChar* xtransport = xmlGetProp(cur, ATTRIBUTE_TRANSPORTATION);
    00176             if (!xmlStrcmp(xtransport,VALUE_RELIABLE)) {
    00177                 transport = RELIABLE ;
    00178             }
    00179             else {
    00180                 if (!xmlStrcmp(xtransport,VALUE_BESTEFFORT)) {
    00181                     transport = BEST_EFFORT ;
    00182                 }
    00183             }
    00184             xmlFree(xtransport);
    00185
    00186             // Order
    00187             xmlChar* xorder = xmlGetProp(cur, ATTRIBUTE_ORDER);
    00188             if (!xmlStrcmp(xorder, VALUE_TSO)) {
    00189                 order = TIMESTAMP ;
    00190             }
    00191             else {
    00192                 if (!xmlStrcmp(xorder, VALUE_RO)) {
    00193                     order = RECEIVE ;
    00194                 }
    00195             }
    00196             xmlFree(xorder);
    00197             ObjectClassAttribute *attr = new ObjectClassAttribute(name,transport,order);
    00198             // Routing space
    00199             char *space = (char *) xmlGetProp(cur, ATTRIBUTE_SPACE);
    00200             if (space) {
    00201                 SpaceHandle h ;
    00202                 try {
    00203                     h = root->getRoutingSpaceHandle(string(space));
    00204                 }
    00205                 catch (Exception &e) {
    00206                     cerr << "warning: Incorrect space name for attribute"
    00207                          << endl ;
    00208                 }
    00209                 attr->setSpace(h);
    00210             }
    00211             xmlFree(space);
    00212
    00213             // Attribute complete, adding to the class
    00214             current->addAttribute(attr);
    00215         }
    00216         // Subclass
    00217         if ((!xmlStrcmp(cur->name, NODE_OBJECT_CLASS))) {
    00218             this->parseClass(current);
    00219         }
    00220         cur = cur->next ;
    00221     }
    00222     cur = prev ;
    00223 }
    00224
    00225 // ----------------------------------------------------------------------------
    00226 void
    00227 XmlParser::parseInteraction(Interaction* parent)
    00228 {
    00229     D[pdTrace] << "New Interaction Class" << endl;
    00230     std::string name;
    00231     TransportType transport;
    00232     OrderType order;
    00233
    00234     xmlNodePtr prev = cur ;
    00235
    00236     // Name
    00237     name = std::string(CleanXmlGetProp(cur,ATTRIBUTE_NAME));
    00238
    00239     // Transportation
    00240     xmlChar* xtransport = xmlGetProp(cur, ATTRIBUTE_TRANSPORTATION);
    00241     if (!xmlStrcmp(xtransport, VALUE_RELIABLE)) {
    00242         transport = RELIABLE ;
    00243     }
    00244     else {
    00245         if (!xmlStrcmp(xtransport,VALUE_BESTEFFORT))  {
    00246             transport = BEST_EFFORT ;
    00247         }
    00248     }
    00249     xmlFree(xtransport);
    00250
    00251     // Order
    00252     xmlChar* xorder = xmlGetProp(cur, ATTRIBUTE_ORDER);
    00253     if (!xmlStrcmp(xorder, VALUE_TSO)) {
    00254         order = TIMESTAMP ;
    00255     }
    00256     else {
    00257         if (!xmlStrcmp(xorder, VALUE_RO)) {
    00258             order = RECEIVE ;
    00259         }
    00260     }
    00261     xmlFree(xorder);
    00262     Interaction* current = new Interaction(name,freeInteractionClassHandle++,transport,order);
    00263
    00264     // Routing space
    00265     char *space = (char *) xmlGetProp(cur, ATTRIBUTE_SPACE);
    00266     if (space) {
    00267         SpaceHandle h ;
    00268         try {
    00269             h = root->getRoutingSpaceHandle(string(space));
    00270         }
    00271         catch (Exception &e) {
    00272             cerr << "warning: Incorrect space name for interaction"
    00273                  << endl ;
    00274         }
    00275         current->setSpace(h);
    00276     }
    00277     xmlFree(space);
    00278
    00279     // Add to interactions list, and build inheritance relation
    00280     root->addInteractionClass(current,parent);
    00281
    00282     cur = cur->xmlChildrenNode ;
    00283     while (cur != NULL) {
    00284         if ((!xmlStrcmp(cur->name, NODE_PARAMETER))) {
    00285             Parameter *param = new Parameter();
    00286             param->setName(CleanXmlGetProp(cur,ATTRIBUTE_NAME));
    00287             param->setHandle(freeParameterHandle++);
    00288             current->addParameter(param);
    00289         }
    00290         // Subinteraction
    00291         if ((!xmlStrcmp(cur->name, NODE_INTERACTION_CLASS))) {
    00292             this->parseInteraction(current);
    00293         }
    00294         cur = cur->next ;
    00295     }
    00296     cur = prev ;
    00297 }
    00298
    00299 // ----------------------------------------------------------------------------
    00300 void
    00301 XmlParser::parseRoutingSpace()
    00302 {
    00303     D[pdTrace] << "New Routing Space" << endl ;
    00304
    00305     DimensionHandle freeDimensionHandle = 1 ;
    00306     xmlNodePtr prev = cur ;
    00307     RoutingSpace current ;
    00308     current.setHandle(freeSpaceHandle++);
    00309     current.setName(CleanXmlGetProp(cur,ATTRIBUTE_NAME));
    00310
    00311     // Dimensions
    00312     cur = cur->xmlChildrenNode ;
    00313     while (cur != NULL) {
    00314         if ((!xmlStrcmp(cur->name, NODE_DIMENSION))) {
    00315             Dimension dimension(freeDimensionHandle++);
    00316             dimension.setName(CleanXmlGetProp(cur,ATTRIBUTE_NAME));
    00317             current.addDimension(dimension);
    00318         }
    00319         cur = cur->next ;
    00320     }
    00321     // Routing Space should be added after the
    00322     // Dimension has been added since addRoutingSpace store a copy
    00323     // of the object and not a reference
    00324     // see bug #19534
    00325     // https://savannah.nongnu.org/bugs/?19534
    00326     root->addRoutingSpace(current);
    00327
    00328     cur = prev ;
    00329 }
    00330
    00331 // ----------------------------------------------------------------------------
    00332 bool
    00333 XmlParser::exists()
    00334 {
    00335     return true;
    00336 }
    00337
    00338 } // namespace certi
    00339
    00340 #else // !HAVE_XML
    00341
    00342 namespace certi {
    00343
    00344 XmlParser::XmlParser(RootObject *)
    00345 {
    00346 }
    00347
    00348 RootObject *XmlParser::parse(std::string)
    00349 {
    00350     return 0 ;
    00351 }
    00352
    00353 bool XmlParser::exists()
    00354 {
    00355     return false ;
    00356 }
    00357
    00358 } // namespace certi
    00359
    00360 #endif // HAVE_XML