source: tags/ms_r16q2/GENOM_IMPORT/MetaInfo.cxx

Last change on this file was 8891, checked in by westram, 12 years ago
  • fixed cppcheck warnings
File size: 6.6 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : MetaInfo.cxx                                       //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2006   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "MetaInfo.h"
13#include <RegExpr.hxx>
14
15
16using namespace std;
17
18void Reference::add(const string& field, const string& content)
19{
20    gi_assert(!field.empty());
21    gi_assert(!content.empty());
22
23    stringMapIter existing = entries.find(field);
24    if (existing != entries.end()) {
25        throw GBS_global_string("Duplicated reference entry for '%s'", field.c_str());
26    }
27    entries[field] = content;
28}
29
30const string *Reference::get(const string& field) const
31{
32    stringMapCIter existing = entries.find(field);
33    return (existing != entries.end()) ? &existing->second :  0;
34}
35
36void Reference::getKeys(stringSet& keys) const
37{
38    stringMapCIter e = entries.end();
39    for (stringMapCIter i = entries.begin(); i != e; ++i) {
40        keys.insert(i->first);
41    }
42}
43
44// --------------------------------------------------------------------------------
45
46typedef vector<Reference> RefVector;
47DEFINE_ITERATORS(RefVector);
48
49void References::start()
50{
51    refs.push_back(Reference());
52    latest = &refs.back();
53    ref_count++;
54}
55
56
57void References::getKeys(stringSet& keys) const
58{
59    keys.clear();
60    RefVectorCIter e = refs.end();
61    for (RefVectorCIter i = refs.begin(); i != e; ++i) {
62        i->getKeys(keys);
63    }
64}
65
66string References::tagged_content(const string& refkey) const
67{
68    string content;
69
70    if (ref_count == 1) { // only one reference -> don't tag
71        RefVectorCIter  i           = refs.begin();
72        const string   *ref_content = i->get(refkey);
73
74        gi_assert(ref_content);
75        content = *ref_content;
76    }
77    else {
78        int            count = 1;
79        RefVectorCIter e     = refs.end();
80
81        for (RefVectorCIter i = refs.begin(); i != e; ++i, ++count) {
82            const string *ref_content = i->get(refkey);
83            if (ref_content) {
84                if (!content.empty()) content.append(1, ' ');
85                content.append(GBS_global_string("[REF%i] ", count));
86                content.append(*ref_content);
87            }
88        }
89    }
90    return content;
91}
92
93#if defined(DEBUG)
94void References::dump() const
95{
96    stringSet     keys;
97    getKeys(keys);
98    stringSetIter e = keys.end();
99
100    for (stringSetIter i = keys.begin(); i != e; ++i) {
101        string tagged = tagged_content(*i);
102        printf("%s='%s'\n", i->c_str(), tagged.c_str());
103    }
104}
105#endif // DEBUG
106
107enum DBID_TYPE {
108    DBID_STANDARD,
109    DBID_ACCEPT,
110    DBID_ILLEGAL,
111};
112struct DBID {
113    const char *id;
114    DBID_TYPE   type;
115    const char *arb_field;
116};
117
118// see http://www.ebi.ac.uk/embl/Documentation/User_manual/usrman.html#3_4_10_4
119
120static const DBID dbid_definition[] = {             // accepted DBIDs (EMBL 'RX'-tag)
121    { "DOI",      DBID_STANDARD, "doi_id"      },
122    { "PUBMED",   DBID_STANDARD, "pubmed_id"   },
123    { "AGRICOLA", DBID_STANDARD, "agricola_id" },
124    { "MEDLINE",  DBID_ACCEPT,   "medline_id"  }, // non-standard, but common
125
126    { NULL, DBID_ILLEGAL, NULL }, // end marker
127};
128
129void References::add_dbid(const string& content) {
130    // add embl 'RX' entry
131    //
132    // * 'content' has \n inserted at original line breaks and
133    //   contains database references like 'MEDLINE; id.' or 'PUBMED; id.' etc.
134    // * Multiple database references may be concatenated (each starts on it's own line)
135    // * 'id' is possibly split up on several lines
136
137    RegExpr         reg_dbid("^([A-Z]+);\\s+|\n([A-Z]+);\\s+", false);
138    const RegMatch *dbid_start = reg_dbid.match(content);
139
140    if (!dbid_start) {
141        throw GBS_global_string("Expected database reference id (e.g. 'DOI; ' or 'PUBMED; ')");
142    }
143    else {
144        re_assert(reg_dbid.subexpr_count() == 2);
145        while (dbid_start) {
146            const RegMatch *sub = reg_dbid.subexpr_match(1);
147            if (!sub) sub       = reg_dbid.subexpr_match(2);
148            re_assert(sub);
149
150            string dbid     = sub->extract(content);
151            size_t id_start = dbid_start->posBehindMatch();
152
153            dbid_start = reg_dbid.match(content, id_start); // search for start of next db-id
154
155            DBID_TYPE   type      = DBID_ILLEGAL;
156            const char *arb_field = 0;
157            for (int m = 0; ; m++) {
158                const char *name = dbid_definition[m].id;
159                if (!name) break;
160                if (dbid == name) {
161                    type      = dbid_definition[m].type;
162                    arb_field = dbid_definition[m].arb_field;
163                    break;
164                }
165            }
166            if (type == DBID_ILLEGAL) throw GBS_global_string("Unknown DBID '%s'", dbid.c_str());
167
168            string id = content.substr(id_start, dbid_start ? dbid_start->pos()-id_start : string::npos);
169            if (id.empty()) throw GBS_global_string("Empty database reference for '%s'", dbid.c_str());
170            if (id[id.length()-1] != '.') throw GBS_global_string("Expected terminal '.' in '%s'", id.c_str());
171            id.erase(id.length()-1); // remove terminal '.'
172            add(arb_field, id);
173        }
174    }
175}
176
177// --------------------------------------------------------------------------------
178
179void MetaInfo::add(const MetaTag *meta, const string& content, bool allow_multiple_entries) {
180    stringMapIter existing = entries.find(meta->field);
181    if (existing != entries.end()) { // existing entry
182        if (!allow_multiple_entries) {
183            throw GBS_global_string("Multiple occurrences of tag '%s'", meta->tag.c_str());
184        }
185        existing->second += '\n'+content; // append content
186    }
187    else { // non-existing content
188        entries[meta->field] = content;
189    }
190}
191
192const string& MetaInfo::getAccessionNumber() const {
193    stringMapCIter found = entries.find("acc");
194    if (found == entries.end()) {
195        static string no_acc("<Missing accession number>");
196        return no_acc;
197    }
198    return found->second;
199}
200
201#if defined(DEBUG)
202void MetaInfo::dump() const
203{
204    stringMapCIter e = entries.end();
205
206    printf("MetaInfo:\n");
207    for (stringMapCIter i = entries.begin(); i != e; ++i) {
208        printf("%s='%s'\n", i->first.c_str(), i->second.c_str());
209    }
210}
211#endif // DEBUG
Note: See TracBrowser for help on using the repository browser.