84161997c78fb7f23f9fdb62e8cafd850db6dc88
tdreszer
Mon Nov 22 14:47:56 2010 -0800
Removed a lot of ifdefs whose time had come. Renamed one function for clarity.
diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c
index 5539603..a50001b 100644
--- src/hg/hgTracks/searchTracks.c
+++ src/hg/hgTracks/searchTracks.c
@@ -1,961 +1,953 @@
/* Track search code used by hgTracks CGI */
#include "common.h"
#include "searchTracks.h"
#include "hCommon.h"
#include "memalloc.h"
#include "obscure.h"
#include "dystring.h"
#include "hash.h"
#include "cheapcgi.h"
#include "hPrint.h"
#include "htmshell.h"
#include "cart.h"
#include "hgTracks.h"
#include "web.h"
#include "jksql.h"
#include "hdb.h"
#include "mdb.h"
#include "trix.h"
#include "jsHelper.h"
#include "imageV2.h"
-#ifndef TRACK_SEARCH
-void doSearchTracks(struct group *groupList)
-{
- return;
-}
-#else///ifdef TRACK_SEARCH
-
#define ANYLABEL "Any"
#define TRACK_SEARCH_FORM "trackSearch"
#define SEARCH_RESULTS_FORM "searchResults"
#define METADATA_NAME_PREFIX "hgt_mdbVar"
#define METADATA_VALUE_PREFIX "hgt_mdbVal"
#define TRACK_SEARCH_CURRENT_TAB "tsCurTab"
#define TRACK_SEARCH_SIMPLE "tsSimple"
#define TRACK_SEARCH_ON_NAME "tsName"
#define TRACK_SEARCH_ON_GROUP "tsGroup"
#define TRACK_SEARCH_ON_DESCR "tsDescr"
#define TRACK_SEARCH_SORT "tsSort"
static int gCmpGroup(const void *va, const void *vb)
/* Compare groups based on label. */
{
const struct group *a = *((struct group **)va);
const struct group *b = *((struct group **)vb);
return strcmp(a->label, b->label);
}
// Would like to do a radio button choice ofsorts
enum sortBy
{
sbRelevance=0,
sbAbc =1,
sbHierarchy=2,
};
static int gCmpTrackHierarchy(const void *va, const void *vb)
/* Compare tracks based on longLabel. */
{
const struct slRef *aa = *((struct slRef **)va);
const struct slRef *bb = *((struct slRef **)vb);
const struct track *a = ((struct track *) aa->val);
const struct track *b = ((struct track *) bb->val);
if ( tdbIsFolder(a->tdb) && !tdbIsFolder(b->tdb))
return -1;
else if (!tdbIsFolder(a->tdb) && tdbIsFolder(b->tdb))
return 1;
if ( tdbIsContainer(a->tdb) && !tdbIsContainer(b->tdb))
return -1;
else if (!tdbIsContainer(a->tdb) && tdbIsContainer(b->tdb))
return 1;
if (!tdbIsContainerChild(a->tdb) && tdbIsContainerChild(b->tdb))
return -1;
else if ( tdbIsContainerChild(a->tdb) && !tdbIsContainerChild(b->tdb))
return 1;
return strcasecmp(a->longLabel, b->longLabel);
}
static int gCmpTrack(const void *va, const void *vb)
/* Compare tracks based on longLabel. */
{
const struct slRef *aa = *((struct slRef **)va);
const struct slRef *bb = *((struct slRef **)vb);
const struct track *a = ((struct track *) aa->val);
const struct track *b = ((struct track *) bb->val);
return strcasecmp(a->longLabel, b->longLabel);
}
static void findTracksSort(struct slRef **pTrack, boolean simpleSearch, enum sortBy sortBy)
{
if (sortBy == sbHierarchy)
slSort(pTrack, gCmpTrackHierarchy);
else if (sortBy == sbAbc)
slSort(pTrack, gCmpTrack);
else
slReverse(pTrack);
}
// XXXX make a matchString function to support "contains", "is" etc. and wildcards in contains
// ((sameString(op, "is") && !strcasecmp(track->shortLabel, str)) ||
static boolean isNameMatch(struct track *track, char *str, char *op)
{
return str && strlen(str) &&
((sameString(op, "is") && !strcasecmp(track->shortLabel, str)) ||
(sameString(op, "is") && !strcasecmp(track->longLabel, str)) ||
(sameString(op, "contains") && containsStringNoCase(track->shortLabel, str) != NULL) ||
(sameString(op, "contains") && containsStringNoCase(track->longLabel, str) != NULL));
}
static boolean isDescriptionMatch(struct track *track, char **words, int wordCount)
// We parse str and look for every word at the start of any word in track description (i.e. google style).
{
if(words)
{
// We do NOT lookup up parent hierarchy for html descriptions.
char *html = track->tdb->html;
if(!isEmpty(html))
{
/* This probably could be made more efficient by parsing the html into some kind of b-tree, but I am assuming
that the inner html loop while only happen for 1-2 words for vast majority of the tracks. */
int i, numMatches = 0;
html = stripRegEx(html, "<[^>]*>", REG_ICASE);
for(i = 0; i < wordCount; i++)
{
char *needle = words[i];
char *haystack, *tmp = cloneString(html);
boolean found = FALSE;
while((haystack = nextWord(&tmp)))
{
char *ptr = strstrNoCase(haystack, needle);
if(ptr != NULL && ptr == haystack)
{
found = TRUE;
break;
}
}
if(found)
numMatches++;
else
break;
}
if(numMatches == wordCount)
return TRUE;
}
}
return FALSE;
}
static int getTermArray(struct sqlConnection *conn, char ***pLabels, char ***pTerms, char *type)
// Pull out all term fields from ra entries with given type
// Returns count of items found and items via the terms argument.
{
int ix = 0, count = 0;
char **labels;
char **values;
struct slPair *pairs = mdbValLabelSearch(conn, type, MDB_VAL_STD_TRUNCATION, TRUE, FALSE); // Tables not files
count = slCount(pairs) + 1; // make room for "Any"
AllocArray(labels, count);
AllocArray(values, count);
labels[ix] = cloneString(ANYLABEL);
values[ix] = cloneString(ANYLABEL);
struct slPair *pair = NULL;
while((pair = slPopHead(&pairs)) != NULL)
{
ix++;
labels[ix] = pair->name;
values[ix] = pair->val;
freeMem(pair);
}
*pLabels = labels;
*pTerms = values;
return count;
}
static int metaDbVars(struct sqlConnection *conn, char *** metaVars, char *** metaLabels)
// Search the assemblies metaDb table; If name == NULL, we search every metadata field.
{
char query[256];
struct slPair *oneTerm,*whiteList = mdbCvWhiteList(TRUE,FALSE);
int count =0, whiteCount = slCount(whiteList);
char **retVar = needMem(sizeof(char *) * whiteCount);
char **retLab = needMem(sizeof(char *) * whiteCount);
for(oneTerm=whiteList;oneTerm!=NULL;oneTerm=oneTerm->next)
{
safef(query, sizeof(query), "select count(*) from metaDb where var = '%s'",oneTerm->name);
if(sqlQuickNum(conn,query) > 0)
{
retVar[count] = oneTerm->name;
retLab[count] = oneTerm->val;
count++;
}
}
// Don't do it, unless you clone strings above: slPairFreeValsAndList(&whileList);
*metaVars = retVar;
*metaLabels = retLab;
return count;
}
static int printMdbSelects(struct sqlConnection *conn,struct cart *cart,boolean simpleSearch,char ***pMdbVar,char ***pMdbVal,int *numMetadataNonEmpty,int cols)
// Prints a table of mdb selects if appropriate and returns number of them
{
// figure out how many metadata selects are visible.
int delSearchSelect = cartUsualInt(cart, TRACK_SEARCH_DEL_ROW, 0); // 1-based row to delete
int addSearchSelect = cartUsualInt(cart, TRACK_SEARCH_ADD_ROW, 0); // 1-based row to insert after
int numMetadataSelects = 0;
char **mdbVar = NULL;
char **mdbVal = NULL;
char **mdbVars = NULL;
char **mdbVarLabels = NULL;
int i, count = metaDbVars(conn, &mdbVars, &mdbVarLabels);
for(;;)
{
char buf[256];
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, numMetadataSelects + 1);
char *str = cartOptionalString(cart, buf);
if(isEmpty(str))
break;
else
numMetadataSelects++;
}
if(delSearchSelect)
numMetadataSelects--;
if(addSearchSelect)
numMetadataSelects++;
if(numMetadataSelects)
{
mdbVar = needMem(sizeof(char *) * numMetadataSelects);
mdbVal = needMem(sizeof(char *) * numMetadataSelects);
*pMdbVar = mdbVar;
*pMdbVal = mdbVal;
int i;
for(i = 0; i < numMetadataSelects; i++)
{
char buf[256];
int offset; // used to handle additions/deletions
if(addSearchSelect > 0 && i >= addSearchSelect)
offset = 0; // do nothing to offset (i.e. copy data from previous row)
else if(delSearchSelect > 0 && i + 1 >= delSearchSelect)
offset = 2;
else
offset = 1;
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, i + offset);
mdbVar[i] = cloneString(cartOptionalString(cart, buf));
if(!simpleSearch)
{
int j;
boolean found = FALSE;
// We need to make sure mdbVar[i] is valid in this assembly; if it isn't, reset it to "cell".
for(j = 0; j < count && !found; j++)
if(sameString(mdbVars[j], mdbVar[i]))
found = TRUE;
if(found)
{
safef(buf, sizeof(buf), "%s%d", METADATA_VALUE_PREFIX, i + offset);
mdbVal[i] = cloneString(cartOptionalString(cart, buf));
if(sameString(mdbVal[i], ANYLABEL))
mdbVal[i] = NULL;
}
else
{
mdbVar[i] = cloneString("cell");
mdbVal[i] = NULL;
}
if(!isEmpty(mdbVal[i]))
(*numMetadataNonEmpty)++;
}
}
if(delSearchSelect > 0)
{
char buf[255];
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, numMetadataSelects + 1);
cartRemove(cart, buf);
safef(buf, sizeof(buf), "%s%d", METADATA_VALUE_PREFIX, numMetadataSelects + 1);
cartRemove(cart, buf);
}
}
else
{
// create defaults
numMetadataSelects = 2;
mdbVar = needMem(sizeof(char *) * numMetadataSelects);
mdbVal = needMem(sizeof(char *) * numMetadataSelects);
mdbVar[0] = "cell";
mdbVar[1] = "antibody";
mdbVal[0] = ANYLABEL;
mdbVal[1] = ANYLABEL;
}
hPrintf("
ENCODE terms ", cols,COLOR_DARKGREY);
for(i = 0; i < numMetadataSelects; i++)
{
char **terms = NULL, **labels = NULL;
char buf[256];
int len;
#define PRINT_BUTTON(name,value,msg,js) printf(" ", (name), (value), (msg), (js));
hPrintf("\n");
if(numMetadataSelects > 2 || i >= 2)
{
safef(buf, sizeof(buf), "return delSearchSelect(this, %d);", i + 1);
PRINT_BUTTON(TRACK_SEARCH, "-", "delete this row", buf);
}
else
hPrintf(" ");
hPrintf(" \n");
safef(buf, sizeof(buf), "return addSearchSelect(this, %d);", i + 1);
PRINT_BUTTON(TRACK_SEARCH, "+", "add another row after this row", buf);
hPrintf(" and \n");
safef(buf, sizeof(buf), "%s%i", METADATA_NAME_PREFIX, i + 1);
#ifdef CV_SEARCH_SUPPORTS_FREETEXT
cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' style='font-size:.9em;' onchange='findTracksMdbVarChanged2(this);'");
// TODO: move to lib since hgTracks and hgApi share
enum mdbCvSearchable searchBy = mdbCvSearchMethod(mdbVar[i]);
if (searchBy == cvsSearchByMultiSelect)
{
// TO BE IMPLEMENTED
}
else if (searchBy == cvsSearchBySingleSelect)
{
safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
hPrintf(" is \n",i + 1,buf);
len = getTermArray(conn, &labels, &terms, mdbVar[i]);
cgiMakeDropListFull(buf, labels, terms, len, mdbVal[i], "class='mdbVal single' style='min-width:200px; font-size:.9em;' onchange='findTracksSearchButtonsEnable(true);'");
}
else if (searchBy == cvsSearchByFreeText)
{
safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
hPrintf(" contains \n",i + 1,buf);
hPrintf(" ",
buf,(mdbVal[i] ? mdbVal[i]: ""));
}
else if (searchBy == cvsSearchByDateRange || searchBy == cvsSearchByIntegerRange)
{
// TO BE IMPLEMENTED
}
#else//ifndef CV_SEARCH_SUPPORTS_FREETEXT
cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
hPrintf(" is is\n");
len = getTermArray(conn, &labels, &terms, mdbVar[i]);
safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
cgiMakeDropListFull(buf, labels, terms, len, mdbVal[i], "class='mdbVal' style='min-width:200px; font-size:.9em;' onchange='findTracksSearchButtonsEnable(true);'");
#endif///ndef CV_SEARCH_SUPPORTS_FREETEXT
hPrintf("help \n", i + 1);
hPrintf(" \n");
}
hPrintf(" ", cols);
//hPrintf(" ", cols);
return numMetadataSelects;
}
static struct slRef *simpleSearchForTracksstruct(struct trix *trix,char **descWords,int descWordCount)
// Performs the simple search and returns the found tracks.
{
struct slRef *tracks = NULL;
struct trixSearchResult *tsList;
for(tsList = trixSearch(trix, descWordCount, descWords, TRUE); tsList != NULL; tsList = tsList->next)
{
struct track *track = (struct track *) hashFindVal(trackHash, tsList->itemId);
if (track != NULL) // It is expected that this is NULL (e.g. when the trix references trackDb tracks which have no tables)
{
refAdd(&tracks, track);
}
}
return tracks;
}
static struct slRef *advancedSearchForTracks(struct sqlConnection *conn,struct group *groupList, char **descWords,int descWordCount, char *nameSearch, char *descSearch, char *groupSearch,
int numMetadataNonEmpty,int numMetadataSelects,char **mdbVar,char **mdbVal)
// Performs the advanced search and returns the found tracks.
{
int tracksFound = 0;
struct slRef *tracks = NULL;
if(!isEmpty(nameSearch) || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty)
{
// First do the metaDb searches, which can be done quickly for all tracks with db queries.
struct hash *matchingTracks = newHash(0);
struct slName *el, *metaTracks = NULL;
int i;
for(i = 0; i < numMetadataSelects; i++)
{
if(!isEmpty(mdbVal[i]))
{
#ifdef CV_SEARCH_SUPPORTS_FREETEXT
enum mdbCvSearchable searchBy = mdbCvSearchMethod(mdbVar[i]);
struct slName *tmp = NULL;
// If select is by free text then like
if (searchBy == cvsSearchByMultiSelect)
{
// TO BE IMPLEMENTED
// The mdbVal[1] will hve to be filled cartOptionalSlNameList(cart,???)
struct slName *choices = (struct slName *)mdbVal[i];
if (slCount(choices) == 1)
{
tmp = mdbObjSearch(conn, mdbVar[i], choices->name, "is", MDB_VAL_STD_TRUNCATION, TRUE, FALSE);
}
else if(choices != NULL)
{
// Then slNames will need to be assembled into a string in the form of 'a','b','c'
struct dyString *dyList = dyStringNew(256);
dyStringPrintf(dyList,"'%s'",choices->name);
struct slName *choice = choices->next;
for(;choice!=NULL;choice=choice->next)
dyStringPrintf(dyList,",'%s'",choice->name);
tmp = mdbObjSearch(conn, mdbVar[i], dyStringContents(dyList), "in", MDB_VAL_STD_TRUNCATION, TRUE, FALSE);
dyStringFree(&dyList);
}
}
else if (searchBy == cvsSearchBySingleSelect)
{
tmp = mdbObjSearch(conn, mdbVar[i], mdbVal[i], "is", MDB_VAL_STD_TRUNCATION, TRUE, FALSE);
}
else if (searchBy == cvsSearchByFreeText)
{
tmp = mdbObjSearch(conn, mdbVar[i], mdbVal[i], "like", MDB_VAL_STD_TRUNCATION, TRUE, FALSE);
}
else if (searchBy == cvsSearchByDateRange || searchBy == cvsSearchByIntegerRange)
{
// TO BE IMPLEMENTED
// Requires new mdbObjSearch API and more than one mdbVal[i]
}
if (tmp != NULL)
{
if(metaTracks == NULL)
metaTracks = tmp;
else
metaTracks = slNameIntersection(metaTracks, tmp);
}
#else///ifndif CV_SEARCH_SUPPORTS_FREETEXT
struct slName *tmp = mdbObjSearch(conn, mdbVar[i], mdbVal[i], "is", MDB_VAL_STD_TRUNCATION, TRUE, FALSE);
if(metaTracks == NULL)
metaTracks = tmp;
else
metaTracks = slNameIntersection(metaTracks, tmp);
#endif///ndef CV_SEARCH_SUPPORTS_FREETEXT
}
}
for (el = metaTracks; el != NULL; el = el->next)
hashAddInt(matchingTracks, el->name, 1);
struct group *group;
for (group = groupList; group != NULL; group = group->next)
{
if(groupSearch == NULL || sameString(group->name, groupSearch))
{
if (group->trackList != NULL)
{
struct trackRef *tr;
for (tr = group->trackList; tr != NULL; tr = tr->next)
{
struct track *track = tr->track;
if((isEmpty(nameSearch) || isNameMatch(track, nameSearch, "contains")) &&
(isEmpty(descSearch) || isDescriptionMatch(track, descWords, descWordCount)) &&
(!numMetadataNonEmpty || hashLookup(matchingTracks, track->track) != NULL))
{
if (track != NULL)
{
tracksFound++;
refAdd(&tracks, track);
}
else
warn("found group track is NULL.");
}
if (track->subtracks != NULL)
{
struct track *subTrack;
for (subTrack = track->subtracks; subTrack != NULL; subTrack = subTrack->next)
{
if((isEmpty(nameSearch) || isNameMatch(subTrack, nameSearch, "contains")) &&
(isEmpty(descSearch) || isDescriptionMatch(subTrack, descWords, descWordCount)) &&
(!numMetadataNonEmpty || hashLookup(matchingTracks, subTrack->track) != NULL))
{
// XXXX to parent hash. - use tdb->parent instead.
//hashAdd(parents, subTrack->track, track);
if (track != NULL)
{
tracksFound++;
refAdd(&tracks, subTrack);
}
else
warn("found subtrack is NULL.");
}
}
}
}
}
}
}
}
return tracks;
}
#define MAX_FOUND_TRACKS 100
static void findTracksPageLinks(int tracksFound, int startFrom)
{
if (tracksFound <= MAX_FOUND_TRACKS)
return;
// Opener
int willStartAt = 0;
int curPage = (startFrom/MAX_FOUND_TRACKS) + 1;
int endAt = startFrom+MAX_FOUND_TRACKS;
if (endAt > tracksFound)
endAt = tracksFound;
hPrintf("Listing %d - %d of %d tracks ",startFrom+1,endAt,tracksFound);
// << and <
if (startFrom >= MAX_FOUND_TRACKS)
{
hPrintf("« ",
TRACK_SEARCH,TRACK_SEARCH_PAGER,TRACK_SEARCH_PAGER);
willStartAt = startFrom - MAX_FOUND_TRACKS;
hPrintf(" ",
TRACK_SEARCH,TRACK_SEARCH_PAGER,willStartAt,TRACK_SEARCH_PAGER,willStartAt);
}
// page number links
int lastPage = (tracksFound/MAX_FOUND_TRACKS);
if ((tracksFound % MAX_FOUND_TRACKS) > 0)
lastPage++;
int thisPage = curPage - 3; // Window of 3 pages above and below
if (thisPage < 1)
thisPage = 1;
for (;thisPage <= lastPage && thisPage <= curPage + 3; thisPage++)
{
if (thisPage != curPage)
{
willStartAt = ((thisPage - 1) * MAX_FOUND_TRACKS);
endAt = willStartAt+ MAX_FOUND_TRACKS;
if (endAt > tracksFound)
endAt = tracksFound;
hPrintf(" %d ",
TRACK_SEARCH,TRACK_SEARCH_PAGER,willStartAt,thisPage,willStartAt+1,endAt,TRACK_SEARCH_PAGER,willStartAt,thisPage);
}
else
hPrintf(" %d ",COLOR_DARKGREY,thisPage);
}
// > and >>
if ((startFrom + MAX_FOUND_TRACKS) < tracksFound)
{
willStartAt = startFrom + MAX_FOUND_TRACKS;
hPrintf(" ",
TRACK_SEARCH,TRACK_SEARCH_PAGER,willStartAt,TRACK_SEARCH_PAGER,willStartAt);
willStartAt = tracksFound - (tracksFound % MAX_FOUND_TRACKS);
if (willStartAt == tracksFound)
willStartAt -= MAX_FOUND_TRACKS;
hPrintf(" » \n",
TRACK_SEARCH,TRACK_SEARCH_PAGER,willStartAt,TRACK_SEARCH_PAGER,willStartAt);
}
}
static void displayFoundTracks(struct cart *cart, struct slRef *tracks, int tracksFound,enum sortBy sortBy)
// Routine for displaying found tracks
{
hPrintf("\n"); // This div allows the clear button to empty it
if(tracksFound < 1)
{
hPrintf("
No tracks found
\n");
}
else
{
struct hash *tdbHash = makeTrackHash(database, chromName);
hPrintf("
\n");
// be done with json
hWrites(jsonTdbSettingsUse(&jsonTdbVars));
}
#ifdef OMIT
if(!doSearch)
{
hPrintf("
Recently Done
\n"
"Can now page through found tracks 100 at a time. "
"Added icon for contqainers with a configuration link. Is this okay? "
"SuperTracks can now be found. "
"Configuration of superTrack children's vis should result in proper superTrack reshaping. (This is really an hgTrackUi feature.) "
"Added sort toggle: Relevance, Alphabetically or by Hierarchy. "
"Composite/view visibilites in hgTrackUi get reshaped to reflect found/selected subtracks. (In demo1: only default state composites; demo2: all composites.) "
"Non-data 'container' tracks (composites and supertracks) have '*' to mark them, and can be configured before displaying. Better suggestions? "
" "
"
Suggested improvments:
\n"
"The metadata values will not be white-listed, but it would be nice to have more descriptive text for them. A short label added to cv.ra? "
"Look and feel of found track list (here) and composite subtrack list (hgTrackUi) should converge. Jim suggests look and feel of hgTracks 'Configure Tracks...' list instead. "
"Drop-down list of terms (cells, antibodies, etc.) should be multi-select with checkBoxes as seen in filterComposites. Perhaps saved for v2.0. "
" \n");
}
#endif///def OMIT
hPrintf("
"); // This div allows the clear button to empty it
}
void doSearchTracks(struct group *groupList)
{
if (!advancedJavascriptFeaturesEnabled(cart))
{
warn("Requires advanced javascript features.");
return;
}
struct group *group;
char *groups[128];
char *labels[128];
int numGroups = 1;
groups[0] = ANYLABEL;
labels[0] = ANYLABEL;
char *currentTab = cartUsualString(cart, TRACK_SEARCH_CURRENT_TAB, "simpleTab");
char *nameSearch = cartOptionalString(cart, TRACK_SEARCH_ON_NAME);
char *descSearch;
char *groupSearch = cartOptionalString(cart, TRACK_SEARCH_ON_GROUP);
boolean doSearch = sameString(cartOptionalString(cart, TRACK_SEARCH), "Search") || cartUsualInt(cart, TRACK_SEARCH_PAGER, -1) >= 0;
struct sqlConnection *conn = hAllocConn(database);
boolean metaDbExists = sqlTableExists(conn, "metaDb");
int numMetadataSelects, tracksFound = 0;
int numMetadataNonEmpty = 0;
char **mdbVar = NULL;
char **mdbVal = NULL;
#ifdef ONE_FUNC
struct hash *parents = newHash(4);
#endif///def ONE_FUNC
boolean simpleSearch;
struct trix *trix;
char trixFile[HDB_MAX_PATH_STRING];
char **descWords = NULL;
int descWordCount = 0;
boolean searchTermsExist = FALSE;
int cols;
char buf[512];
if(sameString(currentTab, "simpleTab"))
{
descSearch = cartOptionalString(cart, TRACK_SEARCH_SIMPLE);
simpleSearch = TRUE;
freez(&nameSearch);
freez(&groupSearch);
}
else
{
descSearch = cartOptionalString(cart, TRACK_SEARCH_ON_DESCR);
simpleSearch = FALSE;
}
if(descSearch)
stripChar(descSearch, '"');
trackList = getTrackList(&groupList, -2); // global
makeGlobalTrackHash(trackList);
// NOTE: This is necessary when container cfg by '*' results in vis changes
// This will handle composite/view override when subtrack specific vis exists, AND superTrack reshaping.
parentChildCartCleanup(trackList,cart,oldVars); // Subtrack settings must be removed when composite/view settings are updated
getSearchTrixFile(database, trixFile, sizeof(trixFile));
trix = trixOpen(trixFile);
slSort(&groupList, gCmpGroup);
for (group = groupList; group != NULL; group = group->next)
{
groupTrackListAddSuper(cart, group);
if (group->trackList != NULL)
{
groups[numGroups] = cloneString(group->name);
labels[numGroups] = cloneString(group->label);
numGroups++;
if (numGroups >= ArraySize(groups))
internalErr();
}
}
safef(buf, sizeof(buf),"Search for Tracks in the %s %s Assembly", organism, hFreezeFromDb(database));
webStartWrapperDetailedNoArgs(cart, database, "", buf, FALSE, FALSE, FALSE, FALSE);
hPrintf("");
hPrintf("
\n");
hPrintf("
"); // Restricts to max-width:1000px;
if(descSearch != NULL && !strlen(descSearch))
descSearch = NULL;
if(groupSearch != NULL && sameString(groupSearch, ANYLABEL))
groupSearch = NULL;
if(!isEmpty(descSearch))
{
char *tmp = cloneString(descSearch);
char *val = nextWord(&tmp);
struct slName *el, *descList = NULL;
int i;
while (val != NULL)
{
slNameAddTail(&descList, val);
descWordCount++;
val = nextWord(&tmp);
}
descWords = needMem(sizeof(char *) * descWordCount);
for(i = 0, el = descList; el != NULL; i++, el = el->next)
descWords[i] = strLower(el->name);
}
if (doSearch && simpleSearch && descWordCount <= 0)
doSearch = FALSE;
if(doSearch)
{
// Now search
struct slRef *tracks = NULL;
if(simpleSearch)
tracks = simpleSearchForTracksstruct(trix,descWords,descWordCount);
else
tracks = advancedSearchForTracks(conn,groupList,descWords,descWordCount,nameSearch,descSearch,groupSearch,numMetadataNonEmpty,numMetadataSelects,mdbVar,mdbVal);
// Sort and Print results
enum sortBy sortBy = cartUsualInt(cart,TRACK_SEARCH_SORT,sbRelevance);
tracksFound = slCount(tracks);
if(tracksFound > 1)
findTracksSort(&tracks,simpleSearch,sortBy);
displayFoundTracks(cart,tracks,tracksFound,sortBy);
}
hFreeConn(&conn);
webNewSection("About Track Search");
if(metaDbExists)
hPrintf("Search for terms in track names, descriptions, groups, and ENCODE "
"metadata. If multiple terms are entered, only tracks with all terms "
"will be part of the results.");
else
hPrintf("
Search for terms in track descriptions, groups, and names. "
"If multiple terms are entered, only tracks with all terms "
"will be part of the results.");
hPrintf("more help
\n");
webEndSectionTables();
}
-#endif///def TRACK_SEARCH