source: branches/port5/SL/AW_NAME/AW_rename.cxx

Last change on this file was 6112, checked in by westram, 16 years ago
  • cut off default value when scanning additional field from arb_tcp.dat (completes patch [6084])
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.1 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <time.h>
6// #include <malloc.h>
7#include <arbdb.h>
8#include <arbdbt.h>
9#include <aw_root.hxx>
10#include <aw_device.hxx>
11#include <aw_window.hxx>
12#include <aw_awars.hxx>
13#include "AW_rename.hxx"
14#include "inline.h"
15
16#include <names_client.h>
17#include <servercntrl.h>
18#include <client.h>
19
20static const char *get_addid(GBDATA *gb_main) {
21    GB_transaction ta(gb_main);
22    GBDATA *gb_addid = GB_search(gb_main, AWAR_NAMESERVER_ADDID, GB_FIND);
23    return gb_addid ? GB_read_char_pntr(gb_addid) : 0;
24}
25
26static GB_ERROR set_addid(GBDATA *gb_main, const char *addid) {
27    GB_ERROR error    = GB_push_transaction(gb_main);
28    if (!error) error = GBT_write_string(gb_main, AWAR_NAMESERVER_ADDID, addid ? addid : "");
29    return GB_end_transaction(gb_main, error);
30}
31
32const char *AW_get_nameserver_addid(GBDATA *gb_main) {
33    // return the additional field used for nameserver connection
34    const char *addid = get_addid(gb_main);
35
36    aw_assert(addid); // the current DB has no entry AWAR_NAMESERVER_ADDID! (programmers error)
37    if (!addid) addid = ""; // NDEBUG fallback
38
39    return addid;
40}
41
42GB_ERROR AW_select_nameserver(GBDATA *gb_main, GBDATA *gb_other_main) {
43    // if entry AWAR_NAMESERVER_ADDID isnt defined yet, try to detect a reasonable value
44    // from arb_tcp.dat. Ask user if multiple servers are defined.
45    //
46    // if gb_other_main is defined try to use value from there.
47
48    const char *addid   = get_addid(gb_main);
49    GB_ERROR    error   = 0;
50
51    if (!addid && gb_other_main && gb_other_main != gb_main) {
52        // look whether main DB has a defined addid
53        addid = get_addid(gb_other_main);
54        set_addid(gb_main, addid);
55    }
56
57    if (!addid) {
58        const char * const *nameservers = GBS_get_arb_tcp_entries("ARB_NAME_SERVER*");
59
60        if (!nameservers) error = GB_await_error();
61        else {
62            int serverCount = 0;
63
64            for (int c = 0; nameservers[c]; c++) serverCount++;
65
66            if (serverCount == 0) {
67                error = GBS_global_string("No nameserver defined.");
68            }
69            else {
70                char **fieldNames = (char **)malloc(serverCount*sizeof(*fieldNames));
71                for (int c = 0; c<serverCount; c++) {
72                    const char *ipport = GBS_read_arb_tcp(nameservers[c]);
73                    fieldNames[c]      = nulldup(GBS_scan_arb_tcp_param(ipport, "-f")); // may return 0
74
75                    // parameter -f contains default value (e.g. '-fstart=1')
76                    if (fieldNames[c]) {
77                        char *equal = strchr(fieldNames[c], '=');
78                        if (equal) equal[0] = 0;
79                    }
80                }
81
82                if (serverCount == 1) { // exactly 1 server defined -> don't ask
83                    error = set_addid(gb_main, fieldNames[0]);
84                }
85                else { // let the user select which nameserver to use
86                    int         len     = serverCount; // commas+0term
87                    const char *nofield = "None (only 'acc')";
88
89                    for (int c = 0; c<serverCount; c++) {
90                        if (fieldNames[c]) len += strlen(fieldNames[c]);
91                        else len += strlen(nofield);
92                    }
93
94                    char *buttons = (char*)malloc(len);
95                    buttons[0]    = 0;
96                    for (int c = 0; c<serverCount; c++) {
97                        if (c) strcat(buttons, ",");
98                        strcat(buttons, fieldNames[c] ? fieldNames[c] : nofield);
99                    }
100
101                    int answer = aw_question("Select if and which additional DB field you want to use",
102                                             buttons, false, "namesadmin.hlp");
103
104                    error = set_addid(gb_main, fieldNames[answer]);
105
106                    free(buttons);
107                }
108               
109                for (int c = 0; c<serverCount; c++) free(fieldNames[c]);
110                free(fieldNames);
111            }
112        }
113    }
114
115    return error;
116}
117
118
119//  -----------------------------------
120//      class NameServerConnection
121//  -----------------------------------
122
123class NameServerConnection {
124private:
125    aisc_com   *link;
126    T_AN_LOCAL  locs;
127    T_AN_MAIN   com;
128    int         persistant;     // if true -> connection will not be closed
129    time_t      linktime;       // time, when link has been established
130
131    //  ----------------------------------
132    //      int init_local_com_names()
133    //  ----------------------------------
134    int init_local_com_names()
135    {
136        if (!link) return 1;    /*** create and init local com structure ***/
137        if (aisc_create(link, AN_MAIN, com,
138                        MAIN_LOCAL, AN_LOCAL, &locs,
139                        LOCAL_WHOAMI, "i bin der arb_tree",
140                        NULL)){
141            return 1;
142        }
143        return 0;
144    }
145
146    NameServerConnection(const NameServerConnection& other);
147    NameServerConnection& operator=(const NameServerConnection& /*other*/);
148
149    GB_ERROR reconnect(GBDATA *gb_main) { // reconnect ignoring consistency
150        int old_persistant = persistant;
151
152        printf("Reconnecting name server\n");
153
154        persistant = 0; // otherwise disconnect() won't disconnect
155        disconnect();
156        persistant = old_persistant; // restore previous persistancy
157
158        return connect(gb_main);
159    }
160
161    char *fieldUsedByServer(GB_ERROR& err) {
162        char *field = 0;
163        if (aisc_get(link, AN_MAIN, com,
164                     MAIN_ADD_FIELD, &field,
165                     NULL)) {
166            err = "Connection Problems with the NAME_SERVER";
167            aw_assert(field == 0);
168        }
169        return field;
170    }
171
172    GB_ERROR expectServerUsesField(const char *expected_field) {
173        GB_ERROR  err          = 0;
174        char     *server_field = fieldUsedByServer(err);
175
176        if (!err && strcmp(expected_field, server_field) != 0) {
177            err = GBS_global_string("Additional field doesn't match (expected='%s', server uses='%s')", expected_field, server_field);
178        }
179        free(server_field);
180        return err;
181    }
182
183public:
184
185    NameServerConnection() {
186        link       = 0;
187        locs       = 0;
188        com        = 0;
189        persistant = 0;
190    }
191    virtual ~NameServerConnection() {
192        gb_assert(persistant == 0); // forgot to remove persistancy ?
193        disconnect();
194    }
195
196    GB_ERROR connect(GBDATA *gb_main) {
197        GB_ERROR err = 0;
198        if (!link) {
199            char       *server_id;
200            const char *add_field = AW_get_nameserver_addid(gb_main);
201
202            if (add_field[0] == 0) { // no additional field -> traditional name server
203                server_id = strdup("ARB_NAME_SERVER");
204            }
205            else {
206                server_id = GBS_global_string_copy("ARB_NAME_SERVER_%s", add_field);
207                ARB_strupper(server_id);
208            }
209
210            err = arb_look_and_start_server(AISC_MAGIC_NUMBER, server_id, gb_main);
211
212            if (!err) {
213                const char *ipport = GBS_read_arb_tcp(server_id);
214                if (!ipport) err = GB_await_error();
215                else {
216                    link     = (aisc_com *)aisc_open(ipport, &com,AISC_MAGIC_NUMBER);
217                    linktime = time(0);
218
219                    if (init_local_com_names()) {
220                        err = GBS_global_string("Can't connect %s %s", server_id, ipport);
221                    }
222                    else {
223                        err = expectServerUsesField(add_field);
224                    }
225                }
226            }
227            free(server_id);
228        }
229        else {
230            long linkAge     = int(time(0)-linktime);
231            bool doReconnect = false;
232
233#if defined(DEBUG) && 0
234            // print information about name-server link age
235            static long lastage = -1;
236            if (linkAge != lastage) {
237                printf("Age of NameServerConnection: %li\n", linkAge);
238                lastage = linkAge;
239            }
240#endif // DEBUG
241
242            if (linkAge > (5*60)) { // perform a reconnect after 5 minutes
243                // Reason : The pipe to the name server breaks after some time
244                doReconnect = true;
245            }
246            else {
247                const char *add_field = AW_get_nameserver_addid(gb_main);
248                GB_ERROR    error     = expectServerUsesField(add_field);
249
250                if (error) {
251                    printf("Error: %s\n", error);
252                    doReconnect = true;
253                }
254            }
255
256            if (doReconnect) {
257                err = reconnect(gb_main);
258            }
259        }
260        return err;
261    }
262
263    void disconnect() {
264        if (persistant == 0) {
265            if (link) {
266                aisc_close(link);
267            }
268            link = 0;
269        }
270    }
271   
272    void persistancy(bool persist) {
273        if (persist) {
274            ++persistant;
275        }
276        else {
277            --persistant;
278            if (persistant <= 0) {
279                persistant = 0;
280                disconnect();
281            }
282        }
283    }
284
285
286    aisc_com *getLink() { return link; }
287    T_AN_LOCAL getLocs() { return locs; }
288};
289
290static NameServerConnection name_server;
291
292PersistantNameServerConnection::PersistantNameServerConnection() {
293    name_server.persistancy(true);
294}
295PersistantNameServerConnection::~PersistantNameServerConnection() {
296    name_server.persistancy(false);
297}
298
299// --------------------------------------------------------------------------------
300
301GB_ERROR AW_test_nameserver(GBDATA *gb_main) {
302    GB_ERROR err = name_server.connect(gb_main);
303    return err;
304}
305
306// --------------------------------------------------------------------------------
307
308GB_ERROR AWTC_generate_one_name(GBDATA *gb_main, const char *full_name, const char *acc, const char *addid, char*& new_name, bool openstatus, bool showstatus) {
309    // create a unique short name for 'full_name'
310    // the result is written into 'new_name' (as malloc-copy)
311    // if fails: GB_ERROR!=0 && new_name==0
312    // acc and addid may be 0
313
314    new_name = 0;
315    if (!acc) acc = "";
316
317    if (openstatus) {
318        aw_openstatus(GBS_global_string("Short name for '%s'", full_name));
319        showstatus = true;
320    }
321
322    if (showstatus) {
323        aw_status("Connecting to name server");
324        aw_status((double)0);
325    }
326   
327    GB_ERROR err = name_server.connect(gb_main);
328    if (err) return err;
329
330    if (showstatus) aw_status("Generating name");
331    static char *shrt = 0;
332    if (strlen(full_name)) {
333        if (aisc_nput(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
334                      LOCAL_FULL_NAME,  full_name,
335                      LOCAL_ACCESSION,  acc,
336                      LOCAL_ADDID,      addid ? addid : "",
337                      LOCAL_ADVICE,     "",
338                      NULL)){
339            err = "Connection Problems with the NAME_SERVER";
340        }
341        if (aisc_get(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
342                     LOCAL_GET_SHORT,   &shrt,
343                     NULL)){
344            err = "Connection Problems with the NAME_SERVER";
345        }
346    }
347
348    if (err) {
349        free(shrt);
350    }
351    else {
352        if (shrt) {
353            new_name = shrt;
354            shrt = 0;
355        }
356        else {
357            err = GB_export_errorf("Generation of short name for '%s' failed", full_name);
358        }
359    }
360
361    if (openstatus) aw_closestatus();
362    name_server.disconnect();
363
364    return err;
365}
366
367GB_ERROR AWTC_recreate_name(GBDATA *gb_species, bool update_status) {
368    GBDATA   *gb_main = GB_get_root(gb_species);
369
370    if (update_status) {
371        aw_status("Connecting to name server");
372        aw_status((double)0);
373    }
374
375    GB_ERROR error = name_server.connect(gb_main);
376    if (!error) {
377        if (update_status) aw_status("Generating name");
378
379        const char *add_field = AW_get_nameserver_addid(gb_main);
380        char       *ali_name  = GBT_get_default_alignment(gb_main);
381
382        GBDATA *gb_name      = GB_entry(gb_species, "name");
383        GBDATA *gb_full_name = GB_entry(gb_species, "full_name");
384        GBDATA *gb_acc       = GBT_gen_accession_number(gb_species, ali_name);
385        GBDATA *gb_addfield  = add_field[0] ? GB_entry(gb_species, add_field) : 0;
386
387        char *name      = gb_name?      GB_read_string   (gb_name)     : strdup("");
388        char *full_name = gb_full_name? GB_read_string   (gb_full_name): strdup("");
389        char *acc       = gb_acc?       GB_read_string   (gb_acc)      : strdup("");
390        char *addid     = gb_addfield?  GB_read_as_string(gb_addfield) : strdup("");
391       
392        int   deleted = 0;
393        char *shrt    = 0;
394
395        if (aisc_nput(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
396                      LOCAL_FULL_NAME,  full_name,
397                      LOCAL_ACCESSION,  acc,
398                      LOCAL_ADDID,      addid,
399                      LOCAL_ADVICE,     "",
400                      NULL) != 0 ||
401            aisc_get(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
402                     LOCAL_DEL_SHORT,   &deleted,
403                     NULL)  != 0 ||
404            aisc_get(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
405                     LOCAL_GET_SHORT,   &shrt,
406                     NULL)  !=0)
407        {
408            error = "Connection Problems with the NAME_SERVER";
409        }
410        name_server.disconnect();
411
412        if (!error) {
413            GBT_begin_rename_session(gb_main, 0);
414            error = GBT_rename_species(name, shrt, GB_TRUE);
415            if (error) {
416                if (GBT_find_species(gb_main, shrt)) { // it was a rename error
417                    int done = 0;
418                    error    = 0;
419                    for (int count = 2; !done && !error && count<10; count++) {
420                        const char *other_short = GBS_global_string("%s.%i", shrt, count);
421                        if (!GBT_find_species(gb_main, other_short)) {
422                            error            = GBT_rename_species(name, other_short, GB_TRUE);
423                            if (!error) done = 1;
424                        }
425                    }
426
427                    if (!done && !error) {
428                        error = "Failed to regenerate name. Please use 'Generate new names'";
429                    }
430                }
431            }
432
433            if (error) GBT_abort_rename_session();
434            else {
435                if (update_status) GBT_commit_rename_session(aw_status, aw_status);
436                else GBT_commit_rename_session(0, 0);
437            }
438        }
439
440        free(shrt);
441        free(addid);
442        free(acc);
443        free(full_name);
444        free(name);
445    }
446
447    return error;
448}
449
450char *AWTC_create_numbered_suffix(GB_HASH *species_name_hash, const char *shortname, GB_ERROR& warning) {
451    char *newshort = 0;
452    if (GBS_read_hash(species_name_hash, shortname)) {
453        int i;
454        newshort = (char *)GB_calloc(sizeof(char),strlen(shortname)+20);
455        for (i= 1 ; ; i++) {
456            sprintf(newshort, "%s.%i", shortname, i);
457            if (!GBS_read_hash(species_name_hash, newshort))break;
458        }
459
460        warning = "There are duplicated entries!!.\n"
461            "The duplicated entries contain a '.' character in field 'name'!\n"
462            "Please resolve this problem (see HELP in 'Generate new names' window)";
463    }
464    return newshort;
465}
466
467GB_ERROR AWTC_pars_names(GBDATA *gb_main, int update_status, bool *isWarningPtr)
468// rename species according to name_server
469// 'isWarning' is set to true, in case of duplicates-warning
470{
471    GB_ERROR err       = name_server.connect(gb_main);
472    bool     isWarning = false;
473   
474    if (!err) {
475        err = GBT_begin_rename_session(gb_main,1);
476        if (!err) {
477            char     *ali_name = GBT_get_default_alignment(gb_main);
478            GB_HASH  *hash     = GBS_create_hash(GBT_get_species_hash_size(gb_main), GB_IGNORE_CASE);
479            GB_ERROR  warning  = 0;
480            long      spcount  = 0;
481            long      count    = 0;
482
483            if (update_status) {
484                aw_status("Renaming");
485                spcount = GBT_get_species_count(gb_main);
486            }
487
488            const char *add_field = AW_get_nameserver_addid(gb_main);
489
490            for (GBDATA *gb_species = GBT_first_species(gb_main);
491                 gb_species && !err;
492                 gb_species = GBT_next_species(gb_species))
493            {
494                if (update_status) aw_status(count++/(double)spcount);
495
496                GBDATA *gb_name      = GB_entry(gb_species,"name");
497                GBDATA *gb_full_name = GB_entry(gb_species,"full_name");
498                GBDATA *gb_acc       = GBT_gen_accession_number(gb_species, ali_name);
499                GBDATA *gb_addfield  = add_field[0] ? GB_entry(gb_species, add_field) : 0;
500
501                char *name      = gb_name      ? GB_read_string   (gb_name)     : strdup("");
502                char *full_name = gb_full_name ? GB_read_string   (gb_full_name): strdup("");
503                char *acc       = gb_acc       ? GB_read_string   (gb_acc)      : strdup("");
504                char *addid     = gb_addfield  ? GB_read_as_string(gb_addfield) : strdup(""); // empty value will be set to default by nameserver
505
506                char *shrt = 0;
507
508                if (full_name[0] || acc[0] || addid[0]) {
509                    if (aisc_nput(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
510                                  LOCAL_FULL_NAME,  full_name,
511                                  LOCAL_ACCESSION,  acc,
512                                  LOCAL_ADDID,      addid,
513                                  LOCAL_ADVICE,     name,
514                                  NULL)){
515                        err = "Connection Problems with the NAME_SERVER";
516                    }
517                    if (aisc_get(name_server.getLink(), AN_LOCAL, name_server.getLocs(),
518                                 LOCAL_GET_SHORT,   &shrt,
519                                 NULL)){
520                        err = "Connection Problems with the NAME_SERVER";
521                    }
522                }
523                else {
524                    shrt = strdup(name);
525                }
526                if (!err) {
527                    char *newshrt = AWTC_create_numbered_suffix(hash, shrt, warning);
528                    if (newshrt) freeset(shrt, newshrt);
529
530                    GBS_incr_hash(hash,shrt);
531                    err = GBT_rename_species(name, shrt, GB_TRUE);
532                }
533
534                free(shrt);
535                free(addid);
536                free(acc);
537                free(full_name);
538                free(name);
539            }
540
541            if (err) {
542                GBT_abort_rename_session();
543            }
544            else {
545                // aw_status("Renaming species in trees");
546                // aw_status((double)0);
547                GBT_commit_rename_session(aw_status, aw_status);
548            }
549
550            GBS_free_hash(hash);
551            free(ali_name);
552
553            if (!err) {
554                err = warning;
555                if (warning) isWarning = true;
556            }
557        }
558        name_server.disconnect();
559    }
560
561    if (isWarningPtr) *isWarningPtr = isWarning;
562
563    return err;
564}
565
566
567void awt_rename_cb(AW_window *aww,GBDATA *gb_main)
568{
569    AWUSE(aww);
570    //  int use_advice = (int)aww->get_root()->awar(AWT_RENAME_USE_ADVICE)->read_int();
571    //  int save_data  = (int)aww->get_root()->awar(AWT_RENAME_SAVE_DATA)->read_int();
572    aw_openstatus("Generating new names");
573    aw_status("Contacting name server");
574    GB_ERROR error     = AWTC_pars_names(gb_main,1);
575    aw_closestatus();
576    if (error) aw_message(error);
577
578    aww->get_root()->awar(AWAR_TREE_REFRESH)->touch();
579}
580
581
582AW_window *AWTC_create_rename_window(AW_root *root, AW_CL gb_main)
583{
584    AWUSE(root);
585
586    AW_window_simple *aws = new AW_window_simple;
587    aws->init( root, "AUTORENAME_SPECIES", "AUTORENAME SPECIES");
588
589    aws->load_xfig("awtc/autoren.fig");
590
591    aws->callback( (AW_CB0)AW_POPDOWN);
592    aws->at("close");
593    aws->create_button("CLOSE", "CLOSE","C");
594
595    aws->callback( AW_POPUP_HELP,(AW_CL)"rename.hlp");
596    aws->at("help");
597    aws->create_button("HELP", "HELP","H");
598
599    aws->at("go");
600    aws->highlight();
601    aws->callback((AW_CB1)awt_rename_cb,gb_main);
602    aws->create_button("GO", "GO","G");
603
604    return (AW_window *)aws;
605}
606
607void AWTC_create_rename_awars(AW_root *root,AW_default db1){
608    root->awar_int( AWT_RENAME_USE_ADVICE, 0  ,     db1);
609    root->awar_int( AWT_RENAME_SAVE_DATA, 1  ,  db1);
610}
611
612UniqueNameDetector::UniqueNameDetector(GBDATA *gb_item_data, int additionalEntries) {
613    hash = GBS_create_hash(2*(GB_number_of_subentries(gb_item_data)+additionalEntries), GB_IGNORE_CASE);
614
615    for (GBDATA *gb_item = GB_child(gb_item_data); gb_item; gb_item = GB_nextChild(gb_item)) {
616        GBDATA *gb_name = GB_entry(gb_item, "name");
617        if (gb_name) { // item has name -> insert to hash
618            GBS_write_hash(hash, GB_read_char_pntr(gb_name), 1);
619        }
620    }
621}
622
623UniqueNameDetector::~UniqueNameDetector() { GBS_free_hash(hash); }
624
625static char *makeUniqueShortName(const char *prefix, UniqueNameDetector& existing) {
626    // generates a non-existing short-name (name starts with prefix)
627    //
628    // returns NULL if it fails
629
630    char *result     = 0;
631    int   prefix_len = strlen(prefix);
632
633    gb_assert(prefix_len<8); // prefix has to be shorter than 8 chars!
634    if (prefix_len<8) {
635        const int max_nums[8] = { 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10 };
636        static int next_try[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
637
638        int  max_num = max_nums[prefix_len];
639        char short_name[9];
640        strcpy(short_name, prefix);
641
642        char *dig_pos = short_name+prefix_len;
643        int   num     = next_try[prefix_len];
644        int   stop    = num ? num-1 : max_num;
645
646        while (num != stop) {
647            sprintf(dig_pos, "%i", num);
648            ++num;
649            if (!existing.name_known(short_name))  {
650                result = strdup(short_name);
651                break;
652            }
653            if (num == max_num && stop != max_num) num = 0;
654        }
655        if (num == max_num) num = 0;
656        next_try[prefix_len] = num;
657    }
658    return result;
659}
660
661char *AWTC_makeUniqueShortName(const char *prefix, UniqueNameDetector& existingNames) {
662    // generates a unique species name from prefix
663    // (prefix will be fillup with zero digits and then shortened down to first char)
664    //
665    // returns NULL if failed (and exports error)
666
667    int  len = strlen(prefix);
668    char p[9];
669    strncpy(p, prefix, 8);
670
671    if (len>8) len = 8;
672    else {
673        if (len == 0) p[len++] = 'x'; // don't use digit as first character
674        while (len<8) p[len++] = '0';
675    }
676
677    p[len] = 0;
678
679    char *result = 0;
680
681    for (int l = len-1; l>0 && !result; --l) {
682        p[l]   = 0;
683        result = makeUniqueShortName(p, existingNames);
684    }
685
686    gb_assert(!result || strlen(result) <= 8);
687    if (!result) GB_export_errorf("Failed to create unique shortname (prefix='%s')", prefix);
688
689    return result;
690}
691
692char *AWTC_generate_random_name(UniqueNameDetector& existingNames) {
693    char *new_species_name = 0;
694    char  short_name[9];
695    int   count            = 10000;
696
697    short_name[8] = 0;
698    while (count--) {
699        short_name[0] = 'a'+GB_random(26); // first character has to be alpha
700
701        for (int x=1; x<8; ++x) {
702            int r = GB_random(36); // rest may be alphanumeric
703            short_name[x] = r<10 ? ('0'+r) : ('a'+r-10);
704        }
705
706        if (!existingNames.name_known(short_name))  {
707            new_species_name = strdup(short_name);
708            break;
709        }
710    }
711
712    if (!new_species_name) {
713        aw_message("Failed to generate a random name - retrying (this might hang forever)");
714        return AWTC_generate_random_name(existingNames);
715    }
716
717    return new_species_name;
718}
719
720int AWTC_name_quality(const char *short_name) {
721    // result 0 = ok for external tools
722    //        1 = ok for ARB
723    //        2 = not ok
724
725    int len         = -1;
726    int alnum_count = 0;
727    int ascii_count = 0;
728
729    while (char c = short_name[++len]) {
730        alnum_count += (isalnum(c) != 0);
731        ascii_count += (c > 32 && c < 127);
732    }
733
734    if (len>0) {
735        if (len <= 8) {
736            if (len == alnum_count) return 0; // ok for external programs
737        }
738        if (len == ascii_count) return 1; // ok for ARB
739    }
740    return 2; // not ok
741}
Note: See TracBrowser for help on using the repository browser.