ARB
aditem.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : aditem.cxx //
4 // Purpose : item functions //
5 // items are e.g. species, SAIs, genes, etc //
6 // //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =============================================================== //
11 
12 #include "gb_local.h"
13 
14 #include <arbdbt.h>
15 #include <arb_strbuf.h>
16 
17 
18 GBDATA *GBT_find_or_create_item_rel_item_data(GBDATA *gb_item_data, const char *itemname, const char *id_field, const char *id, bool markCreated) {
28  GBDATA *gb_item = NULp;
30 
31  if (!gb_item_data) error = "Missing parent container";
32  else {
33  gb_item = GBT_find_item_rel_item_data(gb_item_data, id_field, id);
34  if (!gb_item) {
35  error = GB_push_transaction(gb_item_data);
36  if (!error) {
37  gb_item = GB_create_container(gb_item_data, itemname); // create a new item
38  if (!gb_item) error = GB_await_error();
39  else {
40  error = GBT_write_string(gb_item, id_field, id); // write item identifier
41  if (!error && markCreated) GB_write_flag(gb_item, 1); // mark generated item
42  }
43  }
44  error = GB_end_transaction(gb_item_data, error);
45  }
46  }
47 
48  if (!gb_item && !error) error = GB_await_error();
49  if (error) {
50  gb_item = NULp;
51  GB_export_errorf("Can't create %s '%s': %s", itemname, id, error);
52  }
53 
54  return gb_item;
55 }
56 
58  return GBT_find_or_create_item_rel_item_data(gb_species_data, "species", "name", name, markCreated);
59 }
60 
61 GBDATA *GBT_find_or_create_species(GBDATA *gb_main, const char *name, bool markCreated) {
62  return GBT_find_or_create_species_rel_species_data(GBT_get_species_data(gb_main), name, markCreated);
63 }
64 
67  return GBT_find_or_create_item_rel_item_data(GBT_get_SAI_data(gb_main), "extended", "name", name, false);
68 }
69 
70 
71 // ------------------------------------
72 // some simple find procedures
73 
74 GBDATA *GBT_find_item_rel_item_data(GBDATA *gb_item_data, const char *id_field, const char *id_value) {
87  GBDATA *gb_item_id = GB_find_string(gb_item_data, id_field, id_value, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
88  return gb_item_id ? GB_get_father(gb_item_id) : NULp;
89 }
90 
91 GBDATA *GBT_expect_item_rel_item_data(GBDATA *gb_item_data, const char *id_field, const char *id_value) {
93 
94  GBDATA *gb_found = GBT_find_item_rel_item_data(gb_item_data, id_field, id_value);
95  if (!gb_found && !GB_have_error()) { // item simply not exists
96  GBDATA *gb_any = GB_find(gb_item_data, id_field, SEARCH_GRANDCHILD);
97  const char *itemname = gb_any ? GB_read_key_pntr(GB_get_father(gb_any)) : "<item>";
98  GB_export_errorf("Could not find %s with %s '%s'", itemname, id_field, id_value);
99  }
100  return gb_found;
101 }
102 
103 // --------------------------------------------------------------------------------
104 
106  return GBT_find_or_create(gb_main, "species_data", 7);
107 }
108 
110  return GB_first_marked(gb_species_data, "species");
111 }
112 
114  return GB_first_marked(GBT_get_species_data(gb_main), "species");
115 }
117  gb_assert(GB_has_key(gb_species, "species"));
118  return GB_next_marked(gb_species, "species");
119 }
120 
122  return GB_entry(gb_species_data, "species");
123 }
125  return GB_entry(GBT_get_species_data(gb_main), "species");
126 }
127 
129  gb_assert(GB_has_key(gb_species, "species"));
130  return GB_nextEntry(gb_species);
131 }
132 
134  return GBT_find_item_rel_item_data(gb_species_data, "name", name);
135 }
137  return GBT_expect_item_rel_item_data(gb_species_data, "name", name);
138 }
139 GBDATA *GBT_find_species(GBDATA *gb_main, const char *name) {
140  // Search for a species.
141  // Return found species or NULp (in this case an error MAY be exported).
142  //
143  // Note: If you expect the species to exists, use GBT_expect_species!
144  return GBT_find_item_rel_item_data(GBT_get_species_data(gb_main), "name", name);
145 }
146 GBDATA *GBT_expect_species(GBDATA *gb_main, const char *name) {
147  // Returns an existing species or
148  // NULp (in that case an error is exported)
149  return GBT_expect_item_rel_item_data(GBT_get_species_data(gb_main), "name", name);
150 }
151 
152 // --------------------------------------------------------------------------------
153 
155  return GBT_find_or_create(gb_main, "extended_data", 7);
156 }
157 
158 // Search SAIs
160  return GB_entry(gb_sai_data, "extended");
161 }
163  return GB_entry(GBT_get_SAI_data(gb_main), "extended");
164 }
165 
167  gb_assert(GB_has_key(gb_sai, "extended"));
168  return GB_nextEntry(gb_sai);
169 }
170 
171 GBDATA *GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name) {
172  return GBT_find_item_rel_item_data(gb_sai_data, "name", name);
173 }
174 GBDATA *GBT_expect_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name) {
175  return GBT_expect_item_rel_item_data(gb_sai_data, "name", name);
176 }
177 GBDATA *GBT_find_SAI(GBDATA *gb_main, const char *name) {
178  // Search for a SAI.
179  // Return found SAI or NULp (in this case an error MAY be exported).
180  //
181  // Note: If you expect the SAI to exist, use GBT_expect_SAI!
182  return GBT_find_item_rel_item_data(GBT_get_SAI_data(gb_main), "name", name);
183 }
184 GBDATA *GBT_expect_SAI(GBDATA *gb_main, const char *name) {
185  // Returns an existing SAI or
186  // NULp (in that case an error is exported)
187  return GBT_expect_item_rel_item_data(GBT_get_SAI_data(gb_main), "name", name);
188 }
189 
190 // ---------------------
191 // count items
192 
193 static long GBT_get_item_count(GBDATA *gb_parent_of_container, const char *item_container_name) {
194  // returns elements stored in a container
195 
196  GBDATA *gb_item_data;
197  long count = 0;
198 
199  GB_push_transaction(gb_parent_of_container);
200  gb_item_data = GB_entry(gb_parent_of_container, item_container_name);
201  if (gb_item_data) count = GB_number_of_subentries(gb_item_data);
202  GB_pop_transaction(gb_parent_of_container);
203 
204  return count;
205 }
206 
208  return GBT_get_item_count(gb_main, "species_data");
209 }
210 
212  return GBT_get_item_count(gb_main, "extended_data");
213 }
214 
215 // --------------------------------------------------------------------------------
216 
217 static char *GBT_create_unique_item_identifier(GBDATA *gb_item_container, const char *id_field, const char *default_id) {
218  // returns an identifier not used by items in 'gb_item_container'
219  // 'id_field' is the entry that is used as identifier (e.g. 'name' for species)
220  // 'default_id' will be suffixed with a number to generate a unique id
221  //
222  // Note:
223  // * The resulting id may be longer than 8 characters
224  // * This function is slow, so just use in extra-ordinary situations
225 
226  GBDATA *gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, default_id);
227  char *unique_id;
228 
229  if (!gb_item) {
230  unique_id = ARB_strdup(default_id); // default_id is unused
231  }
232  else {
233  char *generated_id = ARB_alloc<char>(strlen(default_id)+20);
234  size_t min_num = 1;
235 
236 #define GENERATE_ID(num) sprintf(generated_id, "%s%zu", default_id, num);
237 
238  GENERATE_ID(min_num);
239  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
240 
241  if (gb_item) {
242  size_t num_items = GB_number_of_subentries(gb_item_container);
243  size_t max_num = 0;
244 
245  gb_assert(num_items); // otherwise deadlock below
246 
247  do {
248  max_num += num_items;
249  GENERATE_ID(max_num);
250  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
251  } while (gb_item && max_num >= num_items);
252 
253  if (max_num<num_items) { // overflow
254  char *uid;
255  generated_id[0] = 'a'+GB_random(26);
256  generated_id[1] = 'a'+GB_random(26);
257  generated_id[2] = 0;
258 
259  uid = GBT_create_unique_item_identifier(gb_item_container, id_field, generated_id);
260  strcpy(generated_id, uid);
261  free(uid);
262  }
263  else {
264  // max_num is unused
265  while ((max_num-min_num)>1) {
266  size_t mid = (min_num+max_num)/2;
267  gb_assert(mid != min_num && mid != max_num);
268 
269  GENERATE_ID(mid);
270  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
271 
272  if (gb_item) min_num = mid;
273  else max_num = mid;
274  }
275  GENERATE_ID(max_num);
276  gb_assert(!GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id));
277  }
278  }
279  unique_id = generated_id;
280 
281 #undef GENERATE_ID
282  }
283 
284  return unique_id;
285 }
286 
287 char *GBT_create_unique_species_name(GBDATA *gb_main, const char *default_name) {
288  return GBT_create_unique_item_identifier(GBT_get_species_data(gb_main), "name", default_name);
289 }
290 
291 
292 // --------------------------------
293 // mark and unmark species
294 
296  // flag == 0 -> unmark
297  // flag == 1 -> mark
298  // flag == 2 -> invert
299 
300  GBDATA *gb_species;
301  GB_push_transaction(gb_main);
302 
303  if (flag == 2) {
304  for (gb_species = GBT_first_species(gb_main);
305  gb_species;
306  gb_species = GBT_next_species(gb_species))
307  {
308  GB_write_flag(gb_species, !GB_read_flag(gb_species));
309  }
310  }
311  else {
312  gb_assert(flag == 0 || flag == 1);
313 
314  for (gb_species = GBT_first_species(gb_main);
315  gb_species;
316  gb_species = GBT_next_species(gb_species))
317  {
318  GB_write_flag(gb_species, flag);
319  }
320  }
321  GB_pop_transaction(gb_main);
322 }
323 void GBT_mark_all_that(GBDATA *gb_main, int flag, bool (*condition)(GBDATA*, void*), void *cd) {
324  GBDATA *gb_species;
325  GB_push_transaction(gb_main);
326 
327  if (flag == 2) {
328  for (gb_species = GBT_first_species(gb_main);
329  gb_species;
330  gb_species = GBT_next_species(gb_species))
331  {
332  if (condition(gb_species, cd)) {
333  GB_write_flag(gb_species, !GB_read_flag(gb_species));
334  }
335  }
336  }
337  else {
338  gb_assert(flag == 0 || flag == 1);
339 
340  for (gb_species = GBT_first_species(gb_main);
341  gb_species;
342  gb_species = GBT_next_species(gb_species))
343  {
344  int curr_flag = GB_read_flag(gb_species);
345  if (curr_flag != flag && condition(gb_species, cd)) {
346  GB_write_flag(gb_species, flag);
347  }
348  }
349  }
350  GB_pop_transaction(gb_main);
351 }
352 
354  GB_transaction ta(gb_main);
356 }
357 
358 char *GBT_store_marked_species(GBDATA *gb_main, bool unmark_all) {
367  GBS_strstruct *out = GBS_stropen(10000);
368  GBDATA *gb_species;
369 
370  for (gb_species = GBT_first_marked_species(gb_main);
371  gb_species;
372  gb_species = GBT_next_marked_species(gb_species))
373  {
374  const char *name = GBT_get_name(gb_species);
375  if (name) {
376  GBS_strcat(out, name);
377  GBS_chrcat(out, ';');
378  if (unmark_all) GB_write_flag(gb_species, 0);
379  }
380  }
381 
382  GBS_str_cut_tail(out, 1); // remove trailing ';'
383  return GBS_strclose(out);
384 }
385 
386 NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata) {
395 #define MAX_NAME_LEN 20
396  char name[MAX_NAME_LEN+1];
397  GB_ERROR error = NULp;
398 
399  while (!error) {
400  const char *p = strchr(stored, ';');
401  int len = p ? (p-stored) : (int)strlen(stored);
402  GBDATA *gb_species;
403 
404  gb_assert(len <= MAX_NAME_LEN);
405  memcpy(name, stored, len);
406  name[len] = 0;
407 
408  gb_species = GBT_find_species(gb_main, name);
409  if (gb_species) {
410  error = doit(gb_species, clientdata);
411  }
412  else {
413  error = "Some stored species where not found.";
414  }
415 
416  if (!p) break;
417  stored = p+1;
418  }
419 #undef MAX_NAME_LEN
420  return error;
421 }
422 
423 static GB_ERROR restore_mark(GBDATA *gb_species, int *) {
424  GB_write_flag(gb_species, 1);
425  return NULp;
426 }
427 
428 GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked) {
434  GBT_mark_all(gb_main, 0); // unmark all species
435  return GBT_with_stored_species(gb_main, stored_marked, restore_mark, NULp);
436 }
437 
438 // ---------------------------------
439 // read species information
440 
445  GB_CSTR result = GBT_read_char_pntr(gb_item, "name");
446  if (!result) result = GBS_global_string("<unnamed_%s>", GB_read_key_pntr(gb_item));
447  return result;
448 }
449 
450 const char *GBT_get_name(GBDATA *gb_item) {
454  GBDATA *gb_name = GB_entry(gb_item, "name");
455  if (!gb_name) return NULp;
456  return GB_read_char_pntr(gb_name);
457 }
458 
460  // goes to header: __ATTR__DEPRECATED_TODO("please use GBT_get_name or GBT_get_name_or_description()")
461 
462  // @@@ r18159 unintentionally broke SINA (binary) compatibility
463  // (remove this function when no longer needed)
464  return GBT_get_name_or_description(gb_item);
465 }
466 
467 GBDATA **GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr) {
469 
470  GBDATA **result = NULp;
471  long speciesCount = 0;
472 
473  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
474  gb_species;
475  gb_species = GBT_next_species(gb_species))
476  {
477  speciesCount ++;
478  }
479 
480  if (speciesCount) {
481  ARB_alloc(result, speciesCount);
482 
483  speciesCount = 0;
484  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
485  gb_species;
486  gb_species = GBT_next_species(gb_species))
487  {
488  result[speciesCount++] = gb_species;
489  }
490  }
491 
492  *speciesCountPtr = speciesCount;
493  return result;
494 }
495 
void GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:295
const char * GB_ERROR
Definition: arb_core.h:25
#define GENERATE_ID(num)
string result
#define MAX_NAME_LEN
void GBT_mark_all_that(GBDATA *gb_main, int flag, bool(*condition)(GBDATA *, void *), void *cd)
Definition: aditem.cxx:323
GBDATA * GBT_next_species(GBDATA *gb_species)
Definition: aditem.cxx:128
GBDATA * GB_find(GBDATA *gbd, const char *key, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:295
static GB_ERROR restore_mark(GBDATA *gb_species, int *)
Definition: aditem.cxx:423
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2549
GBDATA * GBT_first_marked_species_rel_species_data(GBDATA *gb_species_data)
Definition: aditem.cxx:109
GBDATA * GBT_expect_item_rel_item_data(GBDATA *gb_item_data, const char *id_field, const char *id_value)
Definition: aditem.cxx:91
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
bool GB_have_error()
Definition: arb_msg.cxx:349
GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked)
Definition: aditem.cxx:428
GBDATA * GBT_first_SAI(GBDATA *gb_main)
Definition: aditem.cxx:162
GBDATA * GBT_first_species_rel_species_data(GBDATA *gb_species_data)
Definition: aditem.cxx:121
const char * GBT_get_name(GBDATA *gb_item)
Definition: aditem.cxx:450
GB_ERROR(* species_callback)(GBDATA *gb_species, int *clientdata)
Definition: arbdbt.h:82
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1720
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2482
GBDATA * GBT_expect_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:146
#define NOT4PERL
Definition: arbdb_base.h:23
GBS_strstruct * GBS_stropen(long init_size)
Definition: arb_strbuf.cxx:39
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1827
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:441
GBDATA * GBT_find_or_create_species_rel_species_data(GBDATA *gb_species_data, const char *name, bool markCreated)
Definition: aditem.cxx:57
TYPE * ARB_alloc(size_t nelem)
Definition: arb_mem.h:56
GB_CSTR GB_read_key_pntr(GBDATA *gbd)
Definition: arbdb.cxx:1654
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:207
GBDATA * GBT_find_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:139
GBDATA * GBT_expect_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name)
Definition: aditem.cxx:174
GBDATA * gb_species_data
Definition: adname.cxx:34
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2880
GBDATA * GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name)
Definition: aditem.cxx:171
void GBS_strcat(GBS_strstruct *strstr, const char *ptr)
Definition: arb_strbuf.cxx:108
static void error(const char *msg)
Definition: mkptypes.cxx:96
GBDATA * GBT_find_or_create_item_rel_item_data(GBDATA *gb_item_data, const char *itemname, const char *id_field, const char *id, bool markCreated)
Definition: aditem.cxx:18
int GB_random(int range)
Definition: admath.cxx:88
void GBS_str_cut_tail(GBS_strstruct *strstr, size_t byte_count)
Definition: arb_strbuf.cxx:96
GBDATA * GBT_next_marked_species(GBDATA *gb_species)
Definition: aditem.cxx:116
GBDATA * GBT_first_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:113
int GB_read_flag(GBDATA *gbd)
Definition: arbdb.cxx:2784
GBDATA * GBT_find_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:177
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2512
GBDATA * GBT_find_or_create_species(GBDATA *gb_main, const char *name, bool markCreated)
Definition: aditem.cxx:61
bool GB_has_key(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1705
GBDATA ** GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr)
Definition: aditem.cxx:467
long int flag
Definition: f2c.h:39
GBDATA * GBT_find_item_rel_item_data(GBDATA *gb_item_data, const char *id_field, const char *id_value)
Definition: aditem.cxx:74
long GB_number_of_marked_subentries(GBDATA *gbd)
Definition: adquery.cxx:635
void GBS_chrcat(GBS_strstruct *strstr, char ch)
Definition: arb_strbuf.cxx:119
GBDATA * GBT_expect_species_rel_species_data(GBDATA *gb_species_data, const char *name)
Definition: aditem.cxx:136
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:264
GBDATA * GBT_get_SAI_data(GBDATA *gb_main)
Definition: aditem.cxx:154
#define gb_assert(cond)
Definition: arbdbt.h:11
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2761
NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata)
Definition: aditem.cxx:386
static long GBT_get_item_count(GBDATA *gb_parent_of_container, const char *item_container_name)
Definition: aditem.cxx:193
GBDATA * GBT_expect_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:184
GBDATA * GB_next_marked(GBDATA *gbd, const char *keystring)
Definition: adquery.cxx:670
GB_ERROR GBT_write_string(GBDATA *gb_container, const char *fieldpath, const char *content)
Definition: adtools.cxx:451
char * GBT_store_marked_species(GBDATA *gb_main, bool unmark_all)
Definition: aditem.cxx:358
GBDATA * GBT_find_or_create(GBDATA *father, const char *key, long delete_level)
Definition: adtools.cxx:42
char * GBS_strclose(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:69
GBDATA * GBT_first_SAI_rel_SAI_data(GBDATA *gb_sai_data)
Definition: aditem.cxx:159
long GBT_get_SAI_count(GBDATA *gb_main)
Definition: aditem.cxx:211
GBDATA * GB_find_string(GBDATA *gbd, const char *key, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:302
#define NULp
Definition: cxxforward.h:97
static char * GBT_create_unique_item_identifier(GBDATA *gb_item_container, const char *id_field, const char *default_id)
Definition: aditem.cxx:217
GBDATA * GBT_find_species_rel_species_data(GBDATA *gb_species_data, const char *name)
Definition: aditem.cxx:133
GBDATA * GB_first_marked(GBDATA *gbd, const char *keystring)
Definition: adquery.cxx:655
GB_transaction ta(gb_var)
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:898
GBDATA * gb_main
Definition: adname.cxx:33
GBDATA * GBT_next_SAI(GBDATA *gb_sai)
Definition: aditem.cxx:166
long GBT_count_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:353
char * GBT_create_unique_species_name(GBDATA *gb_main, const char *default_name)
Definition: aditem.cxx:287
GBDATA * GBT_find_or_create_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:65
const char * GBT_read_char_pntr(GBDATA *gb_container, const char *fieldpath)
Definition: adtools.cxx:307
const char * GB_CSTR
Definition: arbdb_base.h:25
GB_ERROR mid(GBL_command_arguments *args, int start_index)
Definition: adlang1.cxx:906
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
GBDATA * GBT_get_species_data(GBDATA *gb_main)
Definition: aditem.cxx:105
GB_CSTR GBT_read_name(GBDATA *gb_item)
Definition: aditem.cxx:459