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/fileUi.c src/hg/lib/fileUi.c
index 88fa70c..2f37138 100644
--- src/hg/lib/fileUi.c
+++ src/hg/lib/fileUi.c
@@ -184,31 +184,37 @@
 char *carveSetting = NULL,*setting = NULL;
 if (parentTdb)
     setting = trackDbSetting(parentTdb, FILE_SORT_ORDER);
 if(setting)
     {
     sortOrder = needMem(sizeof(sortOrder_t));
     sortOrder->setting = cloneString(setting);
     carveSetting = sortOrder->setting;
     }
 else
     {
     if (mdbObjs != NULL)
         {
         struct dyString *dySortFields = dyStringNew(512);
         struct mdbObj *commonVars = mdbObjsCommonVars(mdbObjs);
+        // FIXME: Replace with ? cv searchable combined with priority combined with cvDefined?
+        // A good first step was putting the vars in cv order.  Now walk through them, and determine if each should be sortable
         // Problem with making common fieds as sorable is that it REQUIRES a fixed sort order
+        // All in priority order (or so) except: obtainedBy,expId,strain,labProtocolId
+        // All are searchable except: labProtocolId,replicate,submittedDataVersion,dateSubmitted,dateResubmitted,dateUnrestricted
+        // Solution: use cv order and whether searchable.  Define dates as searchable in cv.ra, make searchable: labProtocolId, replicate, submittedDataVersion
+        //           change some orders in cv and other orders here!
         char *sortables[] = {"grant","lab","dataType","cell","strain","age","obtainedBy", "rnaExtract","localization","phase","treatment","antibody","protocol",
                       "labProtocolId","restrictionEnzyme","control","replicate","expId","labExpId","setType","view","submittedDataVersion","subId",
                       "dateSubmitted","dateResubmitted","dateUnrestricted","dataVersion","origAssembly"};//"labVersion","softwareVersion",
         // Not included:    no:not searchable
         // accession no, annotation no,   bioRep no,     composite no, controlId no, dccInternalNotes no, fileIndex no,  fileName no,
         // fragSize no,  fragLength no,   freezeDate no, geoSample,    geoSeries,    insertLength no,     labVersion,    level no,
         // mapAlgorithm, privacy no,      rank no,       readType,     seqPlatform,  sex,                 size no,       softwareVersion,
         // tableName no, uniqueness no
 
         int ix = 0, count = sizeof(sortables)/sizeof(char *);
         for (ix=0;ix<count;ix++)
             {
             // If sortables[ix] is in common vars then then add it to the settings field
             if (mdbObjContains(commonVars,sortables[ix],NULL))
                 {
@@ -637,33 +643,31 @@
                 }
             }
         }
 #ifndef INCLUDE_FILENAMES
     else
 #endif///ndef INCLUDE_FILENAMES
         { // fileName
         printf("<TD nowrap>%s",oneFile->fileName);
         //// FIXME: " The "..." encapsulation could be rebuilt so it could be called here
         //printf("&nbsp;<A HREF='#a_meta_%s' onclick='return metadataShowHide(\"%s\",true,true);' title='Show metadata details...'>...</A>",
         //    oneFile->mdb->obj,oneFile->mdb->obj);
         //printf("<DIV id='div_%s_meta' style='display:none;'></div></td>",oneFile->mdb->obj);
         }
 
     // Extras  grant=Bernstein; lab=Broad; dataType=ChipSeq; setType=exp; control=std;
-    mdbObjRemoveVars(oneFile->mdb,"fileName fileIndex composite project dccInternalNotes"); // Remove this from mdb now so that it isn't displayed in "extras'
-    mdbObjReorderVars(oneFile->mdb,"grant lab dataType cell treatment antibody protocol replicate view",FALSE); // Bring to front
-    mdbObjReorderVars(oneFile->mdb,"subId submittedDataVersion dateResubmitted dataVersion setType inputType controlId tableName",TRUE); // Send to back
+    mdbObjRemoveVars(oneFile->mdb,MDB_VAR_FILENAME " " MDB_VAR_FILEINDEX " " MDB_VAR_COMPOSITE " " MDB_VAR_PROJECT); // Remove this from mdb now so that it isn't displayed in "extras'
     field = mdbObjVarValPairsAsLine(oneFile->mdb,TRUE);
     printf("<TD nowrap>%s</td>",field?field:" &nbsp;");
 
     printf("</TR>\n");
     }
 
 printf("</TBODY><TFOOT class='bgLevel1'>\n");
 printf("<TR valign='top'>");
 
 // Restriction policy link in first column?
 if (restrictedColumn == 1)
     printf("<TH colspan=%d><A HREF='%s' TARGET=BLANK style='font-size:.9em;'>Restriction Policy</A></TH>", (columnCount - restrictedColumn),ENCODE_DATA_RELEASE_POLICY);
 
 printf("<TD colspan=%d>&nbsp;&nbsp;&nbsp;&nbsp;",(restrictedColumn > 1 ? (restrictedColumn - 1) : columnCount));
 
