9b0d9b4ac32562cf2ed51ffafaef6abe8bb2beb6 braney Tue Feb 6 08:10:16 2018 -0800 add a function to get trackDb metadata as an slPair list. Change other functions to use this api diff --git src/hg/lib/trackDbCustom.c src/hg/lib/trackDbCustom.c index 31e6475..55ec2d9 100644 --- src/hg/lib/trackDbCustom.c +++ src/hg/lib/trackDbCustom.c @@ -7,30 +7,32 @@ #include "common.h" #include "linefile.h" #include "jksql.h" #include "trackDb.h" #include "hdb.h" #include "hui.h" #include "ra.h" #include "hash.h" #include "net.h" #include "sqlNum.h" #include "obscure.h" #include "hgMaf.h" #include "customTrack.h" #include "regexHelper.h" +#include "fieldedTable.h" +#include "tagRepo.h" /* ----------- End of AutoSQL generated code --------------------- */ struct trackDb *trackDbNew() /* Allocate a new trackDb with just very minimal stuff filled in. */ { struct trackDb *tdb; AllocVar(tdb); tdb->canPack = 2; /* Unknown value. */ return tdb; } int trackDbCmp(const void *va, const void *vb) /* Compare to sort based on priority; use shortLabel as secondary sort key. @@ -1365,15 +1367,122 @@ else if (tdbIsSuperTrackChild(tdb)) // solo track { safef(buf,sizeof buf, "%s_sel", tdb->track); cartSetString(cart, buf, "1"); // Will reshape supertrack } } boolean trackDbSettingBlocksConfiguration(struct trackDb *tdb, boolean onlyAjax) // Configuration dialogs may be explicitly blocked in tracDb settings { if (SETTING_IS_OFF(trackDbSettingClosestToHome(tdb, "configurable"))) return TRUE; // never configurable return (onlyAjax && SETTING_IS_OFF(trackDbSettingClosestToHome(tdb,"configureByPopup"))); } + +struct slPair *tabSepMetaPairs(char *tabSepMeta, struct trackDb *tdb, char *metaTag) +{ +// If there's no file, there's no data. +if (tabSepMeta == NULL) + return NULL; + +// If the trackDb entry doesn't have a foreign key, there's no data. +if (metaTag == NULL) + return NULL; + +static char *cachedTableName = NULL; +static struct hash *cachedHash = NULL; +static struct fieldedTable *cachedTable = NULL; + +// Cache this table because there's a good chance we'll get called again with it. +if ((cachedTableName == NULL) || differentString(tabSepMeta, cachedTableName)) + { + char *requiredFields[] = {"meta"}; + cachedTable = fieldedTableFromTabFile(tabSepMeta, NULL, requiredFields, sizeof requiredFields / sizeof (char *)); + cachedHash = fieldedTableUniqueIndex(cachedTable, requiredFields[0]); + cachedTableName = cloneString(tabSepMeta); + } + +// Look for this tag in the metadata. +struct fieldedRow *fr = hashFindVal(cachedHash, metaTag); +if (fr == NULL) + return NULL; + +int ii; +struct slPair *pairList = NULL; +for(ii=0; ii < cachedTable->fieldCount; ii++) + { + char *fieldName = cachedTable->fields[ii]; + char *fieldVal = fr->row[ii]; + if (!isEmpty(fieldVal)) + slAddHead(&pairList, slPairNew(fieldName, cloneString(fieldVal))); + } +slReverse(&pairList); + +return pairList; +} + + +static struct slPair *convertNameValueString(char *string) +/* Convert a string composed of name=value pairs separated by white space. */ +{ +char *clone = cloneString(string); +int count = chopByWhiteRespectDoubleQuotes(clone,NULL,0); +char **words = needMem(sizeof(char *) * count); +count = chopByWhiteRespectDoubleQuotes(clone,words,count); +if (count < 1 || words[0] == NULL) + { + errAbort("This is not formatted var=val pairs:\n\t%s\n",string); + } + +int ix; +struct slPair *pairList = NULL, *pair; + +for (ix = 0;ix<count;ix++) + { + if (*words[ix] == '#') + break; + + if (strchr(words[ix], '=') == NULL) // treat this the same as "var=" + { + pair = slPairNew(words[ix], NULL); + } + else + { + char *name = cloneNextWordByDelimiter(&(words[ix]),'='); + char *value = cloneString(words[ix]); + pair = slPairNew(name, value); + } + slAddHead(&pairList, pair); + } + +slReverse(&pairList); + +free(clone); +return pairList; +} + +struct slPair *trackDbMetaPairs(struct trackDb *tdb) +/* Read in metadata given a trackDb entry. This routine understands the three ways + * that metadata can be represented in a trackDb stanza: "metadata" lines per stanza, + * or a tab-separated or tagStorm file with a foreign key specified by the "meta" tag. + */ +{ +char *metaTag = trackDbSetting(tdb, "meta"); +if (metaTag != NULL) + { + char *tabSepMeta = trackDbSetting(tdb, "metaTab"); + if (tabSepMeta) + return tabSepMetaPairs(tabSepMeta, tdb, metaTag); + + char *tagStormFile = trackDbSetting(tdb, "metaDb"); + if (tagStormFile) + return tagRepoPairs(tagStormFile, "meta", metaTag); + } + +char *metadataInTdb = trackDbSetting(tdb, "metadata"); +if (metadataInTdb) + return convertNameValueString(metadataInTdb); + +return NULL; +}