ARB
refentries.cxx
Go to the documentation of this file.
1 // ============================================================ //
2 // //
3 // File : refentries.cxx //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in June 2011 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ============================================================ //
11 
12 #include "refentries.h"
13 
14 #include <awt_config_manager.hxx>
15 #include <item_sel_list.h>
16 
17 #include <aw_root.hxx>
18 #include <aw_awars.hxx>
19 #include <aw_msg.hxx>
20 
21 #include <arbdbt.h>
22 #include <gb_aci.h>
23 
24 #include <cctype>
25 
26 namespace RefEntries {
27 
28  static ARB_ERROR generate_item_error(const char *format, ItemSelector& itemtype, GBDATA *gb_item) {
29  GBDATA *gb_main = GB_get_root(gb_item);
30  char *item_id = itemtype.generate_item_id(gb_main, gb_item);
31  char *item_description = GBS_global_string_copy("%s '%s'", itemtype.item_name, item_id);
32 
33  re_assert(strstr(format, "%s"));
34  ARB_ERROR error = GBS_global_string(format, item_description);
35 
36  free(item_description);
37  free(item_id);
38 
39  return error;
40  }
41 
42  const char *RefSelector::get_refs(ItemSelector& itemtype, GBDATA *gb_item) const {
43  const char *refs = NULp;
44  GBDATA *gb_refs = GB_entry(gb_item, field);
45  if (gb_refs) {
46  refs = GB_read_char_pntr(gb_refs);
47  }
48  else if (error_if_field_missing) {
49  char *err_format = GBS_global_string_copy("%%s has no field '%s'", field);
50  GB_export_error(generate_item_error(err_format, itemtype, gb_item).deliver());
51  free(err_format);
52  }
53  return refs;
54  }
55 
56  char *RefSelector::filter_refs(const char *refs, GBDATA *gb_item) const {
57  return refs ? GB_command_interpreter_in_env(refs, aci, GBL_simple_call_env(gb_item)) : NULp;
58  }
59 
60  static ARB_ERROR addRefsTo(DBItemSet& referred, ItemSelector& itemtype, GBDATA *gb_item, const RefSelector& ref) {
61  const char *refs = ref.get_refs(itemtype, gb_item);
62  char *filtered = ref.filter_refs(refs, gb_item);
63  ARB_ERROR error = GB_incur_error_if(!filtered);
64 
65  if (filtered) {
66  re_assert(!error);
67  ConstStrArray refNames;
68  GBT_split_string(refNames, filtered, ";, ", SPLIT_DROPEMPTY);
69  size_t refCount = refNames.size();
70 
71  for (size_t r = 0; r<refCount && !error; ++r) {
72  GBDATA *gb_main = GB_get_root(gb_item);
73  GBDATA *gb_referred = itemtype.find_item_by_id(gb_main, refNames[r]);
74  if (gb_referred) {
75  referred.insert(gb_referred);
76  }
77  else if (!ref.ignore_unknown_refs()) {
78  error = generate_item_error(GBS_global_string("%%s refers to unknown %s '%s'\n"
79  "in content of field '%s'\n"
80  "(content ='%s',\n"
81  " filtered='%s')\n",
82  itemtype.item_name, refNames[r],
83  ref.get_field(),
84  refs,
85  filtered),
86  itemtype, gb_item);
87  }
88  }
89 
90  free(filtered);
91  }
92 
93  return error;
94  }
95 
97  re_assert(range != QUERY_CURRENT_ITEM); // would need AW_root
98 
100  DBItemSet referred;
101 
102  {
103  GB_transaction ta(gb_main);
104 
105  for (GBDATA *gb_container = itemtype.get_first_item_container(gb_main, NULp, QUERY_ALL_ITEMS);
106  gb_container && !error;
107  gb_container = itemtype.get_next_item_container(gb_container, QUERY_ALL_ITEMS))
108  {
109  for (GBDATA *gb_item = itemtype.get_first_item(gb_container, range);
110  gb_item && !error;
111  gb_item = itemtype.get_next_item(gb_item, range))
112  {
113  error = addRefsTo(referred, itemtype, gb_item, refsel);
114  }
115  }
116  }
117 
118  if (!error) error = callback(gb_main, referred);
119  return error;
120  }
121 
123  DBItemSet referred;
124  ARB_ERROR error = addRefsTo(referred, itemtype, gb_item, refsel);
125  if (!error) error = callback(gb_main, referred);
126  return error;
127  }
128 
129 
130 
131  // ------------------------
132  // GUI related below
133 
134 
135 #define AWAR_MARKBYREF "awt/refs/"
136 #define AWAR_MARKBYREF_ALL AWAR_MARKBYREF "which"
137 #define AWAR_MARKBYREF_FIELD AWAR_MARKBYREF "field"
138 #define AWAR_MARKBYREF_IGNORE_MISSING AWAR_MARKBYREF "ignore_missing"
139 #define AWAR_MARKBYREF_IGNORE_UNKNOWN AWAR_MARKBYREF "ignore_unknown"
140 #define AWAR_MARKBYREF_FILTER AWAR_MARKBYREF "filter"
141 
142 #define AWAR_MARKBYREF_TEMP "tmp/awt/refs/"
143 #define AWAR_MARKBYREF_SELECTED AWAR_MARKBYREF_TEMP "selected"
144 #define AWAR_MARKBYREF_CONTENT AWAR_MARKBYREF_TEMP "content"
145 #define AWAR_MARKBYREF_RESULT AWAR_MARKBYREF_TEMP "result"
146 
148  AW_root *aw_root = aww->get_root();
150 
155 
156  ARB_ERROR error = reh->with_all_referred_items(range, refsel, ricb);
157  aw_message_if(error);
158  }
159 
160  static void refresh_result_cb(AW_root *aw_root, ReferringEntriesHandler *reh) {
161  ItemSelector& itemtype = reh->get_referring_item();
162  GBDATA *gb_main = reh->get_gbmain();
163  GB_transaction ta(gb_main);
164 
165  GBDATA *gb_item = itemtype.get_selected_item(gb_main, aw_root);
166  AW_awar *awar_selected = aw_root->awar(AWAR_MARKBYREF_SELECTED);
167  AW_awar *awar_result = aw_root->awar(AWAR_MARKBYREF_RESULT);
168 
169  awar_result->write_string("<no result>");
170  if (!gb_item) {
171  awar_selected->write_string(GBS_global_string("<no %s selected>", itemtype.item_name));
172  }
173  else {
174  char *id = itemtype.generate_item_id(gb_main, gb_item);
175  if (!id) {
176  awar_selected->write_string(GB_await_error());
177  }
178  else {
179  awar_selected->write_string(id);
180 
181  AW_awar *awar_content = aw_root->awar(AWAR_MARKBYREF_CONTENT);
182 
185  true, true);
186 
187  const char *refs = refsel.get_refs(itemtype, gb_item);
188 
189  if (!refs) {
190  char *err = GBS_string_eval(GB_await_error(), "\n=; ");
191  awar_content->write_string(err);
192  free(err);
193  }
194  else {
195  awar_content->write_string(refs);
196 
197  char *result = refsel.filter_refs(refs, gb_item);
198 
199  if (result) {
200  awar_result->write_string(result);
201  free(result);
202  }
203  else {
204  char *err = GBS_string_eval(GB_await_error(), "\n=;");
205  awar_result->write_string(err);
206  free(err);
207  }
208  }
209 
210  free(id);
211  }
212  }
213  }
214 
216  RootCallback refreshCb = makeRootCallback(refresh_result_cb, reh);
217 
218  aw_root->awar(AWAR_MARKBYREF_FIELD) ->add_callback(refreshCb);
219  aw_root->awar(AWAR_MARKBYREF_FILTER)->add_callback(refreshCb);
220  aw_root->awar(AWAR_SPECIES_NAME) ->add_callback(refreshCb); // @@@ hack
221  }
222 
223  void create_refentries_awars(AW_root *aw_root, AW_default aw_def) {
224  aw_root->awar_string(AWAR_MARKBYREF_FIELD, "used_rels", aw_def);
225  aw_root->awar_string(AWAR_MARKBYREF_FILTER, "/[0-9.]+[%]*://", aw_def);
226 
227  aw_root->awar_string(AWAR_MARKBYREF_SELECTED, "<no item>", aw_def);
228  aw_root->awar_string(AWAR_MARKBYREF_CONTENT, "<no content>", aw_def);
229  aw_root->awar_string(AWAR_MARKBYREF_RESULT, "<no result>", aw_def);
230 
231  aw_root->awar_int(AWAR_MARKBYREF_ALL, 0, aw_def);
232  aw_root->awar_int(AWAR_MARKBYREF_IGNORE_MISSING, 0, aw_def);
233  aw_root->awar_int(AWAR_MARKBYREF_IGNORE_UNKNOWN, 0, aw_def);
234  }
235 
237  { AWAR_MARKBYREF_ALL, "examine" },
238  { AWAR_MARKBYREF_FIELD, "field" },
239  { AWAR_MARKBYREF_IGNORE_MISSING, "ignore_missing" },
240  { AWAR_MARKBYREF_FILTER, "filter" },
241  { AWAR_MARKBYREF_IGNORE_UNKNOWN, "ignore_unknown" },
242 
243  { NULp, NULp }
244  };
245 
247  { "*relatives_used_by_aligner", "For use with 'used_rels' entry as\ngenerated by fast-aligner.", "field='used_rels';filter='/:[0-9]+//'" },
248  { "*next_relatives_of_listed", "For use with entries generated by\n'Search next relatives of listed'.", "field='tmp';filter='/[0-9.]+[%]://'" },
249 
250  { NULp, NULp, NULp }
251  };
252 
253  AW_window *create_refentries_window(AW_root *aw_root, ReferringEntriesHandler *reh, const char *window_id, const char *title, const char *help, client_area_builder build_client_area, const char *action, referred_item_handler action_cb) {
254  AW_window_simple *aws = new AW_window_simple;
255 
256  const int PAD = 10;
257 
258  aws->init(aw_root, window_id, title);
259  aws->at(PAD, PAD);
260  aws->auto_space(PAD, PAD);
261 
262  bind_result_refresh_cbs(aw_root, reh);
263 
264  aws->callback(AW_POPDOWN);
265  aws->create_button("CLOSE", "CLOSE", "C");
266 
267  aws->callback(makeHelpCallback(help));
268  aws->create_button("HELP", "HELP", "H");
269 
270  const int LABEL_LENGTH = 27;
271  const int LABEL_SHORTL = 10;
272  aws->label_length(LABEL_LENGTH);
273 
274  const int HEIGHT_IF = 32; // lineheight of attached input field
275  const int HEIGHT_SB = 25; // lineheight of attached selection butoon
276  const int HEIGHT_DF = 18; // lineheight of attached display field
277 
278  ItemSelector& itemtype = reh->get_referring_item();
279 
280  char *items_name = strdup(itemtype.items_name);
281  items_name[0] = toupper(items_name[0]);
282 
283  aws->at_newline();
284  aws->label(GBS_global_string("%s to examine", items_name));
285  aws->create_option_menu(AWAR_MARKBYREF_ALL);
286  aws->insert_option("Marked", "M", 0);
287  aws->insert_option("All", "A", 1);
288  aws->update_option_menu();
289 
290  aws->at_newline();
291  aws->at_attach_to(true, false, -PAD, HEIGHT_SB);
292  aws->label("Field containing references");
294 
295  aws->at_newline();
296  aws->label("Ignore if field missing?");
297  aws->create_toggle(AWAR_MARKBYREF_IGNORE_MISSING);
298 
299  aws->at_newline();
300  aws->at_attach_to(true, false, -PAD, HEIGHT_IF);
301  aws->label("Filter content by ACI");
302  aws->create_input_field(AWAR_MARKBYREF_FILTER, 30);
303 
304  aws->label_length(LABEL_SHORTL);
305 
306  aws->at_newline();
307  aws->at_attach_to(true, false, -PAD, HEIGHT_DF);
308  aws->label("Selected");
309  aws->create_button(NULp, AWAR_MARKBYREF_SELECTED, NULp, "+");
310 
311  aws->at_newline();
312  aws->at_attach_to(true, false, -PAD, HEIGHT_DF);
313  aws->label("Content");
314  aws->create_button(NULp, AWAR_MARKBYREF_CONTENT, NULp, "+");
315 
316  aws->at_newline();
317  aws->at_attach_to(true, false, -PAD, HEIGHT_DF);
318  aws->label("Result");
319  aws->create_button(NULp, AWAR_MARKBYREF_RESULT, NULp, "+");
320 
321  aws->label_length(LABEL_LENGTH);
322 
323  aws->at_newline();
324  aws->label("Ignore unknown references?");
325  aws->create_toggle(AWAR_MARKBYREF_IGNORE_UNKNOWN);
326 
327  if (build_client_area) build_client_area(aws);
328 
329  aws->at_newline();
330  aws->callback(makeWindowCallback(perform_refentries, reh, action_cb));
331  aws->create_autosize_button("ACTION", action, "");
332 
333  aws->at_attach(-PAD, PAD); // attach icon to NE corner
334  AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "mark_by_ref", markByRef_config_mapping, NULp, markByRef_predefined_config);
335  aws->at_unattach();
336 
337  aws->window_fit();
338 
339  free(items_name);
340 
341  refresh_result_cb(aw_root, reh);
342 
343  return aws;
344  }
345 
346 };
347 
#define AWAR_MARKBYREF_FIELD
Definition: refentries.cxx:137
ARB_ERROR with_all_referred_items(GBDATA *gb_item, const RefSelector &refsel, referred_item_handler cb)
Definition: refentries.cxx:122
ItemSelector & get_referring_item() const
Definition: refentries.h:83
bool ignore_unknown_refs() const
Definition: refentries.h:66
const char * item_name
Definition: items.h:66
string result
#define AWAR_MARKBYREF_FILTER
Definition: refentries.cxx:140
size_t size() const
Definition: arb_strarray.h:85
AliDataPtr format(AliDataPtr data, const size_t wanted_len, GB_ERROR &error)
Definition: insdel.cxx:615
void at(int x, int y)
Definition: AW_at.cxx:93
static void help()
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback &store_cb, const RestoreConfigCallback &load_or_reset_cb, const char *macro_id, const AWT_predefined_config *predef)
long read_int() const
Definition: AW_awar.cxx:184
#define AWAR_MARKBYREF_RESULT
Definition: refentries.cxx:145
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
const char * title
Definition: readseq.c:22
char * GBS_string_eval(const char *insource, const char *icommand)
Definition: admatch.cxx:699
void AW_POPDOWN(AW_window *window)
Definition: AW_window.cxx:52
static AWT_config_mapping_def markByRef_config_mapping[]
Definition: refentries.cxx:236
static AWT_predefined_config markByRef_predefined_config[]
Definition: refentries.cxx:246
GB_ERROR GB_incur_error_if(bool error_may_occur)
Definition: arb_msg.h:56
AW_awar * add_callback(const RootCallback &cb)
Definition: AW_awar.cxx:231
static void bind_result_refresh_cbs(AW_root *aw_root, ReferringEntriesHandler *reh)
Definition: refentries.cxx:215
void create_itemfield_selection_button(AW_window *aws, const FieldSelDef &selDef, const char *at)
const char * read_char_pntr() const
Definition: AW_awar.cxx:168
GB_ERROR GB_export_error(const char *error)
Definition: arb_msg.cxx:257
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
#define AWAR_MARKBYREF_IGNORE_UNKNOWN
Definition: refentries.cxx:139
WindowCallback makeHelpCallback(const char *helpfile)
Definition: aw_window.hxx:106
ARB_ERROR(* referred_item_handler)(GBDATA *gb_main, const DBItemSet &referred)
Definition: refentries.h:43
std::set< GBDATA * > DBItemSet
Definition: dbitem_set.h:22
AW_window * create_refentries_window(AW_root *aw_root, ReferringEntriesHandler *reh, const char *window_id, const char *title, const char *help, client_area_builder build_client_area, const char *action, referred_item_handler action_cb)
Definition: refentries.cxx:253
GBDATA *(* get_selected_item)(GBDATA *gb_main, AW_root *aw_root)
Definition: items.h:76
GBDATA *(* get_first_item_container)(GBDATA *, AW_root *, QUERY_RANGE)
Definition: items.h:70
static void error(const char *msg)
Definition: mkptypes.cxx:96
GBDATA * GB_get_root(GBDATA *gbd)
Definition: arbdb.cxx:1740
GBDATA *(* get_next_item_container)(GBDATA *, QUERY_RANGE)
Definition: items.h:71
const char * items_name
Definition: items.h:67
#define AWAR_SPECIES_NAME
static ARB_ERROR addRefsTo(DBItemSet &referred, ItemSelector &itemtype, GBDATA *gb_item, const RefSelector &ref)
Definition: refentries.cxx:60
void(* client_area_builder)(AW_window *aw_reh)
Definition: refentries.h:93
char *(* generate_item_id)(GBDATA *gb_main, GBDATA *gb_item)
Definition: items.h:59
AW_awar * awar(const char *awar)
Definition: AW_root.cxx:554
GBDATA *(* get_first_item)(GBDATA *, QUERY_RANGE)
Definition: items.h:73
static void perform_refentries(AW_window *aww, ReferringEntriesHandler *reh, referred_item_handler ricb)
Definition: refentries.cxx:147
#define AWAR_MARKBYREF_ALL
Definition: refentries.cxx:136
QUERY_RANGE
Definition: items.h:41
const char * get_field() const
Definition: refentries.h:67
#define re_assert(cond)
Definition: refentries.h:38
GBDATA *(* get_next_item)(GBDATA *, QUERY_RANGE)
Definition: items.h:74
AW_awar * awar_int(const char *var_name, long default_value=0, AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:580
static ARB_ERROR generate_item_error(const char *format, ItemSelector &itemtype, GBDATA *gb_item)
Definition: refentries.cxx:28
#define AWAR_MARKBYREF_IGNORE_MISSING
Definition: refentries.cxx:138
#define AWAR_MARKBYREF_SELECTED
Definition: refentries.cxx:143
ItemSelector & SPECIES_get_selector()
Definition: species.cxx:139
AW_root * get_root()
Definition: aw_window.hxx:359
#define AWAR_MARKBYREF_CONTENT
Definition: refentries.cxx:144
#define NULp
Definition: cxxforward.h:116
GBDATA *(* find_item_by_id)(GBDATA *gb_main, const char *id)
Definition: items.h:60
void create_refentries_awars(AW_root *aw_root, AW_default aw_def)
Definition: refentries.cxx:223
GB_ERROR write_string(const char *aw_string)
void GBT_split_string(ConstStrArray &dest, const char *namelist, const char *separator, SplitMode mode)
Definition: arb_strarray.h:223
NOT4PERL char * GB_command_interpreter_in_env(const char *str, const char *commands, const GBL_call_env &callEnv)
Definition: gb_aci.cxx:361
GB_transaction ta(gb_var)
const char * get_refs(ItemSelector &itemtype, GBDATA *gb_item) const
Definition: refentries.cxx:42
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
Definition: arbdb.cxx:904
GBDATA * gb_main
Definition: adname.cxx:32
static void refresh_result_cb(AW_root *aw_root, ReferringEntriesHandler *reh)
Definition: refentries.cxx:160
AW_awar * awar_string(const char *var_name, const char *default_value="", AW_default default_file=AW_ROOT_DEFAULT)
Definition: AW_root.cxx:570
CONSTEXPR long FIELD_FILTER_STRING
Definition: item_sel_list.h:41
#define AW_ROOT_DEFAULT
Definition: aw_base.hxx:106
GBDATA * GB_entry(GBDATA *father, const char *key)
Definition: adquery.cxx:334
char * filter_refs(const char *refs, GBDATA *gb_item) const
Definition: refentries.cxx:56
void aw_message_if(GB_ERROR error)
Definition: aw_msg.hxx:21
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:194