long saveStopTime = Calendar.getInstance().getTimeInMillis();   if (log.isShoutEnabled()) log.shout("saveToDb done. Experiment Save Time in Seconds: " + (saveStopTime - saveStartTime) / 1000l);
  public void saveToDb(DBConflictHandler ch) {    PopulateDb pdb = null;    // Make sure we have the Community Assembly stored locally    if (commAsb == null) {      if (log.isDebugEnabled()) {	log.debug("saveToDb had no CommAsb for expt " + expID);      }      try {	// retrieve from db	pdb = new PopulateDb(expID, trialID);	// set it locally	commAsb = pdb.getCommAsbForExpt(expID, trialID);	if (commAsb == null) {	  if (log.isDebugEnabled()) {	    log.debug("saveToDb found no comm asb in DB either");	  }	  commAsb = pdb.getNewCommAssembly();	}      } catch (SQLException sqle) {	log.error("saveToDb error getting Comm assembly", sqle);      } catch (IOException ioe) {	log.error("saveToDb error getting Comm assembly", ioe);      } finally {	try {	  if (pdb != null)	    pdb.close();	} catch (SQLException se) {}	pdb = null;      }    }    if (log.isDebugEnabled()) {      log.debug("saveToDb has commAsb " + commAsb + " for expt " + expID);    }    try {      if (log.isInfoEnabled()) {	log.info("Saving experiment " + getExperimentName() + " to database");      }      updateNameServerHostName(); // Be sure this is up-to-date      List components = getComponents();      boolean componentWasRemoved = false;      SocietyComponent sc = getSocietyComponent();      if (sc == null) {        if (log.isErrorEnabled())           log.error("Experiment has no society; cannot save it to database.");        return;      }      if (sc.getAssemblyId() == null) {	// This should never happen!	if (log.isErrorEnabled()) {	  log.error("Saving experiment " + getExperimentName() + " with exptID " + getExperimentID() + " containing society " + sc.getSocietyName() + " but society has now Assembly! Caller trace: ", new Throwable());	}	// Try to save the society that somehow	// was not previously saved	if (! sc.saveToDatabase()) {	  if (log.isErrorEnabled()) {	    log.error("Failed to save society " + sc.getSocietyName() + " so going to give up saving the experiment.");	  }	  return;	}      } else if (sc.isModified()) {	// Save the society before trying to save the Experiment	if (! sc.saveToDatabase()) {	  if (log.isErrorEnabled()) {	    log.error("Failed to save society " + sc.getSocietyName() + " so going to give up saving the experiment.");	  }	  return;	}      }	      // Check all recipe components to see if modified, if so, save them      // Note that below the recipes are added to the experiment's      // table      // and this must happen after start the expt save      RecipeComponent[] rComponents = getRecipeComponents();      for(int i=0; i < rComponents.length; i++) {        RecipeComponent rc = rComponents[i];        if (rc.isModified()) {          rc.saveToDatabase();        }      }      ///////////      // OK: Now go ahead and save the experiment.      pdb =	new PopulateDb("CMT", "CSHNA", "CSMI", getExperimentName(),		       getExperimentID(), trialID, ch, sc.getAssemblyId());      setExperimentID(pdb.getExperimentId());      setTrialID(pdb.getTrialId()); // sets trial id and -D argument      // Save back to DB the selected threads, if necc      saveSelectedThreads();      // store in the DB the community assembly ID being used      pdb.setCommAssemblyId(commAsb);      // Some components will want access to the complete set of Nodes      // in the society, etc. To get that, they must get back to the      // root soc object, and do a getOwner and go from there. Ugly.      // So far we've just created the pdb (which      // sets up the Experimet & Trial IDs, and puts the CMT assembly      // in the right place if necc, and clears out the other       // assemblies (CSMI, CSHNA)      // Gather the HostNodeAgent stuff      generateHNACDATA();      if(log.isErrorEnabled() && completeSociety == null) {        log.error("save: Society Data is null!");      }      // Problem: Societies from files store _tons_ of properties      // on the Agents. This is most of the society definition, in fact.      // It appears that these end up changing (somehow),      // between saves. So this can throw that IllegalArgumentException      // FIXME!!!!      // Save what we have so far in the CSHNA assembly      if (log.isDebugEnabled()) {	log.debug("About to save HNA data");      }      pdb.populateHNA(completeSociety);      // Now let components add in their pieces      componentWasRemoved = askComponentsToAddCDATA();      // If any component removed something, we need      // to recreate the CMT assembly (under the original ID)      // So this, currently destroys the orig CMT      // Note also it does not effect Agent asset data      // or relationships or OPLAN stuff      if (componentWasRemoved) {	if (log.isDebugEnabled()) {	  log.debug("save: After adding CDATA, got a removed.");	}	pdb.populateCSA(completeSociety);      } else {	if (log.isDebugEnabled()) {	  log.debug("save: Done adding CDATA, ready to modify.");	}      }      // then give everyone a chance to modify what they've collectively produced      for (int i = 0, n = components.size(); i < n; i++) {        BaseComponent soc = (BaseComponent) components.get(i);        soc.modifyComponentData(completeSociety, pdb);        if (soc.componentWasRemoved()) {	  if (log.isDebugEnabled()) {	    log.debug("save: After modifying CDATA by comp " + soc.getShortName() + ", got a removed.");	  }          pdb.populateCSA(completeSociety);        }	try {	  // Incrementally save	  // so that later recipes have the benefit	  // of the earlier modifications	  if (log.isDebugEnabled()) {	    log.debug("About to save CSMI data, having just done mod in " + soc.getShortName());	  }	  pdb.populateCSMI(completeSociety);	} catch (IllegalArgumentException iae) {	  if (log.isInfoEnabled()) {	    log.info("Caught iae " + iae.toString() + " while saving modifications. Must redo as a CSA");	  }	  pdb.populateCSA(completeSociety);	}      } // end of loop over components to do mod      // Save the inclusion of these recipes in the experiment      // without re-saving the recipes      pdb.setModRecipes(recipes);      // Now make sure the runtime/ config time assemblies      // are all correct      if (log.isDebugEnabled()) {	log.debug("About to do fix assemblies");      }      if (! pdb.fixAssemblies()) {	// Some sort of error trying to ensure the assemblies are all correct.	if (log.isErrorEnabled()) {	  log.error("Failed to ensure correct assemblies saved.");	}      }      resetModified();    } catch (Exception sqle) {      if (log.isErrorEnabled())	log.error("Error saving experiment to database: ", sqle);      return;    } finally {      if (pdb != null) {	try {	  pdb.close();	} catch (SQLException e) {}      }    }  }