@@ -704,119 +708,118 @@
     // Nice to have: Make filtering and sorting persistent (saved to cart)
 
 // FIXME: Trick while developing:
 if (tdb->table != NULL)
     tdb->track = tdb->table;
 
 boolean debug = cartUsualBoolean(cart,"debug",FALSE);
 
 struct sqlConnection *conn = hAllocConn(db);
 char *mdbTable = mdbTableName(conn,TRUE); // Look for sandBox name first
 if(mdbTable == NULL)
     errAbort("TABLE NOT FOUND: '%s.%s'.\n",db,MDB_DEFAULT_NAME);
 
 // Get an mdbObj list of all that belong to this track and have a fileName
 char buf[256];
-safef(buf,sizeof(buf),"composite=%s fileName=?",tdb->track);
+safef(buf,sizeof(buf),"%s=%s %s=?",MDB_VAR_COMPOSITE,tdb->track,MDB_VAR_FILENAME);
 struct mdbByVar *mdbVars = mdbByVarsLineParse(buf);
 struct mdbObj *mdbList = mdbObjsQueryByVars(conn,mdbTable,mdbVars);
 
 // Now get Indexes  But be sure not to duplicate entries in the list!!!
-safef(buf,sizeof(buf),"composite=%s fileIndex= fileName!=",tdb->track);
+safef(buf,sizeof(buf),"%s=%s %s= %s!=",MDB_VAR_COMPOSITE,tdb->track,MDB_VAR_FILEINDEX,MDB_VAR_FILENAME);
 mdbVars = mdbByVarsLineParse(buf);
 mdbList = slCat(mdbList, mdbObjsQueryByVars(conn,mdbTable,mdbVars));
 mdbObjRemoveHiddenVars(mdbList);
 hFreeConn(&conn);
 
 if (slCount(mdbList) == 0)
     {
     warn("No files specified in metadata for: %s\n%s",tdb->track,tdb->longLabel);
     return;
     }
 
 // Verify file existance and make fileList of those found
 struct fileDb *fileList = NULL, *oneFile = NULL; // Will contain found files
 struct mdbObj *mdbFiles = NULL; // Will caontain a list of mdbs for the found files
 while(mdbList)
     {
     char buf[512];
     boolean found = FALSE;
     struct mdbObj *mdbFile = slPopHead(&mdbList);
     // First for FileName
-    char *fileName = mdbObjFindValue(mdbFile,"fileName");
+    char *fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILENAME);
     if (fileName != NULL)
         {
         oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, tdb->track, fileName);
         if (oneFile)
             {
             slAddHead(&fileList,oneFile);
             oneFile->mdb = mdbFile;
-            slAddHead(&mdbFiles,mdbFile);
+            slAddHead(&mdbFiles,oneFile->mdb);
             found = TRUE;
             }
         else if (debug)
             warn("goldenPath/%s/%s/%s/%s    in mdb but not found in directory",db,ENCODE_DCC_DOWNLOADS, tdb->track,fileName);
         }
     // Now for FileIndexes
     if (fileName && endsWith(fileName,".bam")) // Special to fill in missing .bam.bai's
         {
         safef(buf,sizeof(buf),"%s.bai",fileName);
         fileName = buf;
         }
     else
-        fileName = mdbObjFindValue(mdbFile,"fileIndex");
+        fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILEINDEX);
     if (fileName != NULL)
         {
         // Verify existance first
         oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, tdb->track, fileName);
         if (oneFile)
             {
             slAddHead(&fileList,oneFile);
             if (found) // if already found then need two mdbObjs (assertable but then this is metadata)
                 oneFile->mdb = mdbObjClone(mdbFile);  // Do we really need to clone this?
             else
-                {
                 oneFile->mdb = mdbFile;
-                slAddHead(&mdbFiles,mdbFile);
-                }
+            slAddHead(&mdbFiles,oneFile->mdb);
             found = TRUE;
             }
         else if (debug)
             warn("goldenPath/%s/%s/%s/%s    in mdb but not found in directory",db,ENCODE_DCC_DOWNLOADS, tdb->track,fileName);
         }
     if (!found)
         mdbObjsFree(&mdbFile);
     }
 
 if (slCount(fileList) == 0)
     {
     warn("No downloadable files currently available for: %s\n%s",tdb->track,tdb->longLabel);
     return;  // No files so nothing to do.
     }
 if (debug)
     {
     warn("The following files are in goldenPath/%s/%s/%s/ but NOT in the mdb:",db,ENCODE_DCC_DOWNLOADS, tdb->track);
     fileDbGet(db, ENCODE_DCC_DOWNLOADS, tdb->track, "listAll");
     }
 
 jsIncludeFile("hui.js",NULL);
 jsIncludeFile("ajax.js",NULL);
 
 // standard preamble
 filesDownloadsPreamble(db,tdb);
 
 // Now update all files with their sortable fields and sort the list
