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  // flag == 3 -> count marks
300  //
301  // returns number of marked species (if flag == 3)
302 
303  GBDATA *gb_species;
304  GB_push_transaction(gb_main);
305 
306  long count = 0;
307  if (flag == 2) {
308  for (gb_species = GBT_first_species(gb_main);
309  gb_species;
310  gb_species = GBT_next_species(gb_species))
311  {
312  GB_write_flag(gb_species, !GB_read_flag(gb_species));
313  }
314  }
315  else if (flag == 3) {
317  count = GB_number_of_marked_subentries(gb_species_data);
318  }
319  else {
320  gb_assert(flag == 0 || flag == 1);
321 
322  for (gb_species = GBT_first_species(gb_main);
323  gb_species;
324  gb_species = GBT_next_species(gb_species))
325  {
326  GB_write_flag(gb_species, flag);
327  }
328  }
329  GB_pop_transaction(gb_main);
330 
331  return count;
332 }
333 
334 long GBT_mark_all_that(GBDATA *gb_main, int flag, bool (*condition)(GBDATA*, void*), void *cd) {
335  GBDATA *gb_species;
336  GB_push_transaction(gb_main);
337 
338  long count = 0;
339  if (flag == 2) {
340  for (gb_species = GBT_first_species(gb_main);
341  gb_species;
342  gb_species = GBT_next_species(gb_species))
343  {
344  if (condition(gb_species, cd)) {
345  GB_write_flag(gb_species, !GB_read_flag(gb_species));
346  }
347  }
348  }
349  else {
350  gb_assert(flag == 0 || flag == 1 || flag == 3);
351 
352  for (gb_species = GBT_first_species(gb_main);
353  gb_species;
354  gb_species = GBT_next_species(gb_species))
355  {
356  int curr_flag = GB_read_flag(gb_species);
357  if (curr_flag != flag && condition(gb_species, cd)) {
358  if (flag == 3) {
359  if (curr_flag) ++count;
360  }
361  else {
362  GB_write_flag(gb_species, flag);
363  }
364  }
365  }
366  }
367  GB_pop_transaction(gb_main);
368 
369  return count;
370 }
371 
373  GB_transaction ta(gb_main);
375 }
376 
377 char *GBT_store_marked_species(GBDATA *gb_main, bool unmark_all) {
386  GBS_strstruct out(10000);
387 
388  for (GBDATA *gb_species = GBT_first_marked_species(gb_main);
389  gb_species;
390  gb_species = GBT_next_marked_species(gb_species))
391  {
392  const char *name = GBT_get_name(gb_species);
393  if (name) {
394  out.cat( name);
395  out.put(';');
396  if (unmark_all) GB_write_flag(gb_species, 0);
397  }
398  }
399 
400  out.cut_tail( 1); // remove trailing ';'
401  return out.release_memfriendly();
402 }
403 
404 NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata) {
413 #define MAX_NAME_LEN 20
414  char name[MAX_NAME_LEN+1];
415  GB_ERROR error = NULp;
416 
417  while (!error) {
418  const char *p = strchr(stored, ';');
419  int len = p ? (p-stored) : (int)strlen(stored);
420  GBDATA *gb_species;
421 
422  gb_assert(len <= MAX_NAME_LEN);
423  memcpy(name, stored, len);
424  name[len] = 0;
425 
426  gb_species = GBT_find_species(gb_main, name);
427  if (gb_species) {
428  error = doit(gb_species, clientdata);
429  }
430  else {
431  error = "Some stored species where not found.";
432  }
433 
434  if (!p) break;
435  stored = p+1;
436  }
437 #undef MAX_NAME_LEN
438  return error;
439 }
440 
441 static GB_ERROR restore_mark(GBDATA *gb_species, int *) {
442  GB_write_flag(gb_species, 1);
443  return NULp;
444 }
445 
446 GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked) {
452  GBT_mark_all(gb_main, 0); // unmark all species
453  return GBT_with_stored_species(gb_main, stored_marked, restore_mark, NULp);
454 }
455 
456 // ---------------------------------
457 // read species information
458 
463  GB_CSTR result = GBT_read_char_pntr(gb_item, "name");
464  if (!result) result = GBS_global_string("<unnamed_%s>", GB_read_key_pntr(gb_item));
465  return result;
466 }
467 
468 const char *GBT_get_name(GBDATA *gb_item) {
472  GBDATA *gb_name = GB_entry(gb_item, "name");
473  if (!gb_name) return NULp;
474  return GB_read_char_pntr(gb_name);
475 }
476 
478  // goes to header: __ATTR__DEPRECATED_TODO("please use GBT_get_name or GBT_get_name_or_description()")
479 
480  // @@@ r18159 unintentionally broke SINA (binary) compatibility
481  // (remove this function when no longer needed)
482  return GBT_get_name_or_description(gb_item);
483 }
484 
485 GBDATA **GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr) {
487 
488  GBDATA **result = NULp;
489  long speciesCount = 0;
490 
491  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
492  gb_species;
493  gb_species = GBT_next_species(gb_species))
494  {
495  speciesCount ++;
496  }
497 
498  if (speciesCount) {
499  ARB_alloc(result, speciesCount);
500 
501  speciesCount = 0;
502  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
503  gb_species;
504  gb_species = GBT_next_species(gb_species))
505  {
506  result[speciesCount++] = gb_species;
507  }
508  }
509 
510  *speciesCountPtr = speciesCount;
511  return result;
512 }
513 
const char * GB_ERROR
Definition: arb_core.h:25
#define GENERATE_ID(num)
string result
#define MAX_NAME_LEN
void cut_tail(size_t byte_count)
Definition: arb_strbuf.h:145
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:441
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2561
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:203
bool GB_have_error()
Definition: arb_msg.cxx:338
GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked)
Definition: aditem.cxx:446
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
void cat(const char *from)
Definition: arb_strbuf.h:199
const char * GBT_get_name(GBDATA *gb_item)
Definition: aditem.cxx:468
GB_ERROR(* species_callback)(GBDATA *gb_species, int *clientdata)
Definition: arbdbt.h:82
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1722
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2494
GBDATA * GBT_expect_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:146
#define NOT4PERL
Definition: arbdb_base.h:23
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
GBDATA * GB_create_container(GBDATA *father, const char *key)
Definition: arbdb.cxx:1829
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
long GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:295
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:459
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:1656
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:33
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2892
GBDATA * GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name)
Definition: aditem.cxx:171
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
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:2796
GBDATA * GBT_find_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:177
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2524
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:1707
GBDATA ** GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr)
Definition: aditem.cxx:485
long GBT_mark_all_that(GBDATA *gb_main, int flag, bool(*condition)(GBDATA *, void *), void *cd)
Definition: aditem.cxx:334
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
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:262
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:2773
NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata)
Definition: aditem.cxx:404
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:377
GBDATA * GBT_find_or_create(GBDATA *father, const char *key, long delete_level)
Definition: adtools.cxx:42
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:116
NOT4PERL GB_CSTR GBT_read_name(GBDATA *gb_item)
Definition: aditem.cxx:477
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:904
GBDATA * gb_main
Definition: adname.cxx:32
GBDATA * GBT_next_SAI(GBDATA *gb_sai)
Definition: aditem.cxx:166
long GBT_count_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:372
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
char * release_memfriendly()
Definition: arb_strbuf.h:133
GB_ERROR mid(GBL_command_arguments *args, int start_index)
Definition: adlang1.cxx:907
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
GBDATA * GBT_get_species_data(GBDATA *gb_main)
Definition: aditem.cxx:105
void put(char c)
Definition: arb_strbuf.h:174