9614cd02adbffc856bc229ae7c88a2440cc616f1
hiram
  Wed Feb 6 10:26:35 2019 -0800
returning chrom list from ucsc chromInfo table refs #18869

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index 3c81333..c726cc7 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -12,30 +12,31 @@
 #include "udc.h"
 #include "knetUdc.h"
 #include "genbank.h"
 #include "trackHub.h"
 #include "hgConfig.h"
 #include "hCommon.h"
 #include "hPrint.h"
 #include "bigWig.h"
 #include "hubConnect.h"
 #include "obscure.h"
 #include "errCatch.h"
 #include "vcf.h"
 #include "bedTabix.h"
 #include "bamFile.h"
 #include "jsonParse.h"
+#include "chromInfo.h"
 
 #ifdef USE_HAL
 #include "halBlockViz.h"
 #endif
 
 /*
 +------------------+------------------+------+-----+---------+-------+
 | Field            | Type             | Null | Key | Default | Extra |
 +------------------+------------------+------+-----+---------+-------+
 | hubUrl           | longblob         | NO   | PRI | NULL    |       |
 | shortLabel       | varchar(255)     | NO   |     | NULL    |       |
 | longLabel        | varchar(255)     | NO   |     | NULL    |       |
 | registrationTime | varchar(255)     | NO   |     | NULL    |       |
 | dbCount          | int(10) unsigned | NO   |     | NULL    |       |
 | dbList           | blob             | YES  |     | NULL    |       |
@@ -63,48 +64,56 @@
 static long totalTracks = 0;
 static boolean measureTiming = FALSE;	/* set by CGI parameters */
 static boolean allTrackSettings = FALSE;	/* checkbox setting */
 static char **shortLabels = NULL;	/* public hub short labels in array */
 struct hubPublic *publicHubList = NULL;
 static int publicHubCount = 0;
 static char *defaultHub = "Plants";
 static char *defaultDb = "ce11";
 static long enteredMainTime = 0;	/* will become = clock1000() on entry */
 		/* to allow calculation of when to bail out, taking too long */
 static long timeOutSeconds = 100;
 static boolean timedOut = FALSE;
 
 /* ######################################################################### */
 
-static void jsonInteger(FILE *f, char *tag, int value)
+static void jsonInteger(FILE *f, char *tag, long long value)
 /* output one json interger: "tag":value appropriately quoted and encoded */
 {
-fprintf(f,"\"%s\":%d",tag, value);
+fprintf(f,"\"%s\":%lld",tag, value);
 }
 
 static void jsonStringOut(FILE *f, char *tag, char *value)
 /* output one json string: "tag":"value" appropriately quoted and encoded */
 {
 fprintf(f,"\"%s\":",tag);
 char *a = jsonStringEscape(value);
 if (isEmpty(a))
     fprintf(f, "%s", "null");
 else
     fprintf(f, "\"%s\"", a);
 freeMem(a);
 }
 