+mdbObjReorderByCv(mdbFiles,FALSE);// Start with cv defined order for visible vars. NOTE: will not need to reorder during print!
 sortOrder_t *sortOrder = fileSortOrderGet(cart,tdb,mdbFiles);
 boolean filterable = FALSE;
 if (sortOrder != NULL)
     {
     char *vars = removeCommonMdbVarsNotInSortOrder(mdbFiles,sortOrder);
     if (vars)
         {
         if (debug)
             warn("These terms are common:%s",vars);
         freeMem(vars);
         }
 
     // Fill in and sort fileList
     fileDbSortList(&fileList,sortOrder);
     // FilterBoxes ?
@@ -836,108 +839,107 @@
 // Prints list of files in downloads directories matching mdb search terms. Returns count
 {
 struct sqlConnection *connLocal = conn;
 if (conn == NULL)
     connLocal = hAllocConn(db);
 struct mdbObj *mdbList = mdbObjRepeatedSearch(connLocal,varValPairs,FALSE,TRUE);
 if (conn == NULL)
     hFreeConn(&connLocal);
 if (slCount(mdbList) == 0)
     {
     printf("<DIV id='filesFound'><BR>No files found.<BR></DIV><BR>\n");
     return 0;
     }
 
 // Now sort mdbObjs so that composites will stay together and lookup of files will be most efficient
-mdbObjsSortOnVars(&mdbList, "composite");
+mdbObjsSortOnVars(&mdbList, MDB_VAR_COMPOSITE);
 mdbObjRemoveHiddenVars(mdbList);
 
 #define FOUND_FILE_LIMIT 1000
 int fileCount = 0;
 // Verify file existance and make fileList of those found
 struct fileDb *fileList = NULL, *oneFile = NULL; // Will contain found files
 struct mdbObj *mdbFiles = NULL; // Will caontain a list of mdbs for the found files
 while(mdbList && fileCount < FOUND_FILE_LIMIT)
     {
     boolean found = FALSE;
     struct mdbObj *mdbFile = slPopHead(&mdbList);
-    char *composite = mdbObjFindValue(mdbFile,"composite");
+    char *composite = mdbObjFindValue(mdbFile,MDB_VAR_COMPOSITE);
     if (composite != NULL)
         {
         // First for FileName
-        char *fileName = mdbObjFindValue(mdbFile,"fileName");
+        char *fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILENAME);
         if (fileName != NULL)
             {
             oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, composite, fileName);
             if (oneFile)
                 {
                 //warn("%s == %s",fileType,oneFile->fileType);
                 if (isEmpty(fileType) || sameWord(fileType,"Any")
                 || (oneFile->fileType && sameWord(fileType,oneFile->fileType)))
                     {
                     slAddHead(&fileList,oneFile);
                     oneFile->mdb = mdbFile;
-                    slAddHead(&mdbFiles,mdbFile);
+                    slAddHead(&mdbFiles,oneFile->mdb);
                     fileCount++;
                     found = TRUE;
                     if (fileCount == FOUND_FILE_LIMIT)
                         break;
                     }
                 }
                 else
                     fileDbFree(&oneFile);
             }
         // Now for FileIndexes
-        fileName = mdbObjFindValue(mdbFile,"fileIndex");
+        fileName = mdbObjFindValue(mdbFile,MDB_VAR_FILEINDEX);
         if (fileName != NULL)
             {
            // Verify existance first
             oneFile = fileDbGet(db, ENCODE_DCC_DOWNLOADS, composite, fileName);
             if (oneFile)
                 {
                 //warn("%s == %s",fileType,oneFile->fileType);
                 if (isEmpty(fileType) || sameWord(fileType,"Any")
                 || (oneFile->fileType && sameWord(fileType,oneFile->fileType)))
                    {
                     slAddHead(&fileList,oneFile);
                     if (found) // if already found then need two mdbObjs (assertable but then this is metadata)
                         oneFile->mdb = mdbObjClone(mdbFile);  // Do we really need to clone this?
                     else
-                        {
                         oneFile->mdb = mdbFile;
-                        slAddHead(&mdbFiles,mdbFile);
-                        }
+                    slAddHead(&mdbFiles,oneFile->mdb);
                     fileCount++;
                     found = TRUE;
                     continue;
                     }
                 else
                     fileDbFree(&oneFile);
                 }
             }
         }
     if (!found)
         mdbObjsFree(&mdbFile);
     }
 if (slCount(fileList) == 0)
     {
     printf("<DIV id='filesFound'><BR>No files found.<BR></DIV><BR>\n");
     return 0;  // No files so nothing to do.
     }
 
 // TODO Could sort on varValPairs by creating a sortOrder struct of them
 //// Now update all files with their sortable fields and sort the list
+mdbObjReorderByCv(mdbFiles,FALSE);// Start with cv defined order for visible vars. NOTE: will not need to reorder during print!
 sortOrder_t *sortOrder = fileSortOrderGet(NULL,NULL,mdbFiles); // No cart, no tdb
 if (sortOrder != NULL)
     {
     // Fill in and sort fileList
     fileDbSortList(&fileList,sortOrder);
     }
 
 mdbObjRemoveVars(mdbFiles,"tableName"); // Remove this from mdb now so that it isn't displayed in "extras'
 
 //jsIncludeFile("hui.js",NULL);
 //jsIncludeFile("ajax.js",NULL);
 
 // Print table
 printf("<DIV id='filesFound'>");
 if (mdbList != NULL)