NodeCfg.cc 3.96 KB
/**
 * NodeCfg.cc
 *
 *  Created on: 22 oct. 2012
 *      Author: AKKA IS
 */

#include <iostream>
#include <sstream>
#include <string>

#include <boost/algorithm/string.hpp>

    using namespace std;
    using namespace boost;

#include <libxml/parser.h>
#include <libxml/xmlstring.h>
#include <libxml/xmlschemas.h>

#include "Config.hh"
#include "Constant.hh"
#include "NodeCfg.hh"

namespace AMDA
{
  namespace XMLConfigurator
  {
    //TODO Push log into log4cxx http://stackoverflow.com/questions/12107423/libxml2-get-validation-errors
    //http://xml.developpez.com/telecharger/detail/id/2561/Comment-valider-un-XML-via-un-XSD-en-C-avec-libXML2
    //http://knol2share.blogspot.fr/2009/05/validate-xml-against-xsd-in-c.html
    //http://wiki.njh.eu/XML-Schema_validation_with_libxml2
    int NodeCfg::getIsValid(const xmlNodePtr elem, const char *schema_filename)
    {
      xmlDocPtr schema_doc = xmlReadFile(schema_filename, NULL, XML_PARSE_NONET);
      if (schema_doc == NULL)
        {
          std::cerr << "the schema cannot be loaded or is not well-formed" << std::endl;
          return -1;
        }

      xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(schema_doc);
      if (parser_ctxt == NULL)
        {
           std::cerr << "unable to create a parser context for the schema" << std::endl;
          xmlFreeDoc(schema_doc);
          return -2;
        }

      xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);
      if (schema == NULL)
        {
          std::cerr << "the schema itself is not valid" << std::endl;
          xmlSchemaFreeParserCtxt(parser_ctxt);
          xmlFreeDoc(schema_doc);
          return -3;
        }

      xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);
      if (valid_ctxt == NULL)
        {
          std::cerr << "unable to create a validation context for the schema" << std::endl;
          xmlSchemaFree(schema);
          xmlSchemaFreeParserCtxt(parser_ctxt);
          xmlFreeDoc(schema_doc);
          return -4;
        }

      int is_valid = (xmlSchemaValidateOneElement(valid_ctxt, elem) == 0);

      xmlSchemaFreeValidCtxt(valid_ctxt);
      xmlSchemaFree(schema);
      xmlSchemaFreeParserCtxt(parser_ctxt);
      xmlFreeDoc(schema_doc);

      /* force the return value to be non-negative on success */
      return is_valid ? 1 : 0;
    }

    void NodeGrpCfg::proceed(xmlNodePtr pNode, const AMDA::Parameters::CfgContext& pCtx)
    {
      xmlNodePtr lNode = pNode->xmlChildrenNode;
      while (lNode)
        {
          if ( xmlStrcmp(lNode->name, (const xmlChar *) "text") != 0)
            {
              CfgChildList::iterator it = _cfgChildList.find( std::string((const char*) lNode->name));
              if (it != _cfgChildList.end())
                {
                  it->second->proceed(lNode, pCtx);
                }
              else if (lNode->type != XML_COMMENT_NODE) 
                { //skip warning on comment
                  LOG4CXX_WARN( gLogger, WARNING_NODE_NOT_SUPPORTED << (const char*) lNode->name);
                }
            }
          lNode = lNode->next;
        }
    }

		void NodeGrpCfg::addNodeParser( const char* pXPath, NodeCfgSPtr pNode) {
			addNodeParser( &_cfgChildList, pXPath, pNode);
		}

		void NodeGrpCfg::addNodeParser( CfgChildList* lChildList, const char* pXPath, NodeCfgSPtr pNode) {
		  std::string lXPath = pXPath;
		  NodeGrpCfg* lCurNode = NULL;
		  std::vector <std::string> fields;
		  boost::split( fields, lXPath, boost::is_any_of( "/" ) );
		  int lNbField = fields.size();
		  bool cont = true;
		  for (int i = 0; cont && i < lNbField; ++i) {
			  if ( (i+1) == lNbField) {
				  (*lChildList)[fields[i]]=pNode;
				  cont=false;
			  } else {
				  if((lCurNode = dynamic_cast<NodeGrpCfg*>((*lChildList)[fields[i]].get()))) {
					  lChildList = &lCurNode->getChildList();
				  } else {
					  ERROR_EXCEPTION( "XMLParameterConfigurator::addNode not found group node: " << fields[i]);
				  }
			  }
		  }
	  }


  } /* namespace XMLConfigurator */
} /* namespace AMDA */