+static void jsonStartOutput(FILE *f)
+/* begin json output */
+{
+fputc('{',f);
+jsonStringOut(f, "source", "UCSantaCruz");
+fputc(',',f);
+}
+
 static void hubPublicJsonOutput(struct hubPublic *el, FILE *f) 
 /* Print out hubPublic element in JSON format. */
 {
 fputc('{',f);
 jsonStringOut(f, "hubUrl", el->hubUrl);
 fputc(',',f);
 jsonStringOut(f, "shortLabel", el->shortLabel);
 fputc(',',f);
 jsonStringOut(f, "longLabel", el->longLabel);
 fputc(',',f);
 jsonStringOut(f, "registrationTime", el->registrationTime);
 fputc(',',f);
 jsonInteger(f, "dbCount", el->dbCount);
 fputc(',',f);
 jsonStringOut(f, "dbList", el->dbList);
@@ -519,31 +528,32 @@
 fputc(',',f);
 jsonInteger(f, "hgNearOk", el->hgNearOk);
 fputc(',',f);
 jsonInteger(f, "hgPbOk", el->hgPbOk);
 fputc(',',f);
 jsonStringOut(f, "sourceName", el->sourceName);
 fputc(',',f);
 jsonInteger(f, "taxId", el->taxId);
 fputc('}',f);
 }
 
 static void jsonPublicHubs()
 /* output the hubPublic SQL table */
 {
 struct hubPublic *el = publicHubList;
-printf("{\"source\":\"UCSantaCruz\",\"publicHubs\":[");
+jsonStartOutput(stdout);
+printf("\"publicHubs\":[");
 for ( ; el != NULL; el = el->next )
     {
     hubPublicJsonOutput(el, stdout);
     if (el->next)
        printf(",");
     }
 printf("]}\n");
 }
 
 static int dbDbCmpName(const void *va, const void *vb)
 /* Compare two dbDb elements: name, ignore case. */
 {
 const struct dbDb *a = *((struct dbDb **)va);
 const struct dbDb *b = *((struct dbDb **)vb);
 return strcasecmp(a->name, b->name);
@@ -562,144 +572,193 @@
     {
     el = dbDbLoad(row);
     slAddHead(&dbList, el);
     }
 sqlFreeResult(&sr);
 hDisconnectCentral(&conn);
 slSort(&dbList, dbDbCmpName);
 return dbList;
 }
 
 static void jsonDbDb()
 /* output the dbDb SQL table */
 {
 struct dbDb *dbList = ucscDbDb();
 struct dbDb *el;
-printf("{\"source\":\"UCSantaCruz\",\"ucscGenomes\":[");
+jsonStartOutput(stdout);
+printf("\"ucscGenomes\":[");
 for ( el=dbList; el != NULL; el = el->next )
     {
     dbDbJsonOutput(el, stdout);
     if (el->next)
        printf(",");
     }
 printf("]}\n");
 }
 
+static void chromInfoJsonOutput(char *db, FILE *f, char *track)
+{
+if (track)
+    {
+;
+    }
+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);
+	}
+    fputc('}',f);
+    }
+}
+
+static void chromListJsonOutput(char *db, FILE *f)
+/* return chromsome list from specified UCSC database name,
+ * can be for a specific track if cgiVar(track) exists, otherwise,
+ * the chrom list is from the chromInfo table.
+ */
+{
+char *track = cgiOptionalString("track");
+chromInfoJsonOutput(db, f, track);
+}	/*	static void chromListJsonOutput(char *db, FILE *f)	*/
+
 static void trackDbJsonOutput(char *db, FILE *f)
 /* return track list from specified UCSC database name */
 {
 struct trackDb *tdbList = hTrackDb(db);
 struct trackDb *el;
-fputc('{',f);
-jsonStringOut(f, "source", "UCSantaCruz");
-fputc(',',f);
+jsonStartOutput(f);
 jsonStringOut(f, "db", db);
 fputc(',',f);
 fprintf(f, "\"tracks\":[");
 for (el = tdbList; el != NULL; el = el->next )
     {
     char *a = jsonStringEscape(el->track);
     printf("\"%s\"", a);
     freeMem(a);
     if (el->next)
 	fputc(',',f);
     }
 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 */
+/* 'list' function words[1] is the subCommand */
 {
 if (sameWord("publicHubs", words[1]))
     jsonPublicHubs();
 else if (sameWord("ucscGenomes", words[1]))
     jsonDbDb();
-else if (sameWord("genomes", words[1]))
+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");
 
     struct trackHub *hub = trackHubOpen(hubUrl, "");
     if (hub->genomeList)
 	{
-        printf("{\"source\":\"UCSantaCruz\",");
+        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");
 	}
-    if (isEmpty(hubUrl))
+    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");
 	}
     struct trackHub *hub = trackHubOpen(hubUrl, "");
     if (hub->genomeList)
 	{
 	struct slName *dbTrackList = NULL;
 	(void) genomeList(hub, &dbTrackList, genome);
-        printf("{\"source\":\"UCSantaCruz\",");
+        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");
+	}
+    if (isEmpty(hubUrl))	// missing hubUrl implies UCSC database
+	{
+        chromListJsonOutput(db, stdout); // only need db for this function
+	return;
+	}
+    }
 else
-    errAbort("# ERROR: do not recognize command '%s' for 'list' function\n", words[1]);
+    errAbort("# 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)
@@ -803,33 +862,34 @@
 struct trackHub *hub = trackHubOpen(urlInput, "");
 if (measureTiming)
     {
     long thisTime = clock1000();
     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/genomes?hubUrl=%s'>list genomes from specified hub</a> <em>/cgi-bin/hubApi/list/genomes?hubUrl='%s'</em></li>\n", urlInput, urlInput);
+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("</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;");