public List<Strategy> updateStrategies(
     String tagPath,
     SubnodeConfiguration config,
     Map<String, Strategy> strategies,
     Village village) {
   List<Strategy> deletableStrategies = new ArrayList<Strategy>(strategies.values());
   List<Strategy> addedStrategies = new ArrayList<Strategy>();
   List<Strategy> strategyList = new ArrayList<Strategy>();
   List<SubnodeConfiguration> strategyConfigs = config.configurationsAt(tagPath);
   for (SubnodeConfiguration strategyConfig : strategyConfigs) {
     // Console.getInstance().checkFlags(); // This is wrong
     // Create a candidate strategy
     Strategy candidate = createStrategy(strategyConfig);
     // Check if it is already listed
     String idFromConfig = Strategy.getIdFromConfig(strategyConfig);
     Strategy oldStrategy = strategies.get(idFromConfig);
     if (oldStrategy != null) {
       if (addedStrategies.contains(candidate)) {
         // Strategy just added
         EventLog.log("evt.duplicateStrategy", this.getClass(), candidate.getId());
         continue;
       }
       // Reconfigure existing
       oldStrategy.updateConfig(strategyConfig, util);
       deletableStrategies.remove(oldStrategy);
       strategyList.add(oldStrategy);
     } else {
       // Add new
       addedStrategies.add(candidate);
       candidate.init(strategyConfig, util, village);
       strategies.put(candidate.getId(), candidate);
       strategyList.add(candidate);
     }
   }
   // Delete disabled or removed strategies
   for (Strategy strategy : deletableStrategies) {
     strategy.setDeleted(true);
     strategies.remove(strategy.getId());
     EventLog.log("evt.strategyRemoved", this.getClass(), strategy.getId());
   }
   return strategyList;
 }
 private void updateConfig(SubnodeConfiguration newServerConfig)
     throws InvalidConfigurationException {
   log.debug("Updating server config for " + getServerId());
   this.config = newServerConfig;
   this.util.setServerConfig(newServerConfig);
   this.util.setServer(this);
   this.util.setServerId(user, getServerId()); // set server id for use in report processing
   // check if reading reports from overall server
   reportMode = newServerConfig.getString("/reports", null); // simple format to just read
   reportMode =
       newServerConfig.getString(
           "/reports/@enabled", reportMode); // complex config with processing
   if (reportMode != null) {
     SubnodeConfiguration reportConfig = newServerConfig.configurationAt("/reports");
     reportMode =
         reportConfig.getString("/output/@format", reportMode); // complex config with processing
     EventLog.log(loginUrl + " reportMode=" + reportMode);
     reportReader.setReportsMode(reportMode, reportConfig);
   }
   messageMode = newServerConfig.getString("/messages", null);
   messageMode = newServerConfig.getString("/messages/@enabled", messageMode);
   // note once enabled have to turn off by setting false or will not call to disable
   if (messageMode != null) {
     SubnodeConfiguration messageConfig = newServerConfig.configurationAt("/messages");
     String messageText = messageConfig.getString("/@commands", null);
     EventLog.log(
         loginUrl + " messageMode=" + messageMode + " Command Text (" + messageText + ")");
     // use same as mode or a separate param?
     messageReader.setMessagesMode(messageMode, messageConfig);
   }
   setTribeType(newServerConfig);
   //
   // Update villages
   // When a village is disabled or removed from the configuration, it is deleted from
   // this.villages
   List<Village> deletableVillages = new ArrayList<Village>(villages.values());
   // Loop all enabled villages
   List<SubnodeConfiguration> villageConfigs =
       newServerConfig.configurationsAt("/village[@enabled='true']");
   for (SubnodeConfiguration villageConfig : villageConfigs) {
     String id = Village.getIdFromConfig(villageConfig); // Either uid or url
     Village village = this.villages.get(id);
     if (village == null) {
       // New village
       village = new Village(util, villageConfig, strategyStatus);
       this.villages.put(id, village);
     } else {
       // Village already exists
       village.updateConfig(villageConfig, util);
       deletableVillages.remove(village); // This village is still enabled	
     }
   }
   // Removing deleted or disabled villages
   for (Village village : deletableVillages) {
     this.villages.remove(village.getId());
     village.terminate();
   }
   //
   // Update server strategies
   serverStrategyList =
       updateStrategies(
           "/serverStrategy[@enabled='true']", newServerConfig, serverStrategies, null);
 }
 private TimeWhenRunnable processVillages() throws InvalidConfigurationException {
   TimeWhenRunnable firstTimeWhenRunnable = null;
   try {
     List<SubnodeConfiguration> villageConfigs =
         config.configurationsAt("/village[@enabled='true']");
     for (SubnodeConfiguration villageConfig : villageConfigs) {
       // If configuration changed, abort current loop, update config and restart
       if (isConfigurationChanged()) {
         log.debug("Exiting village loop for configuration update");
         break;
       }
       String id = Village.getIdFromConfig(villageConfig);
       Village village = villages.get(id);
       if (village == null) {
         log.warn(
             "Configuration file not aligned to village map; ignoring village "
                 + villageConfig.getString("/@desc", "")
                 + " "
                 + villageConfig.getString("/url", ""));
         continue;
       }
       try {
         // getTimeWhenRunnable may update to check for triggering resources so can change page
         TimeWhenRunnable currentTimeWhenRunnable = village.getTimeWhenRunnable();
         // log.debug("currentTimeWhenRunnnable:"+currentTimeWhenRunnable);
         if (currentTimeWhenRunnable.before(new Date())) {
           EventLog.log("Processing village \"" + village.getDesc() + "\"");
           village.execute(); // Execute strategies
           currentTimeWhenRunnable = village.getTimeWhenRunnable();
           // log.debug("currentTimeWhenRunnnable after execute:"+currentTimeWhenRunnable);
         } else {
           EventLog.log(
               "Village \"" + village.getDesc() + "\" sleeping until " + currentTimeWhenRunnable);
         }
         // use current here and only reread after execute, then use new below
         if ((firstTimeWhenRunnable == null)
             || firstTimeWhenRunnable.after(currentTimeWhenRunnable)) {
           log.trace("Earlier Village " + village.getDesc() + " " + currentTimeWhenRunnable);
           firstTimeWhenRunnable = currentTimeWhenRunnable;
         }
         // check for earliest sharp strategy in village, return NEVER if none- if is store
         // earliest sharp one
         TimeWhenRunnable newTimeWhenRunnable = village.getTimeWhenSharp();
         if (newTimeWhenRunnable.isSharp()) {
           if (sharpTimeWhenRunnable == null || sharpTimeWhenRunnable.after(newTimeWhenRunnable)) {
             // log.trace("Earlier Village "+village.getDesc()+" "+newTimeWhenRunnable);
             sharpTimeWhenRunnable = newTimeWhenRunnable;
             log.trace(
                 "Earlier sharp Village is " + village.getDesc() + " " + sharpTimeWhenRunnable);
           }
         }
       } catch (SkipVillageRequested e) {
         log.debug("Village skipped");
         continue;
       } catch (SkipRequested e) {
         // Just keep going
         log.debug("Action skipped");
       } catch (ServerFatalException e) {
         throw e; // Will catch below
       } catch (Exception e) {
         String s = "Village \"" + village.getDesc() + "\" error (retrying later): ";
         log.error(s, e);
         EventLog.log(s + e.getMessage());
         util.shortestPause(false); // Just to be safe
         firstTimeWhenRunnable = null; // Retry after userPause
       }
     }
   } catch (ConcurrentModificationException e) {
     // This shouldn't happen anymore
     // Just ignore
     log.debug(
         "Village list was modified while server running (ConcurrentModificationException): skipping and repeating");
   }
   // log.debug("returning firstTimeWhenRunnable:"+firstTimeWhenRunnable);
   return firstTimeWhenRunnable;
 }