00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 namespace stactiverecord {
00034 template <class Klass>
00035 class Record : public CUDPropertyRegister {
00036 private:
00037 Sar_Dbi *_db;
00038 bool dirty;
00039 SarMap<std::string> svalues;
00040 SarMap<int> ivalues;
00041 SarMap< SarVector<int> > rvalues;
00042 SarMap<DateTime> dtvalues;
00043
00044 bool initial_update;
00045
00046
00047 coltype clear_other_values(std::string colname, coltype ct) {
00048 coltype existing_ct = type(colname);
00049 if(existing_ct != NONE && existing_ct != ct) {
00050 std::string coltypename;
00051 coltype_to_name(existing_ct, coltypename);
00052 debug("getting rid of old value for " + colname + " and type " + coltypename);
00053 if(is_registered_new(colname, existing_ct)) {
00054 unregister_new(colname, ct);
00055 } else if(is_registered_changed(colname, existing_ct)) {
00056 unregister_change(colname, existing_ct);
00057 }
00058 register_delete(colname, existing_ct);
00059 switch(ct) {
00060 case INTEGER:
00061 ivalues.remove(colname);
00062 break;
00063 case STRING:
00064 svalues.remove(colname);
00065 break;
00066 case DATETIME:
00067 dtvalues.remove(colname);
00068 break;
00069 };
00070 }
00071 };
00072 protected:
00073 Record() : CUDPropertyRegister(), classname(Klass::classname), id(-1), _db(Sar_Dbi::dbi), initial_update(false) {
00074 check_classname(classname);
00075 _db->initialize_tables(classname);
00076 dirty = true;
00077 };
00078 Record(int _id) : CUDPropertyRegister(), classname(Klass::classname), id(_id), _db(Sar_Dbi::dbi), initial_update(false) {
00079 check_classname(classname);
00080 _db->initialize_tables(classname);
00081 if(!_db->exists(classname, id))
00082 throw Sar_NoSuchObjectException("There is no " + classname + " with given id.");
00083 };
00084 public:
00085 int id;
00086 std::string classname;
00087
00089 void update() {
00090 if(id == -1)
00091 throw Sar_NoSuchObjectException("Cannot update an object with id of -1");
00092 else if(!_db->exists(classname, id))
00093 throw Sar_NoSuchObjectException("The object id given does not exist.");
00094 else {
00095 _db->get(id, classname, svalues);
00096 _db->get(id, classname, ivalues);
00097 _db->get(id, classname, rvalues);
00098 _db->get(id, classname, dtvalues);
00099 initial_update = true;
00100 }
00101 };
00102
00103 bool operator==(const Record& other) const {
00104 return (this->id == other.id && this->classname == other.classname);
00105 };
00106
00107 bool operator!=(const Record &other) const {
00108 return !(*this == other);
00109 }
00110
00112 void save() {
00113
00114
00115 if(dirty || id == -1) {
00116 if(id == -1) {
00117 id = _db->next_id(classname);
00118 _db->make_existing(classname, id);
00119 } else if (!initial_update) {
00120 update();
00121 }
00122
00123 SarVector<std::string> propkeys;
00124 SarMap<std::string> spropvalues;
00125 SarMap<int> ipropvalues;
00126 SarMap<DateTime> dtpropvalues;
00127
00128
00129 get_new(propkeys, STRING);
00130 svalues.submap(propkeys, spropvalues);
00131 _db->set(id, classname, spropvalues, true);
00132
00133
00134 propkeys.clear();
00135 get_changed(propkeys, STRING);
00136 svalues.submap(propkeys, spropvalues);
00137 _db->set(id, classname, spropvalues, false);
00138
00139
00140 propkeys.clear();
00141 get_deleted(propkeys, STRING);
00142 _db->del(id, classname, propkeys, STRING);
00143
00144
00145 propkeys.clear();
00146 get_new(propkeys, INTEGER);
00147 ivalues.submap(propkeys, ipropvalues);
00148 _db->set(id, classname, ipropvalues, true);
00149
00150
00151 propkeys.clear();
00152 get_changed(propkeys, INTEGER);
00153 ivalues.submap(propkeys, ipropvalues);
00154 _db->set(id, classname, ipropvalues, false);
00155
00156
00157 propkeys.clear();
00158 get_deleted(propkeys, INTEGER);
00159 _db->del(id, classname, propkeys, STRING);
00160
00161
00162 propkeys.clear();
00163 get_new(propkeys, DATETIME);
00164 dtvalues.submap(propkeys, dtpropvalues);
00165 _db->set(id, classname, dtpropvalues, true);
00166
00167
00168 propkeys.clear();
00169 get_changed(propkeys, DATETIME);
00170 dtvalues.submap(propkeys, dtpropvalues);
00171 _db->set(id, classname, dtpropvalues, false);
00172
00173
00174 propkeys.clear();
00175 get_deleted(propkeys, DATETIME);
00176 _db->del(id, classname, propkeys, DATETIME);
00177
00178
00179 propkeys.clear();
00180 get_changed(propkeys, RECORD);
00181 SarVector<int> related_ids;
00182 std::string related_classname;
00183 for(unsigned int i=0; i<propkeys.size(); i++) {
00184 related_ids.clear();
00185 related_classname = propkeys[i];
00186 _db->get(id, classname, related_classname, related_ids);
00187 SarVector<int> new_ids = related_ids.get_new(rvalues[related_classname]);
00188 SarVector<int> deleted_ids = rvalues[related_classname].get_new(related_ids);
00189 _db->set(id, classname, new_ids, related_classname);
00190 _db->del(id, classname, deleted_ids, related_classname);
00191 }
00192
00193
00194 clear_registers();
00195 dirty = false;
00196 }
00197 };
00198
00199 void set(std::string key, const char * s) {
00200 if(!initial_update && id!=-1) update();
00201 set(key, std::string(s));
00202 };
00203
00204 void set(std::string key, std::string value) {
00205 if(!initial_update && id!=-1) update();
00206
00207 if(svalues.has_key(key) && svalues[key] == value)
00208 return;
00209
00210 if(svalues.has_key(key)) {
00211 register_change(key, STRING);
00212 } else if(is_registered_deleted(key, STRING)) {
00213
00214 unregister_delete(key, STRING);
00215 register_change(key, STRING);
00216 } else {
00217 clear_other_values(key, STRING);
00218 register_new(key, STRING);
00219 }
00220 svalues[key] = value;
00221 dirty = true;
00222 };
00223
00224 void set(std::string key, int value) {
00225 if(!initial_update && id!=-1) update();
00226
00227 if(ivalues.has_key(key) && ivalues[key] == value)
00228 return;
00229
00230 if(ivalues.has_key(key)) {
00231 register_change(key, INTEGER);
00232 } else if(is_registered_deleted(key, INTEGER)) {
00233
00234 unregister_delete(key, INTEGER);
00235 register_change(key, INTEGER);
00236 } else {
00237 clear_other_values(key, INTEGER);
00238 register_new(key, INTEGER);
00239 }
00240 ivalues[key] = value;
00241 dirty = true;
00242 };
00243
00244 void set(std::string key, DateTime value) {
00245 if(!initial_update && id!=-1) update();
00246
00247 if(dtvalues.has_key(key) && dtvalues[key] == value)
00248 return;
00249
00250 if(dtvalues.has_key(key)) {
00251 register_change(key, DATETIME);
00252 } else if(is_registered_deleted(key, DATETIME)) {
00253
00254 unregister_delete(key, DATETIME);
00255 register_change(key, DATETIME);
00256 } else {
00257 clear_other_values(key, DATETIME);
00258 register_new(key, DATETIME);
00259 }
00260 dtvalues[key] = value;
00261 dirty = true;
00262 };
00263
00264 void set(std::string key, bool value) {
00265 if(!initial_update && id!=-1) update();
00266 set(key, ((value) ? 1 : 0));
00267 };
00268
00269 void get(std::string key, std::string& value, std::string alt) {
00270 if(!initial_update && id!=-1) update();
00271 if(svalues.has_key(key))
00272 value = svalues[key];
00273 else
00274 value = alt;
00275 };
00276
00277 void get(std::string key, std::string& value) {
00278 if(!initial_update && id!=-1) update();
00279 if(svalues.has_key(key))
00280 value = svalues[key];
00281 else throw Sar_NoSuchPropertyException("property \"" + key + "\" does not exist");
00282 };
00283
00284 void get(std::string key, int& value, int alt) {
00285 if(!initial_update && id!=-1) update();
00286 if(ivalues.has_key(key))
00287 value = ivalues[key];
00288 else
00289 value = alt;
00290 };
00291
00292 void get(std::string key, int& value) {
00293 if(!initial_update && id!=-1) update();
00294 if(ivalues.has_key(key))
00295 value = ivalues[key];
00296 else throw Sar_NoSuchPropertyException("property \"" + key + "\" does not exist");
00297 };
00298
00299 void get(std::string key, bool& value, bool alt) {
00300 if(!initial_update && id!=-1) update();
00301 if(ivalues.has_key(key))
00302 value = (ivalues[key]==0) ? false : true;
00303 else
00304 value = alt;
00305 };
00306
00307 void get(std::string key, bool& value) {
00308 if(!initial_update) update();
00309 if(ivalues.has_key(key))
00310 value = (ivalues[key]==0) ? false : true;
00311 else throw Sar_NoSuchPropertyException("property \"" + key + "\" does not exist");
00312 };
00313
00314 void get(std::string key, DateTime& value, DateTime alt) {
00315 if(!initial_update && id!=-1) update();
00316 if(dtvalues.has_key(key))
00317 value = dtvalues[key];
00318 else
00319 value = alt;
00320 };
00321
00322 void get(std::string key, DateTime& value) {
00323 if(!initial_update && id!=-1) update();
00324 if(dtvalues.has_key(key))
00325 value = dtvalues[key];
00326 else throw Sar_NoSuchPropertyException("property \"" + key + "\" does not exist");
00327 };
00328
00330 void del(std::string key) {
00331 if(!initial_update && id!=-1) update();
00332 coltype ct = type(key);
00333 if(ct == NONE) return;
00334
00335 if(is_registered_new(key, ct))
00336 unregister_new(key, ct);
00337 else {
00338 unregister_change(key, ct);
00339 register_delete(key, ct);
00340 }
00341
00342 switch(ct) {
00343 case INTEGER:
00344 ivalues.remove(key);
00345 break;
00346 case STRING:
00347 svalues.remove(key);
00348 break;
00349 case DATETIME:
00350 dtvalues.remove(key);
00351 break;
00352 };
00353 };
00354
00356 bool isset(std::string colname) {
00357 if(!initial_update && id!=-1) update();
00358 return (type(colname) == NONE);
00359 };
00360
00362 template <class T> bool isset() {
00363 ObjGroup<T> others = getMany<T>();
00364 return others.size() > 0;
00365 };
00366
00370 coltype type(std::string colname) {
00371 if(!initial_update && id!=-1) update();
00372 if(svalues.has_key(colname) || is_registered_new(colname, STRING))
00373 return STRING;
00374 if(ivalues.has_key(colname) || is_registered_new(colname, INTEGER))
00375 return INTEGER;
00376 if(dtvalues.has_key(colname) || is_registered_new(colname, DATETIME))
00377 return DATETIME;
00378 return NONE;
00379 };
00380
00382 void del() {
00383 if(!initial_update && id!=-1) update();
00384 if(id != -1)
00385 _db->delete_record(id, classname);
00386 };
00387
00388 bool has_been_saved() {
00389 return id != -1;
00390 };
00391
00393 template <class T> void setOne(Record<T>& r) {
00394 if(!initial_update && id!=-1) update();
00395 if(r.id == -1 || !T::exists(r.id)) {
00396 std::string msg = "You cannot set an object relation with an object ";
00397 msg += "that either has not yet been saved or has been deleted.";
00398 throw Sar_NoSuchObjectException(msg);
00399 }
00400
00401 std::string key = r.classname;
00402 if(!rvalues.has_key(key))
00403 rvalues[key] = SarVector<int>();
00404
00405
00406 if(!rvalues[key].includes(r.id)) {
00407 rvalues[key] << r.id;
00408 register_change(key, RECORD);
00409 dirty = true;
00410 }
00411 };
00412
00414 template <class T> void setMany(ObjGroup<T> og) {
00415 if(!initial_update && id!=-1) update();
00416
00417 SarVector<int> og_ids;
00418 for(unsigned int i=0; i<og.size(); i++) {
00419 setOne<T>(og[i]);
00420 og_ids << og[i].id;
00421 }
00422
00423
00424 std::string classname = T::classname;
00425 SarVector<int> to_delete = og_ids.get_new(rvalues[classname]);
00426 for(unsigned int i=0; i<to_delete.size(); i++) {
00427 rvalues[classname].remove(to_delete[i]);
00428 }
00429 if(rvalues.size() > 0)
00430 register_change(classname, RECORD);
00431 };
00432
00434 template <class T> void del() {
00435 if(!initial_update && id!=-1) update();
00436 std::string related_classname = T::classname;
00437 if(rvalues.has_key(related_classname) && rvalues[related_classname].size() > 0) {
00438 rvalues[related_classname] = SarVector<int>();
00439 register_change(related_classname, RECORD);
00440 dirty = true;
00441 }
00442 };
00443
00445 template <class T> void getOne(T& record) {
00446 if(!initial_update && id!=-1) update();
00447 std::string related_classname = T::classname;
00448 if(rvalues.has_key(related_classname) && rvalues[related_classname].size() > 0) {
00449 record = T(rvalues[related_classname][0]);
00450 } else throw Sar_RecordNotFoundException("Could not find related record \"" + related_classname + "\"");
00451 };
00452
00454 template <class T> ObjGroup<T> getMany() {
00455 if(!initial_update && id!=-1) update();
00456 std::string related_classname = T::classname;
00457 if(rvalues.has_key(related_classname))
00458 return ObjGroup<T>(rvalues[related_classname]);
00459 return ObjGroup<T>();
00460 };
00461
00463 static ObjGroup<Klass> find(Q query) {
00464 SarVector<int> results = query.test(Klass::classname);
00465
00466 query.free();
00467 return ObjGroup<Klass>(results);
00468 };
00469
00471 static ObjGroup<Klass> all() {
00472 SarVector<int> results;
00473 Sar_Dbi::dbi->get(Klass::classname, results);
00474 return ObjGroup<Klass>(results);
00475 }
00476
00478 static bool exists(int id) {
00479 return Sar_Dbi::dbi->exists(Klass::classname, id);
00480 };
00481
00483 static void delete_all() {
00484 Sar_Dbi::dbi->delete_records(Klass::classname);
00485 };
00486 };
00487
00488 };