Add nlohmann/json parser
[anna.git] / example / diameter / batchConverter / main.cpp
index 14300cc..7a7a2f4 100644 (file)
@@ -23,6 +23,7 @@
 #include <anna/xml/xml.hpp>
 #include <anna/diameter/stack/Engine.hpp>
 #include <anna/diameter/codec/Engine.hpp>
+#include <anna/diameter/codec/EngineManager.hpp>
 #include <anna/diameter/codec/Message.hpp>
 //#include <anna/diameter/codec/functions.hpp> // ApplicationId anna::diameter::codec::functions::getApplicationId(const anna::DataBlock &) throw(anna::RuntimeException);
 
@@ -30,8 +31,7 @@
 using namespace anna;
 using namespace anna::diameter;
 
-anna::diameter::codec::Message *G_codecMsg;
-anna::diameter::codec::Engine *G_codecEngine;
+anna::diameter::codec::Message G_codecMsg;
 
 bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) throw() {
   // Get hex string
@@ -68,14 +68,17 @@ void _exit(const std::string &message, int resultCode = 1) {
 }
 
 // Decodes a diameter message coming from a datablock
-void decodeDataBlock(const anna::DataBlock &db/*, unsigned int & detectedApplicationId*/) throw() {
+bool decodeDataBlock(const anna::DataBlock &db/*, unsigned int & detectedApplicationId*/) throw() {
   try {
-    //detectedApplicationId = anna::diameter::codec::functions::getApplicationId(db);
-    //G_codecEngine->setDictionary(detectedApplicationId); we enabled this feature in the codec engine: selectStackWithApplicationId(true);
-    G_codecMsg->decode(db);
+    G_codecMsg.clear();
+    G_codecMsg.decode(db);
   } catch(RuntimeException &ex) {
-    _exit(ex.asString());
+    std::cerr << ex.asString() << std::endl << std::endl;
+    //_exit(ex.asString());
+    return false;
   }
+
+  return true;
 }
 
 //-------------------------------------------------------------------
@@ -89,7 +92,7 @@ int main(int argc, char **argv) {
   if(argc < 3) {
     std::string msg = "Usage: "; msg += exec;
     msg += " <stacks> <working directory> [--hex-only] [--xml-only] [--no-validation] [--ignore-flags] [--debug]\n\n";
-    msg += "       stacks:                  <id1,dictionary1#id2,dictionary2#...#idN,dictionaryN>\n";
+    msg += "       stacks:                  <appid1,dictionary1#appid2,dictionary2#...#appidN,dictionaryN>\n";
     msg += "                                This is a list of #-separated stacks defined by a comma-separated pair <application-id,xml dictionary pathfile>\n";
     msg += "                                If only one stack is provided, application-id could be omitted and then, all the messages will be decoded with the\n";
     msg += "                                dictionary regardless the value of the application-id (the stack will be registered with id=0).\n";
@@ -122,12 +125,13 @@ int main(int argc, char **argv) {
   bool processHex = xmlOnly ? false:true;
   Logger::setLevel(debug ? Logger::Debug:Logger::Warning);
   Logger::initialize(execBN.c_str(), new TraceWriter(filetrace.c_str(), 2048000));
-  G_codecEngine = new anna::diameter::codec::Engine();
-  G_codecMsg = G_codecEngine->createMessage();
   anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
+  anna::diameter::codec::EngineManager &em = anna::diameter::codec::EngineManager::instantiate();
+  anna::diameter::codec::Engine *ce;
+  unsigned int appid = 0;
+
 
   // Register stacks:
-  bool multistack = false;
   try {
     anna::Tokenizer stacksTok;
     stacksTok.apply(stacks, "#");
@@ -141,26 +145,25 @@ int main(int argc, char **argv) {
       if(stackTok.size() == 1) {
         if(stacksTok.size() != 1)
           throw anna::RuntimeException("Application Id value is mandatory when more than one stack is going to be configured", ANNA_FILE_LOCATION);
-
-        anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* no matter */, stack); // the stack is the dictionary
-        G_codecEngine->setDictionary(d);
+        anna::diameter::stack::Dictionary *d = stackEngine.createDictionary(appid, stack); // the stack is the dictionary
+        ce = new anna::diameter::codec::Engine("CodecEngineForUniqueStackId_0", d);
+        em.registerCodecEngine(0, ce);
         break;
       }
 
       if(stackTok.size() != 2)
-        throw anna::RuntimeException("Each stack must be in the form '<application-id>#<xml dictionary pathfile>'", ANNA_FILE_LOCATION);
+        throw anna::RuntimeException("Each stack must be in the form '<application-id>,<xml dictionary pathfile>'", ANNA_FILE_LOCATION);
 
-      multistack = true;
       stack_it = stackTok.begin();
       unsigned int stackId = atoll(anna::Tokenizer::data(stack_it));
       stack_it++;
       std::string file = anna::Tokenizer::data(stack_it);
-      anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(stackId, file);
+      anna::diameter::stack::Dictionary *d = stackEngine.createDictionary(stackId, file);
+      std::string codecEngineName = anna::functions::asString("CodecEngineForStackId_%llu", stackId);
+      ce = new anna::diameter::codec::Engine(codecEngineName.c_str(), d);
+      em.registerCodecEngine(stackId, ce);
     }
 
-    // Auto stack selection based on Application-ID:
-    if (multistack) G_codecEngine->selectStackWithApplicationId(true);
-
     std::cout << "Stacks provided:          " << std::endl;
     std::cout << anna::functions::tab(stackEngine.asString(false /* light */));
     std::cout << std::endl;
@@ -173,10 +176,13 @@ int main(int argc, char **argv) {
   }
 
   // Validation kindness
-  G_codecEngine->setFixMode(anna::diameter::codec::EngineImpl::FixMode::Never); // we will encode "as is" (because --no-validation is assumed as user desire)
-  G_codecEngine->setValidationDepth(anna::diameter::codec::EngineImpl::ValidationDepth::Complete); // complete validation for better reports
-  if(no_validation) G_codecEngine->setValidationMode(anna::diameter::codec::EngineImpl::ValidationMode::Never);
-  if(ignore_flags) G_codecEngine->ignoreFlagsOnValidation(true);
+  for (anna::diameter::codec::appid_codec_engines_it it = em.begin(); it != em.end(); it++) {
+    ce = it->second;
+    ce->setFixMode(anna::diameter::codec::EngineImpl::FixMode::Never); // we will encode "as is" (because --no-validation is assumed as user desire)
+    ce->setValidationDepth(anna::diameter::codec::EngineImpl::ValidationDepth::Complete); // complete validation for better reports
+    if(no_validation) ce->setValidationMode(anna::diameter::codec::EngineImpl::ValidationMode::Never);
+    if(ignore_flags) ce->ignoreFlagsOnValidation(true);
+  }
 
   // Auxiliary variables:
   anna::DataBlock db_aux(true);
@@ -188,7 +194,7 @@ int main(int argc, char **argv) {
   directoryHex.read(wkDir.c_str(), anna::io::Directory::Mode::FullPath);
   directoryXml.setPattern(".xml$");
   directoryXml.read(wkDir.c_str(), anna::io::Directory::Mode::FullPath);
-  
+
   // Processing .hex files:
   bool anyHexConverted = false;
   if (processHex) {
@@ -200,15 +206,16 @@ int main(int argc, char **argv) {
         _exit("Error reading hex file provided");
 
       // Decode datablock:
-      decodeDataBlock(db_aux);
+      if (decodeDataBlock(db_aux)) {
 
-      // Write conversion:
-      std::string outputFile = entry + ".as.xml";
-      std::ofstream out(outputFile.c_str(), std::ifstream::out);
-      out << G_codecMsg->asXMLString();
-      out.close();
+        // Write conversion:
+        std::string outputFile = entry + ".as.xml";
+        std::ofstream out(outputFile.c_str(), std::ifstream::out);
+        out << G_codecMsg.asXMLString();
+        out.close();
 
-      anyHexConverted = true;
+        anyHexConverted = true;
+      }
     }
   }
 
@@ -218,17 +225,17 @@ int main(int argc, char **argv) {
     for (anna::io::Directory::const_iterator it = directoryXml.begin(); it != directoryXml.end(); it++) {
       const std::string& entry = anna::io::Directory::data (it);
       LOGDEBUG(anna::Logger::debug(entry + " is being converted to hex", ANNA_FILE_LOCATION));
-  
+
       // Load file:
-      G_codecMsg->loadXML(entry);  
-      
+      G_codecMsg.loadXMLFile(entry);
+
       // Write conversion:
-      std::string hexString = anna::functions::asHexString(G_codecMsg->code());
+      std::string hexString = anna::functions::asHexString(G_codecMsg.code());
       std::string outputFile = entry + ".as.hex";
       std::ofstream out(outputFile.c_str(), std::ifstream::out);
       out.write(hexString.c_str(), hexString.size());
       out.close();
-  
+
       anyXmlConverted = true;
     }
   }