source: tags/arb-6.0.5/MERGE/MG_checkfield.cxx

Last change on this file was 12267, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : MG_checkfield.cxx                                 //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "merge.hxx"
12
13#include <item_sel_list.h>
14#include <awt_sel_boxes.hxx>
15
16#include <aw_awar.hxx>
17#include <aw_root.hxx>
18#include <aw_msg.hxx>
19#include <arb_progress.h>
20
21#include <arbdbt.h>
22#include <arb_strbuf.h>
23
24#include <cctype>
25
26#define AWAR_CHECK AWAR_MERGE_TMP "chk/"
27
28#define AWAR_SOURCE_FIELD AWAR_CHECK "source"
29#define AWAR_DEST_FIELD   AWAR_CHECK "dest"
30#define AWAR_TOUPPER      AWAR_CHECK "ToUpper"
31#define AWAR_EXCLUDE      AWAR_CHECK "exclude"
32#define AWAR_CORRECT      AWAR_CHECK "correct"
33#define AWAR_ETAG         AWAR_CHECK "tag"
34
35
36static int gbs_cmp_strings(char *str1, char *str2, int *tab) { // returns 0 if strings are equal
37    char *s1, *s2;
38    int c1, c2;
39    s1 = str1;
40    s2 = str2;
41    int count = 10;
42    do {
43        do { c1 = *(s1++); } while (tab[c1] < 0);
44        do { c2 = *(s2++); } while (tab[c2] < 0);
45        if (tab[c1] != tab[c2]) {   // difference found
46            return 1;
47        }
48        count --;
49    } while (count && c1 && c2);
50    return 0;
51}
52
53
54static char *GBS_diff_strings(char *str1, char * &str2, char *exclude, long ToUpper, long correct,
55                       char **res1, char **res2, long *corrrected) {
56
57    char  buffer1[256];
58    char  buffer2[256];
59    char *dest1 = buffer1;
60    char *dest2 = buffer2;
61    char *s1, *s2;
62    int   c1, c2;
63    int   count = 3;
64    int   tab[256];
65    int   i;
66
67    s1 = str1;
68    s2 = str2;
69    *dest1 = 0;
70    *dest2 = 0;
71    tab[0] = 0;
72    char gapchar = '#';
73    if (strlen(exclude)) gapchar = exclude[0];
74    else    exclude = 0;
75
76    for (i=1; i<256; i++) {
77        tab[i] = i;
78        if (exclude && strchr(exclude, i)) {
79            tab[i] = -1;
80            continue;
81        }
82        if (ToUpper && i >= 'a' && i <= 'z') {
83            tab[i] = i-'a'+'A';
84        }
85    }
86
87    do {
88        do { c1 = *(s1++); } while (tab[c1] < 0);
89        do { c2 = *(s2++); } while (tab[c2] < 0);
90        if (tab[c1] != tab[c2]) {   // difference found
91            if (correct) {
92                // check substitution
93                {
94                    int c = s2[-1];
95                    s2[-1] = s1[-1];
96                    if (toupper(c1) == toupper(c2) ||
97                        !gbs_cmp_strings(s1, s2, &tab[0])) {
98                        *corrrected = 1;
99                        continue;
100                    }
101                    s2[-1] = c;
102                }
103
104                // check insertion in s2
105                if (!gbs_cmp_strings(s1-1, s2, &tab[0])) {
106                    s2[-1] = gapchar;
107                    do { c2 = *(s2++); } while (tab[c2] < 0); // eat s2
108                    *corrrected = 1;
109                    continue;
110                }
111                // check deletion in s2
112                if (!gbs_cmp_strings(s1, s2-1, &tab[0])) {
113                    int toins = c1;
114                    char *toinspos = s2-1;
115                    if (toinspos > str2) toinspos--;
116                    if (tab[(unsigned char)toinspos[0]]> 0) { // real insertion
117                        GBS_strstruct *str = GBS_stropen(strlen(str2+10));
118                        int pos = s2-str2-1;
119                        GBS_strncat(str, str2, pos);
120                        GBS_chrcat(str, toins);
121                        GBS_strcat(str, str2+pos);
122                        delete str2;
123                        str2 = GBS_strclose(str);
124                        s2 = str2+pos+1;
125                        *corrrected = 1;
126                        continue;
127                    }
128                    int side=1; // 0 = left   1= right
129                    if (tab[(unsigned char)s1[0]]<0) side = 0;
130                    if (! side) {
131                        while (toinspos > str2 &&
132                                tab[(unsigned char)toinspos[-1]] < 0) toinspos--;
133                    }
134                    toinspos[0] = toins;
135                    *corrrected = 1;
136                    do { c1 = *(s1++); } while (tab[c1] < 0); // eat s1
137                    continue;
138                }
139            }
140            if (count >= 0) {
141                sprintf(dest1, "%ti ", s1-str1-1);
142                sprintf(dest2, "%ti ", s2-str2-1);
143                dest1 += strlen(dest1);
144                dest2 += strlen(dest2);
145            }
146            count --;
147        }
148    } while (c1 && c2);
149
150    if (c1 || c2) {
151        sprintf(dest1, "... %ti ", s1-str1-1);
152        sprintf(dest2, "... %ti ", s2-str2-1);
153        dest1 += strlen(dest1);
154        dest2 += strlen(dest2);
155    }
156    if (count<0) {
157        sprintf(dest1, "and %i more", 1-count);
158        sprintf(dest2, "and %i more", 1-count);
159        dest1 += strlen(dest1);
160        dest2 += strlen(dest2);
161    }
162    if (strlen(buffer1)) {
163        *res1 = strdup(buffer1);
164        *res2 = strdup(buffer2);
165    }
166    else {
167        *res1 = 0;
168        *res2 = 0;
169    }
170    return 0;
171}
172
173int mg_count_queried(GBDATA *gb_main) {
174    int queried  = 0;
175    for (GBDATA *gb_spec = GBT_first_species(gb_main);
176         gb_spec;
177         gb_spec = GBT_next_species(gb_spec))
178    {
179        if (IS_QUERIED_SPECIES(gb_spec)) queried++;
180    }
181    return queried;
182}
183
184static void mg_check_field_cb(AW_window *aww) {
185    AW_root  *root    = aww->get_root();
186    GB_ERROR  error   = 0;
187    char     *source  = root->awar(AWAR_SOURCE_FIELD)->read_string();
188    char     *dest    = root->awar(AWAR_DEST_FIELD)->read_string();
189    char     *exclude = root->awar(AWAR_EXCLUDE)->read_string();
190    long      ToUpper = root->awar(AWAR_TOUPPER)->read_int();
191    long      correct = root->awar(AWAR_CORRECT)->read_int();
192    char     *tag     = root->awar(AWAR_ETAG)->read_string();
193
194    if (source[0] == 0) {
195        error = "Please select a source field";
196    }
197    else if (dest[0] == 0) {
198        error = "Please select a dest field";
199    }
200    else {
201        error = GB_begin_transaction(GLOBAL_gb_src);
202
203        if (!error) {
204            error = GB_begin_transaction(GLOBAL_gb_dst);
205
206            GBDATA *gb_src_species_data = GBT_get_species_data(GLOBAL_gb_src);
207            GBDATA *gb_dst_species_data = GBT_get_species_data(GLOBAL_gb_dst);
208
209            GBDATA *gb_src_species;
210            GBDATA *gb_dst_species;
211
212            // First step: count selected species
213            arb_progress progress("Checking fields", mg_count_queried(GLOBAL_gb_src));
214
215            // Delete all 'dest' fields in target database
216            for (gb_dst_species = GBT_first_species_rel_species_data(gb_dst_species_data);
217                 gb_dst_species && !error;
218                 gb_dst_species = GBT_next_species(gb_dst_species))
219            {
220                GBDATA *gbd    = GB_search(gb_dst_species, dest, GB_FIND);
221                if (gbd) error = GB_delete(gbd);
222            }
223
224            for (gb_src_species = GBT_first_species_rel_species_data(gb_src_species_data);
225                 gb_src_species && !error;
226                 gb_src_species = GBT_next_species(gb_src_species))
227            {
228                {
229                    GBDATA *gbd    = GB_search(gb_src_species, dest, GB_FIND);
230                    if (gbd) error = GB_delete(gbd);
231                }
232
233                if (!error) {
234                    if (IS_QUERIED_SPECIES(gb_src_species)) {
235                        const char *src_name = GBT_read_name(gb_src_species);
236                        gb_dst_species    = GB_find_string(gb_dst_species_data, "name", src_name, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
237                        if (!gb_dst_species) {
238                            aw_message(GBS_global_string("WARNING: Species %s not found in target DB", src_name));
239                        }
240                        else {
241                            gb_dst_species = GB_get_father(gb_dst_species);
242
243                            GBDATA *gb_src_field = GB_search(gb_src_species, source, GB_FIND);
244                            GBDATA *gb_dst_field = GB_search(gb_dst_species, source, GB_FIND);
245
246                            char *src_val = gb_src_field ? GB_read_as_tagged_string(gb_src_field, tag) : 0;
247                            char *dst_val = gb_dst_field ? GB_read_as_tagged_string(gb_dst_field, tag) : 0;
248
249                            if (src_val || dst_val) {
250                                char *src_positions = 0;
251                                char *dst_positions = 0;
252
253                                if (src_val && dst_val) {
254                                    long corrected = 0;
255                                    GBS_diff_strings(src_val, dst_val, exclude, ToUpper, correct, &src_positions, &dst_positions, &corrected);
256                                    if (corrected) {
257                                        error = GB_write_as_string(gb_dst_field, dst_val);
258                                        if (!error) GB_write_flag(gb_dst_species, 1);
259                                    }
260                                }
261                                else {
262                                    src_positions = GBS_global_string_copy("field missing in %s DB", src_val ? "other" : "this");
263                                    dst_positions = GBS_global_string_copy("field missing in %s DB", dst_val ? "other" : "this");
264                                }
265
266                                if (src_positions && !error) {
267                                    error             = GBT_write_string(gb_dst_species, dest, dst_positions);
268                                    if (!error) error = GBT_write_string(gb_src_species, dest, src_positions);
269                                }
270
271                                free(dst_positions);
272                                free(src_positions);
273                            }
274
275                            free(dst_val);
276                            free(src_val);
277                        }
278                        progress.inc_and_check_user_abort(error);
279                    }
280                }
281            }
282
283            error = GB_end_transaction(GLOBAL_gb_src, error);
284            error = GB_end_transaction(GLOBAL_gb_dst, error);
285        }
286    }
287    if (error) aw_message(error);
288
289    free(tag);
290    free(exclude);
291    free(dest);
292    free(source);
293}
294
295
296AW_window *create_mg_check_fields_window(AW_root *aw_root) {
297    aw_root->awar_string(AWAR_SOURCE_FIELD);
298    aw_root->awar_string(AWAR_DEST_FIELD, "tmp", AW_ROOT_DEFAULT);
299    aw_root->awar_string(AWAR_EXCLUDE, ".-", AW_ROOT_DEFAULT);
300    aw_root->awar_string(AWAR_ETAG, "");
301    aw_root->awar_int(AWAR_TOUPPER);
302    aw_root->awar_int(AWAR_CORRECT);
303
304    AW_window_simple *aws = new AW_window_simple;
305    aws->init(aw_root, "MERGE_COMPARE_FIELDS", "COMPARE DATABASE FIELDS");
306    aws->load_xfig("merge/seqcheck.fig");
307
308    aws->callback((AW_CB0)AW_POPDOWN);
309    aws->create_button("CLOSE", "CLOSE", "C");
310
311    aws->at("help");
312    aws->callback(makeHelpCallback("checkfield.hlp"));
313    aws->create_button("HELP", "HELP", "H");
314
315
316    aws->at("exclude");
317    aws->create_input_field(AWAR_EXCLUDE);
318
319    aws->at("toupper");
320    aws->create_toggle(AWAR_TOUPPER);
321
322    aws->at("correct");
323    aws->create_toggle(AWAR_CORRECT);
324
325    aws->at("tag");
326    aws->create_input_field(AWAR_ETAG, 6);
327
328    create_selection_list_on_itemfields(GLOBAL_gb_dst, aws, AWAR_SOURCE_FIELD, true, FIELD_FILTER_STRING,        "source", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
329    create_selection_list_on_itemfields(GLOBAL_gb_dst, aws, AWAR_DEST_FIELD,   true, (1<<GB_STRING)|(1<<GB_INT), "dest",   0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
330
331#if defined(WARN_TODO)
332#warning check code above. Maybe one call has to get GLOBAL_gb_src ?
333#endif
334
335
336    aws->at("go");
337    aws->highlight();
338    aws->callback(mg_check_field_cb);
339    aws->create_button("GO", "GO");
340
341    return aws;
342}
Note: See TracBrowser for help on using the repository browser.