8567de90c15406a451dd684f28884e197c6f8feb
tdreszer
  Fri Mar 11 16:08:51 2011 -0800
Added const to a couple of APIs and changed some stuff to aid fleUi filterFiles functionality
diff --git src/hg/lib/mdb.c src/hg/lib/mdb.c
index ee6b2e2..ac0abd2 100644
--- src/hg/lib/mdb.c
+++ src/hg/lib/mdb.c
@@ -1692,37 +1692,37 @@
     return sameOk(foundVal,val);
     }
 struct mdbVar *mdbVar = NULL;
 for(mdbVar=mdbObj->vars;mdbVar!=NULL;mdbVar=mdbVar->next)
     {
     if(differentStringNullOk(var,mdbVar->var) != 0)
         continue;
     if(differentStringNullOk(val,mdbVar->val) != 0)
         continue;
     return TRUE;
     }
 
 return FALSE;
 }
 
-boolean mdbObjsContainAtleastOne(struct mdbObj *mdbObjs, char *var)
+boolean mdbObjsContainAltleastOneMatchingVar(struct mdbObj *mdbObjs, char *var, char *val)
 // Returns TRUE if any object in set contains var
 {
 struct mdbObj *mdbObj = mdbObjs;
 for(;mdbObj!=NULL; mdbObj=mdbObj->next)
     {
-    if(mdbObjContains(mdbObj, var, NULL))
+    if(mdbObjContains(mdbObj, var, val))
         return TRUE;
     }
 return FALSE;
 }
 
 struct mdbObj *mdbObjsCommonVars(struct mdbObj *mdbObjs)
 // Returns a new mdbObj with all vars that are contained in every obj passed in.
 // Note that the returnd mdbObj has a meaningles obj name and vals.
 {
 if (mdbObjs == NULL || mdbObjs->vars == NULL)
     return NULL;
 struct mdbObj *mdbObj = mdbObjs;
 struct mdbObj *commonVars = mdbObjClone(mdbObj); // Clone the first obj then prune it
 commonVars->next = NULL;
 mdbObj=mdbObj->next;                             // No need to include first obj in search
@@ -1954,30 +1954,55 @@
             if(count != 0 && mdbObj->varHash != NULL)
                 hashRemove(mdbObj->varHash, mdbVar->var);
 
             mdbVarFree(&mdbVar);
             }
         }
 
     if(keepTheseVars != NULL)
         slReverse(&keepTheseVars);
     mdbObj->vars = keepTheseVars;
     }
     if(words != NULL)
         freeMem(words);
 }
 
