0dbf3efc8d7c425510c124204883708273691ec8 hiram Tue Mar 19 13:36:44 2019 -0700 correctly listing full set of tracks for a hub or database with all attributes refs #18869 diff --git src/hg/hubApi/list.c src/hg/hubApi/list.c index 5ee114d..b464631 100644 --- src/hg/hubApi/list.c +++ src/hg/hubApi/list.c @@ -198,49 +198,69 @@ jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); freeMem(dataTime); jsonWriteNumber(jw, "chromCount", (long long)slCount(ciList)); jsonWriteObjectStart(jw, "chromosomes"); for ( ; el != NULL; el = el->next ) { jsonWriteNumber(jw, el->chrom, (long long)el->size); } jsonWriteObjectEnd(jw); /* chromosomes */ jsonWriteObjectEnd(jw); /* top level */ fputs(jw->dy->string,stdout); } hFreeConn(&conn); } -static void recursiveTrackList(struct jsonWrite *jw, struct trackDb *tdb, char *type) -/* output trackDb tags, recursive when composite track */ +static void recursiveTrackList(struct jsonWrite *jw, struct trackDb *tdb) +/* output trackDb tags only for real tracks, not containers, + * recursive when subtracks exist + */ { -jsonWriteListStart(jw, type); -struct trackDb *el = NULL; -for (el = tdb; el != NULL; el = el->next ) +if (! ( tdbIsComposite(tdb) || tdbIsCompositeView(tdb) ) ) { - jsonWriteObjectStart(jw, NULL); - jsonWriteString(jw, "track", el->track); - jsonWriteString(jw, "shortLabel", el->shortLabel); - jsonWriteString(jw, "type", el->type); - jsonWriteString(jw, "longLabel", el->longLabel); - if (el->parent) - jsonWriteString(jw, "parent", el->parent->track); - if (el->subtracks) - recursiveTrackList(jw, el->subtracks, "subtracks"); + jsonWriteObjectStart(jw, tdb->track); + jsonWriteString(jw, "shortLabel", tdb->shortLabel); + jsonWriteString(jw, "type", tdb->type); + jsonWriteString(jw, "longLabel", tdb->longLabel); + if (tdb->parent) + jsonWriteString(jw, "parent", tdb->parent->track); + if (tdb->settingsHash) + { + jsonWriteString(jw, "hasSettingsHash", "TRUE"); + struct hashEl *hel; + struct hashCookie hc = hashFirst(tdb->settingsHash); + while ((hel = hashNext(&hc)) != NULL) + { + if (sameWord("track", hel->name)) + continue; // already output in header + if (isEmpty((char *)hel->val)) + jsonWriteString(jw, hel->name, "empty"); + else + jsonWriteString(jw, hel->name, (char *)hel->val); + } + } jsonWriteObjectEnd(jw); } -jsonWriteListEnd(jw); + +if (tdb->subtracks) + { + struct trackDb *el = NULL; + for (el = tdb->subtracks; el != NULL; el = el->next ) + { + recursiveTrackList(jw, el); + } + } } /* static void recursiveTrackList() */ static int trackDbTrackCmp(const void *va, const void *vb) /* Compare to sort based on 'track' name; use shortLabel as secondary sort key. * Note: parallel code to hgTracks.c:tgCmpPriority */ { const struct trackDb *a = *((struct trackDb **)va); const struct trackDb *b = *((struct trackDb **)vb); int dif = strcmp(a->track, b->track); if (dif < 0) return -1; else if (dif == 0.0) return strcasecmp(a->shortLabel, b->shortLabel); else return 1; @@ -248,62 +268,73 @@ static void trackDbJsonOutput(char *db, FILE *f) /* return track list from specified UCSC database name */ { struct sqlConnection *conn = hAllocConn(db); char *dataTime = sqlTableUpdate(conn, "trackDb"); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ hFreeConn(&conn); struct trackDb *tdbList = obtainTdb(NULL, db); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "db", db); jsonWriteString(jw, "dataTime", dataTime); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); freeMem(dataTime); -recursiveTrackList(jw, tdbList, "tracks"); +struct trackDb *el = NULL; +for (el = tdbList; el != NULL; el = el->next ) + { + recursiveTrackList(jw, el); + } jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } /* static void trackDbJsonOutput(char *db, FILE *f) */ void apiList(char *words[MAX_PATH_INFO]) /* 'list' function words[1] is the subCommand */ { if (sameWord("publicHubs", words[1])) jsonPublicHubs(); else if (sameWord("ucscGenomes", words[1])) jsonDbDb(); else if (sameWord("hubGenomes", words[1])) { char *hubUrl = cgiOptionalString("hubUrl"); if (isEmpty(hubUrl)) apiErrAbort("must supply hubUrl='http:...' some URL to a hub for /list/hubGenomes"); struct trackHub *hub = errCatchTrackHubOpen(hubUrl); if (hub->genomeList) { + slNameSort((struct slName **)&hub->genomeList); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); - jsonWriteListStart(jw, "genomes"); - struct slName *theList = genomeList(hub, NULL, NULL); - slNameSort(&theList); - struct slName *el = theList; - for ( ; el ; el = el->next ) + jsonWriteObjectStart(jw, "genomes"); + struct trackHubGenome *el; + for ( el = hub->genomeList; el; el = el->next) { - jsonWriteString(jw, NULL, el->name); + jsonWriteObjectStart(jw, el->name); + jsonWriteString(jw, "organism", el->organism); + jsonWriteString(jw, "description", el->description); + jsonWriteString(jw, "trackDbFile", el->trackDbFile); + jsonWriteString(jw, "twoBitPath", el->twoBitPath); + jsonWriteString(jw, "groups", el->groups); + jsonWriteString(jw, "defaultPos", el->defaultPos); + jsonWriteNumber(jw, "orderKey", el->orderKey); + jsonWriteObjectEnd(jw); } - jsonWriteListEnd(jw); + jsonWriteObjectEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } } else if (sameWord("tracks", words[1])) { char *hubUrl = cgiOptionalString("hubUrl"); char *genome = cgiOptionalString("genome"); char *db = cgiOptionalString("db"); if (isEmpty(hubUrl) && isEmpty(db)) apiErrAbort("ERROR: must supply hubUrl or db name to return track list"); if (isEmpty(hubUrl)) // missing hubUrl implies UCSC database { trackDbJsonOutput(db, stdout); // only need db for this function return; @@ -311,32 +342,37 @@ if (isEmpty(genome) || isEmpty(hubUrl)) { if (isEmpty(genome)) warn("# must supply genome='someName' the name of a genome in a hub for /list/tracks\n"); if (isEmpty(hubUrl)) apiErrAbort("ERROR: must supply hubUrl='http:...' some URL to a hub for /list/genomes"); } struct trackHub *hub = errCatchTrackHubOpen(hubUrl); if (hub->genomeList) { struct trackDb *tdbList = NULL; (void) genomeList(hub, &tdbList, genome); slSort(tdbList, trackDbTrackCmp); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); - jsonWriteString(jw, "genome", genome); - recursiveTrackList(jw, tdbList, "tracks"); + jsonWriteObjectStart(jw, genome); + struct trackDb *el = NULL; + for (el = tdbList; el != NULL; el = el->next ) + { + recursiveTrackList(jw, el); + } + jsonWriteObjectEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } } else if (sameWord("chromosomes", words[1])) { char *hubUrl = cgiOptionalString("hubUrl"); // char *genome = cgiOptionalString("genome"); char *db = cgiOptionalString("db"); if (isEmpty(hubUrl) && isEmpty(db)) apiErrAbort("ERROR: must supply hubUrl or db name to return chromosome list"); if (isEmpty(hubUrl)) // missing hubUrl implies UCSC database { chromInfoJsonOutput(stdout, db);