source: gsdl/trunk/lib/dbclass.cpp@ 15655

Last change on this file since 15655 was 15655, checked in by mdewsnip, 16 years ago

(Adding new DB support) Created default implementations of getinfo() and setinfo() in dbclass so they don't necessarily be re-implemented for every subclass.

File size: 8.2 KB
Line 
1/**********************************************************************
2 *
3 * dbclass.cpp --
4 * Copyright (C) 1999-2008 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "dbclass.h"
27#include "OIDtools.h"
28#include "unitool.h"
29
30
31dbclass::~dbclass() {}
32
33
34// May be overwritten by subclasses; returns true if exists
35bool dbclass::exists (const text_t& key)
36{
37 text_t data;
38 return getkeydata (key, data);
39}
40
41
42// May be overwritten by subclasses; returns true on success
43bool dbclass::getinfo (const text_t& key, infodbclass &info)
44{
45 text_t data;
46 if (!getkeydata(key, data)) return false;
47
48 // Use getinfoline() to parse the data value into the infodbclass object
49 text_t::iterator data_iterator = data.begin();
50 text_t ikey, ivalue;
51 info.clear();
52 while (getinfoline(data_iterator, data.end(), ikey, ivalue))
53 {
54 info.addinfo(ikey, ivalue);
55 }
56
57 return true;
58}
59
60
61// returns true on success
62bool dbclass::getinfoline (text_t::iterator &here, text_t::iterator end,
63 text_t &key, text_t &value)
64{
65 key.clear();
66 value.clear();
67
68 // ignore white space
69 while (here != end && is_unicode_space (*here)) ++here;
70
71 // get the '<'
72 if (here == end || *here != '<') return false;
73 ++here;
74
75 // get the key
76 while (here != end && *here != '>') {
77 key.push_back(*here);
78 ++here;
79 }
80
81 // get the '>'
82 if (here == end || *here != '>') return false;
83 ++here;
84
85 // get the value
86 while (here != end && *here != '\n') {
87 if (*here == '\\') {
88 // found escape character
89 ++here;
90 if (here != end) {
91 if (*here == 'n') value.push_back ('\n');
92 else if (*here == 'r') value.push_back ('\r');
93 else value.push_back(*here);
94 }
95
96 } else {
97 // a normal character
98 value.push_back(*here);
99 }
100
101 ++here;
102 }
103
104 return true;
105}
106
107
108// returns true on success
109bool dbclass::setinfo (const text_t &key, const infodbclass &info)
110{
111 text_t subkey;
112 text_t data;
113
114 // get all the keys and values
115 infodbclass::const_iterator info_here = info.begin();
116 infodbclass::const_iterator info_end = info.end();
117 while (info_here != info_end) {
118 // add the key
119 subkey.clear();
120 subkey.push_back('<');
121 text_t::const_iterator subkey_here = (*info_here).first.begin();
122 text_t::const_iterator subkey_end = (*info_here).first.end();
123 while (subkey_here != subkey_end) {
124 if (*subkey_here == '>') {
125 subkey.push_back('\\'); subkey.push_back('>');
126 } else if (*subkey_here == '\n') {
127 subkey.push_back('\\'); subkey.push_back('n');
128 } else if (*subkey_here == '\r') {
129 subkey.push_back('\\'); subkey.push_back('r');
130 } else if (*subkey_here == '\\') {
131 subkey.push_back('\\'); subkey.push_back('\\');
132 } else {
133 subkey.push_back (*subkey_here);
134 }
135 ++subkey_here;
136 }
137 subkey.push_back('>');
138
139 // add the values
140 text_tarray::const_iterator subvalue_here = (*info_here).second.begin();
141 text_tarray::const_iterator subvalue_end = (*info_here).second.end();
142 while (subvalue_here != subvalue_end) {
143 data += subkey;
144
145 text_t::const_iterator thissubvalue_here = (*subvalue_here).begin();
146 text_t::const_iterator thissubvalue_end = (*subvalue_here).end();
147 while (thissubvalue_here != thissubvalue_end) {
148 if (*thissubvalue_here == '>') {
149 data.push_back('\\'); data.push_back('>');
150 } else if (*thissubvalue_here == '\n') {
151 data.push_back('\\'); data.push_back('n');
152 } else if (*thissubvalue_here == '\r') {
153 data.push_back('\\'); data.push_back('r');
154 } else if (*thissubvalue_here == '\\') {
155 data.push_back('\\'); data.push_back('\\');
156 } else {
157 data.push_back (*thissubvalue_here);
158 }
159
160 ++thissubvalue_here;
161 }
162
163 data.push_back('\n');
164 ++subvalue_here;
165 }
166
167 ++info_here;
168 }
169
170 return setkeydata(key, data);
171}
172
173
174// replaces the .fc, .lc, .pr, .rt, .ns and .ps syntax (first child,
175// last child, parent, root, next sibling, previous sibling)
176// it expects child, parent, etc. to exist if syntax has been used
177// so you should test before using
178text_t dbclass::translate_OID (const text_t &inOID, infodbclass &info)
179{
180 if (inOID.size() < 4) return inOID;
181 if (findchar (inOID.begin(), inOID.end(), '.') == inOID.end()) return inOID;
182
183 text_t OID = inOID;
184 text_tarray tailarray;
185 text_t tail = substr (OID.end()-3, OID.end());
186 if (tail == ".rt") {
187 get_top (inOID, OID);
188 return OID;
189 }
190 while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||
191 tail == ".ns" || tail == ".ps") {
192 tailarray.push_back(tail);
193 OID.erase (OID.end()-3, OID.end());
194 tail = substr (OID.end()-3, OID.end());
195 if (tail == ".rt") {
196 get_top (inOID, OID);
197 return OID;
198 }
199 }
200
201 if (tailarray.empty()) return inOID;
202 text_tarray::const_iterator begin = tailarray.begin();
203 text_tarray::const_iterator here = tailarray.end() - 1;
204
205 while (here >= begin) {
206
207 if (*here == ".fc")
208 get_first_child (OID, info);
209 else if (*here == ".lc")
210 get_last_child (OID, info);
211 else if (*here == ".pr")
212 OID = get_parent (OID);
213 else if (*here == ".ns")
214 get_next_sibling (OID, info);
215 else if (*here == ".ps")
216 get_previous_sibling (OID, info);
217
218 if (here == begin)
219 break;
220 --here;
221 }
222
223 return OID;
224}
225
226
227void dbclass::get_first_child (text_t &OID, infodbclass &info)
228{
229 text_t firstchild;
230 if (getinfo (OID, info)) {
231 text_t &contains = info["contains"];
232 if (!contains.empty()) {
233 text_t parent = OID;
234 getdelimitstr (contains.begin(), contains.end(), ';', firstchild);
235 if (firstchild.empty()) OID = contains;
236 else OID = firstchild;
237 if (*(OID.begin()) == '"') translate_parent (OID, parent);
238 }
239 }
240}
241
242
243void dbclass::get_last_child (text_t &OID, infodbclass &info)
244{
245 text_tarray children;
246 if (getinfo (OID, info)) {
247 text_t &contains = info["contains"];
248 if (!contains.empty()) {
249 text_t parent = OID;
250 splitchar (contains.begin(), contains.end(), ';', children);
251 OID = children.back();
252 if (*(OID.begin()) == '"') translate_parent (OID, parent);
253 }
254 }
255}
256
257
258void dbclass::get_next_sibling (text_t &OID, infodbclass &info)
259{
260 text_tarray siblings;
261 text_t parent = get_parent (OID);
262
263 if (getinfo (parent, info)) {
264 text_t &contains = info["contains"];
265 if (!contains.empty()) {
266 splitchar (contains.begin(), contains.end(), ';', siblings);
267 text_tarray::const_iterator here = siblings.begin();
268 text_tarray::const_iterator end = siblings.end();
269 text_t shrunk_OID = OID;
270 shrink_parent (shrunk_OID);
271 while (here != end) {
272 if (*here == shrunk_OID && (here+1 != end)) {
273 OID = *(here+1);
274 if (*(OID.begin()) == '"') translate_parent (OID, parent);
275 break;
276 }
277 ++here;
278 }
279 }
280 }
281}
282
283
284void dbclass::get_previous_sibling (text_t &OID, infodbclass &info)
285{
286 text_tarray siblings;
287 text_t parent = get_parent (OID);
288
289 if (getinfo (parent, info)) {
290 text_t &contains = info["contains"];
291 if (!contains.empty()) {
292 splitchar (contains.begin(), contains.end(), ';', siblings);
293 text_tarray::const_iterator here = siblings.begin();
294 text_tarray::const_iterator end = siblings.end();
295 text_t shrunk_OID = OID;
296 shrink_parent (shrunk_OID);
297 while (here != end) {
298 if (*here == shrunk_OID && (here != siblings.begin())) {
299 OID = *(here-1);
300 if (*(OID.begin()) == '"') translate_parent (OID, parent);
301 break;
302 }
303 ++here;
304 }
305 }
306 }
307}
Note: See TracBrowser for help on using the repository browser.