if (trialId == null || ! trialId.startsWith("EXPT-")) { if (log.isInfoEnabled()) { log.info("fixAsb for base trial (" + trialId + ")? Skip out with error.", new Throwable()); } return false; }
  public boolean fixAssemblies() throws SQLException {    // return false on error    // 1: delete any HNA assembly referenced in config (if not referenced elsewhere)    // --- find any HNA in config    // Use queryConfigTrialAssemblies and loop through? (returns assembly_ids    // and just uses the trial_id)    Statement stmt = getStatement();    ResultSet rs = executeQuery(stmt, dbp.getQuery("queryConfigTrialAssemblies", substitutions));    String assid;        boolean configHasNewHNA = false;    while (rs.next()) {      assid = rs.getString(1);      if (assid.startsWith(hnaType)) {	// This is an HNA assembly ID	if (hnaAssemblyId != null && ! assid.equals(hnaAssemblyId)) {	  // And not the current one	  // So remove it for this Trial and potentially all	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Removing old hna " + assid + " from config for trial " + trialId);	  }	  removeConfigAssembly(assid);	  removeRuntimeAssembly(assid);	  // This should find the asb not in use locally, so this is used anywhere test	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);	  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb not deleting in use HNA asb " + assid);	  }	} else if (hnaAssemblyId != null) {	  // This is the new HNA assembly somehow already there	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Found current HNA (" + hnaAssemblyId + ") already in config for trial " + trialId);	  }	  configHasNewHNA = true;	}      } else if (assid.startsWith(REAL_CMT_TYPE)) {	// This should be the real society definition	if (cmtAssemblyId != null && ! assid.equals(cmtAssemblyId)) {	  // an old CMT assembly still listed somehow. Delete it!	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Found unknown CMT assembly " + assid + " in config for trial " + trialId);	  }	  removeConfigAssembly(assid);	  removeRuntimeAssembly(assid);	  	  // Completely, if necessary - this will delete the asb if no-one uses	  // it. FIXME: Do we not want to delete CMT asbs?	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);		  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb not deleting used CMT " + assid);	  }	} else if (cmtAssemblyId != null) {	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Found current CMT cmtAssID (" + cmtAssemblyId + ") in config for trial " + trialId);	  }	  // This is the current CMT society def in the config area. Good.	  // But if we also have a diff CSA assembly ID, we don't want	  // this assembly in the runtime area, nor do we want	  // a CSMI assembly	  if (csaAssemblyId != null && ! csaAssemblyId.equals(cmtAssemblyId)) {	    // Dont want the cmt assembly ID, this assembly, in the runtime - 	    // using the CSA instead	    if (log.isDebugEnabled()) {	      log.debug("fixAsb: But also have a CSA (" + csaAssemblyId + "), so this CMT better not be in runtime");	    }	    removeRuntimeAssembly(assid);	    // Remove any CSMI as well...	    if (csmiAssemblyId != null) {	      if (log.isDebugEnabled()) {		log.debug("fixAsb: Since have a CSA we also know we don't want a CSMI in runtime");	      }	      removeRuntimeAssembly(csmiAssemblyId);	      removeConfigAssembly(csmiAssemblyId); // should be no-op	      if (! isAssemblyUsed(csmiAssemblyId)) {		cleanAssembly(csmiAssemblyId);	      } else if (log.isDebugEnabled()) {		log.debug("fixAsb not removing used CSMI " + csmiAssemblyId);	      }	      csmiAssemblyId = null;	    }	  }   	} else {	  // Null cmtAssemblyId!!!!	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Trial " + trialId + " has null cmtAssemblyId while examining cmt asb " + assid);	  }	}      } else if (assid.startsWith(CSATYPE)) {	// This could be the cmtAssemblyId 	// and if so, fine.	if (cmtAssemblyId != null && ! assid.equals(cmtAssemblyId)) {	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Got a CSA asb in config (" + assid + ") thats not the society assembly (" + cmtAssemblyId + ") for trial " + trialId);	  }	  // A CSA in configtime that isnt the society definition	  removeConfigAssembly(assid);	  	  // Completely, if necessary. Note this wont delete the CSA	  // from this Trias runtime, which is probably good.	  // First case of this?	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);		  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb not deleting used CSA " + assid);	  }	} else if (cmtAssemblyId == null) {	  // null society def!!!	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Null cmtAssemblyID for trial " + trialId + " while looking at CSA asb " + assid + " and local csaAssemblyID: " + csaAssemblyId);	  }	} else {	  // This CSA assembly is the society def in config time. Good.	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Found the society def CSA (" + assid + ") in config for trial " + trialId);	  }	  // Note that we now know a CMT asb in runtime would be bad	  // But we could still have a CSMI in runtime	}      } else if (assid.startsWith(COMM_ASB_TYPE)) {	// Comm Assembly	if (log.isDebugEnabled()) {	  log.debug("fixAsb: Found a Comm assembly (" + assid + ") in config for trial " + trialId);	}	// FIXME: Do I expect this ID to be in object? Put it there?	// A couple options: This might be an old one	// that needs to be removed?	// Or maybe we already saved it	// then put it in runtime too	// Make sure it is in runtime too?	if (! assemblyInRuntime(assid))	  addAssemblyToRuntime(assid);	// but also want to see if	// the assid we found is also the on in the variable	if (commAssemblyId != null) {	  if (assid.equals(commAssemblyId)) {	    // found local var comm in config	    if (log.isDebugEnabled()) {	      log.debug("fixAsb: found comm asb in config same as local var");	    }	  } else {	    if (log.isDebugEnabled()) {	      log.debug("fixAsb: found comm asb in config not same as that in local var. delete from tables");	    }	    // local var comm is not same as one in config	    removeConfigAssembly(assid);	    removeRuntimeAssembly(assid);	    if (! isAssemblyUsed(assid))	      cleanAssembly(assid);	  }	} else {	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: found comm asb in config but nothing in local var");	    log.debug("fixAsb: save it in local var and use it");	  }	  // Found a comm assembly in config	  // but not in local var	  // Shouldnt I have one in local var?	  // if not I guess set it	  commAssemblyId = assid;	}      } else {	// What kind of assembly is this? CSMI? Delete it!	if (log.isWarnEnabled()) {	  log.warn("fixAsb: Found non CSA/CSHNA/CMT assembly (" + assid + ") in config for trial " + trialId);	}	removeConfigAssembly(assid);		// Completely, if necessary. This, correctly, will leave a CSMI	// in runtime if used by this trial	if (! isAssemblyUsed(assid)) {	  cleanAssembly(assid);	    	} else if (log.isDebugEnabled()) {	  log.debug("fixAsb not removing used CSMI found in config " + assid);	}      }    } // end of loop over config assemblies    rs.close();        // 2: copy into config-time ref to runtime HNA if not already there    if (! configHasNewHNA) {      if (log.isDebugEnabled()) {	log.debug("Adding HNA (" + hnaAssemblyId + ") to config for trial " + trialId);      }      addAssemblyToConfig(hnaAssemblyId);    }        // 3: Ensure config-time has a CMT _or_ CSA    // use queryConfigTrialAssemblies -- see above    // and cmtType and CSATYPE    // if has both => error    //--- do what? Delete the CSA, assuming it was erroneously written    // there when should have only been in runtime?    // Maybe check that there are at least some recipes first?    // Or assume that this is an experiment originally created    // from a CMT society, and the CSA is correct?    // if has none then no society. This is OK, but then it should    // not have  CMT, CSA, or CSMI in runtim    // if no CMT    // and no CSA    // Then ensure no CSMI in runtime. nor CMT or CSA    // 4: Ensure run-time has a CMT _or_ CSA (only CSA if CSA in config_time)    // use queryTrialAssemblies    // and cmtType and CSATYPE    rs = executeQuery(stmt, dbp.getQuery("queryTrialAssemblies", substitutions));    assid = null;    // Loop over all assemblies in runtime for this assembly    while (rs.next()) {      assid = rs.getString(1);      if (assid.startsWith(hnaType)) {	// This is an HNA assembly ID	if (! assid.equals(hnaAssemblyId)) {	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Found old HNA (" + assid + ") in runtime for trial " + trialId);	  }	  // And not the current one	  // So remove it for this Trial and potentially all	  removeRuntimeAssembly(assid);	  	  // While we're here, remove it from config-time as well	  removeConfigAssembly(assid);	  	  // This should now be able to completely remove this asb	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);	  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb in run loop not removing used HNA " + assid);	  }	  	  // But more importantly, this is really an error!	} else {	  // This is the new HNA assembly already there, as expected	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Found current hna (" + assid + ") in run for trial " + trialId);	  }	}      } else if (assid.startsWith(REAL_CMT_TYPE)) {	if (! assid.equals(cmtAssemblyId)) {	  // an old CMT assembly still listed somehow. Delete it!	  	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Found a CMT (" + assid + ") in runtime thats not the current society def for trial " + trialId);	  }	  removeRuntimeAssembly(assid);	  // While we're here, remove it from config as well	  removeConfigAssembly(assid);	  	  // Completely, if necessary	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);		  } else if (log.isDebugEnabled()) {	    log.debug("fixasb in run loop not removing used bogus CMT I found: " + assid);	  }	} else {	  // This is the current CMT in the runtime area. Fine,	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: Found current CMT (" + assid + ") in runtime for trial " + trialId);	  }	  if (csaAssemblyId != null) {	    // Have a CSA. That's odd.	    // if this is in the runtime, should remove the CMT from the runtime.	    if (assemblyInRuntime(csaAssemblyId)) {	      if (log.isWarnEnabled()) {		log.warn("fixAsb: Found CMT cmtAssId (" + assid + ") in runtime. But also have a CSA (" + csaAssemblyId + ") in runtime, for trial " + trialId + ". Remove the CMT from the runtime.");	      }	      removeRuntimeAssembly(assid);	      	      // Also should remove any CSMI in runtime	      // FIXME!!!	      if (csmiAssemblyId != null) {		if (log.isWarnEnabled()) {		  log.warn("fixAsb run loop found CSA (" + csaAssemblyId + ") in runtime thats not the society def, but also have a CSMI defined (" + csmiAssemblyId + "), which I'll remove");		}		removeRuntimeAssembly(csmiAssemblyId);		removeConfigAssembly(csmiAssemblyId); // no-op probably		if (! isAssemblyUsed(csmiAssemblyId)) {		  cleanAssembly(csmiAssemblyId);		} else if (log.isDebugEnabled()) {		  log.debug("fixAsb run not removing bogus used CSMI " + csmiAssemblyId);		}		csmiAssemblyId = null;	      }	    } else {	      // if this is not in the runtime, what is it?	      // Do I add it?	      if (log.isWarnEnabled()) {		log.warn("fixAsb: Have CMT cmtAssID (" + cmtAssemblyId + ") in runtime, but also have a CSA which is not in runtime. What is this CSA? Should I remove the CMT and add the CSA? Trial: " + trialId);	      }	    }	  } // end of loop where found CMT in runtime but have a CSA	  else {	    // csaAssemblyId is null. So would expect to have a CSMI	    // assembly, and no CSA assemblies in the DB	  }	  	  // OK: Found curent society def CMT in runtime	  // and better be same CMT in config	  if (! assemblyInConfig(assid)) {	    // Otherwise, an error	    if (log.isWarnEnabled()) {	      log.warn("fixAsb: Found current CMT cmtAssID (" + cmtAssemblyId + ") in runtime but not in config, trial : " + trialId);	    }	    addAssemblyToConfig(assid);	  }	  	  // Is there more than one CMT now in config? If so, get rid of the one	  // that is not cmtAssemblyId	  	  // FIXME!!	} // end of block dealing with finding the CMT cmtAssemblyId in runtime      } else if (assid.startsWith(CSATYPE)) {	if (assid.equals(cmtAssemblyId)) {	  // Found the CSA society def in runtime	  // It better also be in config time	  if (! assemblyInConfig(cmtAssemblyId)) {	    if (log.isInfoEnabled()) {	      log.info("fixAsb: Found CSA cmtAssemblyId (" + cmtAssemblyId + ") in runtime but not in config, adding it, trial: " + trialId);	    }	    addAssemblyToConfig(assid);	  }	  // and we'd better have only one CSA in runtime	  // FIXME!!!	  if (csaAssemblyId != null && ! csaAssemblyId.equals(cmtAssemblyId)) {	    // But have another CSA assembly than this	    // which is probably the real runtime def	    if (log.isWarnEnabled()) {	      log.warn("fixAsb run found soc def CSA (" + assid + ") in runtime, but have other CSA in local var (" + csaAssemblyId);	    }	    if (assemblyInRuntime(csaAssemblyId)) {	      if (log.isWarnEnabled()) {		log.warn("fixAsb run found that other CSA also in runtime. Remove orig (" + assid + ") from runtime");	      }	      // I guess I need to remove the societyDef CSA asb	      // from runtime	      removeRuntimeAssembly(assid);	    } else {	      // Bogus CSA ID in my local var?	      // or somehow didn't save CSA ID in runtime	      // and remove old society def CSA?	      // FIXME!!!	      if (log.isWarnEnabled()) {		log.warn("fixAsb run says 2nd CSA in var not in runtime, while 1st is. Is local var wrong? Or does runtime have the wrong CSA in runtime?");	      }	    }	  } // end of block checking for 2nd CSA asb	} else if (! assid.equals(csaAssemblyId)) {	  // Found CSA in runtime that is neither the base soc def or	  // separate CSA.	  // an old CSA assembly still listed somehow 	  	  // it is wrong, remove it.	  removeRuntimeAssembly(assid);	  removeConfigAssembly(assid); // should be a no-op	  	  // Completely, if necessary	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);		  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb run not removing unknown CSA in use " + assid);	  }	} else {	  // This is the current non original society-def CSA in the runtime area.	  // It better not be in config	  if (assemblyInConfig(assid)) {	    if (log.isWarnEnabled()) {	      log.warn("fixAsb: Found non society-def CSA (" + csaAssemblyId + ") in config, must remove, trial: " + trialId);	    }	    removeConfigAssembly(assid);	  }	  // Better not be a CMT in runtime	  if (assemblyInRuntime(cmtAssemblyId)) {	    if (log.isWarnEnabled()) {	      log.warn("fixAsb: Have non-orig soc CSA (" + csaAssemblyId + ") in runtime, but also orig CMT/CSA (" + cmtAssemblyId + "), which is wrong. Remove it: trial " + trialId);	    }	    removeRuntimeAssembly(cmtAssemblyId);	  }	  	  // or a CSMI in runtime	  if (csmiAssemblyId != null && assemblyInRuntime(csmiAssemblyId)) {	    if (log.isWarnEnabled()) {	      log.warn("fixAsb: Have non-orig soc CSA (" + csaAssemblyId + ") in runtime, but also a CSMI (" + csmiAssemblyId + "), which is wrong. Remove it: trial " + trialId);	    }	    removeRuntimeAssembly(csmiAssemblyId);	    removeConfigAssembly(csmiAssemblyId); // should be a no-op	    // completely, if necc.	    if (! isAssemblyUsed(csmiAssemblyId)) {	      cleanAssembly(csmiAssemblyId);	    } else if (log.isDebugEnabled()) {	      log.debug("fixAsb run removed bogus CSMI, but not completely: " + csmiAssemblyId);	    }	    csmiAssemblyId = null;	  } // end of block dealing with bogus CSMI	} // end of block handling finding non-orig soc CSA in runtime	// Should be done with finding a CSA type assembly altogether      } else if (assid.startsWith(REAL_CSMI_TYPE)) {	if (! assid.equals(csmiAssemblyId)) {	  if (log.isWarnEnabled()) {	    log.warn("fixAsb: Got unknown csmi (" + assid + ") in runtime for trial " + trialId + " while examining csmi " + assid);	  }	  // not an expected CSMI. delete it	  removeRuntimeAssembly(assid);	  removeConfigAssembly(assid); // should be a no-op	  	  // Completely, if necessary	  if (! isAssemblyUsed(assid)) {	    cleanAssembly(assid);		  } else if (log.isDebugEnabled()) {	    log.debug("fixAsb run didn't completely delete used but unknown CSMI " + assid);	  }	} else if (csmiAssemblyId != null) {	  // Got our CSMI. Make sure have either CMT or CSA as well, and if CSA,	  // it is also in config time	  if (log.isDebugEnabled()) {	    log.debug("Found our csmi (" + csmiAssemblyId + ") in runtime for trial " + trialId);	  }	  	  // FIXME: Check on CMT/CSA, etc	  if (csaAssemblyId != null) {	    if (csaAssemblyId.equals(cmtAssemblyId)) {	      // Fine. it should be in both runtime & config time	      if (! assemblyInConfig(csaAssemblyId)) {		if (log.isDebugEnabled()) {		  log.debug("fixAsb run found our CSMI, and our single CSA (" + csaAssemblyId + ") was not in config. Adding it");		}		addAssemblyToConfig(csaAssemblyId);	      }	      if (! assemblyInRuntime(csaAssemblyId)) {		if (log.isWarnEnabled()) {		  log.warn("fixAsb run found our CSMI, and our single CSA (" + csaAssemblyId + ") was not in runtime. Adding it");		}		addAssemblyToRuntime(csaAssemblyId);	      }	    } else {	      // Error. This suggests we had a removal / mod. Probably want	      // to delete the CSMI altoghether	      if (log.isWarnEnabled()) {		log.warn("fixAsb run found our CSMI, but have 2 CSAs. I'll assume we had a mod and want to remove the CSMI");	      }	      removeRuntimeAssembly(assid);	      removeConfigAssembly(assid); // should be a no-op	      if (! isAssemblyUsed(assid)) {		cleanAssembly(assid);	      } else if (log.isDebugEnabled()) {		log.debug("fixAsb run didnt completely remove rogue CSMI " + assid);	      }	      csmiAssemblyId = null;	    } // end of bogus CSMI block	  } else {	    if (cmtAssemblyId == null) {	      if (log.isErrorEnabled()) {		log.error("fixAsb has null CSA: " + csaAssemblyId + " + and null cmtAsb: " + cmtAssemblyId + " with csmiAsb " + csmiAssemblyId + " for trial " + trialId);	      }	      continue;	    }	    // OK. Have no CSA, just this cmt. It should be in runtime & config	    if (! assemblyInConfig(cmtAssemblyId)) {	      if (log.isDebugEnabled()) {		log.debug("fixAsb run found our CSMI, and our single CSA/CMT (" + cmtAssemblyId + ") was not in config. Adding it");	      }	      addAssemblyToConfig(cmtAssemblyId);	    }	    if (! assemblyInRuntime(cmtAssemblyId)) {	      if (log.isWarnEnabled()) {		log.warn("fixAsb run found our CSMI, and our single CSA/CMT (" + cmtAssemblyId + ") was not in runtime. Adding it");	      }	      addAssemblyToRuntime(cmtAssemblyId);	    }	  } // end of block dealing with having just cmtAsbID & csmiAsbId	} else {	  // csmiAssemblyId is null	  // I'd expect to have cmt != csa	  if (csaAssemblyId == null || csaAssemblyId.equals(cmtAssemblyId)) {	    // Just have one society def, no separate assembly	    // for recipe add/remove/modify. That's odd!	    if (log.isDebugEnabled()) {	      log.debug("fixAsb run says we have no CSMI, but have just one soc assembly: " + cmtAssemblyId);	    }	  }	}      } else if (assid.startsWith(COMM_ASB_TYPE)) {	// Comm Assembly	if (log.isDebugEnabled()) {	  log.debug("fixAsb: Found a Comm assembly (" + assid + ") in runtime for trial " + trialId);	}	// FIXME: Do I expect this ID to be in object? Put it there?	// This might be an old one to remove, or the one in the local	// var to leave there		// Make sure it is in config too?	if (! assemblyInConfig(assid))	  addAssemblyToConfig(assid);		if (commAssemblyId != null) {	  if (assid.equals(commAssemblyId)) {	    // found local var comm in runtime	    if (log.isDebugEnabled()) {	      log.debug("fixAsb: found comm asb in runtime same as local var");	    }	  } else {	    if (log.isDebugEnabled()) {	      log.debug("fixAsb: found comm asb in runtime not same as that in local var. delete from tables");	    }	    // local var comm is not same as one in runtime	    removeConfigAssembly(assid);	    removeRuntimeAssembly(assid);	    if (! isAssemblyUsed(assid))	      cleanAssembly(assid);	  }	} else {	  if (log.isDebugEnabled()) {	    log.debug("fixAsb: found comm asb in runtime but nothing in local var");	    log.debug("fixAsb: save it in local var and use it");	  }	  // Found a comm assembly in runtime	  // but not in local var	  // Shouldnt I have one in local var?	  // if not I guess set it	  commAssemblyId = assid;	}	      } else {	// What kind of assembly is this. Delete it!	if (log.isWarnEnabled()) {	  log.warn("Found unknown assembly (" + assid + ") in runtime for trial " + trialId);	}	removeRuntimeAssembly(assid);	removeConfigAssembly(assid);		// Completely, if necessary	if (! isAssemblyUsed(assid)) {	  cleanAssembly(assid);	    	} else if (log.isDebugEnabled()) {	  log.debug("fixAsb run found unknown asb type thats in use: " + assid);	}      } // end of block for unknown soc type    } // end of loop over runtime assemblies    rs.close();    stmt.close();    // Should have neither if config-time had neither    // if config had and runtime does not: this will not    // be runnable. It at least should not have a CSMI either. But    // really it makes no sense.    // if config did not and runtime does not, that is OK (should    // not have a CSMI either)    // if config had CMT and runtime has CMT, it had better be the _same_.    // if it is not same, then ERROR    // if config had CMT and runtme has CSA, that is OK.    // if config has CSA and runtime has CMT - ERROR    // if runtime has _both_ => ERROR. If config has same CMT then likely    // could remove the CMT ref in runtime, but don't know for sure    // 5: Ensure run-time only has a CSMI if run-time has a CMT or run-time    // has same CSA as in config-time    // 6: Ensure config-time has no CSMI    // Do some cleanup: Use this opportunity to remove any orphaned    // assemblies    removeOrphanNonSocietyAssemblies();    return true;  } // end of fixAssemblies