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 
146  // goes to header: __ATTR__DEPRECATED_TODO("obsolete. use GBT_add_new_species_changekey() instead")
147  //
148  // this method is required for sina 1.3 binary backward compatibility
149  // (needed as long as we support ubuntu 10.04)
150  //
151  // Note: was broken by [19140].
152  return GBT_add_new_species_changekey(gb_main, name, GB_TYPES(type));
153 }
154 
158  char *dataField = GBS_global_string_copy("%s/data", ali);
159  GB_ERROR error = GBT_add_new_species_changekey(gb_main, dataField, GB_STRING);
160  free(dataField);
161  return error;
162 }
163 
164 static GB_ERROR write_int_converted(GBDATA *gbfield, const char *data, bool trimmed, size_t *rounded) {
165  // 'rounded' is incremented each time a float value was
166  // converted to integer (even if float value can convert lossless, e.g. "4.0").
167 
168  char *end = NULp;
169  unsigned long i = strtoul(data, &end, 10);
170  GB_ERROR error = NULp;
171 
172  if (end == data || end[0] != 0) {
173  if (trimmed) {
174  // fallback: convert to double and round
175 
176  double d = strtod(data, &end);
177  if (end == data || end[0] != 0) {
178  error = GBS_global_string("cannot convert '%s' to rounded numeric value", data);
179  }
180  else {
181  (*rounded)++;
182  i = d>0 ? (int)(d+0.5) : (int)(d-0.5);
183  error = GB_write_int(gbfield, i);
184  if (error) error = GBS_global_string("write error (%s)", error);
185  }
186  }
187  else {
188  char *trimmed_data = GBS_trim(data);
189  error = write_int_converted(gbfield, trimmed_data, true, rounded);
190  free(trimmed_data);
191  }
192  }
193  else {
194  error = GB_write_int(gbfield, i);
195  if (error) error = GBS_global_string("write error (%s)", error);
196  }
197 
198  return error;
199 }
200 
201 static GB_ERROR write_float_converted(GBDATA *gbfield, const char *data, bool trimmed) {
202  char *end = NULp;
203  float f = strtof(data, &end);
204  GB_ERROR error = NULp;
205 
206  if (end == data || end[0] != 0) {
207  if (trimmed) {
208  error = GBS_global_string("cannot convert '%s' to numeric value", data);
209  }
210  else {
211  char *trimmed_data = GBS_trim(data);
212  error = write_float_converted(gbfield, trimmed_data, true);
213  free(trimmed_data);
214  }
215  }
216  else {
217  error = GB_write_float(gbfield, f);
218  if (error) error = GBS_global_string("write error (%s)", error);
219  }
220 
221  return error;
222 }
223 
224 GB_ERROR GBT_write_int_converted(GBDATA *gb_int_writable, const char *data, size_t *rounded) {
225  // Note: has functional similarities to GB_write_autoconv_string
226  return write_int_converted(gb_int_writable, data, false, rounded);
227 }
228 GB_ERROR GBT_write_float_converted(GBDATA *gb_float_writable, const char *data) {
229  // Note: has functional similarities to GB_write_autoconv_string
230  return write_float_converted(gb_float_writable, data, false);
231 }
232 
233 GB_ERROR GBT_convert_changekey(GBDATA *gb_main, const char *name, GB_TYPES target_type) {
235  bool need_convert = true;
236 
237  if (!error) {
238  GBDATA *gbkey = GBT_get_changekey(gb_main, name, CHANGE_KEY_PATH);
239  if (gbkey) {
240  GB_TYPES source_type = (GB_TYPES)*GBT_read_int(gbkey, CHANGEKEY_TYPE);
241  if (source_type == target_type) need_convert = false;
242  }
243  else {
244  if (!name[0] || strcmp(name, NO_FIELD_SELECTED) == 0) {
245  error = "Please select field to convert";
246  }
247  else {
248  error = GBS_global_string("Unknown changekey '%s'", name);
249  }
250  }
251  }
252 
253  if (!error && need_convert) {
254  GBDATA *gbspec = GBT_first_species(gb_main);
255  size_t rounded = 0;
256 
257  for (; gbspec; gbspec = GBT_next_species(gbspec)) {
258  GBDATA *gbfield = GB_entry(gbspec, name);
259 
260  // If entry does not exist, no need to convert (sparse population is valid => 'NULp' value)
261  if (gbfield) {
262  char *data = GB_read_as_string(gbfield);
263  if (!data) {
264  error = GBS_global_string("read error (%s)", GB_await_error());
265  }
266  else {
267  error = GB_delete(gbfield);
268  if (!error) {
269  gbfield = GB_create(gbspec, name, target_type);
270  if (!gbfield) {
271  error = GBS_global_string("create error (%s)", GB_await_error());
272  }
273  else {
274  switch (target_type) {
275  case GB_INT:
276  error = GBT_write_int_converted(gbfield, data, &rounded);
277  break;
278 
279  case GB_FLOAT:
280  error = GBT_write_float_converted(gbfield, data);
281  break;
282 
283  case GB_STRING:
284  error = GB_write_string(gbfield, data);
285  if (error) error = GBS_global_string("write error (%s)", error);
286  break;
287 
288  default:
289  error = "Conversion is not possible";
290  break;
291  }
292  }
293  }
294  free(data);
295  }
296  }
297  if (error) break;
298  }
299 
300  if (error && gbspec) {
301  const char *spname = GBT_get_name_or_description(gbspec);
302  error = GBS_global_string("%s for species '%s'", error, spname);
303  }
304 
305  if (!error) error = gbt_set_type_of_changekey(gb_main, name, target_type, CHANGE_KEY_PATH);
306  if (!error && rounded>0) {
307  GB_warningf("%zi values were rounded (loss of precision)", rounded);
308  }
309  }
310 
311  if (error) error = GBS_global_string("GBT_convert: %s", error);
312 
313  return GB_end_transaction(gb_main, error);
314 }
315 
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:203
bool GB_have_error()
Definition: arb_msg.cxx:338
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:342
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:536
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:354
GB_ERROR GBT_add_new_changekey(GBDATA *gb_main, const char *name, int type)
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:947
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:262
#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
GB_ERROR GBT_add_new_species_changekey(GBDATA *gb_main, const char *name, GB_TYPES type)
#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:116
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:32
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:459
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:194
Definition: arbdb.h:66