e06aca36b8d5f820603188308c7bec8749427fe0
hiram
  Wed Feb 6 14:32:14 2019 -0800
chrom list from specific track on ucsc database output and jsonErr output refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index c726cc7..40f8e25 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -583,35 +583,85 @@
 /* output the dbDb SQL table */
 {
 struct dbDb *dbList = ucscDbDb();
 struct dbDb *el;
 jsonStartOutput(stdout);
 printf("\"ucscGenomes\":[");
 for ( el=dbList; el != NULL; el = el->next )
     {
     dbDbJsonOutput(el, stdout);
     if (el->next)
        printf(",");
     }
 printf("]}\n");
 }
 
+static void jsonErrAbort(char *format, ...)
+/* Issue an error message in json format. */
+{
+char errMsg[2048];
+va_list args;
+va_start(args, format);
+vsnprintf(errMsg, sizeof(errMsg), format, args);
+fputc('{',stdout);
+jsonStringOut(stdout, "error", errMsg);
+fputc('}',stdout);
+}
+
 static void chromInfoJsonOutput(char *db, FILE *f, char *track)
 {
 if (track)
     {
-;
+    struct sqlConnection *conn = hAllocConn(db);
+    if (! sqlTableExists(conn, track))
+	jsonErrAbort("ERROR: endpoint: /list/chromosomes?db=%&table=%s ERROR table does not exist", db, track);
+    if (sqlColumnExists(conn, track, "chrom"))
+	{
+	jsonStartOutput(f);
+	jsonStringOut(f, "genome", db);
+	fputc(',',f);
+	jsonStringOut(f, "track", track);
+	fputc(',',f);
+        struct slPair *list = NULL;
+	char query[2048];
+        sqlSafef(query, sizeof(query), "select distinct chrom from %s", track);
+	struct sqlResult *sr = sqlGetResult(conn, query);
+	char **row;
+	while ((row = sqlNextRow(sr)) != NULL)
+    	{
+            int size = hChromSize(db, row[0]);
+	    slAddHead(&list, slPairNew(row[0], intToPt(size)));
+    	}
+	sqlFreeResult(&sr);
+        slPairIntSort(&list);
+        slReverse(&list);
+        jsonInteger(f, "chromCount", slCount(list));
+        fputc(',',f);
+        struct slPair *el = list;
+        for ( ; el != NULL; el = el->next )
+	    {
+            jsonInteger(f, el->name, ptToInt(el->val));
+	    if (el->next)
+		fputc(',',f);
+	    }
+        fputc('}',f);
+	}
+    else
+	{
+	jsonErrAbort("ERROR: table '%s' is not a position table, no chromosomes for genome: '%s'", track, db);
+	}
+    hFreeConn(&conn);
     }
 else
     {
     struct chromInfo *ciList = createChromInfoList(NULL, db);
     struct chromInfo *el = ciList;
     jsonStartOutput(f);
     jsonStringOut(f, "genome", db);
     fputc(',',f);
     jsonInteger(f, "chromCount", slCount(ciList));
     fputc(',',f);
     for ( ; el != NULL; el = el->next )
 	{
         jsonInteger(f, el->chrom, el->size);
 	if (el->next)
            fputc(',',f);
@@ -650,143 +700,139 @@
 fprintf(f, "]}\n");
 }	/*	static void trackDbJsonOutput(char *db, FILE *f)	*/
 
 #define MAX_PATH_INFO 32
 static 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))
-	errAbort("# must supply hubUrl='http:...' some URL to a hub for /list/genomes\n");
+	jsonErrAbort("ERROR: must supply hubUrl='http:...' some URL to a hub for /list/genomes\n");
 
     struct trackHub *hub = trackHubOpen(hubUrl, "");
     if (hub->genomeList)
 	{
         jsonStartOutput(stdout);
 	jsonStringOut(stdout, "hubUrl", hubUrl);
 	fputc(',',stdout);
 	printf("\"genomes\":[");
 	struct slName *theList = genomeList(hub, NULL, NULL);
 	slNameSort(&theList);
 	struct slName *el = theList;
 	for ( ; el ; el = el->next )
 	    {
 	    char *a = jsonStringEscape(el->name);
 	    printf("\"%s\"", a);
 	    freeMem(a);
 	    if (el->next)
 		fputc(',',stdout);
 	    }
 	printf("]}\n");
 	}
     }
 else if (sameWord("tracks", words[1]))
     {
     char *hubUrl = cgiOptionalString("hubUrl");
     char *genome = cgiOptionalString("genome");
     char *db = cgiOptionalString("db");
     if (isEmpty(hubUrl) && isEmpty(db))
-	{
-	errAbort("# ERROR: must supply hubUrl or db name to return track list");
-	}
+      jsonErrAbort("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;
 	}
     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))
