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; }