55b54d043a87a29773ca196c360a0af1346947ec
hiram
  Mon Feb 18 07:05:59 2019 -0800
the trackDb from hubs appears to be flattened ?  refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 8df3375..a80b2df 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -104,30 +104,32 @@
 }
 
 static void trackSettings(struct trackDb *tdb)
 /* process the settingsHash for a track */
 {
 hPrintf("    <ul>\n");
 struct hashEl *hel;
 struct hashCookie hc = hashFirst(tdb->settingsHash);
 while ((hel = hashNext(&hc)) != NULL)
     {
     if (isEmpty((char *)hel->val))
 	hPrintf("    <li>%s : &lt;empty&gt;</li>\n", hel->name);
     else
 	hPrintf("    <li>%s : '%s'</li>\n", hel->name, (char *)hel->val);
     }
+if (tdb->subtracks)
+    trackSettings(tdb->subtracks);
 hPrintf("    </ul>\n");
 }
 
 static int bbiBriefMeasure(char *type, char *bigDataUrl, char *bigDataIndex, long *chromCount, long *itemCount, struct dyString *errors)
 /* check a bigDataUrl to find chrom count and item count */
 {
 int retVal = 0;
 *chromCount = 0;
 *itemCount = 0;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     if (startsWithWord("bigNarrowPeak", type)
             || startsWithWord("bigBed", type)
             || startsWithWord("bigGenePred", type)
@@ -229,93 +231,97 @@
 destination->colorB = source->colorB;
 destination->altColorR = source->altColorR;
 destination->altColorG = source->altColorG;
 destination->altColorB = source->altColorB;
 destination->useScore = source->useScore;
 destination->private = source->private;
 destination->url = cloneString(source->url);
 destination->html = cloneString(source->html);
 destination->grp = cloneString(source->grp);
 destination->canPack = source->canPack;
 destination->settings = cloneString(source->settings);
 destination->settingsHash = source->settingsHash;
 }
 #endif
 
-static void hubTrackList(struct trackDb *tdb, struct trackHubGenome *genome)
+static void hubTrackList(struct trackDb *topTrackDb, struct trackHubGenome *genome)
 /* process the track list to show all tracks, return trackDb list */
 {
-if (tdb)
+if (topTrackDb)
     {
     struct hash *countTracks = hashNew(0);
     hPrintf("    <ul>\n");
-    struct trackDb *track = tdb;
-    for ( ; track; track = track->next )
+    struct trackDb *tdb = NULL;
+    for ( tdb = topTrackDb; tdb; tdb = tdb->next )
 	{
-	char *bigDataUrl = trackDbSetting(track, "bigDataUrl");
-	char *compositeTrack = trackDbSetting(track, "compositeTrack");
-	char *superTrack = trackDbSetting(track, "superTrack");
+	char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
+	char *compositeTrack = trackDbSetting(tdb, "compositeTrack");
+	char *superTrack = trackDbSetting(tdb, "superTrack");
 	boolean depthSearch = cartUsualBoolean(cart, "depthSearch", FALSE);
 	if (compositeTrack)
 	    hashIncInt(countTracks, "composite container");
 	else if (superTrack)
 	    hashIncInt(countTracks, "superTrack container");
-	else if (isEmpty(track->type))
+	else if (isEmpty(tdb->type))
 	    hashIncInt(countTracks, "no type specified");
 	else
-	    hashIncInt(countTracks, track->type);
+	    hashIncInt(countTracks, tdb->type);
 	if (depthSearch && bigDataUrl)
 	    {
 	    char *bigDataIndex = NULL;
-	    char *relIdxUrl = trackDbSetting(tdb, "bigDataIndex");
+	    char *relIdxUrl = trackDbSetting(topTrackDb, "bigDataIndex");
 	    if (relIdxUrl != NULL)
 		bigDataIndex = trackHubRelativeUrl(genome->trackDbFile, relIdxUrl);
 
 	    long chromCount = 0;
 	    long itemCount = 0;
 	    struct dyString *errors = newDyString(1024);
-	    int retVal = bbiBriefMeasure(track->type, bigDataUrl, bigDataIndex, &chromCount, &itemCount, errors);
+	    int retVal = bbiBriefMeasure(tdb->type, bigDataUrl, bigDataIndex, &chromCount, &itemCount, errors);
             if (retVal)
 		{
-		    hPrintf("    <li>%s : %s : <font color='red'>ERROR: %s</font></li>\n", track->track, track->type, errors->string);
+		    hPrintf("    <li>%s : %s : <font color='red'>ERROR: %s</font></li>\n", tdb->track, tdb->type, errors->string);
 		}
 	    else
 		{
-		if (startsWithWord("bigBed", track->type))
-		    hPrintf("    <li>%s : %s : %ld chroms : %ld item count</li>\n", track->track, track->type, chromCount, itemCount);
-		else if (startsWithWord("bigWig", track->type))
-		    hPrintf("    <li>%s : %s : %ld chroms : %ld bases covered</li>\n", track->track, track->type, chromCount, itemCount);
+		if (startsWithWord("bigBed", tdb->type))
+		    hPrintf("    <li>%s : %s : %ld chroms : %ld item count</li>\n", tdb->track, tdb->type, chromCount, itemCount);
+		else if (startsWithWord("bigWig", tdb->type))
+		    hPrintf("    <li>%s : %s : %ld chroms : %ld bases covered</li>\n", tdb->track, tdb->type, chromCount, itemCount);
 		else
-		    hPrintf("    <li>%s : %s : %ld chroms : %ld count</li>\n", track->track, track->type, chromCount, itemCount);
+		    hPrintf("    <li>%s : %s : %ld chroms : %ld count</li>\n", tdb->track, tdb->type, chromCount, itemCount);
 		}
 	    }
 	else
 	    {
 	    if (compositeTrack)
-		hPrintf("    <li>%s : %s : composite track container</li>\n", track->track, track->type);
+		hPrintf("    <li>%s : %s : composite track container</li>\n", tdb->track, tdb->type);
 	    else if (superTrack)
-		hPrintf("    <li>%s : %s : superTrack container</li>\n", track->track, track->type);
+		hPrintf("    <li>%s : %s : superTrack container</li>\n", tdb->track, tdb->type);
 	    else if (! depthSearch)
-		hPrintf("    <li>%s : %s : %s</li>\n", track->track, track->type, bigDataUrl);
+		hPrintf("    <li>%s : %s : %s</li>\n", tdb->track, tdb->type, bigDataUrl);
             else
-		hPrintf("    <li>%s : %s</li>\n", track->track, track->type);
+		hPrintf("    <li>%s : %s</li>\n", tdb->track, tdb->type);
 	    }
+	if (tdb->subtracks)
+	    hPrintf("    <li>hasSubtracks : TRUE</li>\n");
+	else
+	    hPrintf("    <li>hasSubtracks : FALSE</li>\n");
         if (allTrackSettings)
-            trackSettings(track); /* show all settings */
+            trackSettings(tdb); /* show all settings */
 	if (timeOutReached())
 	    break;
-	}	/*	for ( ; track; track = track->next )	*/
+	}	/*	for ( tdb = topTrackDb; tdb; tdb = tdb->next )	*/
     hPrintf("    <li>%d different track types</li>\n", countTracks->elCount);
     if (countTracks->elCount)
 	{
         hPrintf("        <ul>\n");
         struct hashEl *hel;
         struct hashCookie hc = hashFirst(countTracks);
         while ((hel = hashNext(&hc)) != NULL)
 	    {
             int prevCount = ptToInt(hashFindVal(trackCounter, hel->name));
 	    totalTracks += ptToInt(hel->val);
 	    hashReplace(trackCounter, hel->name, intToPt(prevCount + ptToInt(hel->val)));
 	    hPrintf("        <li>%d - %s</li>\n", ptToInt(hel->val), hel->name);
 	    }
         hPrintf("        </ul>\n");
 	}
@@ -484,37 +490,37 @@
 
 struct hashEl *hel = hashLookup(apiFunctionHash, words[0]);
 if (hel == NULL)
     apiErrAbort("no such command: '%s' for endpoint '/%s'", words[0], pathInfo);
 void (*apiFunction)(char **) = hel->val;
 // void (*apiFunction)(char **) = hashMustFindVal(apiFunctionHash, words[0]);
 
 (*apiFunction)(words);
 
 }	/*	static void apiFunctionSwitch(char *pathInfo)	*/
 
 static void tracksForUcscDb(char * ucscDb)
 {
 hPrintf("<p>Tracks in UCSC genome: '%s'<br>\n", ucscDb);
 struct trackDb *tdbList = hTrackDb(ucscDb);
-struct trackDb *track;
+struct trackDb *tdb;
 hPrintf("<ul>\n");
-for (track = tdbList; track != NULL; track = track->next )
+for (tdb = tdbList; tdb != NULL; tdb = tdb->next )
     {
-    hPrintf("<li>%s</li>\n", track->track);
+    hPrintf("<li>%s</li>\n", tdb->track);
     if (allTrackSettings)
-        trackSettings(track); /* show all settings */
+        trackSettings(tdb); /* show all settings */
     }
 hPrintf("</ul>\n");
 hPrintf("</p>\n");
 }
 
 static void showExamples(char *url, struct trackHubGenome *hubGenome, char *ucscDb)
 {
 
 hPrintf("<h2>Example URLs to return json data structures:</h2>\n");
 hPrintf("<ol>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/publicHubs' target=_blank>list public hubs</a> <em>/cgi-bin/hubApi/list/publicHubs</em></li>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/ucscGenomes' target=_blank>list database genomes</a> <em>/cgi-bin/hubApi/list/ucscGenomes</em></li>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/hubGenomes?hubUrl=%s' target=_blank>list genomes from specified hub</a> <em>/cgi-bin/hubApi/list/hubGenomes?hubUrl=%s</em></li>\n", url, url);
 hPrintf("<li><a href='/cgi-bin/hubApi/list/tracks?hubUrl=%s&genome=%s' target=_blank>list tracks from specified hub and genome</a> <em>/cgi-bin/hubApi/list/tracks?hubUrl=%s&genome=%s</em></li>\n", url, hubGenome->name, url, hubGenome->name);
 hPrintf("<li><a href='/cgi-bin/hubApi/list/tracks?db=%s' target=_blank>list tracks from specified UCSC database</a> <em>/cgi-bin/hubApi/list/tracks?db=%s</em></li>\n", ucscDb, ucscDb);