executeUpdate(dbp.getQuery("insertComponentHierarchy", substitutions));
if (exptId != null || ! parent.getType().equals(ComponentData.SOCIETY)) { executeUpdate(dbp.getQuery("insertComponentHierarchy", substitutions)); }
  private boolean populate(ComponentData data, float insertionOrder, String assemblyId)    throws SQLException  {    boolean result = false;    ComponentData parent = data.getParent();    String id = getComponentAlibId(data);    addComponentDataSubstitutions(data);    substitutions.put(":assembly_id:", sqlQuote(assemblyId));    substitutions.put(":insertion_order:", String.valueOf(insertionOrder));    SortedSet oldArgs = (SortedSet) componentArgs.get(id);    if (oldArgs == null) {  // Don't know what the current args are      insureAlib();       // Insure that the alib and lib components are defined      Statement stmt = getStatement();      ResultSet rs;      rs = executeQuery(stmt, dbp.getQuery("queryComponentArgs", substitutions));      oldArgs = new TreeSet();      while (rs.next()) {	oldArgs.add(new Argument(rs.getString(1), rs.getFloat(2)));      }      rs.close();      stmt.close();      if (parent != null) {	// Is given component in runtime hierarchy?	String cchq = dbp.getQuery("checkComponentHierarchy", substitutions);// 	if (log.isDebugEnabled()) {// 	  log.debug("populate for assembly " + assemblyId + " and alib_id " + id + ": Doing query: " + cchq);// 	}	stmt = getStatement();	rs = executeQuery(stmt, cchq);	// If not, add it	if (!rs.next()) {	  executeUpdate(dbp.getQuery("insertComponentHierarchy",				     substitutions));	  // if it is an agent	  if (data.getType().equals(ComponentData.AGENT)) {	    // Added this Agent. Add it to the list	    // WARNING: This just means the agent	    // was not previously in the hierarchy.	    // It does not mean that the Agent itself	    // was not already in the CMT assembly, for example	    // It doesn't really matter: 	    // all the insertions in populateAgent check	    // for themselves before doing inserts// 	    if (log.isDebugEnabled()) {// 	      log.debug("Found new contained agent for this hierarchy");// 	    }	    addedAgents.add(id);	  }	  result = true; // Modified the experiment in the database 	}	rs.close();	stmt.close();      }      componentArgs.put(id, oldArgs); // Avoid doing this again    }    // Now build a SortedSet of what the args should be    SortedSet newArgs = new TreeSet();    Object[] params = data.getParameters();    for (int i = 0; i < params.length; i++) {      newArgs.add(new Argument(params[i].toString(), i));    }        // For debugging, dump out the old & new arguments now:    // FIXME: THIS MUST BE CHANGED SOMEHOW!!!!    // If I sense a removal / modification, set some     // flag and abort probably...    // The new args must only contain additions. There must be no    // deletions or alterations of the old args nor is it allowed    // to change the relative order of the existing arguments. If    // there are fewer newArgs than oldArgs, there is clearly a    // violation of this premise.    int excess = newArgs.size() - oldArgs.size();    if (excess < 0) {      if (log.isInfoEnabled()) {	log.info("Attempt to remove "	 + (-excess)		 + " args from "		 + data);      }      // Throw something I'll recognize      // Catch it in the Experiment, so I know to call populateCSA      // FIXME!!!      componentWasRemoved = true;      throw new IllegalArgumentException("Attempt to remove "					 + (-excess)					 + " args from "					 + data);    } else {      if (log.isDebugEnabled()) {	log.debug("Count new args minus old is: " + excess);      }    }    // Prepare to iterate through both old and new args.    // argsToInsert accumulates the new arguments to be inserted.    // Each of the new args is compared with the next unaccounted    // for old arg. If the new arg has a value different from the    // next old arg it is assumed to be an insertion since    // deletions and modifications are disallowed. But, if the    // excess new arg count has been reduced to zero, then no new    // args are possible because there won't be enought old args    // to match the remaining new ones so we throw an exception.    // The argument order is interpolated between the preceding    // and following old argument.    Iterator newIter = newArgs.iterator();    Iterator oldIter = oldArgs.iterator();    List argsToInsert = new ArrayList();    float prev = Float.NaN;    while (oldIter.hasNext()) {      Argument newArg = (Argument) newIter.next();      Argument oldArg = (Argument) oldIter.next();//       if (log.isDebugEnabled()) {// 	log.debug("Comp args for " + data.getName() + ". New " + newArg.toString() + ", Old: " + oldArg.toString());// 	// print out the number, the values....//       }		       while (!newArg.argument.equals(oldArg.argument)) {	if(log.isInfoEnabled()) {	  log.info("newArg != oldArg, new: " +newArg.toString() + " old: " + oldArg.toString());	}	// Assume arguments were inserted	excess--;	if (excess < 0) {	  if (log.isInfoEnabled()) {	    log.info("Component args cannot be modified or removed: " + data);	  }	  // Throw something recognizable that the experiment	  // can catch and call populateCSA	  componentWasRemoved = true;	  throw new IllegalArgumentException("Component args cannot be modified or removed: " + data);	}	if (Float.isNaN(prev)) prev = oldArg.order - 1f;	argsToInsert.add(new Argument(newArg.argument, (prev + oldArg.order) * 0.5f));	newArg = (Argument) newIter.next();      } // end of loop while argument values differ      prev = oldArg.order;    } // loop over old arguments    // Finally, any remaining new args are appended    if (Float.isNaN(prev)) prev = 0f;    while (newIter.hasNext()) {      Argument newArg = (Argument) newIter.next();      prev += 1f;      argsToInsert.add(new Argument(newArg.argument, prev));    }    // Now write all the new arguments that were not previously    // present to the database.    for (Iterator i = argsToInsert.iterator(); i.hasNext(); ) {      Argument arg = (Argument) i.next();//       if (log.isDebugEnabled()) {// 	log.debug("Adding new argument to " + data.getName() + ": " + arg.argument);//       }      substitutions.put(":argument_value:", sqlQuote(arg.argument));      substitutions.put(":argument_order:", sqlQuote(String.valueOf(arg.order)));      executeUpdate(dbp.getQuery("insertComponentArg", substitutions));      oldArgs.add(arg);      result = true;    }    // For agents, only keep going if this isn't the HNA assembly    if (data.getType().equals(ComponentData.AGENT)) {      if (!assemblyId.equals(hnaAssemblyId)) {	// was this agent added to the hierarchy	// since we saved its AgentData	// Note however that this means that recipes	// will have trouble adding relationships!!!	// If the checks in this method are good,	// I should get rid of this whole addedAgents thing	// FIXME!!!!!!!!	if (addedAgents.contains(id)) {	  if (log.isDebugEnabled()) {	    log.debug("Calling populateAgent for agent alib_id: " + id + " in assembly " + assemblyId);	  }	  populateAgent(data, true);	  addedAgents.remove(id);	  result = true;	}      } else {	// If this is an Agent and we're in the CSHNA assembly,	// don't save the plugins, etc now. Just return.	return result;      }    } else {//       if (log.isDebugEnabled()) {// 	log.debug("Not an agent: " + data.getName() + ", its a " + data.getType());//       }    }         ComponentData[] children = data.getChildren();    // The following assumes that the insertion order of old    // children equals their index in the array and that the    // insertion order of all new children should be the their    // index in the array as well.    for (int i = 0, n = children.length; i < n; i++) {      if (log.isDebugEnabled()) {	log.debug("Recursing into populate from " + data.getName() + " for " + children[i].getName());      }      result |= populate(children[i], i, assemblyId);    }    return result;  }