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 #if defined(WARN_TODO)
19 #warning check if search for CHANGEKEY_NAME should be case-sensitive!
20 #endif
21  GBDATA *gb_key = NULp;
22  GBDATA *gb_key_data = GB_search(gb_main, change_key_path,
24 
25  if (gb_key_data) {
26  GBDATA *gb_key_name = GB_find_string(gb_key_data, CHANGEKEY_NAME, key, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
27  if (gb_key_name) {
28  gb_key = GB_get_father(gb_key_name);
29  }
30  }
31  return gb_key;
32 }
33 
34 GB_TYPES GBT_get_type_of_changekey(GBDATA *gb_main, const char *field_name, const char *change_key_path) {
35  // get the type of an item key
37  GBDATA *gbd = GBT_get_changekey(gb_main, field_name, change_key_path);
38 
39  if (gbd) {
40  long *typePtr = GBT_read_int(gbd, CHANGEKEY_TYPE);
41  if (typePtr) {
42  type = (GB_TYPES)*typePtr;
43  }
44  }
45 
46  return type;
47 }
48 
49 static GB_ERROR gbt_set_type_of_changekey(GBDATA *gb_main, const char *field_name, GB_TYPES type, const char *change_key_path) {
51  GBDATA *gbd = GBT_get_changekey(gb_main, field_name, change_key_path);
52 
53  if (!gbd) {
54  error = GBS_global_string("Can't set type of nonexistent changekey \"%s\"", field_name);
55  }
56  else {
57  error = GBT_write_int(gbd, CHANGEKEY_TYPE, type);
58  }
59  return error;
60 }
61 
62 GBDATA *GBT_searchOrCreate_itemfield_according_to_changekey(GBDATA *gb_item, const char *field_name, const char *change_key_path) {
70  GBDATA *gb_entry = GB_search(gb_item, field_name, GB_FIND);
71  if (!gb_entry) {
73 
74  GB_TYPES type = GBT_get_type_of_changekey(GB_get_root(gb_item), field_name, change_key_path);
75  if (type == GB_NONE) {
76  GB_export_errorf("Cannot create field '%s' (no type information available)", field_name);
77  }
78  else {
79  gb_entry = GB_search(gb_item, field_name, type);
80  }
81  }
82  gb_assert(gb_entry || GB_have_error());
83  return gb_entry;
84 }
85 
86 
87 GB_ERROR GBT_add_new_changekey_to_keypath(GBDATA *gb_main, const char *name, int type, const char *keypath) { // @@@ type should be GB_TYPES (not int)
89  GBDATA *gb_key = GBT_get_changekey(gb_main, name, keypath);
90  const char *c = GB_first_non_key_char(name);
91 
92  if (c) {
93  char *new_name = ARB_strdup(name);
94 
95  *(char*)GB_first_non_key_char(new_name) = 0;
96 
97  if (*c == '/') error = GBT_add_new_changekey(gb_main, new_name, GB_DB);
98  else error = GBS_global_string("Cannot add '%s' to your key list (illegal character '%c')", name, *c);
99 
100  free(new_name);
101  }
102 
103  if (!error) {
104  if (!gb_key) { // create new key
105  GBDATA *gb_key_data = GB_search(gb_main, keypath, GB_CREATE_CONTAINER);
106  gb_key = gb_key_data ? GB_create_container(gb_key_data, CHANGEKEY) : NULp;
107 
108  if (!gb_key) error = GB_await_error();
109  else {
110  error = GBT_write_string(gb_key, CHANGEKEY_NAME, name);
111  if (!error) error = GBT_write_int(gb_key, CHANGEKEY_TYPE, type);
112  }
113  }
114  else { // check type of existing key
115  long *elem_type = GBT_read_int(gb_key, CHANGEKEY_TYPE);
116 
117  if (!elem_type) error = GB_await_error();
118  else if (*elem_type != type) error = GBS_global_string("Key '%s' exists, but has different type", name);
119  }
120  }
121 
122  gb_assert(gb_key || error);
123 
124  return error;
125 }
126 
127 GB_ERROR GBT_add_new_changekey(GBDATA *gb_main, const char *name, int type) { // @@@ type should be GB_TYPES (not int)
128  return GBT_add_new_changekey_to_keypath(gb_main, name, type, CHANGE_KEY_PATH);
129 }
130 
132  return GBT_add_new_changekey_to_keypath(gb_main, name, type, CHANGE_KEY_PATH_GENES); // @@@ type should be GB_TYPES (not int)
133 }
134 
136  return GBT_add_new_changekey_to_keypath(gb_main, name, type, CHANGE_KEY_PATH_EXPERIMENTS); // @@@ type should be GB_TYPES (not int)
137 }
138 
139 static GB_ERROR write_int_converted(GBDATA *gbfield, const char *data, bool trimmed, size_t *rounded) {
140  // 'rounded' is incremented each time a float value was
141  // converted to integer (even if float value can convert lossless, e.g. "4.0").
142 
143  char *end = NULp;
144  unsigned long i = strtoul(data, &end, 10);
145  GB_ERROR error = NULp;
146 
147  if (end == data || end[0] != 0) {
148  if (trimmed) {
149  // fallback: convert to double and round
150 
151  double d = strtod(data, &end);
152  if (end == data || end[0] != 0) {
153  error = GBS_global_string("cannot convert '%s' to rounded numeric value", data);
154  }
155  else {
156  (*rounded)++;
157  i = d>0 ? (int)(d+0.5) : (int)(d-0.5);
158  error = GB_write_int(gbfield, i);
159  if (error) error = GBS_global_string("write error (%s)", error);
160  }
161  }
162  else {
163  char *trimmed_data = GBS_trim(data);
164  error = write_int_converted(gbfield, trimmed_data, true, rounded);
165  free(trimmed_data);
166  }
167  }
168  else {
169  error = GB_write_int(gbfield, i);
170  if (error) error = GBS_global_string("write error (%s)", error);
171  }
172 
173  return error;
174 }
175 
176 static GB_ERROR write_float_converted(GBDATA *gbfield, const char *data, bool trimmed) {
177  char *end = NULp;
178  float f = strtof(data, &end);
179  GB_ERROR error = NULp;
180 
181  if (end == data || end[0] != 0) {
182  if (trimmed) {
183  error = GBS_global_string("cannot convert '%s' to numeric value", data);
184  }
185  else {
186  char *trimmed_data = GBS_trim(data);
187  error = write_float_converted(gbfield, trimmed_data, true);
188  free(trimmed_data);
189  }
190  }
191  else {
192  error = GB_write_float(gbfield, f);
193  if (error) error = GBS_global_string("write error (%s)", error);
194  }
195 
196  return error;
197 }
198 
199 GB_ERROR GBT_write_int_converted(GBDATA *gb_int_writable, const char *data, size_t *rounded) {
200  // Note: has functional similarities to GB_write_autoconv_string
201  return write_int_converted(gb_int_writable, data, false, rounded);
202 }
203 GB_ERROR GBT_write_float_converted(GBDATA *gb_float_writable, const char *data) {
204  // Note: has functional similarities to GB_write_autoconv_string
205  return write_float_converted(gb_float_writable, data, false);
206 }
207 
208 GB_ERROR GBT_convert_changekey(GBDATA *gb_main, const char *name, GB_TYPES target_type) {
210  bool need_convert = true;
211 
212  if (!error) {
213  GBDATA *gbkey = GBT_get_changekey(gb_main, name, CHANGE_KEY_PATH);
214  if (gbkey) {
215  GB_TYPES source_type = (GB_TYPES)*GBT_read_int(gbkey, CHANGEKEY_TYPE);
216  if (source_type == target_type) need_convert = false;
217  }
218  else {
219  if (!name[0] || strcmp(name, NO_FIELD_SELECTED) == 0) {
220  error = "Please select field to convert";
221  }
222  else {
223  error = GBS_global_string("Unknown changekey '%s'", name);
224  }
225  }
226  }
227 
228  if (!error && need_convert) {
229  GBDATA *gbspec = GBT_first_species(gb_main);
230  size_t rounded = 0;
231 
232  for (; gbspec; gbspec = GBT_next_species(gbspec)) {
233  GBDATA *gbfield = GB_entry(gbspec, name);
234 
235  // If entry does not exist, no need to convert (sparse population is valid => 'NULp' value)
236  if (gbfield) {
237  char *data = GB_read_as_string(gbfield);
238  if (!data) {
239  error = GBS_global_string("read error (%s)", GB_await_error());
240  }
241  else {
242  error = GB_delete(gbfield);
243  if (!error) {
244  gbfield = GB_create(gbspec, name, target_type);
245  if (!gbfield) {
246  error = GBS_global_string("create error (%s)", GB_await_error());
247  }
248  else {
249  switch (target_type) {
250  case GB_INT:
251  error = GBT_write_int_converted(gbfield, data, &rounded);
252  break;
253 
254  case GB_FLOAT:
255  error = GBT_write_float_converted(gbfield, data);
256  break;
257 
258  case GB_STRING:
259  error = GB_write_string(gbfield, data);
260  if (error) error = GBS_global_string("write error (%s)", error);
261  break;
262 
263  default:
264  error = "Conversion is not possible";
265  break;
266  }
267  }
268  }
269  free(data);
270  }
271  }
272  if (error) break;
273  }
274 
275  if (error && gbspec) {
276  const char *spname = GBT_get_name_or_description(gbspec);
277  error = GBS_global_string("%s for species '%s'", error, spname);
278  }
279 
280  if (!error) error = gbt_set_type_of_changekey(gb_main, name, target_type, CHANGE_KEY_PATH);
281  if (!error && rounded>0) {
282  GB_warningf("%zi values were rounded (loss of precision)", rounded);
283  }
284  }
285 
286  if (error) error = GBS_global_string("GBT_convert: %s", error);
287 
288  return GB_end_transaction(gb_main, error);
289 }
290 
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 GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1385
GBDATA * GBT_searchOrCreate_itemfield_according_to_changekey(GBDATA *gb_item, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:62
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2549
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
char * GB_read_as_string(GBDATA *gbd)
Definition: arbdb.cxx:1054
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
bool GB_have_error()
Definition: arb_msg.cxx:349
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1720
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2482
#define NO_FIELD_SELECTED
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1904
GB_TYPES GBT_get_type_of_changekey(GBDATA *gb_main, const char *field_name, const char *change_key_path)
Definition: adChangeKey.cxx:34
GB_ERROR GBT_add_new_experiment_changekey(GBDATA *gb_main, const char *name, int type)
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
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:1827
Definition: arbdb.h:67
Definition: arbdb.h:78
void GB_warningf(const char *templat,...)
Definition: arb_msg.cxx:490
GBDATA * GB_create(GBDATA *father, const char *key, GB_TYPES type)
Definition: arbdb.cxx:1779
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:365
GB_ERROR GBT_add_new_changekey(GBDATA *gb_main, const char *name, int 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:1738
#define CHANGEKEY_NAME
Definition: arbdbt.h:91
Definition: arbdb.h:86
GB_ERROR GB_write_float(GBDATA *gbd, float f)
Definition: arbdb.cxx:1279
#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:1244
Definition: arbdb.h:63
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:264
#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:49
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
GB_ERROR GBT_add_new_gene_changekey(GBDATA *gb_main, const char *name, int type)
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
#define NULp
Definition: cxxforward.h:97
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:441
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
GB_ERROR GBT_add_new_changekey_to_keypath(GBDATA *gb_main, const char *name, int type, const char *keypath)
Definition: adChangeKey.cxx:87
Definition: arbdb.h:66