+void mdbObjRemoveHiddenVars(struct mdbObj *mdbObjs)
+// Prunes list of vars for mdb objs that have been declared as hidden in cv.ra typeOfTerms
+{
+// make comma delimited list of hidden vars
+struct hash *cvTermTypes = (struct hash *)mdbCvTermTypeHash();
+struct hashEl *el, *elList = hashElListHash(cvTermTypes);
+struct dyString *dyRemoveVars = dyStringNew(256);
+
+for (el = elList; el != NULL; el = el->next)
+    {
+    struct hash *varHash = el->val;
+    if (SETTING_IS_ON(hashFindVal(varHash, "hidden")))
+        {
+        assert(mdbCvSearchMethod(el->name) == cvsNotSearchable);  // Good idea to assert but cv.ra is a user updatable file
+        dyStringPrintf(dyRemoveVars,"%s ",el->name);
+        }
+    }
+hashElFreeList(&elList);
+
+if (dyStringLen(dyRemoveVars))
+    mdbObjRemoveVars(mdbObjs, dyStringContents(dyRemoveVars));
+
+dyStringFree(&dyRemoveVars);
+}
+
 char *mdbRemoveCommonVar(struct mdbObj *mdbList, char *var)
 // Removes var from set of mdbObjs but only if all that have it have a commmon val
 // Returns the val if removed, else NULL
 {
 char *val = NULL;
 struct mdbObj *mdb = NULL;
 for(mdb = mdbList; mdb; mdb=mdb->next)
     {
     char *thisVal = mdbObjFindValue(mdb,var);
     if (thisVal == NULL) // If var isn't found in some, that is okay
         continue;
     if (val == NULL)
         val = thisVal;
     else if(differentWord(val,thisVal))
         return NULL;
@@ -2252,31 +2277,31 @@
 struct slName *mdbNames = NULL;
 struct mdbObj *mdbObj = mdbObjs;
 for( ;mdbObj!=NULL; mdbObj=mdbObj->next)
     {
     slAddHead(&mdbNames,slNameNew(mdbObj->obj)); //allocates memory
     }
 slReverse(&mdbNames);
 return mdbNames;
 }
 
 // ----------------- Validateion and specialty APIs -----------------
 int mdbObjsValidate(struct mdbObj *mdbObjs, boolean full)
 // Validates vars and vals against cv.ra.  Returns count of errors found.
 // Full considers vars not defined in cv as invalids
 {
-struct hash *termTypeHash = mdbCvTermTypeHash();
+struct hash *termTypeHash = (struct hash *)mdbCvTermTypeHash();
 struct mdbObj *mdbObj = NULL;
 int invalids = 0;
 for( mdbObj=mdbObjs; mdbObj!=NULL; mdbObj=mdbObj->next )
     {
     struct mdbVar *mdbVar = NULL;
     for(mdbVar = mdbObj->vars;mdbVar != NULL;mdbVar=mdbVar->next)
         {
         struct hash *termHash = hashFindVal(termTypeHash,mdbVar->var);
         if (termHash == NULL) // No cv definition for term so no validation can be done
             {
             if (!full)
                 continue;
             if (sameString(mdbVar->var,"objType")
             && (sameString(mdbVar->val,"table") || sameString(mdbVar->val,"file") || sameString(mdbVar->val,"composite")))
                 continue;
@@ -2293,44 +2318,44 @@
 
         // NOTE: Working on memory in hash but we are throwing away a comment and removing trailing spaces so that is okay
         strSwapChar(validationRule,'#','\0'); // Chop off any comment in the setting
         validationRule = trimSpaces(validationRule);
 
         // Validate should be or start with known word
         if (startsWithWord("cv",validationRule))
             {
             if (SETTING_NOT_ON(hashFindVal(termHash,"cvDefined"))) // Known type of term but no validation to be done
                 {
                 verbose(1,"ERROR in cv.ra: Term %s says validate in cv but is not 'cvDefined'.\n",mdbVar->var);
                 continue;
                 }
 
            // cvDefined so every val should be in cv
-           struct hash *cvTermHash = mdbCvTermHash(mdbVar->var);
+           struct hash *cvTermHash = (struct hash *)mdbCvTermHash(mdbVar->var);
            if (cvTermHash == NULL)
                 {
                 verbose(1,"ERROR in cv.ra: Term %s says validate in cv but not found as a cv term.\n",mdbVar->var);
                 continue;
                 }
             if (hashFindVal(cvTermHash,mdbVar->val) == NULL) // No cv definition for term so no validation can be done
                 {
                 char * orControl = skipBeyondDelimit(validationRule,' ');
                 if (orControl && sameString(orControl,"or None") && sameString(mdbVar->val,"None"))
                     continue;
                 else if (orControl && sameString(orControl,"or control"))
                     {
-                    cvTermHash = mdbCvTermHash("control");
+                    cvTermHash = (struct hash *)mdbCvTermHash("control");
                     if (cvTermHash == NULL)
                         {
                         verbose(1,"ERROR in cv.ra: Term control says validate in cv but not found as a cv term.\n");
                         continue;
                         }
                     if (hashFindVal(cvTermHash,mdbVar->val) != NULL)
                         continue;
                     }
                 printf("INVALID cv lookup: %s -> %s = %s\n",mdbObj->obj,mdbVar->var,mdbVar->val);
                 invalids++;
                 }
            }
         else if (startsWithWord("date",validationRule))
             {
             if (dateToSeconds(mdbVar->val,"%F") == 0)
@@ -2888,31 +2913,31 @@
 struct dyString *dyTerms = dyStringNew(256);
 // Build list of terms as "var1=val1 var2=val2a,val2b,val2c var3=%val3%"
 for(onePair = varValPairs; onePair != NULL; onePair = onePair->next)
     {
     if (isEmpty(((char *)(onePair->val)))) // NOTE: All the commas are needed to get the macro to do the right thing
         continue;
     enum mdbCvSearchable searchBy = mdbCvSearchMethod(onePair->name);
     if (searchBy == cvsSearchBySingleSelect || searchBy == cvsSearchByMultiSelect)  // multiSelect val will be filled with a comma delimited list
         dyStringPrintf(dyTerms,"%s=%s ",onePair->name,(char *)onePair->val);
     else if (searchBy == cvsSearchByFreeText)                                      // If select is by free text then like
         dyStringPrintf(dyTerms,"%s=%%%s%% ",onePair->name,(char *)onePair->val);
     else if (searchBy == cvsSearchByDateRange || searchBy == cvsSearchByIntegerRange)
         {
         // TO BE IMPLEMENTED
         // Requires new mdbObjSearch API and more than one (char *)onePair->val
-        warn("mdb search by date is not yet implemented.");
+        warn("mdb search by date or number is not yet implemented.");
         }
     }
 // Be sure to include table or file in selections
 if (tables)
     dyStringAppend(dyTerms,"objType=table ");
 if (files)
     dyStringAppend(dyTerms,"fileName=? ");
 
 // Build the mdbByVals struct and then select all mdbObjs in one query
 struct mdbByVar *mdbByVars = mdbByVarsLineParse(dyStringContents(dyTerms));
 dyStringClear(dyTerms);
 char *tableName = mdbTableName(conn,TRUE); // Look for sandBox name first
 struct mdbObj *mdbObjs = mdbObjsQueryByVars(conn,tableName,mdbByVars);
 
 return mdbObjs;
@@ -2968,146 +2993,149 @@
 // TODO: decide to make this public or hide it away inside the one function so far that uses it.
 static char *cv_file()
 // return default location of cv.ra
 {
 static char filePath[PATH_LEN];
 char *root = hCgiRoot();
 if (root == NULL || *root == 0)
     root = "/usr/local/apache/cgi-bin/"; // Make this check out sandboxes?
 //    root = "/cluster/home/tdreszer/kent/src/hg/makeDb/trackDb/cv/alpha/"; // Make this check out sandboxes?
 safef(filePath, sizeof(filePath), "%s/encode/cv.ra", root);
 if(!fileExists(filePath))
     errAbort("Error: can't locate cv.ra; %s doesn't exist\n", filePath);
 return filePath;
 }
 
-struct hash *mdbCvTermHash(char *term)
+const struct hash *mdbCvTermHash(char *term)
 // returns a hash of hashes of a term which should be defined in cv.ra
+// NOTE: in static memory: DO NOT FREE
 {
 static struct hash *cvHashOfHashOfHashes = NULL;
 if (sameString(term,"cell"))
     term = "Cell Line";
 else if (sameString(term,"antibody"))
     term = "Antibody";
 
 if (cvHashOfHashOfHashes == NULL)
     cvHashOfHashOfHashes = hashNew(0);
 
 struct hash *cvTermHash = hashFindVal(cvHashOfHashOfHashes,term);
 // Establish cv hash of Term Types if it doesn't already exist
 if (cvTermHash == NULL)
     {
     cvTermHash = raReadWithFilter(cv_file(), "term","type",term);
     if (cvTermHash != NULL)
         hashAdd(cvHashOfHashOfHashes,term,cvTermHash);
     }
 
 return cvTermHash;
 }
 
-struct slPair *mdbValLabelSearch(struct sqlConnection *conn, char *var, int limit, boolean tables, boolean files)
+struct slPair *mdbValLabelSearch(struct sqlConnection *conn, char *var, int limit, boolean tags, boolean tables, boolean files)
 // Search the metaDb table for vals by var and returns val (as pair->name) and controlled vocabulary (cv) label
 // (if it exists) (as pair->val).  Can impose (non-zero) limit on returned string size of name.
+// if requested, return cv tag instead of mdb val.  If requested, limit to table objs or file objs
 // Return is case insensitive sorted on label (cv label or else val).
 {  // TODO: Change this to use normal mdb struct routines?
 if (!tables && !files)
     errAbort("mdbValSearch requests values for neither table nor file objects.\n");
 
 char *tableName = mdbTableName(conn,TRUE); // Look for sandBox name first
 
 struct dyString *dyQuery = dyStringNew(512);
 if (limit > 0)
     dyStringPrintf(dyQuery,"select distinct LEFT(val,%d)",limit);
 else
     dyStringPrintf(dyQuery,"select distinct val");
 
 dyStringPrintf(dyQuery," from %s l1 where l1.var='%s' ",tableName,var);
 
 if (!tables || !files)
     dyStringPrintf(dyQuery,"and exists (select l2.obj from %s l2 where l2.obj = l1.obj and l2.var='objType' and l2.val='%s')",
                    tableName,tables?"table":"file");
-dyStringAppend(dyQuery," order by val");
 
-struct hash *varHash = mdbCvTermHash(var);
+struct hash *varHash = (struct hash *)mdbCvTermHash(var);
 
-struct slPair *pairs = NULL, *pair;
+struct slPair *pairs = NULL;
 struct sqlResult *sr = sqlGetResult(conn, dyStringContents(dyQuery));
 dyStringFree(&dyQuery);
 char **row;
-struct hash *valHash = NULL;
 while ((row = sqlNextRow(sr)) != NULL)
     {
-    AllocVar(pair);
-    char *name = cloneString(row[0]);
-    pair = slPairNew(name,name);  // defaults the label to the metaDb.val
-    valHash = hashFindVal(varHash,name);
+    char *val = row[0];
+    char *label = NULL;
+    if (varHash != NULL)
+        {
+        struct hash *valHash = hashFindVal(varHash,val);
     if (valHash != NULL)
         {
-        char *label = hashFindVal(valHash,"label");
-        if (label != NULL)
+            label = cloneString(hashOptionalVal(valHash,"label",row[0]));
+            if (tags)
             {
-            label = strSwapChar(cloneString(label),'_',' ');  // vestigial _ meaning space
-            if (limit > 0 && strlen(label) > limit)
-                label[limit] = '\0';
-            freeMem(pair->val); // Allocated when pair was created
-            pair->val = label;
+                char *tag = hashFindVal(valHash,"tag");
+                if (tag != NULL)
+                    val = tag;
+                }
             }
         }
-    slAddHead(&pairs, pair);
+    if (label == NULL);
+        label = cloneString(row[0]);
+    label = strSwapChar(label,'_',' ');  // vestigial _ meaning space
+    slPairAdd(&pairs,val,label);
     }
 sqlFreeResult(&sr);
 slPairValSortCase(&pairs);
 return pairs;
 }
 
-struct hash *mdbCvTermTypeHash()
+const struct hash *mdbCvTermTypeHash()
 // returns a hash of hashes of mdb and controlled vocabulary (cv) term types
 // Those terms should contain label,description,searchable,cvDefined,hidden
+// NOTE: in static memory: DO NOT FREE
 { // NOTE: "typeOfTerm" is specialized, so don't use mdbCvTermHash
 static struct hash *cvHashOfTermTypes = NULL;
 
 // Establish cv hash of Term Types if it doesn't already exist
 if (cvHashOfTermTypes == NULL)
     {
     cvHashOfTermTypes = raReadWithFilter(cv_file(), "term","type","typeOfTerm");
     // Patch up an ugly inconsistency with 'cell'
     struct hash *cellHash = hashRemove(cvHashOfTermTypes,"cellType");
     if (cellHash)
         {
         hashAdd(cvHashOfTermTypes,"cell",cellHash);
         hashReplace(cellHash, "term", cloneString("cell")); // spilling memory of 'cellType' val
         }
     struct hash *abHash = hashRemove(cvHashOfTermTypes,"Antibody");
     if (abHash)
         {
         hashAdd(cvHashOfTermTypes,"antibody",abHash);
         hashReplace(abHash, "term", cloneString("antibody")); // spilling memory of 'Antibody' val
         }
     }
 
-
 return cvHashOfTermTypes;
 }
 
 struct slPair *mdbCvWhiteList(boolean searchTracks, boolean cvDefined)
 // returns the official mdb/controlled vocabulary terms that have been whitelisted for certain uses.
 // TODO: change to return struct that includes searchable!
 {
 struct slPair *whitePairs = NULL;
 
 // Get the list of term types from thew cv
-struct hash *termTypeHash = mdbCvTermTypeHash();
+struct hash *termTypeHash = (struct hash *)mdbCvTermTypeHash();
 struct hashCookie hc = hashFirst(termTypeHash);
 struct hashEl *hEl;
 while ((hEl = hashNext(&hc)) != NULL)
     {
     char *setting = NULL;
     struct hash *typeHash = (struct hash *)hEl->val;
     //if (!includeHidden)
         {
         setting = hashFindVal(typeHash,"hidden");
         if(SETTING_IS_ON(setting))
             continue;
         }
     if (searchTracks)
         {
         setting = hashFindVal(typeHash,"searchable");
@@ -3125,48 +3153,52 @@
     char *label = hashFindVal(typeHash,"label");
     if (label == NULL)
         label = term;
     slPairAdd(&whitePairs, term, cloneString(label)); // Term gets cloned in slPairAdd
     }
 if (whitePairs != NULL)
     slPairValSortCase(&whitePairs);
 
 return whitePairs;
 }
 
 enum mdbCvSearchable mdbCvSearchMethod(char *term)
 // returns whether the term is searchable // TODO: replace with mdbCvWhiteList() returning struct
 {
 // Get the list of term types from thew cv
-struct hash *termTypeHash = mdbCvTermTypeHash();
+struct hash *termTypeHash = (struct hash *)mdbCvTermTypeHash();
 struct hash *termHash = hashFindVal(termTypeHash,term);
 if (termHash != NULL)
     {
     char *searchable = hashFindVal(termHash,"searchable");
     if (searchable != NULL)
         {
         if (sameWord(searchable,"select"))
             return cvsSearchBySingleSelect;
         if (sameWord(searchable,"multiSelect"))
             return cvsSearchByMultiSelect;
         if (sameWord(searchable,"freeText"))
             return cvsSearchByFreeText;
+        //if (sameWord(searchable,"date"))
+        //    return cvsSearchByDateRange;
+        //if (sameWord(searchable,"numeric"))
+        //    return cvsSearchByIntegerRange;
         }
     }
 return cvsNotSearchable;
 }
 
 const char *cvLabel(char *term)
 // returns cv label if term found or else just term
 {
 // Get the list of term types from thew cv
-struct hash *termTypeHash = mdbCvTermTypeHash();
+struct hash *termTypeHash = (struct hash *)mdbCvTermTypeHash();
 struct hash *termHash = hashFindVal(termTypeHash,term);
 if (termHash != NULL)
     {
     char *label = hashFindVal(termHash,"label");
     if (label != NULL)
         return label;
     }
 return term;
 }