OpenTracker

An Open Architecture for Reconfigurable Tracking based on XML | Contact

ConfigurationParser.cxx

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (c) 2006,
00003  * Institute for Computer Graphics and Vision
00004  * Graz University of Technology
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  * Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the following disclaimer.
00013  *
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the distribution.
00017  *
00018  * Neither the name of the Graz University of Technology nor the names of
00019  * its contributors may be used to endorse or promote products derived from
00020  * this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00023  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00024  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00025  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00026  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * ========================================================================
00034  * PROJECT: OpenTracker
00035  * ======================================================================== */
00042 /* ======================================================================= */
00043 
00044 #include <stdlib.h>
00045 #include "../tool/FixWinCE.h"
00046 #include <ace/Log_Msg.h>
00047 #include <ace/Env_Value_T.h>
00048 #include "../tool/OT_ACE_Log.h"
00049 
00050 #include "ConfigurationParser.h"
00051 
00052 #ifdef USE_XERCES
00053 #include <xercesc/dom/DOM.hpp>
00054 #include <xercesc/util/XMLString.hpp>
00055 #include <xercesc/util/XMLUniDefs.hpp>
00056 #include <xercesc/parsers/XercesDOMParser.hpp>
00057 #include <xercesc/util/PlatformUtils.hpp>
00058 #include <xercesc/util/XMLEntityResolver.hpp>
00059 #include <xercesc/framework/LocalFileInputSource.hpp>
00060 #endif //USE_XERCES
00061 
00062 #include "DOMTreeErrorReporter.h"
00063 #include "RefNode.h"
00064 
00065 #include <iostream>
00066 
00067 //using namespace std;
00068 
00069 #ifdef USE_XERCES
00070 XERCES_CPP_NAMESPACE_USE
00071 #endif //USE_XERCES
00072 
00073 
00074 namespace ot {
00075 
00076 #ifdef USE_XERCES
00077     const XMLCh ud_node[] = { chLatin_n, chLatin_o, chLatin_d, chLatin_e, chNull };
00078 
00079     class OpenTrackerResolver : public XMLEntityResolver {
00080     protected:
00081         Context * context;
00082 
00083     public:
00084         OpenTrackerResolver ( Context * context_ ) : context(context_)
00085         {};
00086 
00087         virtual InputSource * resolveEntity( XMLResourceIdentifier * resourceIdentifier );
00088     };
00089 
00090     InputSource * OpenTrackerResolver::resolveEntity( XMLResourceIdentifier * resourceIdentifier )
00091     {
00092         if (resourceIdentifier->getResourceIdentifierType() == XMLResourceIdentifier::ExternalEntity)
00093         {
00094             XMLCh * test = XMLString::transcode("opentracker.dtd");
00095             if(XMLString::endsWith(resourceIdentifier->getSystemId(), test))
00096             {
00097                 ACE_Env_Value<std::string> otroot(ACE_TEXT("OTROOT"), "");
00098                 std::string otrootvalue = (std::string)otroot;
00099                 std::string otdatadir;
00100                 if( otrootvalue.compare("") != 0 )
00101                 {
00102                     otdatadir = otrootvalue + "/data";
00103                     context->addDirectoryLast(otdatadir);
00104                 }
00105                 char * file = XMLString::transcode(resourceIdentifier->getSystemId());
00106                 std::string filename( file ), fullname;
00107                 XMLString::release( &file );
00108                 bool result = context->findFile( filename, fullname );
00109                 if( otrootvalue.compare("") != 0 )
00110                 {
00111                     context->removeDirectory(otdatadir);
00112                 }
00113                 if( result == true )
00114                 {
00115                     XMLCh * file = XMLString::transcode( fullname.c_str());
00116                     LocalFileInputSource * input = new LocalFileInputSource( file );
00117                     XMLString::release( &file );
00118                     XMLString::release( &test );
00119                     return input;
00120                 }
00121             }
00122             XMLString::release( &test );
00123         }
00124         return NULL;
00125     }
00126 
00127 #endif //USE_XERCES
00128 
00129     // constructor method
00130 
00131     ConfigurationParser::ConfigurationParser( Context & context_)
00132         : context( context_ )
00133     {
00134 #ifdef USE_XERCES
00135         // Initialize the XercesC system
00136         try {
00137             XMLPlatformUtils::Initialize();
00138         }
00139         catch (const XMLException& toCatch) {
00140             char * message = XMLString::transcode( toCatch.getMessage());
00141             LOG_ACE_ERROR( "ot: ConfigurationParser Error during initialization: %s\n", message );
00142             XMLString::release( &message );
00143             exit(1);
00144         }
00145 #endif //USE_XERCES
00146     }
00147 
00148     // Destructor method.
00149 
00150     ConfigurationParser::~ConfigurationParser()
00151     {
00152         references.clear();
00153     }
00154 
00155     // builds a tree of configuration nodes.
00156 
00157     ConfigNode * ConfigurationParser::buildConfigTree( OT_DOMELEMENT * element )
00158     {
00159 #ifdef USE_XERCES
00160         std::auto_ptr<StringTable> map ( parseElement( element ));
00161         char * tempName = XMLString::transcode( element->getLocalName());
00162         std::string tagName = tempName;
00163         XMLString::release( &tempName );
00164         ConfigNode * config = new ConfigNode( *map );
00165         config->setParent( element );
00166         //auto_ptr<DOMNodeList> list( element->getChildNodes());
00167         DOMNodeList * list = element->getChildNodes();
00168         for( unsigned int i = 0; i < list->getLength(); i ++ )
00169         {
00170             if( list->item(i)->getNodeType() == DOMNode::ELEMENT_NODE )
00171             {
00172                 OT_DOMELEMENT * childElement = (OT_DOMELEMENT *)list->item(i);
00173                 ConfigNode * child = buildConfigTree( childElement );
00174             }
00175         }
00176         return config;
00177 #endif //USE_XERCES
00178 
00179 #ifdef USE_TINYXML
00180         std::auto_ptr<StringTable> map ( parseElement( element ));
00181         std::string tagName = element->Value();
00182         ConfigNode * config = new ConfigNode( *map );
00183         config->setParent( element );
00184 
00185         TiXmlElement * el = element->FirstChildElement();
00186         while( el != NULL )
00187         {
00188             ConfigNode * child = buildConfigTree( el);
00189             el = el->NextSiblingElement();
00190         }
00191         return config;
00192 #endif //USE_TINYXML
00193     }
00194 
00195     // builds the tracker tree starting from a certain DOM_Element.
00196 
00197     Node * ConfigurationParser::buildTree( OT_DOMELEMENT * element)
00198     {
00199 #ifdef USE_XERCES
00200         char * tempName = XMLString::transcode( element->getLocalName());
00201         std::string tagName = tempName;
00202         XMLString::release( &tempName );
00203         std::auto_ptr<StringTable> map ( parseElement( element ));
00204         // Test for a reference node
00205         if( tagName.compare("Ref") == 0 )
00206         {
00207             NodeMap::iterator find = references.find(map->get("USE"));
00208             if( find != references.end()){
00209                 RefNode * ref = new RefNode( (*find).second );
00210                 ref->type = tagName;
00211                 ref->setParent( element );
00212                 LOG_ACE_INFO("ot:Build Reference node -> %s\n", map->get("USE").c_str());
00213                 return ref;
00214             } else
00215             {
00216                 LOG_ACE_ERROR("ot:Undefined reference %s\n", map->get("USE").c_str());
00217                 return NULL;
00218             }
00219         }
00220 
00221         Node * value = context.factory.createNode( tagName , *map );
00222         if( value != NULL )
00223         {
00224             value->setParent( element );
00225             // Test for ID
00226             if( map->containsKey("DEF"))
00227             {
00228                 references[map->get("DEF")] = value;
00229                 value->name = map->get("DEF");
00230                 LOG_ACE_INFO("ot:Storing Reference %s\n", map->get("USE").c_str());
00231             }
00232             //auto_ptr<DOMNodeList> list ( element->getChildNodes());
00233             DOMNodeList * list = element->getChildNodes();
00234             for( unsigned int i = 0; i < list->getLength(); i ++ )
00235             {
00236                 if( list->item(i)->getNodeType() == DOMNode::ELEMENT_NODE )
00237                 {
00238                     OT_DOMELEMENT * childElement = (OT_DOMELEMENT *)list->item(i);
00239                     Node * childNode = buildTree( childElement );
00240                 }
00241             }
00242         }
00243         else
00244         {
00245             LOG_ACE_INFO("ot:Warning : Could not parse element %s\n", tagName.c_str());
00246         }
00247         return value;
00248 #endif //USE_XERCES
00249 
00250 #ifdef USE_TINYXML
00251         std::string tagName = element->Value();
00252         std::auto_ptr<StringTable> map ( parseElement( element ));
00253         // Test for a reference node
00254         if( tagName.compare("Ref") == 0 )
00255         {
00256             NodeMap::iterator find = references.find(map->get("USE"));
00257             if( find != references.end()){
00258                 RefNode * ref = new RefNode( (*find).second );
00259                 ref->type = tagName;
00260                 ref->setParent( element );
00261                 LOG_ACE_INFO("ot:Build Reference node -> %s\n", map->get("USE").c_str());
00262                 return ref;
00263             } else
00264             {
00265                 LOG_ACE_ERROR("ot:Undefined reference %s\n", map->get("USE").c_str());
00266                 return NULL;
00267             }
00268         }
00269 
00270         Node * value = context.factory.createNode( tagName , *map );
00271         if( value != NULL )
00272         {
00273             value->setParent( element );
00274             // Test for ID
00275             if( map->containsKey("DEF"))
00276             {
00277                 references[map->get("DEF")] = value;
00278                 value->name = map->get("DEF");
00279                 LOG_ACE_INFO("ot:Storing Reference %s\n", map->get("USE").c_str());
00280             }
00281 
00282             TiXmlElement * el = element->FirstChildElement();
00283             while( el != NULL )
00284             {
00285                 Node * childNode = buildTree( el );
00286                 el = el->NextSiblingElement();
00287             }
00288         }
00289         else
00290         {
00291             LOG_ACE_INFO("ot:Warning : Could not parse element %s\n", tagName.c_str());
00292         }
00293         return value;
00294 #endif //USE_TINYXML
00295     }
00296 
00297 
00298     // This method parses an XML configuration file.
00299 
00300     Node * ConfigurationParser::parseConfigurationFile(const std::string& filename)
00301     {
00302 #ifdef USE_XERCES
00303         // read and parse configuration file
00304         XercesDOMParser * parser = new XercesDOMParser();
00305         parser->setValidationScheme( XercesDOMParser::Val_Auto );
00306         parser->setIncludeIgnorableWhitespace( false );
00307         parser->setDoNamespaces(true);
00308         parser->setDoSchema(true);
00309 
00310         OpenTrackerResolver resolver( &context);
00311         parser->setXMLEntityResolver( &resolver );
00312 
00313         DOMTreeErrorReporter errReporter;
00314         parser->setErrorHandler( &errReporter );
00315 
00316         try
00317         {
00318             parser->parse( filename.c_str() );
00319         }
00320         catch (const XMLException& e)
00321         {
00322             char * message = XMLString::transcode( e.getMessage());
00323             LOG_ACE_ERROR("ot:An error occured during parsing\n   Message: %s\n", message);
00324             XMLString::release( & message );
00325             exit(1);
00326         }
00327         catch (const DOMException& e)
00328         {
00329             char * message = XMLString::transcode( e.msg );
00330             LOG_ACE_ERROR("ot:An error occured during parsing\n   Message: %s\n", message);
00331             XMLString::release( & message );
00332             exit(1);
00333         }
00334         if( errReporter.errorsEncountered() > 0 )
00335         {
00336             LOG_ACE_ERROR("ot:There were non fatal errors in the configuration file !\n");
00337             LOG_ACE_ERROR("ot:Please check the file and start again.\n");
00338             exit(1);
00339         }
00340 
00341         DOMDocument * doc = parser->getDocument();
00342         DOMElement * root = doc->getDocumentElement();
00343         Node * node = new Node();
00344         node->setParent( root );
00345         char * tempName = XMLString::transcode( root->getLocalName());
00346         LOG_ACE_INFO("ot:Root node is %s\n", tempName);
00347         XMLString::release( & tempName );
00348 
00349         const XMLCh* xmlspace = root->getNamespaceURI();
00350         if (xmlspace != NULL) {
00351             char * tempSpace = XMLString::transcode( xmlspace );
00352             LOG_ACE_INFO("ot:Namespace is %s\n", tempSpace);
00353             XMLString::release( & tempSpace );
00354         }
00355         else {
00356             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Not using namespaces!\n")));
00357         }
00358 
00359         // get the configuration part
00360         XMLCh * configurationCh = XMLString::transcode( "configuration" );
00361         //auto_ptr<DOMNodeList> list( root->getElementsByTagName( configurationCh.get() ));
00362         DOMNodeList * list = root->getElementsByTagNameNS(xmlspace, configurationCh);
00363         XMLString::release( & configurationCh );
00364         if( list->getLength() != 1 )
00365         {
00366             ACE_DEBUG((LM_ERROR, ACE_TEXT("ot:not valid config file, not exactly one configuration tag\n")));
00367             LOG_ACE_INFO("ot:%d configurations.\n", list->getLength());
00368             exit(1);
00369         }
00370 
00371         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:parsing configuration section\n")));
00372 
00373         // parse configuration elements subelements
00374         DOMElement * config = (DOMElement *)list->item(0);
00375         //auto_ptr<DOMNodeList> configlist( config->getChildNodes());
00376         DOMNodeList * configlist = config->getChildNodes();
00377         unsigned int i;
00378         for( i = 0; i < configlist->getLength(); i ++ )
00379         {
00380             if( configlist->item(i)->getNodeType() == DOMNode::ELEMENT_NODE )
00381             {
00382                 DOMElement * configElement = (DOMElement *)configlist->item(i);
00383                 std::auto_ptr<StringTable> attributes( parseElement( configElement ));
00384                 char * tempName = XMLString::transcode( configElement->getLocalName());
00385                 std::string tagName = tempName;
00386                 XMLString::release( &tempName );
00387                 ConfigNode * base = new ConfigNode( *attributes );
00388                 base->setParent( configElement );
00389                 LOG_ACE_INFO("ot:config for %s\n", tagName.c_str());
00390 
00391                 //auto_ptr<DOMNodeList> nodelist( configElement->getChildNodes());
00392                 DOMNodeList * nodelist = configElement->getChildNodes();
00393 
00394                 unsigned int j;
00395                 for( j = 0; j < nodelist->getLength(); j++ )
00396                 {
00397                     if( nodelist->item(j)->getNodeType() == DOMNode::ELEMENT_NODE )
00398                     {
00399                         DOMElement * element = (DOMElement *)nodelist->item(j);
00400                         ConfigNode * child = buildConfigTree( element );
00401                     }
00402                 }
00403                 Module * module = context.getModule( tagName );
00404                 if( module != NULL )
00405                 {
00406                     module->init( *attributes, base );
00407                 }
00408             }
00409         }
00410 
00411         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:parsing tracker tree section\n")));
00412 
00413         // parse the rest of the elements
00414         //auto_ptr<DOMNodeList> rootlist( root->getChildNodes());
00415         DOMNodeList * rootlist = root->getChildNodes();
00416         for( i = 0; i < rootlist->getLength(); i++ )
00417         {
00418             if( rootlist->item(i)->getNodeType() != DOMNode::ELEMENT_NODE )   // not an element node !
00419             {
00420                 continue;
00421             }
00422             DOMElement * element = (DOMElement *)rootlist->item(i);
00423             char * tempTagName = XMLString::transcode(element->getLocalName());
00424             if( 0 == XMLString::compareString( tempTagName, "configuration" ))    // the configuration element, already handled
00425             {
00426                 XMLString::release( &tempTagName );
00427                 continue;
00428             }
00429             XMLString::release( &tempTagName );
00430             buildTree( element );
00431         }
00432         return node;
00433 #endif //USE_XERCES
00434 
00435 
00436 #ifdef USE_TINYXML
00437         TiXmlDocument* document = new TiXmlDocument();
00438 
00439         if(!document->LoadFile(filename.c_str()))
00440         {
00441             LOG_ACE_ERROR("ot:An error occured during parsing\n   Message: %s\n", document->ErrorDesc());
00442             exit(1);
00443         }
00444 
00445         TiXmlElement* root = document->RootElement();
00446         Node * node = new Node();
00447         node->setParent( root );
00448         const char* tempName = root->Value();
00449 
00450         LOG_ACE_INFO("ot:Root node is %s\n", tempName);
00451 
00452         const char* xmlspace = NULL; //root->getNamespaceURI();
00453         if (xmlspace != NULL) {
00454             LOG_ACE_INFO("ot:Namespace is %s\n", xmlspace);
00455         }
00456         else {
00457             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:Not using namespaces!\n")));
00458         }
00459 
00460         // get the configuration part
00461         const char* configurationCh = "configuration";
00462 
00463         TiXmlElement * config = root->FirstChildElement(configurationCh);
00464         if(config->NextSiblingElement(configurationCh))
00465         {
00466             ACE_DEBUG((LM_INFO, ACE_TEXT("ot:not valid config file, not exactly one configuration tag\n")));
00467             exit(1);
00468         }
00469 
00470         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:parsing configuration section\n")));
00471 
00472         TiXmlElement * configElement = config->FirstChildElement();
00473         while(configElement)
00474         {
00475             std::auto_ptr<StringTable> attributes( parseElement( configElement ));
00476             std::string tagName = configElement->Value();
00477             ConfigNode * base = new ConfigNode( *attributes );
00478             base->setParent( configElement );
00479             LOG_ACE_INFO("ot:config for %s\n", tagName.c_str());
00480 
00481             TiXmlElement * element = configElement->FirstChildElement();
00482             while(element)
00483             {
00484                 ConfigNode * child = buildConfigTree( element );
00485                 element = element->NextSiblingElement();
00486             }
00487 
00488             Module * module = context.getModule( tagName );
00489             if( module != NULL )
00490             {
00491                 module->init( *attributes, base );
00492             }
00493 
00494             configElement = configElement->NextSiblingElement();
00495         }
00496 
00497         ACE_DEBUG((LM_INFO, ACE_TEXT("ot:parsing tracker tree section\n")));
00498 
00499         // parse the rest of the elements
00500 
00501         TiXmlElement * element = root->FirstChildElement();
00502         while(element)
00503         {
00504             if(strcmp(element->Value(), "configuration")!=0)
00505                 buildTree( element );
00506 
00507             element = element->NextSiblingElement();
00508         }
00509 
00510         return node;
00511 #endif //USE_TINYXML
00512     }
00513 
00514     // parses an Elements attributes and returns a StringMap describing them.
00515 
00516     StringTable * ConfigurationParser::parseElement( OT_DOMELEMENT * element)
00517     {
00518 #ifdef USE_XERCES
00519         StringTable * value = new StringTable;
00520         // auto_ptr<DOMNamedNodeMap> map( element->getAttributes());   // is it still owned by the library ?
00521         DOMNamedNodeMap * map = element->getAttributes();
00522         for( unsigned int i = 0; i < map->getLength(); i++ )
00523         {
00524             DOMAttr * attribute = (DOMAttr *)map->item( i );
00525             char * nameTemp = XMLString::transcode( attribute->getName());
00526             char * valueTemp = XMLString::transcode( attribute->getValue());
00527             value->put(nameTemp, valueTemp );
00528             XMLString::release( &valueTemp );
00529             XMLString::release( &nameTemp );
00530         }
00531         return value;
00532 #endif //USE_XERCES
00533 
00534 
00535 #ifdef USE_TINYXML
00536         StringTable * value = new StringTable;
00537 
00538         TiXmlAttribute* attribute = element->FirstAttribute();
00539         while(attribute)
00540         {
00541             value->put(attribute->Name(), attribute->Value());
00542             attribute = attribute->Next();
00543         }
00544         return value;
00545 #endif //USE_TINYXML
00546     }
00547 
00548 
00549 } // namespace ot
00550 
00551 /* 
00552  * ------------------------------------------------------------
00553  *   End of ConfigurationParser.cxx
00554  * ------------------------------------------------------------
00555  *   Automatic Emacs configuration follows.
00556  *   Local Variables:
00557  *   mode:c++
00558  *   c-basic-offset: 4
00559  *   eval: (c-set-offset 'substatement-open 0)
00560  *   eval: (c-set-offset 'case-label '+)
00561  *   eval: (c-set-offset 'statement 'c-lineup-runin-statements)
00562  *   eval: (setq indent-tabs-mode nil)
00563  *   End:
00564  * ------------------------------------------------------------ 
00565  */

copyright (c) 2006 Graz University of Technology