-
rds authoredc9d9893e
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
acedbServer.c 126.76 KiB
/* File: acedbServer.c
* Author: Ed Griffiths (edgrif@sanger.ac.uk)
* Copyright (c) 2006: Genome Research Ltd.
*-------------------------------------------------------------------
* ZMap is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
*-------------------------------------------------------------------
* This file is part of the ZMap genome database package
* and was written by
* Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk,
* Roy Storey (Sanger Institute, UK) rds@sanger.ac.uk
*
* Description: Implements the method functions for a zmap server
* by making the appropriate calls to the acedb server.
*
* Exported functions: See zmapServer.h
* HISTORY:
* Last edited: May 22 10:03 2009 (rds)
* Created: Wed Aug 6 15:46:38 2003 (edgrif)
* CVS info: $Id: acedbServer.c,v 1.136 2009-05-22 09:05:07 rds Exp $
*-------------------------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <AceConn.h>
#include <glib.h>
#include <ZMap/zmapUtils.h>
#include <ZMap/zmapGLibUtils.h>
#include <ZMap/zmapConfigIni.h>
#include <ZMap/zmapConfigStrings.h>
#include <ZMap/zmapGFF.h>
#include <ZMap/zmapStyle.h>
#include <zmapServerPrototype.h>
#include <acedbServer_P.h>
typedef struct
{
gboolean first_method ;
gboolean find_string ;
gboolean name_list ;
GString *str ;
} ZMapTypesStringStruct, *ZMapTypesString ;
typedef struct
{
GList *methods ;
GHashTable *method_2_data ;
GData *styles ;
} LoadableStruct, *Loadable ;
typedef struct
{
AcedbServer server ;
GList *feature_set_methods ;
GList *feature_methods ;
GList *required_styles ;
GHashTable *set_2_styles ;
gboolean error ;
} GetMethodsStylesStruct, *GetMethodsStyles ;
typedef struct
{
GQuark feature_set_id ;
char *remark ;
GHashTable *method_2_feature_set ;
} HashFeatureSetStruct, *HashFeatureSet ;
typedef struct
{
GQuark feature_set ;
} ZMapColGroupDataStruct, *ZMapColGroupData ;
typedef struct
{
ZMapServerResponseType result ;
AcedbServer server ;
GData *styles ;
GHFunc eachBlock ;
} DoAllAlignBlocksStruct, *DoAllAlignBlocks ;
typedef struct
{
char *name ;
char *spec ;
} AcedbColourSpecStruct, *AcedbColourSpec ;
typedef struct
{
GHashTable *method_2_data ;
GData *styles;
GList *fetch_methods ;
} MethodFetchStruct, *MethodFetch ;
typedef struct
{
char *draw ;
char *fill ;
char *border ;
} StyleColourStruct, *StyleColour ;
typedef struct
{
StyleColourStruct normal ;
StyleColourStruct selected ;
} StyleFeatureColoursStruct, *StyleFeatureColours ;
typedef struct
{
GList *names_list ;
GQuark feature_set ;
GList *required_styles ;
} ColGroupNamesStruct, *ColGroupNames ;
typedef ZMapFeatureTypeStyle (*ParseMethodFunc)(char *method_str_in,
char **end_pos, ZMapColGroupData *col_group_data) ;
typedef gboolean (*ParseMethodNamesFunc)(AcedbServer server, char *method_str_in,
char **end_pos, gpointer user_data) ;
/* These provide the interface functions for an acedb server implementation, i.e. you
* shouldn't change these prototypes without changing all the other server prototypes..... */
static gboolean globalInit(void) ;
static gboolean createConnection(void **server_out,
ZMapURL url, char *format,
char *version_str, int timeout) ;
static ZMapServerResponseType openConnection(void *server) ;
static ZMapServerResponseType getInfo(void *server, char **database_path) ;
static ZMapServerResponseType getFeatureSetNames(void *server,
GList **feature_sets_out,
GList **required_styles,
GHashTable **featureset_2_stylelist_inout) ;
static ZMapServerResponseType getStyles(void *server, GData **styles_out) ;
static ZMapServerResponseType haveModes(void *server, gboolean *have_mode) ;
static ZMapServerResponseType getSequences(void *server_in, GList *sequences_inout) ;
static ZMapServerResponseType setContext(void *server, ZMapFeatureContext feature_context) ;
static ZMapServerResponseType getFeatures(void *server_in, GData *styles, ZMapFeatureContext feature_context_out) ;
static ZMapServerResponseType getContextSequence(void *server_in, GData *styles, ZMapFeatureContext feature_context_out) ;
static char *lastErrorMsg(void *server) ;
static ZMapServerResponseType closeConnection(void *server_in) ;
static ZMapServerResponseType destroyConnection(void *server) ;
/* general internal routines. */
static ZMapServerResponseType findColStyleTags(AcedbServer server,
GList **feature_set_methods_inout,
GList **feature_methods_out,
GList **required_styles_out,
GHashTable **featureset_2_stylelist_inout) ;
static GList *getMethodsLoadable(GList *all_methods, GHashTable *method_2_data, GData *styles) ;
static void loadableCB(gpointer data, gpointer user_data) ;
static char *getMethodString(GList *styles_or_style_names,
gboolean style_name_list, gboolean find_string, gboolean find_methods) ;
static void addTypeName(gpointer data, gpointer user_data) ;
static gboolean sequenceRequest(AcedbServer server, GData *styles, ZMapFeatureBlock feature_block) ;
static gboolean blockDNARequest(AcedbServer server, GData *styles, ZMapFeatureBlock feature_block) ;
static gboolean getDNARequest(AcedbServer server, char *sequence_name, int start, int end,
int *dna_length_out, char **dna_sequence_out) ;
static gboolean getSequenceMapping(AcedbServer server, ZMapFeatureContext feature_context) ;
static gboolean getSMapping(AcedbServer server, char *class,
char *sequence, int start, int end,
char **parent_class_out, char **parent_name_out,
ZMapMapBlock child_to_parent_out) ;
static gboolean getSMapLength(AcedbServer server, char *obj_class, char *obj_name,
int *obj_length_out) ;
static gboolean checkServerVersion(AcedbServer server) ;
static gboolean findSequence(AcedbServer server, char *sequence_name) ;
static gboolean setQuietMode(AcedbServer server) ;
static gboolean parseTypes(AcedbServer server, GData **styles_out,
ParseMethodNamesFunc parse_func_in, gpointer user_data) ;
static ZMapServerResponseType findMethods(AcedbServer server, char *search_str, int *num_found) ;
static ZMapServerResponseType getObjNames(AcedbServer server, GList **style_names_out) ;
static ZMapFeatureTypeStyle parseMethod(char *method_str_in,
char **end_pos, ZMapColGroupData *col_group_data) ;
static gboolean parseMethodColGroupNames(AcedbServer server, char *method_str_in,
char **end_pos, gpointer user_data) ;
static void addMethodCB(gpointer data, gpointer user_data) ;
gint resortStyles(gconstpointer a, gconstpointer b, gpointer user_data) ;
int getFoundObj(char *text) ;
static void eachAlignment(gpointer key, gpointer data, gpointer user_data) ;
static void eachBlockSequenceRequest(gpointer key, gpointer data, gpointer user_data) ;
static void eachBlockDNARequest(gpointer key, gpointer data, gpointer user_data);
static char *getAcedbColourSpec(char *acedb_colour_name) ;
static gboolean parseMethodStyleNames(AcedbServer server, char *method_str_in,
char **end_pos, gpointer user_data) ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
static void printCB(gpointer data, gpointer user_data) ;
static void stylePrintCB(gpointer data, gpointer user_data) ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
static ZMapFeatureTypeStyle parseStyle(char *method_str_in,
char **end_pos, ZMapColGroupData *col_group_data) ;
static gboolean getStyleColour(StyleFeatureColours style_colours, char **line_pos) ;
static ZMapServerResponseType doGetSequences(AcedbServer server, GList *sequences_inout) ;
static gboolean getServerInfo(AcedbServer server, char **database_path_out) ;
static int equaliseLists(AcedbServer server, GList **feature_sets_inout, GList *method_names,
char *query_name, char *reference_name) ;
static gint quarkCaseCmp(gconstpointer a, gconstpointer b) ;
static void setErrMsg(AcedbServer server, char *new_msg) ;
static void resetErr(AcedbServer server) ;
static char *get_url_query_value(char *full_query, char *key) ;
static gboolean get_url_query_boolean(char *full_query, char *key) ;
static void freeDataCB(gpointer data) ;
static void freeSetCB(gpointer data) ;
/*
* Server interface functions.
*/
/* Compulsory routine, without this we can't do anything....returns a list of functions
* that can be used to contact an acedb server. The functions are only visible through
* this struct. */
void acedbGetServerFuncs(ZMapServerFuncs acedb_funcs)
{
acedb_funcs->global_init = globalInit ;
acedb_funcs->create = createConnection ;
acedb_funcs->open = openConnection ;
acedb_funcs->get_info = getInfo ;
acedb_funcs->feature_set_names = getFeatureSetNames ;
acedb_funcs->get_styles = getStyles ;
acedb_funcs->have_modes = haveModes ;
acedb_funcs->get_sequence = getSequences ;
acedb_funcs->set_context = setContext ;
acedb_funcs->get_features = getFeatures ;
acedb_funcs->get_context_sequences = getContextSequence ;
acedb_funcs->errmsg = lastErrorMsg ;
acedb_funcs->close = closeConnection;
acedb_funcs->destroy = destroyConnection ;
return ;
}
/*
* Although these routines are static they form the external interface to the acedb server.
*/
/* For stuff that just needs to be done once at the beginning..... */
static gboolean globalInit(void)
{
gboolean result = TRUE ;
return result ;
}
static gboolean createConnection(void **server_out,
ZMapURL url, char *format,
char *version_str, int timeout)
{
gboolean result = FALSE ;
gboolean use_methods = FALSE;
AcedbServer server ;
/* Always return a server struct as it contains error message stuff. */
server = (AcedbServer)g_new0(AcedbServerStruct, 1) ;
resetErr(server) ;
server->host = g_strdup(url->host) ;
server->port = url->port ;
/* We need a minimum server version but user can specify a higher one in the config file. */
if (version_str)
{
if (zMapCompareVersionStings(ACEDB_SERVER_MIN_VERSION, version_str))
server->version_str = g_strdup(version_str) ;
else
{
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Requested server version was %s but minimum supported is %s.",
version_str, ACEDB_SERVER_MIN_VERSION) ;
server->version_str = g_strdup(ACEDB_SERVER_MIN_VERSION) ;
}
}
else
server->version_str = g_strdup(ACEDB_SERVER_MIN_VERSION) ;
server->has_new_tags = TRUE ;
use_methods = get_url_query_boolean(url->query, "use_methods");
server->has_new_tags = !use_methods;
if (server->has_new_tags)
{
server->method_2_data = g_hash_table_new_full(NULL, NULL, NULL, freeDataCB) ;
server->method_2_feature_set = g_hash_table_new_full(NULL, NULL, NULL, freeSetCB) ;
}
*server_out = (void *)server ;
if ((server->last_err_status =
AceConnCreate(&(server->connection), server->host, url->port, url->user, url->passwd, timeout)) == ACECONN_OK)
result = TRUE ;
return result ;
}
/* When we open the connection we not only check the acedb version of the server but also
* set "quiet" mode on so that we can get dna, gff and other stuff back unadulterated by
* extraneous information. */
static ZMapServerResponseType openConnection(void *server_in)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if ((server->last_err_status = AceConnConnect(server->connection)) == ACECONN_OK)
{
if (checkServerVersion(server) && setQuietMode(server))
result = ZMAP_SERVERRESPONSE_OK ;
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could open connection because: %s", server->last_err_msg) ;
}
}
return result ;
}
static ZMapServerResponseType getInfo(void *server_in, char **database_path)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if (getServerInfo(server, database_path))
{
result = ZMAP_SERVERRESPONSE_OK ;
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could not get server info because: %s", server->last_err_msg) ;
}
return result ;
}
/* Feature Set names passed to the acedb server _MUST_ be the names of Method objects in the
* database.
* If we are using the new method/style tags then the Method objects may contain Column_group
* tags which are used to combine several feature sets into one and each method that contains
* features must have a zmap style.
*
* This function must do a lot of checking and it is vital this is done well otherwise we end up
* with styles/methods we don't need or much worse we don't load all the styles that the
* feature sets require.
*
* This function takes a list of names, checks that it can find the corresponding Method objects
* and then retrieves those methods. It looks in the methods for Column_group tags and uses them
* to construct a new list of all the feature sets that need to be retrieved from the server.
*
* */
static ZMapServerResponseType getFeatureSetNames(void *server_in,
GList **feature_sets_inout,
GList **required_styles_out,
GHashTable **featureset_2_stylelist_inout)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
char *method_string = NULL ;
int num_methods = 0, num_feature_sets ;
GList *feature_sets, *feature_set_methods, *feature_methods, *col_group_methods, *method_names ;
GList *required_styles ;
GHashTable *featureset_2_stylelist ;
resetErr(server) ;
if (server->all_methods)
{
g_list_free(server->all_methods) ;
server->all_methods = NULL ;
}
if (server->has_new_tags)
{
g_hash_table_destroy(server->method_2_data) ;
server->method_2_data = g_hash_table_new_full(NULL, NULL, NULL, freeDataCB) ;
g_hash_table_destroy(server->method_2_feature_set) ;
server->method_2_feature_set = g_hash_table_new_full(NULL, NULL, NULL, freeSetCB) ;
}
/* Here we need to find methods for all the given feature set names and then look
* for column groups and styles if the new tag sets are being used.
*
* The list needs to be stored inside the server struct for later use in getting styles..*/
feature_sets = *feature_sets_inout ;
feature_set_methods = col_group_methods = required_styles = method_names = NULL ;
num_feature_sets = g_list_length(feature_sets) ;
/* 1) find methods to match feature set names, puts methods into acedb's active keyset.
* (method_string is an acedb query string to find all those methods). */
method_string = getMethodString(feature_sets, TRUE, TRUE, TRUE) ;
if ((result = findMethods(server_in, method_string, &num_methods)) != ZMAP_SERVERRESPONSE_OK)
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not find feature set methods in server because: %s", server->last_err_msg) ;
}
else if (num_feature_sets != num_methods)
{
if (num_feature_sets > num_methods)
{
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"%s", "Some featuresets could not be found.") ;
}
else
{
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", "Too many featuresets found ! Ace Server Query probably incorrect !") ;
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
}
g_free(method_string) ;
/* 2) Check feature set names against method names, remove any feature sets for which there is
* no method, we fail if no methods are found. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
if ((result = getObjNames(server, &feature_set_methods)) == ZMAP_SERVERRESPONSE_OK)
{
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
zMap_g_list_quark_print(feature_set_methods, "feature_set_methods", FALSE) ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
if (num_feature_sets != num_methods)
{
if (!equaliseLists(server, &(feature_sets), feature_set_methods, "Feature Sets", "Methods"))
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
}
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not get list of feature set methods from server because: %s",
server->last_err_msg) ;
}
}
/* If we are using styles/column groups then extra processing is required, otherwise we just
* return what methods we have and if possible the list of required styles. The all_methods
* list is used by acedb in retrieving just those features in a seqget/seqfeatures call. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL && server->has_new_tags)
{
featureset_2_stylelist = *featureset_2_stylelist_inout ;
if ((result = findColStyleTags(server,
&feature_sets, &feature_methods,
&required_styles, &featureset_2_stylelist))
!= ZMAP_SERVERRESPONSE_REQFAIL)
{
server->all_methods = feature_methods ;
*feature_sets_inout = feature_sets ;
*required_styles_out = required_styles ;
*featureset_2_stylelist_inout = featureset_2_stylelist ;
}
}
else if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
server->all_methods = feature_set_methods ;
*feature_sets_inout = feature_sets ;
*required_styles_out = g_list_copy(feature_set_methods) ;
/* We need to create the one-to-one relationship */
if((feature_set_methods = g_list_first(feature_set_methods)) &&
featureset_2_stylelist_inout)
{
do
{
GQuark feature_set_id, feature_set_name_id;;
/* We _must_ canonicalise here. */
feature_set_name_id = GPOINTER_TO_UINT(feature_set_methods->data);
feature_set_id = zMapStyleCreateID((char *)g_quark_to_string(feature_set_name_id));
zMap_g_hashlist_insert(*featureset_2_stylelist_inout,
feature_set_id,
GUINT_TO_POINTER(feature_set_id));
}
while((feature_set_methods = g_list_next(feature_set_methods)));
}
}
return result ;
}
static ZMapServerResponseType getStyles(void *server_in, GData **styles_out)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if (!findMethods(server, NULL, NULL) == ZMAP_SERVERRESPONSE_OK)
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could not find types on server because: %s", server->last_err_msg) ;
}
else
{
if (parseTypes(server, styles_out, NULL, NULL))
{
result = ZMAP_SERVERRESPONSE_OK ;
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could not get types from server because: %s", server->last_err_msg) ;
}
}
return result ;
}
/* acedb Method objects do not usually have any mode information (e.g. transcript etc),
* Zmap_Style objects do.
*
* We can't test for this until the config file is read which happens when we make
* the connection. */
static ZMapServerResponseType haveModes(void *server_in, gboolean *have_mode)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if (server->connection)
{
if (server->has_new_tags)
*have_mode = TRUE ;
else
*have_mode = FALSE ;
result = ZMAP_SERVERRESPONSE_OK ;
}
return result ;
}
static ZMapServerResponseType getSequences(void *server_in, GList *sequences_inout)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if (!sequences_inout)
{
setErrMsg(server, g_strdup("getSequences request made but no sequence names specified.")) ;
server->last_err_status = ACECONN_BADARGS ;
}
else
{
/* For acedb the default is to use the style names as the feature sets. */
if ((result = doGetSequences(server_in, sequences_inout)) == ZMAP_SERVERRESPONSE_OK)
{
/* Nothing to do I think.... */
;
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could not get sequences from server because: %s", server->last_err_msg) ;
}
}
return result ;
}
/* the struct/param handling will not work in these routines now and needs sorting out.... */
static ZMapServerResponseType setContext(void *server_in, ZMapFeatureContext feature_context)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_OK ;
AcedbServer server = (AcedbServer)server_in ;
gboolean status ;
resetErr(server) ;
server->req_context = feature_context ;
/* HERE WE NEED TO ACCEPT A PASSED IN FEATURE CONTEXT AND THEN COPY IT AND FILL IT IN,
THE COPY CONTEXT NEEDS TO HAPPEN HERE.....*/
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
feature_context = zMapFeatureContextCreate(server->sequence) ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
if (!(status = getSequenceMapping(server, feature_context)))
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Could not map %s because: %s",
g_quark_to_string(server->req_context->sequence_name), server->last_err_msg) ;
}
else
server->current_context = feature_context ;
return result ;
}
/* Get features sequence. */
static ZMapServerResponseType getFeatures(void *server_in, GData *styles, ZMapFeatureContext feature_context)
{
AcedbServer server = (AcedbServer)server_in ;
DoAllAlignBlocksStruct get_features ;
resetErr(server) ;
server->current_context = feature_context ;
get_features.result = ZMAP_SERVERRESPONSE_OK ;
get_features.server = (AcedbServer)server_in ;
get_features.server->last_err_status = ACECONN_OK ;
get_features.styles = styles ;
get_features.eachBlock = eachBlockSequenceRequest;
zMapPrintTimer(NULL, "In thread, getting features") ;
/* Fetch all the alignment blocks for all the sequences. */
g_hash_table_foreach(feature_context->alignments, eachAlignment, (gpointer)&get_features) ;
zMapPrintTimer(NULL, "In thread, got features") ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
{
GError *error = NULL ;
zMapFeatureDumpStdOutFeatures(feature_context, styles, &error) ;
}
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
return get_features.result ;
}
/* Get features and/or sequence. */
static ZMapServerResponseType getContextSequence(void *server_in, GData *styles, ZMapFeatureContext feature_context)
{
AcedbServer server = (AcedbServer)server_in ;
DoAllAlignBlocksStruct get_sequence ;
resetErr(server) ;
get_sequence.result = ZMAP_SERVERRESPONSE_OK;
get_sequence.server = server ;
get_sequence.styles = styles ;
get_sequence.server->last_err_status = ACECONN_OK;
get_sequence.eachBlock = eachBlockDNARequest;
g_hash_table_foreach(feature_context->alignments, eachAlignment, (gpointer)&get_sequence) ;
return get_sequence.result;
}
char *lastErrorMsg(void *server_in)
{
char *err_msg = NULL ;
AcedbServer server = (AcedbServer)server_in ;
zMapAssert(server_in) ;
if (server->last_err_msg)
err_msg = server->last_err_msg ;
else if (server->last_err_status != ACECONN_OK)
server->last_err_msg = err_msg =
g_strdup(AceConnGetErrorMsg(server->connection, server->last_err_status)) ;
return err_msg ;
}
static ZMapServerResponseType closeConnection(void *server_in)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
if ((server->last_err_status = AceConnConnectionOpen(server->connection)) == ACECONN_OK
&& (server->last_err_status = AceConnDisconnect(server->connection)) == ACECONN_OK)
result = ZMAP_SERVERRESPONSE_OK ;
return result ;
}
static ZMapServerResponseType destroyConnection(void *server_in)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_OK ;
AcedbServer server = (AcedbServer)server_in ;
resetErr(server) ;
AceConnDestroy(server->connection) ; /* Does not fail. */
server->connection = NULL ; /* Prevents accidental reuse. */
g_free(server->host) ;
if (server->last_err_msg)
g_free(server->last_err_msg) ;
if (server->version_str)
g_free(server->version_str) ;
g_free(server) ;
return result ;
}
/*
* Internal routines
*/
/* Assumes that server has a keyset of methods to be searched for Column_XXX and Style tags.
* The methods are the "columns" and each method may directly represent features itself or
* may group together other methods that represent features via the Column tags.
*
* This all takes a few stages as below.
* */
static ZMapServerResponseType findColStyleTags(AcedbServer server,
GList **feature_sets_inout,
GList **feature_methods_out,
GList **required_styles_out,
GHashTable **featureset_2_stylelist_inout)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_OK ;
GList *feature_sets, *feature_set_methods = NULL, *feature_methods = NULL, *required_styles = NULL ;
GHashTable *featureset_2_stylelist ;
char *method_string ;
int num_orig, num_curr ;
feature_sets = *feature_sets_inout ;
featureset_2_stylelist = *featureset_2_stylelist_inout ;
/*
* Check methods/styles for columns.
*/
/* Check that all of the methods either have a column_child tag and no style
* or have a style and no column_child tag, any that don't will be excluded (n.b. we don't
* validate the style it may come from another server.) This step also gets all the
* methods that are required to load features. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
GetMethodsStylesStruct get_sets = {NULL} ;
num_orig = g_list_length(feature_sets) ;
if (parseTypes(server, NULL, parseMethodColGroupNames, &(get_sets)))
{
result = ZMAP_SERVERRESPONSE_OK ;
feature_set_methods = get_sets.feature_set_methods ;
feature_methods = get_sets.feature_methods ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
printf("\n=======================\n") ;
zMap_g_list_quark_print(feature_set_methods, "Column feature_sets", FALSE) ;
printf("\n=======================\n") ;
zMap_g_list_quark_print(feature_methods, "Child methods", FALSE) ;
printf("\n=======================\n") ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
num_curr = g_list_length(feature_set_methods) ;
/* Check the list of feature sets against valid methods, remove any feature sets
* without a valid method, we fail if no methods are found. */
if (num_orig != num_curr)
{
if (!equaliseLists(server, &(feature_sets), feature_set_methods, "Feature Sets", "Valid Methods"))
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
}
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not fetch methods to look for Column_child and Style tags: %s", server->last_err_msg) ;
}
}
/*
* Check methods/styles for feature sets.
*/
/* 2) Check that all feature methods have a style, any that don't will be excluded.
* Also check whether any reference a parent column group. Update hash of both for
* reference in reading features. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
/* 2a) Get all methods into acedb's active keyset. */
num_orig = g_list_length(feature_methods) ;
method_string = getMethodString(feature_methods, TRUE, TRUE, TRUE) ;
if ((result = findMethods(server, method_string, &num_curr)) != ZMAP_SERVERRESPONSE_OK)
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not find feature set methods in server because: %s", server->last_err_msg) ;
}
else if (num_orig != num_curr)
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
if (num_orig > num_curr)
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"%s", "Some featuresets could not be found.") ;
else
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", "Too many featuresets found ! Ace Server Query probably incorrect !") ;
}
g_free(method_string) ;
}
/* 2b) Check all methods were found, remove any methods that were not, we fail if no methods are found. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
GList *curr_methods = NULL ;
if ((result = getObjNames(server, &curr_methods)) == ZMAP_SERVERRESPONSE_OK)
{
if (num_orig != num_curr)
{
if (!equaliseLists(server, &(feature_methods), curr_methods, "Feature Methods", "Methods"))
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
}
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not get list of feature set methods from server because: %s",
server->last_err_msg) ;
}
g_list_free(curr_methods) ;
}
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
GetMethodsStylesStruct get_sets = {NULL} ;
num_orig = g_list_length(feature_methods) ;
get_sets.server = server ;
get_sets.set_2_styles = featureset_2_stylelist ;
if (parseTypes(server, NULL, parseMethodStyleNames, &(get_sets)))
{
result = ZMAP_SERVERRESPONSE_OK ;
required_styles = get_sets.required_styles ;
featureset_2_stylelist = get_sets.set_2_styles ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
zMap_g_list_quark_print(required_styles, "feature_sets", FALSE) ;
printf("\n=======================\n") ;
zMap_g_hashlist_print(featureset_2_stylelist) ;
printf("\n=======================\n") ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
num_curr = g_list_length(get_sets.feature_methods) ;
if (num_orig != num_curr)
{
if (!equaliseLists(server, &(feature_methods), get_sets.feature_methods, "Feature Methods", "Methods"))
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
}
}
else
{
result = ZMAP_SERVERRESPONSE_REQFAIL ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Could not fetch " COL_CHILD " methods to look for zmap_styles: %s", server->last_err_msg) ;
}
}
/* Return results if all ok. */
if (result != ZMAP_SERVERRESPONSE_REQFAIL)
{
*feature_sets_inout = feature_sets ;
*feature_methods_out = feature_methods ;
*required_styles_out = required_styles ;
*featureset_2_stylelist_inout = featureset_2_stylelist ;
}
return result ;
}
static GList *getMethodsLoadable(GList *all_methods, GHashTable *method_2_data, GData *styles)
{
GList *loadable_methods = NULL ;
LoadableStruct loadable_data ;
loadable_data.methods = NULL ;
loadable_data.method_2_data = method_2_data ;
loadable_data.styles = styles ;
g_list_foreach(all_methods, loadableCB, &loadable_data) ;
loadable_methods = loadable_data.methods ;
return loadable_methods ;
}
static void loadableCB(gpointer data, gpointer user_data)
{
GQuark methods_id = GPOINTER_TO_UINT(data) ; /* Not needed. */
Loadable loadable_data = ( Loadable)user_data ;
ZMapGFFSource source_data ;
methods_id = zMapStyleCreateID((char *)g_quark_to_string(methods_id)) ;
if ((source_data = g_hash_table_lookup(loadable_data->method_2_data, GINT_TO_POINTER(methods_id))))
{
GQuark real_id ;
ZMapFeatureTypeStyle style ;
real_id = zMapStyleCreateID((char *)g_quark_to_string(source_data->style_id)) ;
if ((style = zMapFindStyle(loadable_data->styles, real_id)))
{
gboolean deferred = FALSE ;
g_object_get(style, ZMAPSTYLE_PROPERTY_DEFERRED, &deferred, NULL) ;
if (!deferred)
loadable_data->methods = g_list_append(loadable_data->methods, GUINT_TO_POINTER(data)) ;
}
}
return ;
}
/* Make up a string that contains method names in the correct format for an acedb "Find" command
* (find_string == TRUE) or to be part of an acedb "seqget" command.
* We may be passed either a list of style names in GQuark form (style_name_list == TRUE)
* or a list of the actual styles. */
static char *getMethodString(GList *styles_or_style_names,
gboolean style_name_list, gboolean find_string, gboolean find_methods)
{
char *type_names = NULL ;
ZMapTypesStringStruct types_data ;
GString *str ;
gboolean free_string = TRUE ;
zMapAssert(styles_or_style_names) ;
str = g_string_new("") ;
if (find_string)
{
if (find_methods)
str = g_string_append(str, "query find method ") ;
else
str = g_string_append(str, "query find zmap_style ") ;
}
else
str = g_string_append(str, "+method ") ;
types_data.first_method = TRUE ;
types_data.find_string = find_string ;
types_data.name_list = style_name_list ;
types_data.str = str ;
g_list_foreach(styles_or_style_names, addTypeName, (void *)&types_data) ;
if (*(str->str))
free_string = FALSE ;
type_names = g_string_free(str, free_string) ;
return type_names ;
}
/* GFunc() callback function, appends style names to a string, its called for lists
* of either style name GQuarks or lists of style structs. */
static void addTypeName(gpointer data, gpointer user_data)
{
char *type_name = NULL ;
GQuark key_id ;
ZMapTypesString types_data = (ZMapTypesString)user_data ;
/* We might be passed either a list of style names (as quarks) or a list of the actual styles
* from which we need to extract the style name. */
if (types_data->name_list)
key_id = GPOINTER_TO_UINT(data) ;
else
{
ZMapFeatureTypeStyle style = (ZMapFeatureTypeStyle)data;
key_id = zMapStyleGetID(style) ;
}
type_name = (char *)g_quark_to_string(key_id) ;
if (!types_data->first_method)
{
if (types_data->find_string)
types_data->str = g_string_append(types_data->str, " OR ") ;
else
types_data->str = g_string_append(types_data->str, "|") ;
}
else
types_data->first_method = FALSE ;
if (types_data->find_string)
{
g_string_append_printf(types_data->str, "\"%s\"", type_name) ;
}
else
types_data->str = g_string_append(types_data->str, type_name) ;
return ;
}
/* bit of an issue over returning error messages here.....sort this out as some errors many be
* aceconn errors, others may be data processing errors, e.g. in GFF etc., e.g.
*
* If we issue a command like this: "gif seqget obj ; seqfeatures" then we have a problem because
* the server treats this as one command and returns any errors from the seqget() munged on the
* front of the GFF output from the seqfeatures() like this:
*
* // ERROR - Sequence:"yk47h9.3" (5' match) and Sequence:"yk47h9.3" (3' match) are in wrong orientation.
* // ERROR - Sequence:"AW057380" (5' match) and Sequence:"AW057380" (3' match) are in wrong orientation.
* // ERROR - Sequence:"OSTR010G5_1" (5' match) and Sequence:"OSTR010G5_1" (3' match) are in wrong orientation.
* ##gff-version 2
* ##source-version sgifaceserver:ACEDB 4.9.27
* ##date 2004-09-21
* ##sequence-region F22D3 1 35712
* F22D3 Genomic_canonical region 1 200 . + . Sequence "B0252"
*
* so what to do...agh....
*
* I guess the best thing is to shove the errors out to the log and look for the gff start...
*
*/
static gboolean sequenceRequest(AcedbServer server, GData *styles, ZMapFeatureBlock feature_block)
{
gboolean result = FALSE ;
char *gene_finder_cmds = "seqactions -gf_features no_draw ;" ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
GList *loadable_methods = NULL ;
char *methods = "" ;
gboolean no_clip = TRUE ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
/* Get any styles stored in the context. */
styles = ((ZMapFeatureContext)(feature_block->parent->parent))->styles ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
/* Exclude any methods that have "deferred loading" set in their styles, if no styles then
* include all methods. */
if (server->has_new_tags)
loadable_methods = getMethodsLoadable(server->all_methods, server->method_2_data, styles) ;
else
loadable_methods = g_list_copy(server->all_methods) ;
methods = getMethodString(loadable_methods, TRUE, FALSE, FALSE) ;
g_list_free(loadable_methods) ;
loadable_methods = NULL ;
/* Check for presence of genefinderfeatures method, if present we need to tell acedb to send
* us the gene finder methods... */
if ((zMap_g_ascii_strstrcasecmp(methods, ZMAP_FIXED_STYLE_GFF_NAME)))
server->fetch_gene_finder_features = TRUE ;
/* Here we can convert the GFF that comes back, in the end we should be doing a number of
* calls to AceConnRequest() as the server slices...but that will need a change to my
* AceConn package.....
* We make the big assumption that what comes back is a C string for now, this is true
* for most acedb requests, only images/postscript are not and we aren't asking for them. */
/* -rawmethods makes sure that the server does _not_ use the GFF_source field in the method obj
* to output the source field in the gff, we need to see the raw methods.
* -refseq makes sure that the coords returned are relative to the reference sequence, _not_
* to the object at the top of the smap tree .
*
* Note that we specify the methods both for the seqget and the seqfeatures to try and exclude
* the parent sequence if it is not required, this is actually quite fiddly to do in the acedb
* code in a way that won't break zmap so we do it here. */
zMapPrintTimer(NULL, "In thread, about to ask for features") ;
acedb_request = g_strdup_printf("gif seqget %s -coords %d %d %s %s ; "
" %s "
"seqfeatures -refseq %s -rawmethods -zmap %s",
g_quark_to_string(feature_block->original_id),
feature_block->features_start,
feature_block->features_end,
no_clip ? "-noclip" : "",
methods,
(server->fetch_gene_finder_features ? gene_finder_cmds : ""),
g_quark_to_string(feature_block->original_id),
methods) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request, &reply, &reply_len))
== ACECONN_OK)
{
char *next_line ;
ZMapReadLine line_reader ;
gboolean inplace = TRUE ;
char *first_error = NULL ;
zMapPrintTimer(NULL, "In thread, got features and about to parse into context") ;
line_reader = zMapReadLineCreate((char *)reply, inplace) ;
/* Look for "##gff-version" at start of line which signals start of GFF, as detailed above
* there may be errors before the GFF output. */
result = TRUE ;
do
{
if (!(result = zMapReadLineNext(line_reader, &next_line)))
{
/* If the readline fails it may be because of an error or because its reached the
* end, if next_line is empty then its reached the end. */
if (*next_line)
{
setErrMsg(server, g_strdup_printf("Request from server contained incomplete line: %s",
next_line)) ;
if (!first_error)
first_error = next_line ; /* Remember first line for later error
message.*/
}
else
{
if (first_error)
setErrMsg(server, g_strdup_printf("No GFF found in server reply,"
"but did find: \"%s\"", first_error)) ;
else
setErrMsg(server, g_strdup_printf("%s", "No GFF found in server reply.")) ;
}
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
}
else
{
/* The ace server first gives us all the errors from the seqget/seqfeatures as
* comments as then finally we get to the gff. */
if (g_str_has_prefix((char *)next_line, "##gff-version"))
{
break ;
}
else
{
if (g_str_has_prefix((char *)next_line, "// ERROR"))
{
setErrMsg(server, g_strdup_printf("Error fetching features: %s",
next_line)) ;
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
}
else if (g_str_has_prefix((char *)next_line, "//"))
{
setErrMsg(server, g_strdup_printf("Information from server: %s",
next_line)) ;
ZMAPSERVER_LOG(Message, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
}
else
{
setErrMsg(server, g_strdup_printf("Bad GFF line: %s",
next_line)) ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
}
if (!first_error)
first_error = next_line ; /* Remember first line for later error
message.*/
}
}
}
while (result && *next_line) ;
if (result)
{
ZMapGFFParser parser ;
gboolean free_on_destroy ;
parser = zMapGFFCreateParser(styles, FALSE) ;
/* If we are doing cols/styles then set hash tables in parser to map the gff source
* name to the Feature Set (== Column) and a Style. */
if (server->has_new_tags)
{
zMapGFFParseSetSourceHash(parser, server->method_2_feature_set, server->method_2_data) ;
}
/* We probably won't have to deal with part lines here acedb should only return whole lines
* ....but should check for sure...bomb out for now.... */
result = TRUE ;
do
{
/* Note that we already have the first line from the loop above. */
if (!zMapGFFParseLine(parser, next_line))
{
/* This is a hack, I would like to make the acedb code have a quiet mode but
* as usual this is not straight forward and will take a bit of fixing...
* The problem for us is that the gff output is terminated with with a couple
* of acedb comment lines which then screw up our parsing....so we ignore
* lines starting with "//" hoping this doesn't conflict with gff.... */
if (!g_str_has_prefix(next_line, "//"))
{
GError *error = zMapGFFGetError(parser) ;
if (!error)
{
setErrMsg(server,
g_strdup_printf("zMapGFFParseLine() failed with no GError for line %d: %s",
zMapGFFGetLineNumber(parser), next_line)) ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
result = FALSE ;
}
else
{
/* If the error was serious we stop processing and return the error,
* otherwise we just log the error. */
if (zMapGFFTerminated(parser))
{
result = FALSE ;
setErrMsg(server, g_strdup_printf("%s", error->message)) ;
}
else
{
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"%s", error->message) ;
}
}
}
}
if (!(result = zMapReadLineNext(line_reader, &next_line)))
{
/* If the readline fails it may be because of an error or because its reached the
* end, if next_line is empty then its reached the end. */
if (*next_line)
{
setErrMsg(server, g_strdup_printf("Request from server contained incomplete line: %s",
next_line)) ;
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"%s", server->last_err_msg) ;
}
else
result = TRUE ;
}
}
while (result && *next_line) ;
free_on_destroy = TRUE ;
if (result)
{
if (zMapGFFGetFeatures(parser, feature_block))
{
free_on_destroy = FALSE ; /* Make sure parser does _not_ free our
data. ! */
}
else
result = FALSE ;
}
zMapGFFSetFreeOnDestroy(parser, free_on_destroy) ;
zMapGFFDestroyParser(parser) ;
}
zMapReadLineDestroy(line_reader, FALSE) ; /* n.b. don't free string as it is the
same as reply which is freed later.*/
g_free(reply) ;
zMapPrintTimer(NULL, "In thread, finished parsing features") ;
}
if(acedb_request)
g_free(acedb_request) ;
if(methods)
g_free(methods);
return result ;
}
static void eachBlockDNARequest(gpointer key, gpointer data, gpointer user_data)
{
ZMapFeatureBlock feature_block = (ZMapFeatureBlock)data ;
DoAllAlignBlocks get_sequence = (DoAllAlignBlocks)user_data ;
/* We should check that there is a sequence context here and report an error if there isn't... */
/* We should be using the start/end info. in context for the below stuff... */
if (!blockDNARequest(get_sequence->server, get_sequence->styles, feature_block))
{
/* If the call failed it may be that the connection failed or that the data coming
* back had a problem. */
if (get_sequence->server->last_err_status == ACECONN_OK)
{
get_sequence->result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
else if (get_sequence->server->last_err_status == ACECONN_TIMEDOUT)
{
get_sequence->result = ZMAP_SERVERRESPONSE_TIMEDOUT ;
}
else
{
/* Probably we will want to analyse the response more than this ! */
get_sequence->result = ZMAP_SERVERRESPONSE_SERVERDIED ;
}
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, get_sequence->server->host,
"Could not get DNA sequence for %s because: %s",
g_quark_to_string(get_sequence->server->req_context->sequence_name),
get_sequence->server->last_err_msg) ;
}
return ;
}
/* bit of an issue over returning error messages here.....sort this out as some errors many be
* aceconn errors, others may be data processing errors, e.g. in GFF etc., e.g.
*
*
*/
static gboolean blockDNARequest(AcedbServer server, GData *styles, ZMapFeatureBlock feature_block)
{
gboolean result = FALSE ;
ZMapFeatureContext context = NULL ;
int block_start, block_end, dna_length = 0 ;
char *dna_sequence = NULL ;
context = (ZMapFeatureContext)zMapFeatureGetParentGroup((ZMapFeatureAny)feature_block,
ZMAPFEATURE_STRUCT_CONTEXT) ;
block_start = feature_block->block_to_sequence.q1 ;
block_end = feature_block->block_to_sequence.q2 ;
/* These block numbers appear correct, but I may have the wrong
* end of the block_to_sequence stick! */
/* Because the acedb "dna" command works on the current keyset, we have to find the sequence
* first before we can get its dna. A bit poor really but otherwise
* we will have to add a new code to acedb to do the dna for a named key. */
if ((result = getDNARequest(server,
(char *)g_quark_to_string(server->req_context->sequence_name),
block_start, block_end,
&dna_length, &dna_sequence)))
{
ZMapFeature feature = NULL;
ZMapFeatureSet feature_set = NULL;
ZMapFeatureTypeStyle dna_style = NULL;
if (zMapFeatureDNACreateFeatureSet(feature_block, &feature_set))
{
ZMapFeatureTypeStyle temp_style = NULL;
/* This temp style creation feels wrong, and probably is,
* but we don't have the merged in default styles in here,
* or so it seems... */
if (!(dna_style = zMapFindStyle(styles, zMapStyleCreateID(ZMAP_FIXED_STYLE_DNA_NAME))))
temp_style = dna_style = zMapStyleCreate(ZMAP_FIXED_STYLE_DNA_NAME,
ZMAP_FIXED_STYLE_DNA_NAME_TEXT);
feature = zMapFeatureDNACreateFeature(feature_block, dna_style,
dna_sequence, dna_length);
if(temp_style)
zMapStyleDestroy(temp_style);
}
/* I'm going to create the three frame translation up front! */
if (zMap_g_list_find_quark(context->feature_set_names, zMapStyleCreateID(ZMAP_FIXED_STYLE_3FT_NAME)))
{
if ((zMapFeature3FrameTranslationCreateSet(feature_block, &feature_set)))
{
ZMapFeatureTypeStyle frame_style = NULL;
gboolean style_absolutely_required = FALSE;
frame_style = zMapFindStyle(styles, zMapStyleCreateID(ZMAP_FIXED_STYLE_3FT_NAME));
if(style_absolutely_required && !frame_style)
zMapLogWarning("Cowardly refusing to create features '%s' without style",
ZMAP_FIXED_STYLE_3FT_NAME);
else
zMapFeature3FrameTranslationSetCreateFeatures(feature_set, frame_style);
}
}
/* everything should now be done, result is true */
result = TRUE ;
}
return result ;
}
/* bit of an issue over returning error messages here.....sort this out as some errors many be
* aceconn errors, others may be data processing errors, e.g. in GFF etc., e.g.
*
*
*/
static gboolean getDNARequest(AcedbServer server, char *sequence_name, int start, int end,
int *dna_length_out, char **dna_sequence_out)
{
gboolean result = FALSE ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
/* Because the acedb "dna" command works on the current keyset, we have to find the sequence
* first before we can get its dna. A bit poor really but otherwise
* we will have to add a new code to acedb to do the dna for a named key. */
if (findSequence(server, sequence_name))
{
int dna_length ;
/* Here we get all the dna in one go, in the end we should be doing a number of
* calls to AceConnRequest() as the server slices...but that will need a change to my
* AceConn package....
* -u says get the dna as a single line.*/
acedb_request = g_strdup_printf("dna -u -x1 %d -x2 %d", start, end) ;
server->last_err_status = AceConnRequest(server->connection, acedb_request, &reply, &reply_len) ;
if (server->last_err_status == ACECONN_OK)
{
if ((reply_len - 1) != ((dna_length = end - start + 1)))
{
setErrMsg(server, g_strdup_printf("DNA request failed (\"%s\"), "
"expected dna length: %d "
"returned length: %d",
acedb_request,
dna_length, (reply_len - 1))) ;
result = FALSE ;
}
else
{
*dna_length_out = dna_length ;
*dna_sequence_out = reply ;
/* everything should now be done, result is true */
result = TRUE ;
}
}
g_free(acedb_request) ;
}
return result ;
}
/* Tries to smap sequence into whatever its parent is, if the call fails then we set all the
* mappings in feature_context to be something sensible...we hope....
*/
static gboolean getSequenceMapping(AcedbServer server, ZMapFeatureContext feature_context)
{
gboolean result = FALSE ;
char *parent_name = NULL, *parent_class = NULL ;
ZMapMapBlockStruct sequence_to_parent = {0, 0, 0, 0}, parent_to_self = {0, 0, 0, 0} ;
int parent_length = 0 ;
/* We have a special case where the caller can specify end == 0 meaning "get the sequence
* up to the end", in this case we explicitly find out what the end is. */
if (server->req_context->sequence_to_parent.c2 == 0)
{
int child_length ;
/* NOTE that we hard code sequence in here...but what to do...gff does not give back the
* class of the sequence object..... */
if (getSMapLength(server, "sequence",
(char *)g_quark_to_string(server->req_context->sequence_name),
&child_length))
server->req_context->sequence_to_parent.c2 = child_length ;
}
if (getSMapping(server, NULL, (char *)g_quark_to_string(server->req_context->sequence_name),
server->req_context->sequence_to_parent.c1, server->req_context->sequence_to_parent.c2,
&parent_class, &parent_name, &sequence_to_parent)
&& ((server->req_context->sequence_to_parent.c2 - server->req_context->sequence_to_parent.c1 + 1) == (sequence_to_parent.c2 - sequence_to_parent.c1 + 1))
&& getSMapLength(server, parent_class, parent_name, &parent_length))
{
feature_context->length = sequence_to_parent.c2 - sequence_to_parent.c1 + 1 ;
parent_to_self.p1 = parent_to_self.c1 = 1 ;
parent_to_self.p2 = parent_to_self.c2 = parent_length ;
feature_context->parent_name = g_quark_from_string(parent_name) ;
g_free(parent_name) ;
if (feature_context->sequence_to_parent.p1 < feature_context->sequence_to_parent.p2)
{
feature_context->parent_span.x1 = parent_to_self.p1 ;
feature_context->parent_span.x2 = parent_to_self.p2 ;
}
else
{
feature_context->parent_span.x1 = parent_to_self.p2 ;
feature_context->parent_span.x2 = parent_to_self.p1 ;
}
feature_context->sequence_to_parent.c1 = sequence_to_parent.c1 ;
feature_context->sequence_to_parent.c2 = sequence_to_parent.c2 ;
feature_context->sequence_to_parent.p1 = sequence_to_parent.p1 ;
feature_context->sequence_to_parent.p2 = sequence_to_parent.p2 ;
result = TRUE ;
}
return result ;
}
/* Gets the mapping of a sequence object into its ultimate SMap parent, uses the
* smap and smaplength commands to do this. Note that we currently assume that the
* object is of the sequence class. If the smap call succeeds then returns TRUE,
* FALSE otherwise (server->last_err_msg is set to show the problem).
*
* To do this we issue the smap request to the server:
*
* gif smap -from sequence:<seq_name>
*
* and receive a reply in the form:
*
* SMAP Sequence:<parent_name> 10995378 11034593 1 39216 PERFECT_MAP
* // 0 Active Objects
*
* on error we get something like:
*
* // gif smap error: invalid from object
* // 0 Active Objects
*
*/
static gboolean getSMapping(AcedbServer server, char *class,
char *sequence, int start, int end,
char **parent_class_out, char **parent_name_out,
ZMapMapBlock child_to_parent_out)
{
gboolean result = FALSE ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
acedb_request = g_strdup_printf("gif smap -coords %d %d -from sequence:%s",
start, end, sequence) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request, &reply, &reply_len))
== ACECONN_OK)
{
char *reply_text = (char *)reply ;
/* this is a hack, none of the acedb commands return an error code so the only way you know
* if anything has gone wrong is to examine the contents of the text that is returned...
* in our case if the reply starts with acedb comment chars, this means trouble.. */
if (g_str_has_prefix(reply_text, "//"))
{
setErrMsg(server, g_strdup_printf("SMap request failed, "
"request: \"%s\", "
"reply: \"%s\"", acedb_request, reply_text)) ;
result = FALSE ;
}
else
{
enum {FIELD_BUFFER_LEN = 257} ;
char parent_class[FIELD_BUFFER_LEN] = {'\0'}, parent_name[FIELD_BUFFER_LEN] = {'\0'} ;
char status[FIELD_BUFFER_LEN] = {'\0'} ;
ZMapMapBlockStruct child_to_parent = {0, 0, 0, 0} ;
enum {FIELD_NUM = 7} ;
char *format_str = "SMAP %256[^:]:%256s%d%d%d%d%256s" ;
int fields ;
if ((fields = sscanf(reply_text, format_str, &parent_class[0], &parent_name[0],
&child_to_parent.p1, &child_to_parent.p2,
&child_to_parent.c1, &child_to_parent.c2,
&status[0])) != FIELD_NUM)
{
setErrMsg(server, g_strdup_printf("Could not parse smap data, "
"request: \"%s\", "
"reply: \"%s\"", acedb_request, reply_text)) ;
result = FALSE ;
}
else
{
/* Really we need to do more than this, we should check the status of the mapping. */
if (parent_class_out)
*parent_class_out = g_strdup(&parent_class[0]) ;
if (parent_name_out)
*parent_name_out = g_strdup(&parent_name[0]) ;
if (child_to_parent_out)
*child_to_parent_out = child_to_parent ; /* n.b. struct copy. */
result = TRUE ;
}
}
g_free(reply) ;
}
g_free(acedb_request) ;
return result ;
}
/* Makes smaplength request to server for a given object. If the smap call succeeds
* then returns TRUE, FALSE otherwise (server->last_err_msg is set to show the problem).
*
* To do this we issue the smap request to the server:
*
* smaplength Sequence:CHROMOSOME_V
*
* and receive a reply in the form:
*
* SMAPLENGTH Sequence:"CHROMOSOME_V" 20922231
* // 0 Active Objects
*
* on error we get something like:
*
* // smaplength error: object "Sequence:CHROMOSOME_V" does not exist.
* // 0 Active Objects
*
* */
static gboolean getSMapLength(AcedbServer server, char *obj_class, char *obj_name,
int *obj_length_out)
{
gboolean result = FALSE ;
char *command = "smaplength" ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
acedb_request = g_strdup_printf("%s %s:%s", command, obj_class, obj_name) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request, &reply, &reply_len))
== ACECONN_OK)
{
char *reply_text = (char *)reply ;
/* this is a hack, none of the acedb commands return an error code so the only way you know
* if anything has gone wrong is to examine the contents of the text that is returned...
* in our case if the reply starts with acedb comment chars, this means trouble.. */
if (g_str_has_prefix(reply_text, "//"))
{
setErrMsg(server, g_strdup_printf("%s request failed, "
"request: \"%s\", "
"reply: \"%s\"", command, acedb_request, reply_text)) ;
result = FALSE ;
}
else
{
enum {FIELD_BUFFER_LEN = 257} ;
char obj_class_name[FIELD_BUFFER_LEN] = {'\0'} ;
int length = 0 ;
enum {FIELD_NUM = 2} ;
char *format_str = "SMAPLENGTH %256s%d" ;
int fields ;
if ((fields = sscanf(reply_text, format_str, &obj_class_name[0], &length)) != FIELD_NUM)
{
setErrMsg(server, g_strdup_printf("Could not parse smap data, "
"request: \"%s\", "
"reply: \"%s\"", acedb_request, reply_text)) ;
result = FALSE ;
}
else
{
if (obj_length_out)
*obj_length_out = length ;
result = TRUE ;
}
}
g_free(reply) ;
}
g_free(acedb_request) ;
return result ;
}
/* Makes status request to get acedb server code version. Returns TRUE if server version is
* same or more recent than ours, returns FALSE if version is older or it call fails
* failure implies a serious error.
*
* Command and output to do this are like this:
*
* acedb> status -code
* // ************************************************
* // AceDB status at 2004-11-09_15:17:03
* //
* // - Code
* // Program: giface
* // Version: ACEDB 4.9.28
* // Build: Nov 9 2004 13:34:42
* //
* // ************************************************
*
*/
static gboolean checkServerVersion(AcedbServer server)
{
gboolean result = FALSE ;
char *command = "status -code" ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
if (server->version_str == NULL)
result = TRUE ;
else
{
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
char *reply_text = (char *)reply ;
char *scan_text = reply_text ;
char *next_line = NULL ;
/* Scan lines for "Version:" and then extract the version, release and update numbers. */
while ((next_line = strtok(scan_text, "\n")))
{
scan_text = NULL ;
if (strstr(next_line, "Version:"))
{
/* Parse this string: "// Version: ACEDB 4.9.28" */
char *next ;
next = strtok(next_line, ":") ;
next = strtok(NULL, " ") ;
next = strtok(NULL, " ") ;
if (!(result = zMapCompareVersionStings(server->version_str, next)))
setErrMsg(server, g_strdup_printf("Server version must be at least %s "
"but this server is %s.",
server->version_str, next)) ;
break ;
}
}
g_free(reply) ;
}
g_free(acedb_request) ;
}
return result ;
}
/* Makes "find sequence x" request to get sequence into current keyset on server.
* Returns TRUE if sequence found, returns FALSE otherwise.
*
* Command and output to do this are like this:
*
* acedb> find sequence b0250
*
* // Found 1 objects in this class
* // 1 Active Objects
*
*
*/
static gboolean findSequence(AcedbServer server, char *sequence_name)
{
gboolean result = FALSE ;
char *command = "find sequence" ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
acedb_request = g_strdup_printf("%s %s", command, sequence_name) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
char *reply_text = (char *)reply ;
char *scan_text = reply_text ;
char *next_line = NULL ;
/* Scan lines for "Found" and then extract the version, release and update numbers. */
while ((next_line = strtok(scan_text, "\n")))
{
scan_text = NULL ;
if (strstr(next_line, "Found"))
{
/* Parse this string: "// Found 1 objects in this class" */
char *next ;
int num_obj ;
next = strtok(next_line, " ") ;
next = strtok(NULL, " ") ;
next = strtok(NULL, " ") ;
num_obj = atoi(next) ;
if (num_obj == 1)
result = TRUE ;
else
setErrMsg(server, g_strdup_printf("Expected to find \"1\" sequence object with name %s, "
"but found %d objects.",
sequence_name, num_obj)) ;
break ;
}
}
g_free(reply) ;
}
g_free(acedb_request) ;
return result ;
}
/* Makes "quiet -on" request to stop acedb outputting all sorts of informational junk
* for every single request. Returns TRUE if request ok, returns FALSE otherwise.
*
* (n.b. if the request was successful then there is no output from the command !)
*
*/
static gboolean setQuietMode(AcedbServer server)
{
gboolean result = FALSE ;
char *command = "quiet -on" ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
result = TRUE ;
if (reply_len != 0)
{
zMapLogWarning("Replay to \"%s\" should have been NULL but was: \"%s\"",
command, (char *)reply) ;
g_free(reply) ;
}
}
g_free(acedb_request) ;
return result ;
}
/* Uses the "status" command to get database and code information, e.g.
*
* acedb> status -database
* // ************************************************
* // AceDB status at 2008-02-08_10:59:02
* //
* // - Database
* // Title: <undefined>
* // Name: <undefined>
* // Release: 4_0
* // Directory: /nfs/team71/acedb/edgrif/acedb/databases/JAMES.NEWSTYLES/
* // Session: 7
* // User: edgrif
* // Last Save: 2008-02-06_15:47:52
* // Write Access: No
* // Global Address: 3470
* //
* // ************************************************
*
* // 0 Active Objects
* acedb>
*
*
* */
static gboolean getServerInfo(AcedbServer server, char **database_path_out)
{
gboolean result = FALSE ;
char *command ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
/* We could add "status -code" later..... */
command = "status -database" ;
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
char *scan_text = (char *)reply ;
char *next_line = NULL ;
char *curr_pos = NULL ;
while ((next_line = strtok_r(scan_text, "\n", &curr_pos)))
{
scan_text = NULL ;
if (strstr(next_line, "Directory") != NULL)
{
char *target ;
char *tag_pos = NULL ;
target = strtok_r(next_line, ":", &tag_pos) ;
target = strtok_r(NULL, " ", &tag_pos) ;
if (target)
{
result = TRUE ;
*database_path_out = g_strdup(target) ;
}
else
setErrMsg(server, g_strdup("No directory name after \"Directory\" in acedb response.")) ;
break ;
}
}
g_free(reply) ;
reply = NULL ;
}
g_free(acedb_request) ;
return result ;
}
/* Makes requests "find method" and "show -a" to get all methods in a form we can
* parse, e.g.
*
* The "query find" command is used to find either a requested list of methods
* or all methods:
*
* acedb> query find method "coding" OR "genepairs" OR "genefinder"
*
* // Found 3 objects
* // 3 Active Objects
* acedb>
*
*
* Then the "show" command is used to display the methods themselves:
*
* acedb> show -a
*
* Method : "wublastx_briggsae"
* Remark "wublastx search of C. elegans genomic clones vs C. briggsae peptides"
* Colour LIGHTGREEN
* Frame_sensitive
* Show_up_strand
* Score_by_width
* Score_bounds 10.000000 100.000000
* Right_priority 4.750000
* Join_blocks
* Blixem_X
* GFF_source "wublastx"
* GFF_feature "similarity"
*
* <more methods>
*
* // 7 objects dumped
* // 7 Active Objects
*
*
*
* */
static gboolean parseTypes(AcedbServer server, GData **types_out,
ParseMethodNamesFunc parse_func_in, gpointer user_data)
{
gboolean result = FALSE ;
char *command ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
GData *types = NULL ;
/* Get all the methods and then filter them if there are requested types. */
command = "show -a" ;
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
ParseMethodFunc parse_func ;
int num_types = 0 ;
char *method_str = (char *)reply ;
char *scan_text = method_str ;
char *curr_pos = NULL ;
char *next_line = NULL ;
/* Set correct parser. */
if (!parse_func_in)
{
if (server->has_new_tags)
parse_func = parseStyle ;
else
parse_func = parseMethod ;
}
while ((next_line = strtok_r(scan_text, "\n", &curr_pos))
&& !g_str_has_prefix(next_line, "// "))
{
ZMapFeatureTypeStyle style = NULL ;
ZMapColGroupData col_group = NULL ;
scan_text = NULL ;
if (parse_func_in)
{
GQuark method_id ;
if ((method_id = (parse_func_in)(server, next_line, &curr_pos, user_data)))
{
num_types++ ;
}
}
else if ((style = (parse_func)(next_line, &curr_pos, &col_group)))
{
g_datalist_id_set_data(&types, zMapStyleGetUniqueID(style), style) ;
num_types++ ;
}
}
if (!num_types)
{
result = FALSE ;
setErrMsg(server, g_strdup("Styles found on server but they could not be parsed, check the log.")) ;
}
else
{
result = TRUE ;
if (!parse_func_in)
{
*types_out = types ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
g_list_foreach(types, stylePrintCB, NULL) ; /* debug */
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
}
}
g_free(reply) ;
reply = NULL ;
}
g_free(acedb_request) ;
return result ;
}
/* Makes request "query find method" to get all methods into keyset on server.
*
* The "query find" command is used to find all methods:
*
* acedb> query find method
*
* // Found 3 objects
* // 3 Active Objects
* acedb>
*
* Function returns TRUE if methods were found, FALSE otherwise.
*
* */
static ZMapServerResponseType findMethods(AcedbServer server, char *search_str, int *num_found_out)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
char *command ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
if (search_str)
{
command = search_str ;
}
else
{
/* Get all the methods or styles into the current keyset on the server. */
if (server->has_new_tags)
command = "query find zmap_style" ;
else
command = "query find method" ;
}
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
/* reply is:
*
* <blank line>
* // Found 132 objects in this class
* // 132 Active Objects
*
*/
char *scan_text = (char *)reply ;
char *next_line = NULL ;
int num_methods ;
while ((next_line = strtok(scan_text, "\n")))
{
scan_text = NULL ;
if (g_str_has_prefix(next_line, "// "))
{
num_methods = getFoundObj(next_line) ;
if (num_methods > 0)
{
if (num_found_out)
*num_found_out = num_methods ;
result = ZMAP_SERVERRESPONSE_OK ;
}
else
setErrMsg(server, g_strdup_printf("Expected to find %s objects but found none.",
(server->has_new_tags ? "ZMap_style" : "Method"))) ;
break ;
}
}
g_free(reply) ;
reply = NULL ;
}
g_free(acedb_request) ;
return result ;
}
/* The method string should be of the form:
*
* Method : "wublastx_briggsae"
* Remark "wublastx search of C. elegans genomic clones vs C. briggsae peptides"
* Colour LIGHTGREEN
* etc
* Style
* <white space only lines>
* more methods....
*
* Only called if we are using zmap_styles. This parses the method looking
* for Style tags, returns FALSE if they are invalid and logs the error.
*
* We also record the Remark if there is one.
*
* The function also returns a pointer to the blank line that ends the current
* method.
*
*/
static gboolean parseMethodStyleNames(AcedbServer server, char *method_str_in,
char **end_pos, gpointer user_data)
{
gboolean result = FALSE ;
char *method_str = method_str_in ;
char *next_line = method_str ;
GetMethodsStyles get_sets = (GetMethodsStyles)user_data ;
char *name = NULL, *zmap_style = NULL, *col_parent = NULL, *remark = NULL ;
int obj_lines ;
/* This should be in parse types really and then parsetypes should move on to next obj. */
if (!g_str_has_prefix(method_str, "Method : "))
return FALSE ;
obj_lines = 0 ; /* Used to detect empty objects. */
do
{
char *tag = NULL ;
char *line_pos = NULL ;
if (!(tag = strtok_r(next_line, "\t ", &line_pos)))
break ;
/* We don't formally test this but Method _MUST_ be the first line of the acedb output
* representing an object. */
if (g_ascii_strcasecmp(tag, "Method") == 0)
{
/* Line format: Method : "possibly long method name" */
name = strtok_r(NULL, "\"", &line_pos) ;
name = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
if (!name)
{
result = FALSE ;
break ;
}
else
{
result = TRUE ;
}
}
else if (server->has_new_tags && g_ascii_strcasecmp(tag, "Style") == 0)
{
/* Format for this tag: Style "some_zmap_style" */
zmap_style = strtok_r(NULL, "\"", &line_pos) ; /* Skip '"' */
zmap_style = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
if (!zmap_style)
{
result = FALSE ;
break ;
}
else
{
result = TRUE ;
}
}
else if (server->has_new_tags && g_ascii_strcasecmp(tag, COL_PARENT) == 0)
{
/* Format for this tag: Column_parent "some_method" */
if ((col_parent = strtok_r(NULL, "\"", &line_pos))) /* Skip '"' */
col_parent = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (server->has_new_tags && g_ascii_strcasecmp(tag, "Remark") == 0)
{
/* Line format: Remark "possibly quite long bit of text" */
remark = strtok_r(NULL, "\"", &line_pos) ;
remark = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
}
while (++obj_lines && **end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
/* acedb can have empty objects which consist of a first line only. */
if (obj_lines == 1)
{
result = FALSE ;
}
/* If we failed while processing a method we won't have reached the end of the current
* method paragraph so we need to skip to the end so the next method can be processed. */
if (!result)
{
while (**end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
}
if (result)
{
GQuark method_id = 0, style_id = 0, text_id = 0, feature_set_id ;
ZMapGFFSource source_data ;
/* name/style are mandatory, remark is optional. */
method_id = zMapStyleCreateID(name) ;
style_id = zMapStyleCreateID(zmap_style) ;
if (remark)
text_id = g_quark_from_string(remark) ;
get_sets->feature_methods = g_list_append(get_sets->feature_methods,
GINT_TO_POINTER(method_id)) ;
get_sets->required_styles = g_list_append(get_sets->required_styles,
GINT_TO_POINTER(style_id)) ;
if (col_parent)
feature_set_id = zMapStyleCreateID(col_parent) ;
else
feature_set_id = zMapStyleCreateID(name) ;
zMap_g_hashlist_insert(get_sets->set_2_styles, feature_set_id, GINT_TO_POINTER(style_id)) ;
/* Record mappings we need later for parsing features. */
source_data = g_new0(ZMapGFFSourceStruct, 1) ;
source_data->source_id = method_id ;
source_data->style_id = style_id ;
source_data->source_text = text_id ;
g_hash_table_insert(server->method_2_data, GINT_TO_POINTER(method_id), source_data) ;
}
else
{
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Feature Set \"%s\" : Method obj for feature set does not have a valid ZMap_style"
" so this feature set will be excluded.", name) ;
}
g_free(name) ;
g_free(zmap_style) ;
g_free(remark) ;
return result ;
}
/* The method string should be of the form:
*
* Method : "wublastx_briggsae"
* Remark "wublastx search of C. elegans genomic clones vs C. briggsae peptides"
* Colour LIGHTGREEN
* Frame_sensitive
* Show_up_strand
* etc
* Column_parent | Column_child
* Style
* <white space only lines>
* more methods....
*
* Only called if we are using zmap_styles. Parses the method and:
*
* if Column_child and _no_ Style tag found then the name of the child method
* is added to feature_methods_out and TRUE is returned.
*
* or if _no_ Column_XXX tags and a Style tag is found then the name of _this_ method
* is added to feature_methods_out and TRUE is returned.
*
* otherwise returns FALSE and logs the error.
*
* The function also returns a pointer to the blank line that ends the current
* method.
*
*/
static gboolean parseMethodColGroupNames(AcedbServer server, char *method_str_in,
char **end_pos, gpointer user_data)
{
gboolean result = TRUE ;
char *method_str = method_str_in ;
char *next_line = method_str ;
GetMethodsStyles get_sets = (GetMethodsStyles)user_data ;
GList *feature_sets, *method_list, *child_list = NULL ;
char *name = NULL, *column_parent = NULL, *column_child = NULL, *style = NULL, *remark = NULL ;
int obj_lines = 0 ; /* Used to detect empty objects. */
if (!g_str_has_prefix(method_str, "Method : "))
{
get_sets->error = TRUE ;
return FALSE ;
}
feature_sets = get_sets->feature_set_methods ;
method_list = get_sets->feature_methods ;
do
{
char *tag = NULL ;
char *line_pos = NULL ;
if (!(tag = strtok_r(next_line, "\t ", &line_pos)))
break ;
/* We don't formally test this but Method _MUST_ be the first line of the acedb output
* representing an object. */
if (g_ascii_strcasecmp(tag, "Method") == 0)
{
/* Line format: Method : "possibly long method name" */
name = strtok_r(NULL, "\"", &line_pos) ;
name = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, COL_PARENT) == 0)
{
/* Format for this tag: Column_parent "some_method_object" */
column_parent = strtok_r(NULL, "\"", &line_pos) ; /* Skip '"' */
column_parent = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, COL_CHILD) == 0)
{
/* Format for this tag: Column_child "some_method_object", keep a list of all
* children found. */
column_child = strtok_r(NULL, "\"", &line_pos) ; /* Skip '"' */
column_child = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
child_list = g_list_append(child_list, GINT_TO_POINTER(zMapStyleCreateID(column_child))) ;
g_free(column_child) ;
}
else if (g_ascii_strcasecmp(tag, STYLE) == 0)
{
/* Format for this tag: Style "some_style_object" */
style = strtok_r(NULL, "\"", &line_pos) ; /* Skip '"' */
style = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Remark") == 0)
{
/* Line format: Remark "possibly quite long bit of text" */
remark = strtok_r(NULL, "\"", &line_pos) ;
remark = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
}
while (++obj_lines && **end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
/* acedb can have empty objects which consist of a first line only. */
if (obj_lines == 1)
{
result = FALSE ;
get_sets->error = TRUE ;
}
if (!result)
{
/* If we failed while processing a method we won't have reached the end of the current
* method paragraph so we need to skip to the end so the next method can be processed. */
while (**end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
}
else
{
if (column_parent)
{
/* None of these methods should be true "child" methods, they should either be parent
* methods or feature set methods in their own right. */
result = FALSE ;
}
else
{
if ((child_list && !style) || (!child_list && style))
{
HashFeatureSetStruct hash_data = {0} ;
GQuark feature_set_id ;
feature_set_id = zMapStyleCreateID(name) ;
hash_data.feature_set_id = feature_set_id ;
hash_data.remark = remark ;
hash_data.method_2_feature_set = server->method_2_feature_set ;
/* Add this feature_set to valid list. */
feature_sets = g_list_append(feature_sets, GINT_TO_POINTER(feature_set_id)) ;
if (!child_list)
{
addMethodCB(GINT_TO_POINTER(zMapStyleCreateID(name)), &hash_data) ;
/* This has no children but has it's own features so add it to the feature
* method list. */
method_list = g_list_append(method_list, GINT_TO_POINTER(g_quark_from_string(name))) ;
}
else
{
g_list_foreach(child_list, addMethodCB, &hash_data) ;
/* Add all the child methods to the feature method list. */
method_list = g_list_concat(method_list, child_list) ; /* Subsumes child list, no
need to free. */
child_list = NULL ;
}
get_sets->feature_set_methods = feature_sets ;
get_sets->feature_methods = method_list ;
}
else
{
zMapLogWarning("Method \"%s\" ignored, Column Methods should either have " COL_CHILD
" or " STYLE " tags, not both.", name) ;
result = FALSE ;
}
}
}
if (child_list)
g_list_free(child_list) ;
g_free(name) ;
g_free(column_parent) ;
g_free(style) ;
return result ;
}
/* GFunc() to add child entries to our hash of methods to feature_sets. */
static void addMethodCB(gpointer data, gpointer user_data)
{
GQuark child_id = GPOINTER_TO_INT(data) ;
HashFeatureSet hash_data = (HashFeatureSet)user_data ;
ZMapGFFSet set_data ;
set_data = g_new0(ZMapGFFSetStruct, 1) ;
set_data->feature_set_id = hash_data->feature_set_id ;
set_data->description = hash_data->remark ;
g_hash_table_insert(hash_data->method_2_feature_set,
GINT_TO_POINTER(child_id),
set_data) ;
return ;
}
/* The method string should be of the form:
*
* Method : "wublastx_briggsae"
* Remark "wublastx search of C. elegans genomic clones vs C. briggsae peptides"
* Colour LIGHTGREEN
* Frame_sensitive
* Show_up_strand
* <white space only line>
* more methods....
*
* This parses the method using it to create a style struct which it returns.
* The function also returns a pointer to the blank line that ends the current
* method.
*
* If the method name is not in the list of methods in requested_types
* then NULL is returned. NOTE that this is not just dependent on comparing method
* name to the requested list we have to look in column group as well.
*
* Acedb had the concept of empty objects, these are objects whose name/class can
* be looked up but which do not have an instance in the database. The code will NOT
* produce styles for these objects.
*
* Acedb methods can also contain a "No_display" tag which says "do not display this
* object at all", if we find this tag we honour it. NOTE however that this can lead
* to error messages during zmap display if the feature_set erroneously tries to
* display features with this method.
*
*/
ZMapFeatureTypeStyle parseMethod(char *method_str_in,
char **end_pos, ZMapColGroupData *col_group_data_out)
{
ZMapFeatureTypeStyle style = NULL ;
char *method_str = method_str_in ;
char *next_line = method_str ;
char *name = NULL, *remark = NULL, *parent = NULL ;
char *colour = NULL, *cds_colour = NULL, *outline = NULL, *foreground = NULL, *background = NULL ;
char *gff_source = NULL, *gff_feature = NULL ;
char *column_group = NULL, *orig_style = NULL ;
ZMapStyleBumpMode default_bump_mode = ZMAPBUMP_OVERLAP, curr_bump_mode = ZMAPBUMP_UNBUMP ;
double width = -999.0 ; /* this is going to cause problems.... */
gboolean strand_specific = FALSE, show_up_strand = FALSE ;
ZMapStyle3FrameMode frame_mode = ZMAPSTYLE_3_FRAME_INVALID ;
ZMapStyleMode mode = ZMAPSTYLE_MODE_INVALID ;
gboolean displayable = TRUE ;
ZMapStyleColumnDisplayState col_state = ZMAPSTYLE_COLDISPLAY_INVALID ;
double min_mag = 0.0, max_mag = 0.0 ;
gboolean score_set = FALSE ;
double min_score = 0.0, max_score = 0.0 ;
gboolean score_by_histogram = FALSE ;
double histogram_baseline = 0.0 ;
gboolean status = TRUE, outline_flag = FALSE, directional_end = FALSE, gaps = FALSE, join_aligns = FALSE ;
gboolean deferred_flag = FALSE;
int obj_lines ;
int within_align_error = 0, between_align_error = 0 ;
if (!g_str_has_prefix(method_str, "Method : "))
return style ;
obj_lines = 0 ; /* Used to detect empty objects. */
do
{
char *tag = NULL ;
char *line_pos = NULL ;
if (!(tag = strtok_r(next_line, "\t ", &line_pos)))
break ;
/* We don't formally test this but Method _MUST_ be the first line of the acedb output
* representing an object. */
if (g_ascii_strcasecmp(tag, "Method") == 0)
{
/* Line format: Method : "possibly long method name" */
name = strtok_r(NULL, "\"", &line_pos) ;
name = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
if (g_ascii_strcasecmp(tag, "Remark") == 0)
{
/* Line format: Remark "possibly quite long bit of text" */
remark = strtok_r(NULL, "\"", &line_pos) ;
remark = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Colour") == 0)
{
char *tmp_colour ;
tmp_colour = strtok_r(NULL, " ", &line_pos) ;
/* Is colour one of the standard acedb colours ? It's really an acedb bug if it
* isn't.... */
if (!(colour = getAcedbColourSpec(tmp_colour)))
colour = tmp_colour ;
colour = g_strdup(colour) ;
}
else if (g_ascii_strcasecmp(tag, "ZMap_mode_text") == 0)
{
mode = ZMAPSTYLE_MODE_TEXT ;
}
else if (g_ascii_strcasecmp(tag, "ZMap_mode_basic") == 0)
{
mode = ZMAPSTYLE_MODE_BASIC ;
}
else if (g_ascii_strcasecmp(tag, "ZMap_mode_graph") == 0)
{
mode = ZMAPSTYLE_MODE_GRAPH ;
}
else if (g_ascii_strcasecmp(tag, "Deferred") == 0)
{
deferred_flag = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Immediate") == 0)
{
deferred_flag = FALSE ;
}
else if (g_ascii_strcasecmp(tag, "Outline") == 0)
{
outline_flag = TRUE;
}
else if (g_ascii_strcasecmp(tag, "CDS_colour") == 0)
{
char *tmp_colour ;
tmp_colour = strtok_r(NULL, " ", &line_pos) ;
/* Is colour one of the standard acedb colours ? It's really an acedb bug if it
* isn't.... */
if (!(cds_colour = getAcedbColourSpec(tmp_colour)))
cds_colour = tmp_colour ;
cds_colour = g_strdup(cds_colour) ;
}
/* The link between bump mode and what actually happens to the column is not straight
* forward in acedb, really it should be partly dependant on feature type.... */
else if (g_ascii_strcasecmp(tag, "Bump") == 0)
{
default_bump_mode = ZMAPBUMP_OVERLAP ;
curr_bump_mode = ZMAPBUMP_UNBUMP ;
}
else if (g_ascii_strcasecmp(tag, "Bumpable") == 0
|| g_ascii_strcasecmp(tag, "Cluster") == 0)
{
default_bump_mode = curr_bump_mode = ZMAPBUMP_NAME_BEST_ENDS ;
}
else if (g_ascii_strcasecmp(tag, "GFF_source") == 0)
{
gff_source = g_strdup(strtok_r(NULL, " \"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "GFF_feature") == 0)
{
gff_feature = g_strdup(strtok_r(NULL, " \"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Width") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &width)))
{
zMapLogWarning("No value for \"Width\" specified in method: %s", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Strand_sensitive") == 0)
strand_specific = TRUE ;
else if (g_ascii_strcasecmp(tag, "Show_up_strand") == 0)
show_up_strand = TRUE ;
else if (g_ascii_strcasecmp(tag, "Frame_sensitive") == 0)
frame_mode = ZMAPSTYLE_3_FRAME_ALWAYS ;
else if (g_ascii_strcasecmp(tag, "No_display") == 0)
{
/* Objects that have the No_display tag set should not be shown at all. */
displayable = FALSE ;
/* If No_display is the first tag in the models file we end
* up breaking here and obj_lines == 1 forcing status =
* FALSE later on. */
#ifdef CANT_BREAK_HERE
break ;
#endif
}
else if (g_ascii_strcasecmp(tag, "init_hidden") == 0)
{
col_state = ZMAPSTYLE_COLDISPLAY_HIDE ;
}
else if (g_ascii_strcasecmp(tag, "Directional_ends") == 0)
{
directional_end = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Gapped") == 0)
{
char *value ;
gaps = TRUE ;
if ((value = strtok_r(NULL, " ", &line_pos)))
{
if (!(status = zMapStr2Int(value, &within_align_error)))
{
zMapLogWarning("Bad value for \"Gapped\" align error specified in method: %s", name) ;
break ;
}
}
}
else if (g_ascii_strcasecmp(tag, "Join_aligns") == 0)
{
char *value ;
join_aligns = TRUE ;
if ((value = strtok_r(NULL, " ", &line_pos)))
{
if (!(status = zMapStr2Int(value, &between_align_error)))
{
zMapLogWarning("Bad value for \"Join_aligns\" align error specified in method: %s", name) ;
break ;
}
}
}
else if (g_ascii_strcasecmp(tag, "Min_mag") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &min_mag)))
{
zMapLogWarning("Bad value for \"Min_mag\" specified in method: %s", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Max_mag") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &max_mag)))
{
zMapLogWarning("Bad value for \"Max_mag\" specified in method: %s", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Score_by_histogram") == 0)
{
char *value ;
score_by_histogram = TRUE ;
if((value = strtok_r(NULL, " ", &line_pos)))
{
if (!(status = zMapStr2Double(value, &histogram_baseline)))
{
zMapLogWarning("Bad value for \"Score_by_histogram\" specified in method: %s", name) ;
break ;
}
}
}
else if (g_ascii_strcasecmp(tag, "Score_bounds") == 0)
{
char *value ;
score_set = TRUE ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &min_score)))
{
zMapLogWarning("Bad value for \"Score_bounds\" specified in method: %s", name) ;
score_set = FALSE ;
break ;
}
else
{
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &max_score)))
{
zMapLogWarning("Bad value for \"Score_bounds\" specified in method: %s", name) ;
score_set = FALSE ;
break ;
}
}
}
}
while (++obj_lines && **end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
/* acedb can have empty objects which consist of a first line only. */
if (obj_lines == 1)
{
status = FALSE ;
}
/* If we failed while processing a method we won't have reached the end of the current
* method paragraph so we need to skip to the end so the next method can be processed. */
if (!status)
{
while (**end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
}
/* Set some final method stuff and create the ZMap style. */
if (status)
{
/* NOTE that style is created with the method name, NOT the column_group, column
* names are independent of method names, they may or may not be the same.
* Also, there is no way of deriving the mode from the acedb method object
* currently, we have to set it later. */
style = zMapStyleCreate(name, remark) ;
if (mode != ZMAPSTYLE_MODE_INVALID)
zMapStyleSetMode(style, mode) ;
/* In acedb methods the colour is interpreted differently according to the type of the
* feature which we have to intuit here from the GFF type. acedb also has colour names
* that don't exist in X Windows. */
if (colour || cds_colour)
{
/* When it comes to colours acedb has some built in rules which we have to simulate,
* e.g. "Colour" when applied to transcripts means "outline", not "fill".
* */
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
/* THIS IS REALLY THE PLACE THAT WE SHOULD SET UP THE ACEDB SPECIFIC DISPLAY STUFF... */
/* this doesn't work because it messes up the rev. video.... */
if (gff_type && (g_ascii_strcasecmp(gff_type, "\"similarity\"") == 0
|| g_ascii_strcasecmp(gff_type, "\"repeat\"")
|| g_ascii_strcasecmp(gff_type, "\"experimental\"")))
background = colour ;
else
outline = colour ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
/* Set default acedb colours. */
background = colour ;
outline = "black" ;
/* If there's a cds then it must be a transcript which are shown in outline. */
if (cds_colour
|| g_ascii_strcasecmp(name, "coding_transcript") == 0)
{
outline = colour ;
background = NULL ;
}
if (colour)
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_NORMAL, ZMAPSTYLE_COLOURTYPE_NORMAL,
background, foreground, outline) ;
if (cds_colour)
{
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_CDS, ZMAPSTYLE_COLOURTYPE_NORMAL,
NULL, NULL, cds_colour) ;
g_free(cds_colour);
cds_colour = NULL;
}
}
if (width != -999.0)
{
/* acedb widths are wider on the screen than zmaps, so scale them up. */
width = width * ACEDB_MAG_FACTOR ;
zMapStyleSetWidth(style, width) ;
}
if (parent)
zMapStyleSetParent(style, parent) ;
if (min_mag || max_mag)
zMapStyleSetMag(style, min_mag, max_mag) ;
/* Note that we require bounds to be set for graphing.... */
if (score_set)
{
ZMapStyleGraphMode graph_mode = ZMAPSTYLE_GRAPH_HISTOGRAM ; /* Hard coded for now. */
if (score_by_histogram)
zMapStyleSetGraph(style, graph_mode, min_score, max_score, histogram_baseline) ;
else
zMapStyleSetScore(style, min_score, max_score) ;
}
if (strand_specific)
zMapStyleSetStrandSpecific(style, strand_specific) ;
if (show_up_strand)
zMapStyleSetStrandShowReverse(style, show_up_strand) ;
if (frame_mode)
zMapStyleSetFrameMode(style, frame_mode) ;
zMapStyleInitBumpMode(style, default_bump_mode, curr_bump_mode) ;
if (gff_source || gff_feature)
zMapStyleSetGFF(style, gff_source, gff_feature) ;
zMapStyleSetDisplayable(style, displayable) ;
zMapStyleSetDeferred(style, deferred_flag) ;
zMapStyleSetLoaded(style, FALSE) ;
if (col_state != ZMAPSTYLE_COLDISPLAY_INVALID)
zMapStyleSetDisplay(style, col_state) ;
if(directional_end)
zMapStyleSetEndStyle(style, directional_end);
/* Current setting is for gaps to be parsed but they will only
* be displayed when the feature is bumped. */
if (gaps)
zMapStyleSetGappedAligns(style, TRUE, within_align_error) ;
if (join_aligns)
zMapStyleSetJoinAligns(style, between_align_error) ;
}
/* Clean up, note g_free() does nothing if given NULL. */
g_free(name) ;
g_free(remark) ;
g_free(parent) ;
g_free(colour) ;
g_free(foreground) ;
g_free(column_group) ;
g_free(orig_style) ;
g_free(gff_source) ;
g_free(gff_feature) ;
return style ;
}
/* The style string should be of the form:
*
* ZMap_style : "Allele"
* Description "Alleles in WormBase represent small sequence mutations...etc"
* Colours Normal Fill "ORANGE"
* Width 1.100000
* Strand_sensitive
* GFF Source "Allele"
* GFF Feature "Allele"
* <white space only line>
* more styles....
*
* This parses the style using it to create a style struct which it returns.
* The function also returns a pointer to the blank line that ends the current
* style.
*
* If the style name is not in the list of styles in requested_types
* then NULL is returned. NOTE that this is not just dependent on comparing style
* name to the requested list we have to look in column group as well.
*
* Acedb had the concept of empty objects, these are objects whose name/class can
* be looked up but which do not have an instance in the database. The code will NOT
* produce styles for these objects.
*
* Acedb styles can also contain a "No_display" tag which says "do not display this
* object at all", if we find this tag we honour it. NOTE however that this can lead
* to error messages during zmap display if the feature_set erroneously tries to
* display features with this style.
*
*/
ZMapFeatureTypeStyle parseStyle(char *style_str_in,
char **end_pos, ZMapColGroupData *col_group_data_out)
{
ZMapFeatureTypeStyle style = NULL ;
gboolean status = TRUE ;
int obj_lines ;
char *style_str = style_str_in ;
char *next_line = style_str ;
char *name = NULL, *description = NULL, *parent = NULL,
*colour = NULL, *foreground = NULL,
*gff_source = NULL, *gff_feature = NULL,
*column_group = NULL, *orig_style = NULL ;
gboolean width_set = FALSE ;
gboolean deferred = FALSE ;
double width = 0.0 ;
gboolean strand_specific = FALSE, show_up_strand = FALSE ;
ZMapStyle3FrameMode frame_mode = ZMAPSTYLE_3_FRAME_INVALID ;
ZMapStyleMode mode = ZMAPSTYLE_MODE_INVALID ;
ZMapStyleGlyphMode glyph_mode = ZMAPSTYLE_GLYPH_INVALID ;
gboolean displayable_set = TRUE, displayable = TRUE,
show_when_empty_set = FALSE, show_when_empty = FALSE ;
ZMapStyleColumnDisplayState col_state = ZMAPSTYLE_COLDISPLAY_INVALID ;
double min_mag = 0.0, max_mag = 0.0 ;
gboolean directional_end_set = FALSE, directional_end = FALSE ;
gboolean internal = FALSE, external = FALSE, allow_misalign = FALSE ;
int within_align_error = 0, between_align_error = 0 ;
gboolean bump_mode_set = FALSE, bump_default_set = FALSE ;
ZMapStyleBumpMode default_bump_mode = ZMAPBUMP_INVALID, curr_bump_mode = ZMAPBUMP_INVALID ;
gboolean bump_spacing_set = FALSE ;
double bump_spacing = 0.0 ;
gboolean bump_fixed = FALSE ;
gboolean some_colours = FALSE ;
StyleFeatureColoursStruct style_colours = {{NULL}, {NULL}} ;
gboolean some_frame0_colours = FALSE, some_frame1_colours = FALSE, some_frame2_colours = FALSE ;
StyleFeatureColoursStruct frame0_style_colours = {{NULL}, {NULL}},
frame1_style_colours = {{NULL}, {NULL}}, frame2_style_colours = {{NULL}, {NULL}} ;
gboolean some_CDS_colours = FALSE ;
StyleFeatureColoursStruct CDS_style_colours = {{NULL}, {NULL}} ;
double min_score = 0.0, max_score = 0.0 ;
gboolean score_by_width, score_is_percent ;
gboolean histogram = FALSE ;
double histogram_baseline = 0.0 ;
gboolean pfetchable = FALSE ;
ZMapStyleBlixemType blixem_type = ZMAPSTYLE_BLIXEM_INVALID ;
if (g_ascii_strncasecmp(style_str, "ZMap_style : ", strlen("ZMap_style : ")) != 0)
return style ;
obj_lines = 0 ; /* Used to detect empty objects. */
do
{
char *tag = NULL ;
char *line_pos = NULL ;
if (!(tag = strtok_r(next_line, "\t ", &line_pos)))
break ;
/* We don't formally test this but Style _MUST_ be the first line of the acedb output
* representing an object. */
if (g_ascii_strcasecmp(tag, "ZMap_style") == 0)
{
/* Line format: ZMap_style : "possibly long style name" */
name = strtok_r(NULL, "\"", &line_pos) ;
name = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
if (g_ascii_strcasecmp(tag, "Description") == 0)
{
/* Line format: Description "possibly quite long bit of text" */
description = strtok_r(NULL, "\"", &line_pos) ;
description = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Style_parent") == 0)
{
parent = strtok_r(NULL, "\"", &line_pos) ;
parent = g_strdup(strtok_r(NULL, "\"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Deferred") == 0)
{
deferred = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Immediate") == 0)
{
deferred = FALSE ;
}
/* OK, THIS MODE STUFF IS NO GOOD, WE NEED TO USE THE STYLE CALL THAT WILL HAVE THE LATEST
* ENUMS BUILT IN OTHERWISE EVERYTIME WE ADD A NEW TYPE ALL THIS FAILS.... */
/* Grab the mode... */
else if (g_ascii_strcasecmp(tag, "Basic") == 0)
{
mode = ZMAPSTYLE_MODE_BASIC ;
}
else if (g_ascii_strcasecmp(tag, "Transcript") == 0)
{
char *tmp_next_tag ;
mode = ZMAPSTYLE_MODE_TRANSCRIPT ;
if ((tmp_next_tag = strtok_r(NULL, " ", &line_pos)))
{
if (g_ascii_strcasecmp(tmp_next_tag, "CDS_colour") == 0)
{
gboolean colour_parse ;
if ((colour_parse = getStyleColour(&CDS_style_colours, &line_pos)))
some_CDS_colours = TRUE ;
else
zMapLogWarning("Style \"%s\": Bad CDS colour spec: %s", name, next_line) ;
}
/* OTHER THINGS WILL NEED TO BE PARSED HERE AS WE EXPAND THIS.... */
}
}
else if (g_ascii_strcasecmp(tag, "Alignment") == 0)
{
char *align_type ;
char *value ;
mode = ZMAPSTYLE_MODE_ALIGNMENT ;
if ((align_type = strtok_r(NULL, " ", &line_pos)))
{
if (g_ascii_strcasecmp(align_type, "Internal") == 0)
internal = TRUE ;
else if (g_ascii_strcasecmp(align_type, "External") == 0)
external = TRUE ;
else if (g_ascii_strcasecmp(align_type, "Allow_misalign") == 0)
allow_misalign = TRUE ;
else if (g_ascii_strcasecmp(align_type, "Pfetchable") == 0)
pfetchable = TRUE ;
else if (g_ascii_strcasecmp(align_type, "Blixem_N") == 0)
blixem_type = ZMAPSTYLE_BLIXEM_N ;
else if (g_ascii_strcasecmp(align_type, "Blixem_X") == 0)
blixem_type = ZMAPSTYLE_BLIXEM_X ;
else
zMapLogWarning("Style \"%s\": Unknown tag \"%s\" for \"Alignment\" specified in style: %s",
name, align_type, name) ;
if (internal || external)
{
int *target ;
if (internal)
target = &within_align_error ;
else
target = &between_align_error ;
value = strtok_r(NULL, " ", &line_pos) ;
/* If no value is set then the error margin is set to 0 */
if (!value)
*target = 0 ;
else if (!(status = zMapStr2Int(value, target)))
{
zMapLogWarning("Style \"%s\": Bad error factor for \"Alignment %s\" specified in style: %s",
name, (internal ? "Internal" : "External"), name) ;
break ;
}
}
}
}
else if (g_ascii_strcasecmp(tag, "Sequence") == 0)
{
mode = ZMAPSTYLE_MODE_RAW_SEQUENCE ;
}
else if (g_ascii_strcasecmp(tag, "Peptide") == 0)
{
mode = ZMAPSTYLE_MODE_PEP_SEQUENCE ;
}
else if (g_ascii_strcasecmp(tag, "Assembly_path") == 0)
{
mode = ZMAPSTYLE_MODE_ASSEMBLY_PATH ;
}
else if (g_ascii_strcasecmp(tag, "Plain_text") == 0)
{
mode = ZMAPSTYLE_MODE_TEXT ;
}
else if (g_ascii_strcasecmp(tag, "Graph") == 0)
{
char *tmp_next_tag ;
mode = ZMAPSTYLE_MODE_GRAPH ;
tmp_next_tag = strtok_r(NULL, " ", &line_pos) ;
if (g_ascii_strcasecmp(tmp_next_tag, "Histogram") == 0)
{
histogram = TRUE ;
}
else if (g_ascii_strcasecmp(tmp_next_tag, "Baseline") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &histogram_baseline)))
{
zMapLogWarning("Style \"%s\": No value for \"Baseline\".", name) ;
break ;
}
}
}
else if (g_ascii_strcasecmp(tag, "Glyph") == 0)
{
char *tmp_next_tag ;
mode = ZMAPSTYLE_MODE_GLYPH ;
tmp_next_tag = strtok_r(NULL, " ", &line_pos) ;
if (tmp_next_tag && g_ascii_strcasecmp(tmp_next_tag, "Splice") == 0)
{
glyph_mode = ZMAPSTYLE_GLYPH_SPLICE ;
}
}
else if (g_ascii_strcasecmp(tag, "Colours") == 0)
{
gboolean colour_parse ;
if ((colour_parse = getStyleColour(&style_colours, &line_pos)))
some_colours = TRUE ;
else
zMapLogWarning("Style \"%s\": Bad colour spec: %s", name, next_line) ;
}
else if (g_ascii_strcasecmp(tag, "Frame_0") == 0
|| g_ascii_strcasecmp(tag, "Frame_1") == 0
|| g_ascii_strcasecmp(tag, "Frame_2") == 0)
{
StyleFeatureColours colours = NULL ;
gboolean *set = NULL ;
if (g_ascii_strcasecmp(tag, "Frame_0") == 0)
{
colours = &frame0_style_colours ;
set = &some_frame0_colours ;
}
else if (g_ascii_strcasecmp(tag, "Frame_1") == 0)
{
colours = &frame1_style_colours ;
set = &some_frame1_colours ;
}
else if (g_ascii_strcasecmp(tag, "Frame_2") == 0)
{
colours = &frame2_style_colours ;
set = &some_frame2_colours ;
}
if (!colours)
{
zMapLogWarning("Style \"%s\": Bad Frame name: %s", name, next_line) ;
}
else
{
gboolean colour_parse ;
if ((colour_parse = getStyleColour(colours, &line_pos)))
*set = TRUE ;
else
zMapLogWarning("Style \"%s\": Bad colour spec: %s", name, next_line) ;
}
}
/* Bumping types */
else if (g_ascii_strcasecmp(tag, "Bump_initial") == 0 || g_ascii_strcasecmp(tag, "Bump_default") == 0)
{
char *tmp_next_tag ;
ZMapStyleBumpMode *tmp_bump ;
if (g_ascii_strcasecmp(tag, "Bump_initial") == 0)
{
tmp_bump = &curr_bump_mode ;
bump_mode_set = TRUE ;
}
else
{
tmp_bump = &default_bump_mode ;
bump_default_set = TRUE ;
}
tmp_next_tag = strtok_r(NULL, " ", &line_pos) ;
if (g_ascii_strcasecmp(tmp_next_tag, "Unbump") == 0)
*tmp_bump = ZMAPBUMP_UNBUMP ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Overlap") == 0)
*tmp_bump = ZMAPBUMP_OVERLAP ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Navigator") == 0)
*tmp_bump = ZMAPBUMP_NAVIGATOR ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Start_position") == 0)
*tmp_bump = ZMAPBUMP_START_POSITION ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Alternating") == 0)
*tmp_bump = ZMAPBUMP_ALTERNATING ;
else if (g_ascii_strcasecmp(tmp_next_tag, "All") == 0)
*tmp_bump = ZMAPBUMP_ALL ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Name") == 0)
*tmp_bump = ZMAPBUMP_NAME ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Name_interleave") == 0)
*tmp_bump = ZMAPBUMP_NAME_INTERLEAVE ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Name_no_interleave") == 0)
*tmp_bump = ZMAPBUMP_NAME_NO_INTERLEAVE ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Name_colinear") == 0)
*tmp_bump = ZMAPBUMP_NAME_COLINEAR ;
else if (g_ascii_strcasecmp(tmp_next_tag, "Name_best_ends") == 0)
*tmp_bump = ZMAPBUMP_NAME_BEST_ENDS ;
else
zMapLogWarning("Style \"%s\": Bad bump spec: %d", name, *tmp_bump) ;
}
else if (g_ascii_strcasecmp(tag, "Bump_spacing") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if ((status = zMapStr2Double(value, &bump_spacing)))
{
bump_spacing_set = TRUE ;
}
else
{
zMapLogWarning("Style \"%s\": No value for \"Bump_spacing\".", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Bump_fixed") == 0)
{
bump_fixed = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "GFF") == 0)
{
char *gff_type ;
gff_type = strtok_r(NULL, " ", &line_pos) ;
if (g_ascii_strcasecmp(tag, "Source") == 0)
gff_source = g_strdup(strtok_r(NULL, " \"", &line_pos)) ;
else if (g_ascii_strcasecmp(tag, "Feature") == 0)
gff_feature = g_strdup(strtok_r(NULL, " \"", &line_pos)) ;
}
else if (g_ascii_strcasecmp(tag, "Width") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if ((status = zMapStr2Double(value, &width)))
{
width_set = TRUE ;
}
else
{
zMapLogWarning("Style \"%s\": No value for \"Width\".", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Strand_sensitive") == 0)
strand_specific = TRUE ;
else if (g_ascii_strcasecmp(tag, "Show_up_strand") == 0)
show_up_strand = TRUE ;
else if (g_ascii_strcasecmp(tag, "Frame_sensitive") == 0)
frame_mode = ZMAPSTYLE_3_FRAME_ALWAYS ;
else if (g_ascii_strcasecmp(tag, "Show_only_as_3_frame") == 0)
frame_mode = ZMAPSTYLE_3_FRAME_ONLY_3 ;
else if (g_ascii_strcasecmp(tag, "Show_only_as_1_column") == 0)
frame_mode = ZMAPSTYLE_3_FRAME_ONLY_1 ;
else if (g_ascii_strcasecmp(tag, "Not_displayable") == 0)
{
/* Objects that have the Not_displayable tag set should not be shown at all. */
displayable_set = displayable = FALSE ;
break ;
}
else if (g_ascii_strcasecmp(tag, "Hide") == 0)
{
col_state = ZMAPSTYLE_COLDISPLAY_HIDE ;
}
else if (g_ascii_strcasecmp(tag, "Show_when_empty") == 0)
{
show_when_empty_set = show_when_empty = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Directional_ends") == 0)
{
directional_end_set = directional_end = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Min_mag") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &min_mag)))
{
zMapLogWarning("Style \"%s\": Bad value for \"Min_mag\"", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Max_mag") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &max_mag)))
{
zMapLogWarning("Style \"%s\": Bad value for \"Max_mag\".", name) ;
break ;
}
}
else if (g_ascii_strcasecmp(tag, "Score_by_width") == 0)
{
score_by_width = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Score_percent") == 0)
{
score_is_percent = TRUE ;
}
else if (g_ascii_strcasecmp(tag, "Score_bounds") == 0)
{
char *value ;
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &min_score)))
{
zMapLogWarning("Style \"%s\": Bad value for \"Score_bounds\".", name) ;
break ;
}
else
{
value = strtok_r(NULL, " ", &line_pos) ;
if (!(status = zMapStr2Double(value, &max_score)))
{
zMapLogWarning("Style \"%s\": Bad value for \"Score_bounds\".", name) ;
break ;
}
}
}
}
while (++obj_lines && **end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
/* acedb can have empty objects which consist of a first line only. */
if (obj_lines == 1)
{
status = FALSE ;
}
/* If we failed while processing a style we won't have reached the end of the current
* style paragraph so we need to skip to the end so the next style can be processed. */
if (!status)
{
while (**end_pos != '\n' && (next_line = strtok_r(NULL, "\n", end_pos))) ;
}
/* Create the style and add all the bits to it. */
if (status)
{
/* NOTE that style is created with the style name, NOT the column_group, column
* names are independent of style names, they may or may not be the same.
* Also, there is no way of deriving the mode from the acedb style object
* currently, we have to set it later. */
style = zMapStyleCreate(name, description) ;
if (mode != ZMAPSTYLE_MODE_INVALID)
zMapStyleSetMode(style, mode) ;
if (glyph_mode != ZMAPSTYLE_GLYPH_INVALID)
zMapStyleSetGlyphMode(style, glyph_mode) ;
if (parent)
zMapStyleSetParent(style, parent) ;
if (deferred)
zMapStyleSetDeferred(style, deferred) ;
if (some_colours)
{
/* May need to put some checking code here to test which colours set. */
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_NORMAL, ZMAPSTYLE_COLOURTYPE_NORMAL,
style_colours.normal.fill, style_colours.normal.draw, style_colours.normal.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_NORMAL, ZMAPSTYLE_COLOURTYPE_SELECTED,
style_colours.selected.fill, style_colours.selected.draw, style_colours.selected.border) ;
}
if (some_frame0_colours || some_frame1_colours || some_frame2_colours)
{
if (some_frame0_colours && some_frame1_colours && some_frame2_colours)
{
/* May need to put some checking code here to test which colours set. */
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME0, ZMAPSTYLE_COLOURTYPE_NORMAL,
frame0_style_colours.normal.fill, frame0_style_colours.normal.draw, frame0_style_colours.normal.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME0, ZMAPSTYLE_COLOURTYPE_SELECTED,
frame0_style_colours.selected.fill, frame0_style_colours.selected.draw, frame0_style_colours.selected.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME1, ZMAPSTYLE_COLOURTYPE_NORMAL,
frame1_style_colours.normal.fill, frame1_style_colours.normal.draw, frame1_style_colours.normal.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME1, ZMAPSTYLE_COLOURTYPE_SELECTED,
frame1_style_colours.selected.fill, frame1_style_colours.selected.draw, frame1_style_colours.selected.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME2, ZMAPSTYLE_COLOURTYPE_NORMAL,
frame2_style_colours.normal.fill, frame2_style_colours.normal.draw, frame2_style_colours.normal.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_FRAME2, ZMAPSTYLE_COLOURTYPE_SELECTED,
frame2_style_colours.selected.fill, frame2_style_colours.selected.draw, frame2_style_colours.selected.border) ;
}
else
zMapLogWarning("Style \"%s\": Bad frame colour spec, following were not set:%s%s%s", name,
(some_frame0_colours ? "" : " frame0"),
(some_frame1_colours ? "" : " frame1"),
(some_frame2_colours ? "" : " frame2")) ;
}
if (some_CDS_colours)
{
/* May need to put some checking code here to test which colours set. */
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_CDS, ZMAPSTYLE_COLOURTYPE_NORMAL,
CDS_style_colours.normal.fill, CDS_style_colours.normal.draw, CDS_style_colours.normal.border) ;
zMapStyleSetColours(style, ZMAPSTYLE_COLOURTARGET_CDS, ZMAPSTYLE_COLOURTYPE_SELECTED,
CDS_style_colours.selected.fill, CDS_style_colours.selected.draw, CDS_style_colours.selected.border) ;
}
if (width_set)
zMapStyleSetWidth(style, width) ;
if (min_mag || max_mag)
zMapStyleSetMag(style, min_mag, max_mag) ;
/* OTHER SCORE STUFF MUST BE SET HERE.... */
if (min_score && max_score)
zMapStyleSetScore(style, min_score, max_score) ;
if (strand_specific)
zMapStyleSetStrandSpecific(style, strand_specific) ;
if (show_up_strand)
zMapStyleSetStrandShowReverse(style, show_up_strand) ;
if (frame_mode)
zMapStyleSetFrameMode(style, frame_mode) ;
if (bump_mode_set || bump_default_set)
zMapStyleInitBumpMode(style, default_bump_mode, curr_bump_mode) ;
if (bump_spacing_set)
zMapStyleSetBumpSpace(style, bump_spacing) ;
if (bump_fixed)
zMapStyleSet(style,
ZMAPSTYLE_PROPERTY_BUMP_FIXED, bump_fixed,
NULL) ;
if (gff_source || gff_feature)
zMapStyleSetGFF(style, gff_source, gff_feature) ;
if (displayable_set)
zMapStyleSetDisplayable(style, displayable) ;
if (col_state != ZMAPSTYLE_COLDISPLAY_INVALID)
zMapStyleSetDisplay(style, col_state) ;
if (show_when_empty_set)
zMapStyleSetShowWhenEmpty(style, show_when_empty) ;
if(directional_end_set)
zMapStyleSetEndStyle(style, directional_end);
if (internal)
zMapStyleSetGappedAligns(style, TRUE, within_align_error) ;
if (external)
zMapStyleSetJoinAligns(style, between_align_error) ;
if (pfetchable)
zMapStyleSetPfetch(style, pfetchable) ;
/* Should be building the list dynamically.....could do this on the create step using
* my zMapStyleCreateV() function. */
if (blixem_type)
zMapStyleSet(style,
ZMAPSTYLE_PROPERTY_ALIGNMENT_BLIXEM, blixem_type,
ZMAPSTYLE_PROPERTY_ALIGNMENT_ALLOW_MISALIGN, allow_misalign,
NULL) ;
}
/* Clean up, note g_free() does nothing if given NULL. */
g_free(name) ;
g_free(description) ;
g_free(colour) ;
g_free(foreground) ;
g_free(column_group) ;
g_free(orig_style) ;
g_free(gff_source) ;
g_free(gff_feature) ;
return style ;
}
/* Gets a list of all styles by name on the server (this is the list of acedb methods/styles).
* Returns TRUE and the list if database contained any methods, FALSE otherwise.
*
*
* acedb> list
*
* KeySet : Answer_1
* Method:
* cDNA_for_RNAi
* code default
* Coding
* Coding_transcript
* Coil
* curated
*
*
* // 6 object listed
* // 6 Active Objects
* acedb>
*
* */
static ZMapServerResponseType getObjNames(AcedbServer server, GList **style_names_out)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
char *command ;
char *acedb_request = NULL ;
void *reply = NULL ;
int reply_len = 0 ;
/* List all the methods in the current keyset on the serve. */
command = "list" ;
acedb_request = g_strdup_printf("%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request,
&reply, &reply_len)) == ACECONN_OK)
{
char *scan_text = (char *)reply ;
char *next_line = NULL ;
gboolean found_method = FALSE ;
GList *style_names = NULL ;
while ((next_line = strtok(scan_text, "\n")))
{
scan_text = NULL ;
/* Look for start/end of methods list. */
if (!found_method && g_str_has_prefix(next_line, "Method:"))
{
found_method = TRUE ;
continue ;
}
else if (found_method && (*next_line == '/'))
break ;
if (found_method)
{
/* Watch out...hacky...method names have a space in front of them...sigh... */
style_names = g_list_append(style_names,
GINT_TO_POINTER(g_quark_from_string(next_line + 1))) ;
}
}
if (style_names)
{
*style_names_out = style_names ;
result = ZMAP_SERVERRESPONSE_OK ;
}
else
{
setErrMsg(server, g_strdup_printf("No styles found.")) ;
result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
g_free(reply) ;
reply = NULL ;
}
else
result = server->last_err_status ;
g_free(acedb_request) ;
return result ;
}
/* GCompareDataFunc () used to resort our list of styles to match users original sorting. */
gint resortStyles(gconstpointer a, gconstpointer b, gpointer user_data)
{
gint result = 0 ;
ZMapFeatureTypeStyle style_a = (ZMapFeatureTypeStyle)a, style_b = (ZMapFeatureTypeStyle)b ;
GList *style_list = (GList *)user_data ;
gint pos_a, pos_b ;
pos_a = g_list_index(style_list, GUINT_TO_POINTER(zMapStyleGetUniqueID(style_a))) ;
pos_b = g_list_index(style_list, GUINT_TO_POINTER(zMapStyleGetUniqueID(style_b))) ;
zMapAssert(pos_a >= 0 && pos_b >= 0 && pos_a != pos_b) ;
if (pos_a < pos_b)
result = -1 ;
else
result = 1 ;
return result ;
}
/* Parses the string returned by an acedb "find" command, if the command found objects
* it returns a string of the form:
* "// Found 1 objects in this class"
*/
int getFoundObj(char *text)
{
int num_obj = 0 ;
if (strstr(text, "Found"))
{
char *next ;
next = strtok(text, " ") ;
next = strtok(NULL, " ") ;
next = strtok(NULL, " ") ;
num_obj = atoi(next) ;
}
return num_obj ;
}
/* Process all the alignments in a context. */
static void eachAlignment(gpointer key, gpointer data, gpointer user_data)
{
ZMapFeatureAlignment alignment = (ZMapFeatureAlignment)data ;
DoAllAlignBlocks all_data = (DoAllAlignBlocks)user_data ;
if (all_data->result == ZMAP_SERVERRESPONSE_OK && all_data->eachBlock)
g_hash_table_foreach(alignment->blocks, all_data->eachBlock, (gpointer)all_data) ;
return ;
}
static void eachBlockSequenceRequest(gpointer key_id, gpointer data, gpointer user_data)
{
ZMapFeatureBlock feature_block = (ZMapFeatureBlock)data ;
DoAllAlignBlocks get_features = (DoAllAlignBlocks)user_data ;
if (get_features->result == ZMAP_SERVERRESPONSE_OK)
{
if (!sequenceRequest(get_features->server, get_features->styles, feature_block))
{
/* If the call failed it may be that the connection failed or that the data coming
* back had a problem. */
if (get_features->server->last_err_status == ACECONN_OK)
{
get_features->result = ZMAP_SERVERRESPONSE_REQFAIL ;
}
else if (get_features->server->last_err_status == ACECONN_TIMEDOUT)
{
get_features->result = ZMAP_SERVERRESPONSE_TIMEDOUT ;
}
else
{
/* Probably we will want to analyse the response more than this ! */
get_features->result = ZMAP_SERVERRESPONSE_SERVERDIED ;
}
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, get_features->server->host,
"Could not map %s because: %s",
g_quark_to_string(get_features->server->req_context->sequence_name),
get_features->server->last_err_msg) ;
}
}
return ;
}
/* This table is derived from acedb/w2/graphcolour.c, since acedb colours have not changed
* in a long time it is unlikely to need updating very often.
*
* The reason for having this function is that acedb colour names do not ALL match the standard
* colour names in the X11 colour database and so cannot be used as input to the gdk colour
* functions. I tried to use a proper Xcms colour spec but stupid gdk_color_parse() does
* not understand these colours so have used the now deprecated "#RRGGBB" format below.
* */
static char *getAcedbColourSpec(char *acedb_colour_name)
{
char *colour_spec = NULL ;
static AcedbColourSpecStruct colours[] =
{
{"WHITE", "#ffffff"},
{"BLACK", "#000000"},
{"LIGHTGRAY", "#c8c8c8"},
{"DARKGRAY", "#646464"},
{"RED", "#ff0000"},
{"GREEN", "#00ff00"},
{"BLUE", "#0000ff"},
{"YELLOW", "#ffff00"},
{"CYAN", "#00ffff"},
{"MAGENTA", "#ff00ff"},
{"LIGHTRED", "#ffa0a0"},
{"LIGHTGREEN", "#a0ffa0"},
{"LIGHTBLUE", "#a0c8ff"},
{"DARKRED", "#af0000"},
{"DARKGREEN", "#00af00"},
{"DARKBLUE", "#0000af"},
{"PALERED", "#ffe6d2"},
{"PALEGREEN", "#d2ffd2"},
{"PALEBLUE", "#d2ebff"},
{"PALEYELLOW", "#ffffc8"},
{"PALECYAN", "#c8ffff"},
{"PALEMAGENTA", "#ffc8ff"},
{"BROWN", "#a05000"},
{"ORANGE", "#ff8000"},
{"PALEORANGE", "#ffdc6e"},
{"PURPLE", "#c000ff"},
{"VIOLET", "#c8aaff"},
{"PALEVIOLET", "#ebd7ff"},
{"GRAY", "#969696"},
{"PALEGRAY", "#ebebeb"},
{"CERISE", "#ff0080"},
{"MIDBLUE", "#56b2de"},
} ;
AcedbColourSpec colour ;
colour = &(colours[0]) ;
while (colour->name)
{
if (g_ascii_strcasecmp(colour->name, acedb_colour_name) == 0)
{
colour_spec = colour->spec ;
break ;
}
colour++ ;
}
return colour_spec ;
}
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
static void stylePrintCB(gpointer data, gpointer user_data)
{
ZMapFeatureTypeStyle style = (ZMapFeatureTypeStyle)data ;
printf("%s (%s)\n", g_quark_to_string(zMapStyleGetID(style)),
g_quark_to_string(zMapStyleGetUniqueID(style))) ;
return ;
}
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
static gboolean getStyleColour(StyleFeatureColours style_colours, char **line_pos)
{
gboolean result = FALSE ;
char *colour_type ;
char *colour_target ;
char *colour ;
StyleColour style_colour = NULL ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
if ((colour_type = strtok_r(NULL, " ", line_pos))
&& (colour_target = strtok_r(NULL, " ", line_pos))
&& (colour = strtok_r(NULL, "\"", line_pos))
&& (colour = strtok_r(NULL, "\"", line_pos)))
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
colour_type = strtok_r(NULL, " ", line_pos) ;
colour_target = strtok_r(NULL, " ", line_pos) ;
colour = strtok_r(NULL, "\"", line_pos) ;
#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
colour = strtok_r(NULL, "\"", line_pos) ;
#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
if (colour)
{
if (g_ascii_strcasecmp(colour_type, "Normal") == 0)
style_colour = &(style_colours->normal) ;
else if (g_ascii_strcasecmp(colour_type, "Selected") == 0)
style_colour = &(style_colours->selected) ;
if (style_colour)
{
result = TRUE ;
if (g_ascii_strcasecmp(colour_target, "Draw") == 0)
style_colour->draw = g_strdup(colour) ;
else if (g_ascii_strcasecmp(colour_target, "Fill") == 0)
style_colour->fill = g_strdup(colour) ;
else if (g_ascii_strcasecmp(colour_target, "Border") == 0)
style_colour->border = g_strdup(colour) ;
else
result = FALSE ;
}
}
return result ;
}
/* For each sequence makes a request to find the sequence and then to dump its dna:
*
* acedb> find sequence RDS00121111
* <blank line>
* // Found 1 objects in this class
* acedb> dna -u
* gactctttgcaggggagaagctccacaacctcagcaaa....etc etc
* acedb>
*
*
* Function returns ZMAP_SERVERRESPONSE_OK if sequences were found and retrieved,
* ZMAP_SERVERRESPONSE_REQFAIL otherwise.
*
* */
static ZMapServerResponseType doGetSequences(AcedbServer server, GList *sequences_inout)
{
ZMapServerResponseType result = ZMAP_SERVERRESPONSE_REQFAIL ;
GList *next_seq ;
GString *acedb_request = NULL ;
acedb_request = g_string_new(NULL) ;
/* We need to loop round finding each sequence and then fetching its dna... */
next_seq = sequences_inout ;
while (next_seq)
{
char *command ;
void *reply = NULL ;
int reply_len = 0 ;
ZMapSequence sequence = (ZMapSequence)(next_seq->data) ;
/* Try to find the sequence... */
command = "find sequence" ;
g_string_printf(acedb_request, "%s %s", command, g_quark_to_string(sequence->name)) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request->str,
&reply, &reply_len)) == ACECONN_OK)
{
/* reply should be:
*
* <blank line>
* // Found 1 objects in this class
* // 1 Active Objects
*/
char *scan_text = (char *)reply ;
char *next_line = NULL ;
int num_objs ;
while ((next_line = strtok(scan_text, "\n")))
{
scan_text = NULL ;
if (g_str_has_prefix(next_line, "// "))
{
num_objs = getFoundObj(next_line) ;
if (num_objs == 1)
result = ZMAP_SERVERRESPONSE_OK ;
else
setErrMsg(server, g_strdup_printf("Expected to find 1 sequence object"
"named \"%s\" but found %d.",
g_quark_to_string(sequence->name), num_objs)) ;
break ;
}
}
g_free(reply) ;
reply = NULL ;
}
/* All ok ? Then get the dna.... */
if (server->last_err_status == ZMAP_SERVERRESPONSE_OK)
{
command = "dna -u" ;
g_string_printf(acedb_request, "%s", command) ;
if ((server->last_err_status = AceConnRequest(server->connection, acedb_request->str,
&reply, &reply_len)) == ACECONN_OK)
{
/* reply should be:
*
* gactctttgcaggggagaagctccacaacctcagcaaa....etc etc
*/
sequence->length = reply_len - 1 ;
sequence->sequence = reply ;
}
}
next_seq = g_list_next(next_seq) ;
}
g_string_free(acedb_request, TRUE) ;
return result ;
}
/* Checks that each name in query_names_inout can be found in reference_names, if a name
* is not found then it is removed from query_names_inout (i.e. query_names_inout could be
* NULL on return).
*
* Returns the number of names missing.
*
* Note function assumes names occur only once in each list.
*/
static int equaliseLists(AcedbServer server, GList **query_names_inout, GList *reference_names,
char *query_name, char *reference_name)
{
int num_found = 0 ;
int num_query ;
GString *missing ;
GList *curr ;
GList *query_names ;
query_names = *query_names_inout ;
num_query = g_list_length(query_names) ;
missing = g_string_sized_new(1000) ;
/* Must loop round by steam because we are removing links. */
curr = query_names ;
do
{
if ((g_list_find_custom(reference_names, curr->data, quarkCaseCmp)))
{
curr = curr->next ;
num_found++ ;
}
else
{
GList *tmp ;
g_string_append_printf(missing, " \"%s\"", g_quark_to_string(GPOINTER_TO_INT(curr->data))) ;
tmp = curr->next ; /* Best move on before removing link. */
query_names = g_list_delete_link(query_names, curr) ;
curr = tmp ;
}
} while (curr) ;
/* Log any missing methods. */
if (!num_found)
{
ZMAPSERVER_LOG(Critical, ACEDB_PROTOCOL_STR, server->host,
"Complete %s -> %s mismatch, %d %s specified but none found in %s list. Missing %s were: %s",
query_name, reference_name, num_query, query_name, reference_name,
query_name, missing->str) ;
}
else if (num_found < num_query)
{
ZMAPSERVER_LOG(Warning, ACEDB_PROTOCOL_STR, server->host,
"Partial %s -> %s mismatch, %d %s specified but only %d found in %s list. Missing %s were: %s",
query_name, reference_name, num_query, query_name, num_found, reference_name,
query_name, missing->str) ;
}
g_string_free(missing, TRUE) ;
/* Return the names list. */
*query_names_inout = query_names ;
return num_found ;
}
/* A GCompareFunc() to compare names in a case independent way in two lists of GQuarks. */
static gint quarkCaseCmp(gconstpointer a, gconstpointer b)
{
gint result ;
result = g_ascii_strcasecmp(g_quark_to_string(GPOINTER_TO_INT(a)), g_quark_to_string(GPOINTER_TO_INT(b))) ;
return result ;
}
/* It's possible for us to have reported an error and then another error to come along. */
static void setErrMsg(AcedbServer server, char *new_msg)
{
if (server->last_err_msg)
g_free(server->last_err_msg) ;
server->last_err_msg = new_msg ;
return ;
}
/* Reset status/err_msg, needs doing before each command otherwise we can end up seeing the wrong
* message. */
static void resetErr(AcedbServer server)
{
if (server->last_err_msg)
{
g_free(server->last_err_msg) ;
server->last_err_msg = NULL ;
}
server->last_err_status = ACECONN_OK ;
return ;
}
static char *get_url_query_value(char *full_query, char *key)
{
char *value = NULL,
**split = NULL,
**ptr = NULL ;
if(full_query != NULL)
{
split = ptr = g_strsplit(full_query, "&", 0);
while(ptr && *ptr != '\0')
{
char **key_value = NULL, **kv_ptr;
key_value = kv_ptr = g_strsplit(*ptr, "=", 0);
if(key_value[0] && (g_ascii_strcasecmp(key, key_value[0]) == 0))
value = g_strdup(key_value[1]);
g_strfreev(kv_ptr);
ptr++;
}
g_strfreev(split);
}
return value;
}
static gboolean get_url_query_boolean(char *full_query, char *key)
{
gboolean result = FALSE;
char *value = NULL;
if((value = get_url_query_value(full_query, key)))
{
if(g_ascii_strcasecmp("true", value) == 0)
result = TRUE;
g_free(value);
}
return result;
}
/* A GDestroyNotify() to free the method data structs in the method_2_data hash table. */
static void freeDataCB(gpointer data)
{
ZMapGFFSet set_data = (ZMapGFFSet)data ;
g_free(set_data) ;
return ;
}
/* A GDestroyNotify() to free the method data structs in the method_2_data hash table. */
static void freeSetCB(gpointer data)
{
ZMapGFFSource source_data = (ZMapGFFSource)data ;
g_free(source_data) ;
return ;
}