-	    warn("# must supply hubUrl='http:...' some URL to a hub for /list/genomes\n");
-	    errAbort("# ERROR exit");
+            jsonErrAbort("ERROR: must supply hubUrl='http:...' some URL to a hub for /list/genomes\n");
 	}
     struct trackHub *hub = trackHubOpen(hubUrl, "");
     if (hub->genomeList)
 	{
 	struct slName *dbTrackList = NULL;
 	(void) genomeList(hub, &dbTrackList, genome);
         jsonStartOutput(stdout);
 	jsonStringOut(stdout, "hubUrl", hubUrl);
 	fputc(',',stdout);
 	jsonStringOut(stdout, "genome", genome);
 	fputc(',',stdout);
 	slNameSort(&dbTrackList);
 	struct slName *el = dbTrackList;
 	for ( ; el != NULL; el = el->next )
 	    {
 	    char *a = jsonStringEscape(el->name);
 	    printf("\"%s\"", a);
 	    freeMem(a);
 	    if (el->next)
 		fputc(',',stdout);
 	    }
 	printf("]}\n");
 	}
     }
 else if (sameWord("chromosomes", words[1]))
     {
     char *hubUrl = cgiOptionalString("hubUrl");
 //    char *genome = cgiOptionalString("genome");
     char *db = cgiOptionalString("db");
     if (isEmpty(hubUrl) && isEmpty(db))
-	{
-	errAbort("# ERROR: must supply hubUrl or db name to return chromosome list");
-	}
+        jsonErrAbort("ERROR: must supply hubUrl or db name to return chromosome list");
+
     if (isEmpty(hubUrl))	// missing hubUrl implies UCSC database
 	{
         chromListJsonOutput(db, stdout); // only need db for this function
 	return;
 	}
     }
 else
-    errAbort("# ERROR: do not recognize endpoint '/list/%s' function\n", words[1]);
+    jsonErrAbort("ERROR: do not recognize endpoint '/list/%s' function\n", words[1]);
 }
 
 static struct hash *apiFunctionHash = NULL;
 
 static void setupFunctionHash()
 /* initialize the apiFunctionHash */
 {
 if (apiFunctionHash)
     return;
 
 apiFunctionHash = hashNew(0);
 hashAdd(apiFunctionHash, "list", &apiList);
 }
 
 static void apiFunctionSwitch(char *pathInfo)
 /* given a pathInfo string: /command/subCommand/etc...
  *  parse that and decide on which function to acll
  */
 {
 hPrintDisable();	/* turn off all normal HTML output, doing JSON output */
 
 /* the leading slash has been removed from the pathInfo, therefore, the
  * chop will have the first word in words[0]
  */
 char *words[MAX_PATH_INFO];/*expect no more than MAX_PATH_INFO number of words*/
 int wordCount = chopByChar(pathInfo, '/', words, ArraySize(words));
 if (wordCount < 2)
-    errAbort("ERROR: no commands found in path info\n");
+    jsonErrAbort("ERROR: no endpoint commands found ?\n");
 
 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;
 hPrintf("<ul>\n");
 for (track = tdbList; track != NULL; track = track->next )
     {
@@ -866,30 +912,31 @@
     hPrintf("<em>hub open time: %ld millis</em><br>\n", thisTime - lastTime);
     }
 
 hPrintf("<h3>ucscDb: '%s'</h2>\n", ucscDb);
 
 struct trackHubGenome *hubGenome = hub->genomeList;
 
 hPrintf("<h2>Example URLs to return json data structures:</h2>\n");
 hPrintf("<ul>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/publicHubs'>list public hubs</a> <em>/cgi-bin/hubApi/list/publicHubs</em></li>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/ucscGenomes'>list database genomes</a> <em>/cgi-bin/hubApi/list/ucscGenomes</em></li>\n");
 hPrintf("<li><a href='/cgi-bin/hubApi/list/hubGenomes?hubUrl=%s'>list genomes from specified hub</a> <em>/cgi-bin/hubApi/list/hubGenomes?hubUrl='%s'</em></li>\n", urlInput, urlInput);
 hPrintf("<li><a href='/cgi-bin/hubApi/list/tracks?hubUrl=%s&genome=%s'>list tracks from specified hub and genome</a> <em>/cgi-bin/hubApi/list/tracks?hubUrl='%s&genome=%s'</em></li>\n", urlInput, hubGenome->name, urlInput, hubGenome->name);
 hPrintf("<li><a href='/cgi-bin/hubApi/list/tracks?db=%s'>list tracks from specified UCSC database</a> <em>/cgi-bin/hubApi/list/tracks?db='%s'</em></li>\n", ucscDb, ucscDb);
 hPrintf("<li><a href='/cgi-bin/hubApi/list/chromosomes?db=%s'>list chromosomes from specified UCSC database</a> <em>/cgi-bin/hubApi/list/chromosomes?db='%s'</em></li>\n", ucscDb, ucscDb);
+hPrintf("<li><a href='/cgi-bin/hubApi/list/chromosomes?db=%s&track=gap'>list chromosomes from specified track from UCSC databaset</a> <em>/cgi-bin/hubApi/list/chromosomes?db='%s'&track=gap</em></li>\n", ucscDb, ucscDb);
 hPrintf("</ul>\n");
 
 hPrintf("<h4>cart dump</h4>");
 hPrintf("<pre>\n");
 cartDump(cart);
 hPrintf("</pre>\n");
 
 hPrintf("<form action='%s' name='hubApiUrl' id='hubApiUrl' method='GET'>\n\n", "../cgi-bin/hubApi");
 
 hPrintf("<b>Select public hub:&nbsp;</b>");
 #define JBUFSIZE 2048
 #define SMALLBUF 256
 char javascript[JBUFSIZE];
 struct slPair *events = NULL;
 safef(javascript, sizeof(javascript), "this.lastIndex=this.selectedIndex;");