void AgentConfiguration::loadNamespace(dlib::config_reader::kernel_1a &aReader,
                                       const char *aNamespaceType,
                                       NamespaceFunction *aCallback)
{
  // Load namespaces, allow for local file system serving as well.
  if (aReader.is_block_defined(aNamespaceType)) {
    const config_reader::kernel_1a &namespaces = aReader.block(aNamespaceType);
    vector<string> blocks;
    namespaces.get_blocks(blocks);
    
    vector<string>::iterator block;
    for (block = blocks.begin(); block != blocks.end(); ++block)
    {
      const config_reader::kernel_1a &ns = namespaces.block(*block);
      if (*block != "m" && !ns.is_key_defined("Urn"))
      {
        sLogger << LERROR << "Name space must have a Urn: " << *block;
      } else {
        string location, urn;
        if (ns.is_key_defined("Location"))
          location = ns["Location"];
        if (ns.is_key_defined("Urn"))
          urn = ns["Urn"];        
        (*aCallback)(urn, location, *block);
        if (ns.is_key_defined("Path") && !location.empty())
          mAgent->registerFile(location, ns["Path"]);        
      }
    }
  }
}
void AgentConfiguration::loadFiles(dlib::config_reader::kernel_1a &aReader)
{
  if (aReader.is_block_defined("Files")) {
    const config_reader::kernel_1a &files = aReader.block("Files");
    vector<string> blocks;
    files.get_blocks(blocks);
    
    vector<string>::iterator block;
    for (block = blocks.begin(); block != blocks.end(); ++block)
    {
      const config_reader::kernel_1a &file = files.block(*block);
      if (!file.is_key_defined("Location") || !file.is_key_defined("Path"))
      {
        sLogger << LERROR << "Name space must have a Uri and Path: " << *block;
      } else {
        mAgent->registerFile(file["Location"], file["Path"]);
      }
    }
  }
}
void AgentConfiguration::configureLogger(dlib::config_reader::kernel_1a &aReader)
{
  if (mLoggerFile != NULL)
    delete mLoggerFile;

  if (mIsDebug) {
    set_all_logging_output_streams(cout);
    set_all_logging_levels(LDEBUG);
  }
  else
  {
    string name("agent.log");
    RollingFileLogger::RollingSchedule sched = RollingFileLogger::NEVER;
    int maxSize = 10 * 1024 * 1024;
    int maxIndex = 9;
    
    if (aReader.is_block_defined("logger_config"))
    {
      const config_reader::kernel_1a& cr = aReader.block("logger_config");
      
      if (cr.is_key_defined("logging_level"))
        set_all_logging_levels(string_to_log_level(cr["logging_level"]));
      else
        set_all_logging_levels(LINFO);
      
      if (cr.is_key_defined("output"))
      {
        string output = cr["output"];
        if (output == "cout")
          set_all_logging_output_streams(cout);
        else if (output == "cerr")
          set_all_logging_output_streams(cerr);
        else
        {
          istringstream sin(output);
          string one, two, three;
          sin >> one;
          sin >> two;
          sin >> three;
          if (one == "file" && three.size() == 0)
            name = two;
          else
            name = one;
        }
      }
      
      string maxSizeStr = get_with_default(cr, "max_size", "10M");
      stringstream ss(maxSizeStr);
      char mag = '\0';
      ss >> maxSize >> mag;

      switch(mag) {
      case 'G': case 'g': maxSize *= 1024;
      case 'M': case 'm': maxSize *= 1024;
      case 'K': case 'k': maxSize *= 1024;
      case 'B': case 'b': case '\0':
        break;
      }
        
      maxIndex = get_with_default(cr, "max_index", maxIndex);
      string schedCfg = get_with_default(cr, "schedule", "NEVER");
      if (schedCfg == "DAILY")
        sched = RollingFileLogger::DAILY;
      else if (schedCfg == "WEEKLY")
        sched = RollingFileLogger::WEEKLY;
    }
    
    mLoggerFile = new RollingFileLogger(name, maxIndex, maxSize, sched);
    set_all_logging_output_hooks<AgentConfiguration>(*this, &AgentConfiguration::LoggerHook);
  }
void AgentConfiguration::loadAdapters(dlib::config_reader::kernel_1a &aReader,
                                      bool aDefaultPreserve, int aLegacyTimeout,
                                      int aReconnectInterval, bool aIgnoreTimestamps)
{
  Device *device;
  if (aReader.is_block_defined("Adapters")) {
    const config_reader::kernel_1a &adapters = aReader.block("Adapters");
    vector<string> blocks;
    adapters.get_blocks(blocks);
    
    vector<string>::iterator block;
    for (block = blocks.begin(); block != blocks.end(); ++block)
    {      
      const config_reader::kernel_1a &adapter = adapters.block(*block);
      string deviceName;      
      if (adapter.is_key_defined("Device")) {
        deviceName = adapter["Device"].c_str();
        if (deviceName == "*")
          device = defaultDevice();
        else
          device = mAgent->getDeviceByName(deviceName);
      } else {
        deviceName = *block;
        device = mAgent->getDeviceByName(deviceName);
        
        if (device == NULL && mAgent->getDevices().size() == 1)
          device = defaultDevice();
      }
      
      if (device == NULL) {
        throw runtime_error(static_cast<string>("Can't locate device '") + deviceName + "' in XML configuration file.");
      }
      
      const string host = get_with_default(adapter, "Host", (string)"localhost");
      int port = get_with_default(adapter, "Port", 7878);
      int legacyTimeout = get_with_default(adapter, "LegacyTimeout", aLegacyTimeout);
      int reconnectInterval = get_with_default(adapter, "ReconnectInterval", aReconnectInterval);

      
      sLogger << LINFO << "Adding adapter for " << device->getName() << " on "
              << host << ":" << port;
      Adapter *adp = mAgent->addAdapter(device->getName(), host, port, false, legacyTimeout);
      device->mPreserveUuid = get_bool_with_default(adapter, "PreserveUUID", aDefaultPreserve);
      
      // Add additional device information
      if (adapter.is_key_defined("UUID"))
        device->setUuid(adapter["UUID"]);
      if (adapter.is_key_defined("Manufacturer"))
        device->setManufacturer(adapter["Manufacturer"]);
      if (adapter.is_key_defined("Station"))
        device->setStation(adapter["Station"]);
      if (adapter.is_key_defined("SerialNumber"))
        device->setSerialNumber(adapter["SerialNumber"]);       
      
      adp->setDupCheck(get_bool_with_default(adapter, "FilterDuplicates", adp->isDupChecking()));
      adp->setAutoAvailable(get_bool_with_default(adapter, "AutoAvailable", adp->isAutoAvailable()));
      adp->setIgnoreTimestamps(get_bool_with_default(adapter, "IgnoreTimestamps", aIgnoreTimestamps ||
                                                                                  adp->isIgnoringTimestamps()));
      adp->setRealTime(get_bool_with_default(adapter, "RealTime", false));
      adp->setRelativeTime(get_bool_with_default(adapter, "RelativeTime", false));
      adp->setReconnectInterval(reconnectInterval);
      
      if (adapter.is_key_defined("AdditionalDevices")) {
        istringstream devices(adapter["AdditionalDevices"]);
        string name;
        while (getline(devices, name, ',')) 
        {
          size_t index = name.find_first_not_of(" \r\t");
          if (index != string::npos && index > 0)
            name.erase(0, index);
          index = name.find_last_not_of(" \r\t");
          if (index != string::npos)
            name.erase(index + 1);
          
          adp->addDevice(name);
        }
      }
    }
  }
  else if ((device = defaultDevice()) != NULL)
  {
    sLogger << LINFO << "Adding default adapter for " << device->getName() << " on localhost:7878";
    Adapter *adp = mAgent->addAdapter(device->getName(), "localhost", 7878, false, aLegacyTimeout);
    adp->setIgnoreTimestamps(aIgnoreTimestamps || adp->isIgnoringTimestamps());
    adp->setReconnectInterval(aReconnectInterval);
    device->mPreserveUuid = aDefaultPreserve;
  }
  else
  {
    throw runtime_error("Adapters must be defined if more than one device is present");
  }  
}