source: branches/profile/MERGE/MG_checkfield.cxx

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