ARB
adChangeKey.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : adChangeKey.cxx //
4 // Purpose : Changekey management //
5 // //
6 // Coded by Elmar Pruesse and Ralf Westram in May 2009 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =============================================================== //
11 
12 #include <arbdbt.h>
13 #include <arb_global_defs.h>
14 #include "gb_local.h"
15 
16 GBDATA *GBT_get_changekey(GBDATA *gb_main, const char *key, const char *change_key_path) {
17  // get the container of an item key description
18 
19  // @@@ check if search for CHANGEKEY_NAME should be case-sensitive!
20  GBDATA *gb_key = NULp;
21  GBDATA *gb_key_data = GB_search(gb_main, change_key_path,
23 
24  if (gb_key_data) {
25  GBDATA *gb_key_name = GB_find_string(gb_key_data, CHANGEKEY_NAME, key, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
26  if (gb_key_name) {
27  gb_key = GB_get_father(gb_key_name);
28  }
29  }
30  return gb_key;
31 }
32 
33 GB_TYPES GBT_get_type_of_changekey(GBDATA *gb_main, const char *field_name, const char *change_key_path) {
34  // get the type of an item key
36  GBDATA *gbd = GBT_get_changekey(gb_main, field_name, change_key_path);
37 
38  if (gbd) {
39  long *typePtr = GBT_read_int(gbd, CHANGEKEY_TYPE);
40  if (typePtr) {
41  type = (GB_TYPES)*typePtr;
42  }
43  }
44 
45  return type;
46 }
47 
48 static GB_ERROR gbt_set_type_of_changekey(GBDATA *gb_main, const char *field_name, GB_TYPES type, const char *change_key_path) {
50  GBDATA *gbd = GBT_get_changekey(gb_main, field_name, change_key_path);
51 
52  if (!gbd) {
53  error = GBS_global_string("Can't set type of nonexistent changekey \"%s\"", field_name);
54  }
55  else {
56  error = GBT_write_int(gbd, CHANGEKEY_TYPE, type);
57  }
58  return error;
59 }
60 
61 GBDATA *GBT_searchOrCreate_itemfield_according_to_changekey(GBDATA *gb_item, const char *field_name, const char *change_key_path) {
69  GBDATA *gb_entry = GB_search(gb_item, field_name, GB_FIND);
70  if (!gb_entry) {
72 
73  GB_TYPES type = GBT_get_type_of_changekey(GB_get_root(gb_item), field_name, change_key_path);
74  if (type == GB_NONE) {
75  GB_export_errorf("Cannot create field '%s' (no type information available)", field_name);
76  }
77  else {
78  gb_entry = GB_search(gb_item, field_name, type);
79  }
80  }
81  gb_assert(gb_entry || GB_have_error());
82  return gb_entry;
83 }
84 
85 
86 GB_ERROR GBT_add_new_changekey_to_keypath(GBDATA *gb_main, const char *name, GB_TYPES type, const char *keypath) {
95  GBDATA *gb_key = GBT_get_changekey(gb_main, name, keypath);
96  const char *c = GB_first_non_key_char(name);
97 
98  if (c) {
99  char *new_name = ARB_strdup(name);
100 
101  *(char*)GB_first_non_key_char(new_name) = 0;
102 
103  if (*c == '/') error = GBT_add_new_changekey_to_keypath(gb_main, new_name, GB_DB, keypath);
104  else error = GBS_global_string("Cannot add '%s' to your key list (illegal character '%c')", name, *c);
105 
106  free(new_name);
107  }
108 
109  if (!error) {
110  if (!gb_key) { // create new key
111  GBDATA *gb_key_data = GB_search(gb_main, keypath, GB_CREATE_CONTAINER);
112  gb_key = gb_key_data ? GB_create_container(gb_key_data, CHANGEKEY) : NULp;
113 
114  if (!gb_key) error = GB_await_error();
115  else {
116  error = GBT_write_string(gb_key, CHANGEKEY_NAME, name);
117  if (!error) error = GBT_write_int(gb_key, CHANGEKEY_TYPE, type);
118  }
119  }
120  else { // check type of existing key
121  long *elem_type = GBT_read_int(gb_key, CHANGEKEY_TYPE);
122 
123  if (!elem_type) error = GB_await_error();
124  else if (*elem_type != type) error = GBS_global_string("Key '%s' exists, but has different type", name);
125  }
126  }
127 
128  gb_assert(gb_key || error);
129 
130  return error;
131 }
132 
134  return GBT_add_new_changekey_to_keypath(gb_main, name, type, CHANGE_KEY_PATH);
135 }
136 
138  return GBT_add_new_changekey_to_keypath(gb_main, name, type, CHANGE_KEY_PATH_GENES);
139 }
140 
143 }
144 
148  char *dataField = GBS_global_string_copy("%s/data", ali);
149  GB_ERROR error = GBT_add_new_changekey(gb_main, dataField, GB_STRING);
150  free(dataField);
151  return error;
152 }
153 
154 static GB_ERROR write_int_converted(GBDATA *gbfield, const char *data, bool trimmed, size_t *rounded) {
155  // 'rounded' is incremented each time a float value was
156  // converted to integer (even if float value can convert lossless, e.g. "4.0").
157 
158  char *end = NULp;
159  unsigned long i = strtoul(data, &end, 10);
160  GB_ERROR error = NULp;
161 
162  if (end == data || end[0] != 0) {
163  if (trimmed) {
164  // fallback: convert to double and round
165 
166  double d = strtod(data, &end);
167  if (end == data || end[0] != 0) {
168  error = GBS_global_string("cannot convert '%s' to rounded numeric value", data);
169  }
170  else {
171  (*rounded)++;
172  i = d>0 ? (int)(d+0.5) : (int)(d-0.5);
173  error = GB_write_int(gbfield, i);
174  if (error) error = GBS_global_string("write error (%s)", error);
175  }
176  }
177  else {
178  char *trimmed_data = GBS_trim(data);
179  error = write_int_converted(gbfield, trimmed_data, true, rounded);
180  free(trimmed_data);
181  }
182  }
183  else {
184  error = GB_write_int(gbfield, i);
185  if (error) error = GBS_global_string("write error (%s)", error);
186  }
187 
188  return error;
189 }
190 
191 static GB_ERROR write_float_converted(GBDATA *gbfield, const char *data, bool trimmed) {
192  char *end = NULp;
193  float f = strtof(data, &end);
194  GB_ERROR error = NULp;
195 
196  if (end == data || end[0] != 0) {
197  if (trimmed) {
198  error = GBS_global_string("cannot convert '%s' to numeric value", data);
199  }
200  else {
201  char *trimmed_data = GBS_trim(data);
202  error = write_float_converted(gbfield, trimmed_data, true);
203  free(trimmed_data);
204  }
205  }
206  else {
207  error = GB_write_float(gbfield, f);
208  if (error) error = GBS_global_string("write error (%s)", error);
209  }
210 
211  return error;
212 }
213 
214 GB_ERROR GBT_write_int_converted(GBDATA *gb_int_writable, const char *data, size_t *rounded) {
215  // Note: has functional similarities to GB_write_autoconv_string
216  return write_int_converted(gb_int_writable, data, false, rounded);
217 }
218 GB_ERROR GBT_write_float_converted(GBDATA *gb_float_writable, const char *data) {
219  // Note: has functional similarities to GB_write_autoconv_string
220  return write_float_converted(gb_float_writable, data, false);
221 }
222 
223 GB_ERROR GBT_convert_changekey(GBDATA *gb_main, const char *name, GB_TYPES target_type) {
225  bool need_convert = true;
226 
227  if (!error) {
228  GBDATA *gbkey = GBT_get_changekey(gb_main, name, CHANGE_KEY_PATH);
229  if (gbkey) {
230  GB_TYPES source_type = (GB_TYPES)*GBT_read_int(gbkey, CHANGEKEY_TYPE);
231  if (source_type == target_type) need_convert = false;
232  }
233  else {
234  if (!name[0] || strcmp(name, NO_FIELD_SELECTED) == 0) {
235  error = "Please select field to convert";
236  }
237  else {
238  error = GBS_global_string("Unknown changekey '%s'", name);
239  }
240  }
241  }
242 
243  if (!error && need_convert) {
244  GBDATA *gbspec = GBT_first_species(gb_main);
245  size_t rounded = 0;
246 
247  for (; gbspec; gbspec = GBT_next_species(gbspec)) {
248  GBDATA *gbfield = GB_entry(gbspec, name);
249 
250  // If entry does not exist, no need to convert (sparse population is valid => 'NULp' value)
251  if (gbfield) {
252  char *data = GB_read_as_string(gbfield);
253  if (!data) {
254  error = GBS_global_string("read error (%s)", GB_await_error());
255  }
256  else {
257  error = GB_delete(gbfield);
258  if (!error) {
259  gbfield = GB_create(gbspec, name, target_type);
260  if (!gbfield) {
261  error = GBS_global_string("create error (%s)", GB_await_error());
262  }
263  else {
264  switch (target_type) {
265  case GB_INT:
266  error = GBT_write_int_converted(gbfield, data, &rounded);
267  break;
268 
269  case GB_FLOAT:
270  error = GBT_write_float_converted(gbfield, data);
271  break;
272 
273  case GB_STRING:
274  error = GB_write_string(gbfield, data);
275  if (error) error = GBS_global_string("write error (%s)", error);
276  break;
277 
278  default:
279  error = "Conversion is not possible";
280  break;
281  }
282  }
283  }
284  free(data);
285  }
286  }
287  if (error) break;
288  }
289 
290  if (error && gbspec) {
291  const char *spname = GBT_get_name_or_description(gbspec);
292  error = GBS_global_string("%s for species '%s'", error, spname);
293  }
294 
295  if (!error) error = gbt_set_type_of_changekey(gb_main, name, target_type, CHANGE_KEY_PATH);
296  if (!error && rounded>0) {
297  GB_warningf("%zi values were rounded (loss of precision)", rounded);
298  }
299  }
300 
301  if (error) error = GBS_global_string("GBT_convert: %s", error);
302 
303  return GB_end_transaction(gb_main, error);
304 }
305 
static GB_ERROR write_int_converted(GBDATA *gbfield, const char *data, bool trimmed, size_t *rounded)
const char * GB_ERROR
Definition: arb_core.h:25
GB_TYPES type
GB_ERROR GBT_add_alignment_changekeys(GBDATA *gb_main, const char *ali)
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1387
GBDATA * GBT_searchOrCreate_itemfield_according_to_changekey(GBDATA *gb_item, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:61
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2561
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
char * GB_read_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1060
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:202
bool GB_have_error()
Definition: arb_msg.cxx:337
GB_ERROR GBT_add_new_changekey_to_keypath(GBDATA *gb_main, const char *name, GB_TYPES type, const char *keypath)
Definition: adChangeKey.cxx:86
GB_ERROR GBT_add_new_gene_changekey(GBDATA *gb_main, const char *name, GB_TYPES type)
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1722
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2494
#define NO_FIELD_SELECTED
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1916
GB_TYPES GBT_get_type_of_changekey(GBDATA *gb_main, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:33
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:341
NOT4PERL long * GBT_read_int(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:327
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1829
Definition: arbdb.h:67
Definition: arbdb.h:78
void GB_warningf(const char *templat,...)
Definition: arb_msg.cxx:477
GBDATA * GB_create(GBDATA *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1781
const char * GB_first_non_key_char(const char *str)
Definition: adquery.cxx:416
GB_ERROR GBT_convert_changekey(GBDATA *gb_main, const char *name, GB_TYPES target_type)
void GB_clear_error()
Definition: arb_msg.cxx:353
GB_ERROR GBT_add_new_experiment_changekey(GBDATA *gb_main, const char *name, GB_TYPES type)
char * GBS_trim(const char *str)
Definition: adstring.cxx:961
static void error(const char *msg)
Definition: mkptypes.cxx:96
GBDATA * GB_get_root(GBDATA *gbd)
Definition: arbdb.cxx:1740
#define CHANGEKEY_NAME
Definition: arbdbt.h:91
Definition: arbdb.h:86
GB_ERROR GB_write_float(GBDATA *gbd, float f)
Definition: arbdb.cxx:1281
#define CHANGE_KEY_PATH_GENES
Definition: arbdbt.h:87
GB_ERROR GBT_write_int_converted(GBDATA *gb_int_writable, const char *data, size_t *rounded)
GB_ERROR GB_write_int(GBDATA *gbd, long i)
Definition: arbdb.cxx:1250
Definition: arbdb.h:63
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:261
#define gb_assert(cond)
Definition: arbdbt.h:11
static GB_ERROR gbt_set_type_of_changekey(GBDATA *gb_main, const char *field_name, GB_TYPES type, const char *change_key_path)
Definition: adChangeKey.cxx:48
GBDATA * GBT_get_changekey(GBDATA *gb_main, const char *key, const char *change_key_path)
Definition: adChangeKey.cxx:16
GB_ERROR GBT_write_string(GBDATA *gb_container, const char *fieldpath, const char *content)
Definition: adtools.cxx:451
#define CHANGE_KEY_PATH
Definition: arbdbt.h:86
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
#define CHANGEKEY
Definition: arbdbt.h:90
#define CHANGEKEY_TYPE
Definition: arbdbt.h:92
#define CHANGE_KEY_PATH_EXPERIMENTS
Definition: arbdbt.h:88
GBDATA * GB_find_string(GBDATA *gbd, const char *key, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:302
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
#define NULp
Definition: cxxforward.h:114
static GB_ERROR write_float_converted(GBDATA *gbfield, const char *data, bool trimmed)
GB_TYPES
Definition: arbdb.h:62
GB_ERROR GBT_write_int(GBDATA *gb_container, const char *fieldpath, long content)
Definition: adtools.cxx:471
GBDATA * gb_main
Definition: adname.cxx:33
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:460
GB_ERROR GBT_add_new_changekey(GBDATA *gb_main, const char *name, GB_TYPES type)
GB_ERROR GBT_write_float_converted(GBDATA *gb_float_writable, const char *data)
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:193
Definition: arbdb.h:66