| 1 | // =============================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : ps_database.hxx // |
|---|
| 4 | // Purpose : // |
|---|
| 5 | // // |
|---|
| 6 | // Coded by Wolfram Foerster in October 2002 // |
|---|
| 7 | // Institute of Microbiology (Technical University Munich) // |
|---|
| 8 | // http://www.arb-home.de/ // |
|---|
| 9 | // // |
|---|
| 10 | // =============================================================== // |
|---|
| 11 | |
|---|
| 12 | #ifndef PS_DATABASE_HXX |
|---|
| 13 | #define PS_DATABASE_HXX |
|---|
| 14 | |
|---|
| 15 | #ifndef PS_NODE_HXX |
|---|
| 16 | #include "ps_node.hxx" |
|---|
| 17 | #endif |
|---|
| 18 | |
|---|
| 19 | using namespace std; |
|---|
| 20 | |
|---|
| 21 | class PS_Database FINAL_TYPE : PS_Callback, virtual Noncopyable { |
|---|
| 22 | private: |
|---|
| 23 | string FILE_ID; |
|---|
| 24 | |
|---|
| 25 | // file |
|---|
| 26 | PS_FileBuffer *db_file; |
|---|
| 27 | |
|---|
| 28 | // ID<->name mappings |
|---|
| 29 | Name2IDMap db_name2id_map; |
|---|
| 30 | ID2NameMap db_id2name_map; |
|---|
| 31 | |
|---|
| 32 | // tree |
|---|
| 33 | PS_NodePtr db_rootnode; |
|---|
| 34 | |
|---|
| 35 | bool readHeader(PS_FileBuffer *_file); |
|---|
| 36 | void writeHeader(PS_FileBuffer *_file); |
|---|
| 37 | |
|---|
| 38 | void readMappings(PS_FileBuffer *_file, ID2NameMap &_id2name_map, Name2IDMap &_name2id_map); |
|---|
| 39 | void writeMappings(PS_FileBuffer *_file, ID2NameMap &_id2name_map); |
|---|
| 40 | |
|---|
| 41 | void readTree(PS_FileBuffer *_file); |
|---|
| 42 | void writeTree(PS_FileBuffer *_file); |
|---|
| 43 | |
|---|
| 44 | // tree merging data structures and functions |
|---|
| 45 | ID2IDMap db_file2db_id_map; |
|---|
| 46 | PS_NodePtr db_path; |
|---|
| 47 | SpeciesID db_MAX_ID; |
|---|
| 48 | |
|---|
| 49 | void callback(void *_caller) OVERRIDE; |
|---|
| 50 | |
|---|
| 51 | public: |
|---|
| 52 | static const bool READONLY = true; |
|---|
| 53 | static const bool WRITEONLY = false; |
|---|
| 54 | |
|---|
| 55 | // |
|---|
| 56 | // I/O |
|---|
| 57 | // |
|---|
| 58 | bool load() { |
|---|
| 59 | if (!db_file->isReadonly()) return false; // cannot read a writeonly file |
|---|
| 60 | if (!readHeader(db_file)) return false; // not a file i wrote |
|---|
| 61 | readMappings(db_file, db_id2name_map, db_name2id_map); |
|---|
| 62 | readTree(db_file); |
|---|
| 63 | return true; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | bool save() { |
|---|
| 67 | if (db_file->isReadonly()) return false; // cannot write to a readonly file |
|---|
| 68 | writeHeader(db_file); |
|---|
| 69 | writeMappings(db_file, db_id2name_map); |
|---|
| 70 | writeTree(db_file); |
|---|
| 71 | return true; |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | bool saveTo(const char *_filename) { |
|---|
| 75 | PS_FileBuffer *file = new PS_FileBuffer(_filename, PS_FileBuffer::WRITEONLY); |
|---|
| 76 | writeHeader(file); |
|---|
| 77 | writeMappings(file, db_id2name_map); |
|---|
| 78 | writeTree(file); |
|---|
| 79 | if (file) delete file; |
|---|
| 80 | return true; |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | bool merge(const char *_other_db_name); |
|---|
| 84 | |
|---|
| 85 | // |
|---|
| 86 | // access tree |
|---|
| 87 | // |
|---|
| 88 | PS_NodePtr getRootNode() { |
|---|
| 89 | return db_rootnode; |
|---|
| 90 | } |
|---|
| 91 | const PS_NodePtr getConstRootNode() { |
|---|
| 92 | return db_rootnode; |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | // |
|---|
| 96 | // access mappings |
|---|
| 97 | // |
|---|
| 98 | bool getIDForName(SpeciesID &_id, const string &_name) { |
|---|
| 99 | Name2IDMapCIter it = db_name2id_map.find(_name); |
|---|
| 100 | if (it != db_name2id_map.end()) { |
|---|
| 101 | _id = it->second; |
|---|
| 102 | return true; |
|---|
| 103 | } |
|---|
| 104 | else { |
|---|
| 105 | return false; |
|---|
| 106 | } |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | bool getNameForID(const SpeciesID _id, string &_name) { |
|---|
| 110 | ID2NameMapCIter it = db_id2name_map.find(_id); |
|---|
| 111 | if (it != db_id2name_map.end()) { |
|---|
| 112 | _name = it->second; |
|---|
| 113 | return true; |
|---|
| 114 | } |
|---|
| 115 | else { |
|---|
| 116 | return false; |
|---|
| 117 | } |
|---|
| 118 | } |
|---|
| 119 | |
|---|
| 120 | bool insertMapping(SpeciesID _id, const string &_name) { |
|---|
| 121 | ID2NameMapCIter it = db_id2name_map.find(_id); |
|---|
| 122 | if (it != db_id2name_map.end()) { |
|---|
| 123 | return it->second.compare(_name) == 0; // return false if _name is not the string already stored for _id |
|---|
| 124 | } |
|---|
| 125 | else { |
|---|
| 126 | db_id2name_map[_id] = _name; |
|---|
| 127 | db_name2id_map[_name] = _id; |
|---|
| 128 | return true; |
|---|
| 129 | } |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | void setMappings(Name2IDMap &_name2id, ID2NameMap &_id2name) { |
|---|
| 133 | db_name2id_map.clear(); |
|---|
| 134 | db_name2id_map = Name2IDMap(_name2id); |
|---|
| 135 | db_id2name_map.clear(); |
|---|
| 136 | db_id2name_map = ID2NameMap(_id2name); |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | SpeciesID getMaxID() { |
|---|
| 140 | return db_id2name_map.rbegin()->first; |
|---|
| 141 | } |
|---|
| 142 | SpeciesID getMinID() { |
|---|
| 143 | return db_id2name_map.begin()->first; |
|---|
| 144 | } |
|---|
| 145 | long getSpeciesCount() { |
|---|
| 146 | return db_id2name_map.size(); |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | // |
|---|
| 150 | // utility-functions |
|---|
| 151 | // |
|---|
| 152 | bool isReadonly() { return db_file->isReadonly(); } |
|---|
| 153 | |
|---|
| 154 | // |
|---|
| 155 | // initialization-functions |
|---|
| 156 | // |
|---|
| 157 | void reinit(const char *_name, bool _readonly); // reinit. with new file |
|---|
| 158 | |
|---|
| 159 | PS_Database(const char *_name, bool _readonly) |
|---|
| 160 | : FILE_ID("PROBE_SET_DATABASE V1.0\n"), |
|---|
| 161 | db_file(NULp) |
|---|
| 162 | { |
|---|
| 163 | db_rootnode.setNull(); |
|---|
| 164 | reinit(_name, _readonly); |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | ~PS_Database() OVERRIDE { |
|---|
| 168 | if (db_file) delete db_file; |
|---|
| 169 | db_name2id_map.clear(); |
|---|
| 170 | db_id2name_map.clear(); |
|---|
| 171 | db_rootnode.setNull(); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | }; |
|---|
| 175 | |
|---|
| 176 | #else |
|---|
| 177 | #error ps_database.hxx included twice |
|---|
| 178 | #endif // PS_DATABASE_HXX |
|---|