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 }
136 GBDATA *GBT_find_species(GBDATA *gb_main, const char *name) {
137  // Search for a species.
138  // Return found species or NULp (in this case an error MAY be exported).
139  //
140  // Note: If you expect the species to exists, use GBT_expect_species!
141  return GBT_find_item_rel_item_data(GBT_get_species_data(gb_main), "name", name);
142 }
143 
144 GBDATA *GBT_expect_species(GBDATA *gb_main, const char *name) {
145  // Returns an existing species or
146  // NULp (in that case an error is exported)
147  return GBT_expect_item_rel_item_data(GBT_get_species_data(gb_main), "name", name);
148 }
149 
150 // --------------------------------------------------------------------------------
151 
153  return GBT_find_or_create(gb_main, "extended_data", 7);
154 }
155 
156 // Search SAIs
158  return GB_entry(gb_sai_data, "extended");
159 }
161  return GB_entry(GBT_get_SAI_data(gb_main), "extended");
162 }
163 
165  gb_assert(GB_has_key(gb_sai, "extended"));
166  return GB_nextEntry(gb_sai);
167 }
168 
169 GBDATA *GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name) {
170  return GBT_find_item_rel_item_data(gb_sai_data, "name", name);
171 }
172 GBDATA *GBT_find_SAI(GBDATA *gb_main, const char *name) {
173  // Search for a SAI.
174  // Return found SAI or NULp (in this case an error MAY be exported).
175  //
176  // Note: If you expect the SAI to exist, use GBT_expect_SAI!
177  return GBT_find_item_rel_item_data(GBT_get_SAI_data(gb_main), "name", name);
178 }
179 
180 GBDATA *GBT_expect_SAI(GBDATA *gb_main, const char *name) {
181  // Returns an existing SAI or
182  // NULp (in that case an error is exported)
183  return GBT_expect_item_rel_item_data(GBT_get_SAI_data(gb_main), "name", name);
184 }
185 
186 // ---------------------
187 // count items
188 
189 static long GBT_get_item_count(GBDATA *gb_parent_of_container, const char *item_container_name) {
190  // returns elements stored in a container
191 
192  GBDATA *gb_item_data;
193  long count = 0;
194 
195  GB_push_transaction(gb_parent_of_container);
196  gb_item_data = GB_entry(gb_parent_of_container, item_container_name);
197  if (gb_item_data) count = GB_number_of_subentries(gb_item_data);
198  GB_pop_transaction(gb_parent_of_container);
199 
200  return count;
201 }
202 
204  return GBT_get_item_count(gb_main, "species_data");
205 }
206 
208  return GBT_get_item_count(gb_main, "extended_data");
209 }
210 
211 // --------------------------------------------------------------------------------
212 
213 static char *GBT_create_unique_item_identifier(GBDATA *gb_item_container, const char *id_field, const char *default_id) {
214  // returns an identifier not used by items in 'gb_item_container'
215  // 'id_field' is the entry that is used as identifier (e.g. 'name' for species)
216  // 'default_id' will be suffixed with a number to generate a unique id
217  //
218  // Note:
219  // * The resulting id may be longer than 8 characters
220  // * This function is slow, so just use in extra-ordinary situations
221 
222  GBDATA *gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, default_id);
223  char *unique_id;
224 
225  if (!gb_item) {
226  unique_id = ARB_strdup(default_id); // default_id is unused
227  }
228  else {
229  char *generated_id = ARB_alloc<char>(strlen(default_id)+20);
230  size_t min_num = 1;
231 
232 #define GENERATE_ID(num) sprintf(generated_id, "%s%zu", default_id, num);
233 
234  GENERATE_ID(min_num);
235  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
236 
237  if (gb_item) {
238  size_t num_items = GB_number_of_subentries(gb_item_container);
239  size_t max_num = 0;
240 
241  gb_assert(num_items); // otherwise deadlock below
242 
243  do {
244  max_num += num_items;
245  GENERATE_ID(max_num);
246  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
247  } while (gb_item && max_num >= num_items);
248 
249  if (max_num<num_items) { // overflow
250  char *uid;
251  generated_id[0] = 'a'+GB_random(26);
252  generated_id[1] = 'a'+GB_random(26);
253  generated_id[2] = 0;
254 
255  uid = GBT_create_unique_item_identifier(gb_item_container, id_field, generated_id);
256  strcpy(generated_id, uid);
257  free(uid);
258  }
259  else {
260  // max_num is unused
261  while ((max_num-min_num)>1) {
262  size_t mid = (min_num+max_num)/2;
263  gb_assert(mid != min_num && mid != max_num);
264 
265  GENERATE_ID(mid);
266  gb_item = GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id);
267 
268  if (gb_item) min_num = mid;
269  else max_num = mid;
270  }
271  GENERATE_ID(max_num);
272  gb_assert(!GBT_find_item_rel_item_data(gb_item_container, id_field, generated_id));
273  }
274  }
275  unique_id = generated_id;
276 
277 #undef GENERATE_ID
278  }
279 
280  return unique_id;
281 }
282 
283 char *GBT_create_unique_species_name(GBDATA *gb_main, const char *default_name) {
284  return GBT_create_unique_item_identifier(GBT_get_species_data(gb_main), "name", default_name);
285 }
286 
287 
288 // --------------------------------
289 // mark and unmark species
290 
292  // flag == 0 -> unmark
293  // flag == 1 -> mark
294  // flag == 2 -> invert
295 
296  GBDATA *gb_species;
297  GB_push_transaction(gb_main);
298 
299  if (flag == 2) {
300  for (gb_species = GBT_first_species(gb_main);
301  gb_species;
302  gb_species = GBT_next_species(gb_species))
303  {
304  GB_write_flag(gb_species, !GB_read_flag(gb_species));
305  }
306  }
307  else {
308  gb_assert(flag == 0 || flag == 1);
309 
310  for (gb_species = GBT_first_species(gb_main);
311  gb_species;
312  gb_species = GBT_next_species(gb_species))
313  {
314  GB_write_flag(gb_species, flag);
315  }
316  }
317  GB_pop_transaction(gb_main);
318 }
319 void GBT_mark_all_that(GBDATA *gb_main, int flag, bool (*condition)(GBDATA*, void*), void *cd) {
320  GBDATA *gb_species;
321  GB_push_transaction(gb_main);
322 
323  if (flag == 2) {
324  for (gb_species = GBT_first_species(gb_main);
325  gb_species;
326  gb_species = GBT_next_species(gb_species))
327  {
328  if (condition(gb_species, cd)) {
329  GB_write_flag(gb_species, !GB_read_flag(gb_species));
330  }
331  }
332  }
333  else {
334  gb_assert(flag == 0 || flag == 1);
335 
336  for (gb_species = GBT_first_species(gb_main);
337  gb_species;
338  gb_species = GBT_next_species(gb_species))
339  {
340  int curr_flag = GB_read_flag(gb_species);
341  if (curr_flag != flag && condition(gb_species, cd)) {
342  GB_write_flag(gb_species, flag);
343  }
344  }
345  }
346  GB_pop_transaction(gb_main);
347 }
348 
350  GB_transaction ta(gb_main);
352 }
353 
354 char *GBT_store_marked_species(GBDATA *gb_main, bool unmark_all) {
363  GBS_strstruct *out = GBS_stropen(10000);
364  GBDATA *gb_species;
365 
366  for (gb_species = GBT_first_marked_species(gb_main);
367  gb_species;
368  gb_species = GBT_next_marked_species(gb_species))
369  {
370  const char *name = GBT_get_name(gb_species);
371  if (name) {
372  GBS_strcat(out, name);
373  GBS_chrcat(out, ';');
374  if (unmark_all) GB_write_flag(gb_species, 0);
375  }
376  }
377 
378  GBS_str_cut_tail(out, 1); // remove trailing ';'
379  return GBS_strclose(out);
380 }
381 
382 NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata) {
391 #define MAX_NAME_LEN 20
392  char name[MAX_NAME_LEN+1];
393  GB_ERROR error = NULp;
394 
395  while (!error) {
396  const char *p = strchr(stored, ';');
397  int len = p ? (p-stored) : (int)strlen(stored);
398  GBDATA *gb_species;
399 
400  gb_assert(len <= MAX_NAME_LEN);
401  memcpy(name, stored, len);
402  name[len] = 0;
403 
404  gb_species = GBT_find_species(gb_main, name);
405  if (gb_species) {
406  error = doit(gb_species, clientdata);
407  }
408  else {
409  error = "Some stored species where not found.";
410  }
411 
412  if (!p) break;
413  stored = p+1;
414  }
415 #undef MAX_NAME_LEN
416  return error;
417 }
418 
419 static GB_ERROR restore_mark(GBDATA *gb_species, int *) {
420  GB_write_flag(gb_species, 1);
421  return NULp;
422 }
423 
424 GB_ERROR GBT_restore_marked_species(GBDATA *gb_main, const char *stored_marked) {
430  GBT_mark_all(gb_main, 0); // unmark all species
431  return GBT_with_stored_species(gb_main, stored_marked, restore_mark, NULp);
432 }
433 
434 // ---------------------------------
435 // read species information
436 
441  GB_CSTR result = GBT_read_char_pntr(gb_item, "name");
442  if (!result) result = GBS_global_string("<unnamed_%s>", GB_read_key_pntr(gb_item));
443  return result;
444 }
445 
446 const char *GBT_get_name(GBDATA *gb_item) {
450  GBDATA *gb_name = GB_entry(gb_item, "name");
451  if (!gb_name) return NULp;
452  return GB_read_char_pntr(gb_name);
453 }
454 
455 GBDATA **GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr) {
457 
458  GBDATA **result = NULp;
459  long speciesCount = 0;
460 
461  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
462  gb_species;
463  gb_species = GBT_next_species(gb_species))
464  {
465  speciesCount ++;
466  }
467 
468  if (speciesCount) {
469  ARB_alloc(result, speciesCount);
470 
471  speciesCount = 0;
472  for (GBDATA *gb_species = GBT_first_species_rel_species_data(gb_species_data);
473  gb_species;
474  gb_species = GBT_next_species(gb_species))
475  {
476  result[speciesCount++] = gb_species;
477  }
478  }
479 
480  *speciesCountPtr = speciesCount;
481  return result;
482 }
483 
void GBT_mark_all(GBDATA *gb_main, int flag)
Definition: aditem.cxx:291
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:319
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:419
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
GB_ERROR GB_end_transaction(GBDATA *gbd, GB_ERROR error)
Definition: arbdb.cxx:2525
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:424
GBDATA * GBT_first_SAI(GBDATA *gb_main)
Definition: aditem.cxx:160
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:446
GB_ERROR(* species_callback)(GBDATA *gb_species, int *clientdata)
Definition: arbdbt.h:82
GBDATA * GB_get_father(GBDATA *gbd)
Definition: arbdb.cxx:1696
GB_ERROR GB_push_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2458
GBDATA * GBT_expect_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:144
#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:1803
GBDATA * GBT_first_species(GBDATA *gb_main)
Definition: aditem.cxx:124
GB_CSTR GBT_get_name_or_description(GBDATA *gb_item)
Definition: aditem.cxx:437
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:1630
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:203
GBDATA * GBT_find_species(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:136
GBDATA * gb_species_data
Definition: adname.cxx:34
long GB_number_of_subentries(GBDATA *gbd)
Definition: arbdb.cxx:2856
GBDATA * GBT_find_SAI_rel_SAI_data(GBDATA *gb_sai_data, const char *name)
Definition: aditem.cxx:169
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:2760
GBDATA * GBT_find_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:172
GB_ERROR GB_pop_transaction(GBDATA *gbd)
Definition: arbdb.cxx:2488
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:1681
GBDATA ** GBT_gen_species_array(GBDATA *gb_main, long *speciesCountPtr)
Definition: aditem.cxx:455
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
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:264
GBDATA * GBT_get_SAI_data(GBDATA *gb_main)
Definition: aditem.cxx:152
#define gb_assert(cond)
Definition: arbdbt.h:11
void GB_write_flag(GBDATA *gbd, long flag)
Definition: arbdb.cxx:2737
NOT4PERL GB_ERROR GBT_with_stored_species(GBDATA *gb_main, const char *stored, species_callback doit, int *clientdata)
Definition: aditem.cxx:382
static long GBT_get_item_count(GBDATA *gb_parent_of_container, const char *item_container_name)
Definition: aditem.cxx:189
GBDATA * GBT_expect_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:180
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:354
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:157
long GBT_get_SAI_count(GBDATA *gb_main)
Definition: aditem.cxx:207
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:213
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:874
GBDATA * gb_main
Definition: adname.cxx:33
GBDATA * GBT_next_SAI(GBDATA *gb_sai)
Definition: aditem.cxx:164
long GBT_count_marked_species(GBDATA *gb_main)
Definition: aditem.cxx:349
char * GBT_create_unique_species_name(GBDATA *gb_main, const char *default_name)
Definition: aditem.cxx:283
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