9b13731e6e466aa0f781179da2d504db2f4c15a9
tdreszer
  Wed Mar 30 11:28:34 2011 -0700
Made slPairListFromString and slPairListToString optionally handle double quotes. Finally made mdbObjReorderByCv so that priority in cv.ra typeOfTerms is used.
diff --git src/hg/lib/mdb.c src/hg/lib/mdb.c
index 2f997a6..dcd50a3 100644
--- src/hg/lib/mdb.c
+++ src/hg/lib/mdb.c
@@ -727,55 +727,56 @@
 
 // Not found so add it
 struct mdbByVar *newVar = mdbByVarCreate(var, val);
 newVar->notEqual = notEqual;
 slAddTail(&mdbByVars,newVar); // Add to tail to avoid changing passed in pointer
 
 return TRUE;
 }
 
 struct mdbObj *mdbObjCreate(char *obj,char *var, char *val)
 /* Creates a singular mdbObj query object based on obj and all other optional params. */
 {
 struct mdbObj *mdbObj = NULL;
 
     if(obj == NULL)
-        errAbort("Need obj to create mdbObj query object.\n");
+        errAbort("Need obj to create mdbObj object.\n");
 
     AllocVar(mdbObj);
     mdbObj->obj     = cloneString(obj);
 
     if(var != NULL)
         {
         struct mdbVar * mdbVar;
         AllocVar(mdbVar);
 
         mdbVar->var     = cloneString(var);
         if(val != NULL)
             mdbVar->val     = cloneString(val);
         mdbObj->vars = mdbVar; // Only one
         }
 return mdbObj;
 }
 
 struct mdbObj *mdbObjNew(char *obj,struct mdbVar *mdbVars)
 // Returns a new mdbObj with whatever was passed in.
 // An mdbObj requires and obj, so if one is not supplied it will be "[unknown]"
 {
 struct mdbObj *mdbObj = NULL;
 if (obj == NULL)
-    obj =  "[unknown]";
+    errAbort("Need obj to create mdbObj object.\n");
+
 if (mdbVars == NULL)
     {
     AllocVar(mdbObj);
     mdbObj->obj = cloneString(obj);
     return mdbObj;
     }
 else
     {
     mdbObj = mdbObjCreate(obj,mdbVars->var,mdbVars->val);
     mdbObj->varHash = hashNew(0);
     hashAddUnique(mdbObj->varHash, mdbVars->var, mdbObj->vars); // pointer to struct to resolve type
 
     struct mdbVar *var = mdbVars->next;
     for(;var != NULL;var = var->next);
         mdbObjSetVar(mdbObj, var->var,var->val);
@@ -1412,31 +1413,31 @@
 //   var5!=val5      : matches not equal.
 //   var6=           : matches that var exists (same as var6=%). var6!= also works.
 {
 struct mdbByVar *mdbByVars = mdbByVarsLineParse(varVals);
 if (mdbByVars == NULL)
     return NULL;
 return mdbObjsQueryByVars(conn,tableName,mdbByVars);
 }
 
 struct mdbObj *mdbObjsQueryByVarPairs(struct sqlConnection *conn,char *tableName,struct slPair *varValPairs)
 // returns mdbObjs matching varValPairs provided.
 //   The != logic of mdbObjsQueryByVarValString() is not possible, but other cases are supported:
 //   as val may be NULL, a comma delimited list, double quoted string, containing wilds: % and ?
 {
 // Note: there is a bit of inefficiency creating a string then tearing it down, but it streamlines code
-char *varValString = slPairListToString(varValPairs);
+char *varValString = slPairListToString(varValPairs,TRUE); // quotes added when spaces found
 struct mdbObj *mdbObjs = mdbObjsQueryByVarValString(conn,tableName,varValString);
 freeMem(varValString);
 return mdbObjs;
 }
 
 struct mdbObj *mdbObjQueryCompositeObj(struct sqlConnection *conn,char *tableName,struct mdbObj *mdbObj)
 // returns NULL or the composite mdbObj associated with the object passed in.
 {
 char *objType = mdbObjFindValue(mdbObj,MDB_OBJ_TYPE);
 assert(objType != NULL);
 if (sameWord(objType,MDB_VAR_COMPOSITE))
     return mdbObjClone(mdbObj);
 char *compName = mdbObjFindValue(mdbObj,MDB_VAR_COMPOSITE);
 if (compName == NULL)
     return NULL;
@@ -1895,30 +1896,64 @@
     if(!back)  // Add to front of forward list
         {
         for( ix=count-1; ix>=0; ix-- )
             {
             if(varsToReorder[ix] != NULL)
                 slAddHead(&orderedVars,varsToReorder[ix]);
             }
         }
 
     mdbObj->vars = orderedVars;
     freeMem(varsToReorder);
     }
     freeMem(words);
 }
 
+void mdbObjReorderByCv(struct mdbObj *mdbObjs, boolean includeHidden)
+// Reorders vars list based upon cv.ra typeOfTerms priority
+{
+struct hash *cvTermTypes = (struct hash *)cvTermTypeHash();
+struct hashEl *el, *elList = hashElListHash(cvTermTypes);
+
+struct slPair *cvVars = NULL;
+for (el = elList; el != NULL; el = el->next)
+    {
+    struct hash *varHash = el->val;
+    if (includeHidden || SETTING_NOT_ON(hashFindVal(varHash, CV_TOT_HIDDEN))) // Skip the hidden ones
+        {
+        char *priority = hashFindVal(varHash, CV_TOT_PRIORITY);
+        if (priority != NULL) // If there is no priority it will randomly fall to the back of the list
+            slPairAdd(&cvVars,el->name,(char *)sqlUnsignedLong(priority));
+        }
+    }
+hashElFreeList(&elList);
+
+if (cvVars)
+    {
+    slPairIntSort(&cvVars);  // sorts on the integer val
+
+    // Now convert this to a string of names
+    char *orderedVars = slPairNameToString(cvVars,' ',FALSE);
+    slPairFreeList(&cvVars);
+    if (orderedVars != NULL)
+        {
+        mdbObjReorderVars(mdbObjs, orderedVars,FALSE); // Finally we can reorder the vars in the mdbObjs
+        freeMem(orderedVars);
+        }
+    }
+}
+
 int mdbObjVarCmp(const void *va, const void *vb)
 /* Compare to sort on full list of vars and vals. */
 {
 const struct mdbObj *a = *((struct mdbObj **)va);
 const struct mdbObj *b = *((struct mdbObj **)vb);
 struct mdbVar* aVar = a->vars;
 struct mdbVar* bVar = b->vars;
 for(;aVar != NULL && bVar != NULL;aVar=aVar->next,bVar=bVar->next)
     {
     int ret = differentWord(aVar->var, bVar->var); // case insensitive
     if(ret != 0)
         {
         // Look for it by walking vars
         struct mdbVar* tryVar = bVar->next;
         for(;tryVar;tryVar=tryVar->next)
@@ -1962,30 +1997,38 @@
 // This method will use mdbObjsSortOnVars()
 {
 if (varValPairs == NULL)
     return;
 
 struct slPair *onePair = varValPairs;
 struct dyString *dyTerms = dyStringNew(256);
 dyStringAppend(dyTerms,onePair->name);
 onePair = onePair->next;
 for(; onePair != NULL; onePair = onePair->next)
     dyStringPrintf(dyTerms,",%s",onePair->name);
 mdbObjsSortOnVars(mdbObjs,dyStringContents(dyTerms));
 dyStringFree(&dyTerms);
 }
 
+void mdbObjsSortOnCv(struct mdbObj **mdbObjs, boolean includeHidden)
+// Puts obj->vars in order based upon cv.ra typeOfTerms priority,
+//  then case-sensitively sorts all objs in list based upon that var order.
+{  // NOTE: assumes all var pairs match (e.g. every obj has cell,treatment,antibody,... and missing treatment messes up sort)
+mdbObjReorderByCv(*mdbObjs, includeHidden);
+slSort(mdbObjs, mdbObjVarCmp);  // While sort will not be perfect (given missing values) it does a good job none the less.
+}
+
 void mdbObjRemoveVars(struct mdbObj *mdbObjs, char *vars)
 // Prunes list of vars for an object, freeing the memory.  Doesn't touch DB.
 {
 char *cloneLine = NULL;
 int count = 0;
 char **words = NULL;
 if(vars != NULL)
     {
     cloneLine = cloneString(vars);
     count = chopByWhite(cloneLine,NULL,0);
     words = needMem(sizeof(char *) * count);
     count = chopByWhite(cloneLine,words,count);
     }
 struct mdbObj *mdbObj = NULL;
 for( mdbObj=mdbObjs; mdbObj!=NULL; mdbObj=mdbObj->next )