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
00029
00030
00031
00032
00033
00034 #ifndef FREPPLE_UTILS_H
00035 #define FREPPLE_UTILS_H
00036
00037
00038
00039
00040
00041
00042 #if defined(_DEBUG) && defined(_MSC_VER)
00043 #undef _DEBUG
00044 #include "Python.h"
00045 #define _DEBUG
00046 #else
00047 #include "Python.h"
00048 #endif
00049 #include "datetime.h"
00050
00051
00052 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
00053 typedef int Py_ssize_t;
00054 #define PY_SSIZE_T_MAX INT_MAX
00055 #define PY_SSIZE_T_MIN INT_MIN
00056 #endif
00057
00058 #include <iostream>
00059 #include <fstream>
00060 #include <sstream>
00061 #include <stdexcept>
00062 #include <ctime>
00063 #include <assert.h>
00064 #include <typeinfo>
00065
00066
00067
00068 #ifndef DOXYGEN
00069 #ifdef HAVE_EXT_SLIST
00070
00071 #include <ext/slist>
00072 using namespace gnu_cxx;
00073 #else
00074 #ifdef HAVE_SLIST
00075
00076 #include <slist>
00077 #else
00078
00079 #define slist list
00080 #endif
00081 #endif
00082 #endif
00083
00084
00085 #include <list>
00086 #include <map>
00087 #include <set>
00088 #include <string>
00089 #include <stack>
00090 #include <vector>
00091 #include <algorithm>
00092 using namespace std;
00093
00094
00095
00096
00097
00098 #ifdef HAVE_CONFIG_H
00099 #undef PACKAGE_BUGREPORT
00100 #undef PACKAGE_NAME
00101 #undef PACKAGE_STRING
00102 #undef PACKAGE_TARNAME
00103 #undef PACKAGE_VERSION
00104 #include <config.h>
00105 #else
00106
00107 #define PACKAGE_VERSION "0.7.1"
00108 #endif
00109
00110
00111 #if defined(MT)
00112 #if defined(HAVE_PTHREAD_H)
00113 #include <pthread.h>
00114 #elif defined(WIN32)
00115 #define WIN32_LEAN_AND_MEAN
00116 #include <windows.h>
00117 #include <process.h>
00118 #else
00119 #error Multithreading not supported on your platform
00120 #endif
00121 #endif
00122
00123
00124 #ifndef DOXYGEN
00125 #ifndef HAVE_STRNCASECMP
00126 # ifdef _MSC_VER
00127 # define strncasecmp _strnicmp
00128 # else
00129 # ifdef HAVE_STRNICMP
00130 # define strncasecmp(s1,s2,n) strnicmp(s1,s2,n)
00131 # else
00132
00133 # define strncasecmp(s1,s2,n) strnuppercmp(s1,s2,n)
00134 # endif
00135 # endif
00136 #endif
00137 #endif
00138
00139
00140
00141
00142
00143 #define ROUNDING_ERROR 0.000001
00144
00145
00146 #ifndef DOXYGEN
00147 #define XERCES_NEW_IOSTREAMS
00148 #define XML_LIBRARY
00149 #include <xercesc/util/PlatformUtils.hpp>
00150 #include <xercesc/sax2/SAX2XMLReader.hpp>
00151 #include <xercesc/sax2/Attributes.hpp>
00152 #include <xercesc/sax2/DefaultHandler.hpp>
00153 #include <xercesc/framework/MemBufInputSource.hpp>
00154 #include <xercesc/sax2/XMLReaderFactory.hpp>
00155 #include <xercesc/util/XMLUni.hpp>
00156 #include <xercesc/framework/MemBufInputSource.hpp>
00157 #include <xercesc/framework/LocalFileInputSource.hpp>
00158 #include <xercesc/framework/StdInInputSource.hpp>
00159 #include <xercesc/framework/URLInputSource.hpp>
00160 #include <xercesc/util/XMLException.hpp>
00161 #endif
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 #undef DECLARE_EXPORT
00174 #undef MODULE_EXPORT
00175 #if defined(WIN32) && !defined(DOXYGEN)
00176 #ifdef FREPPLE_CORE
00177 #define DECLARE_EXPORT __declspec (dllexport)
00178 #else
00179 #define DECLARE_EXPORT __declspec (dllimport)
00180 #endif
00181 #define MODULE_EXPORT extern "C" __declspec (dllexport)
00182 #else
00183 #define DECLARE_EXPORT
00184 #define MODULE_EXPORT extern "C"
00185 #endif
00186
00187
00188 namespace frepple
00189 {
00190 namespace utils
00191 {
00192
00193
00194 class Object;
00195 class Keyword;
00196 class XMLInput;
00197 class AttributeList;
00198
00199
00200 #include "frepple/tags.h"
00201
00202
00203
00204 enum Action
00205 {
00206
00207
00208 ADD = 0,
00209
00210
00211
00212 CHANGE = 1,
00213
00214
00215 REMOVE = 2,
00216
00217
00218
00219
00220 ADD_CHANGE = 3
00221 };
00222
00223
00224
00225 inline ostream & operator << (ostream & os, const Action & d)
00226 {
00227 switch (d)
00228 {
00229 case ADD: os << "ADD"; return os;
00230 case CHANGE: os << "CHANGE"; return os;
00231 case REMOVE: os << "REMOVE"; return os;
00232 case ADD_CHANGE: os << "ADD_CHANGE"; return os;
00233 default: assert(false); return os;
00234 }
00235 }
00236
00237
00238
00239 enum Signal
00240 {
00241
00242 SIG_ADD = 0,
00243
00244 SIG_REMOVE = 1
00245 };
00246
00247
00248
00249 inline ostream & operator << (ostream & os, const Signal & d)
00250 {
00251 switch (d)
00252 {
00253 case SIG_ADD: os << "ADD"; return os;
00254 case SIG_REMOVE: os << "REMOVE"; return os;
00255 default: assert(false); return os;
00256 }
00257 }
00258
00259
00260
00261 typedef unsigned int hashtype;
00262
00263
00264 extern DECLARE_EXPORT ostream logger;
00265
00266
00267 struct indent
00268 {
00269 unsigned short level;
00270 indent(unsigned short l) : level(l) {}
00271 indent operator() (unsigned short l) {return indent(l);}
00272 };
00273
00274
00275 inline ostream& operator <<(ostream &os, const indent& i)
00276 {
00277 for (unsigned int c = i.level; c; --c) os << ' ';
00278 return os;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 class Environment
00291 {
00292 private:
00293
00294
00295
00296
00297 static DECLARE_EXPORT int processors;
00298
00299
00300 static DECLARE_EXPORT ofstream logfile;
00301
00302
00303 static DECLARE_EXPORT string logfilename;
00304
00305 public:
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 static DECLARE_EXPORT string searchFile(const string);
00317
00318
00319 static int getProcessors() {return processors;}
00320
00321
00322 static void setProcessors(int i) {if (i>=1) processors = i;}
00323
00324
00325 static const string& getLogFile() {return logfilename;}
00326
00327
00328
00329
00330
00331
00332
00333 static DECLARE_EXPORT void setLogFile(const string& x);
00334 };
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 class DataException : public logic_error
00350 {
00351 public:
00352 DataException(const char * c) : logic_error(c) {}
00353 DataException(const string s) : logic_error(s) {}
00354 };
00355
00356
00357
00358
00359
00360
00361
00362
00363 class LogicException: public logic_error
00364 {
00365 public:
00366 LogicException(const char * c) : logic_error(c) {}
00367 LogicException(const string s) : logic_error(s) {}
00368 };
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 class RuntimeException: public runtime_error
00382 {
00383 public:
00384 RuntimeException(const char * c) : runtime_error(c) {}
00385 RuntimeException(const string s) : runtime_error(s) {}
00386 };
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 class NonCopyable
00411 {
00412 protected:
00413 NonCopyable() {}
00414 ~NonCopyable() {}
00415
00416 private:
00417
00418
00419
00420
00421 NonCopyable(const NonCopyable&);
00422
00423
00424
00425
00426
00427 NonCopyable& operator=(const NonCopyable&);
00428 };
00429
00430
00431
00432
00433
00434
00435
00436 class Mutex: public NonCopyable
00437 {
00438 public:
00439 #ifndef MT
00440
00441 Mutex() {}
00442 ~Mutex() {}
00443 void lock() {}
00444 void unlock() {}
00445 #elif defined(HAVE_PTHREAD_H)
00446
00447 Mutex() { pthread_mutex_init(&mtx, 0); }
00448 ~Mutex() { pthread_mutex_destroy(&mtx); }
00449 void lock() { pthread_mutex_lock(&mtx); }
00450 void unlock() { pthread_mutex_unlock(&mtx); }
00451 private:
00452 pthread_mutex_t mtx;
00453 #else
00454
00455 Mutex() { InitializeCriticalSection(&critsec); }
00456 ~Mutex() { DeleteCriticalSection(&critsec); }
00457 void lock() { EnterCriticalSection(&critsec); }
00458 void unlock() { LeaveCriticalSection(&critsec); }
00459 private:
00460 CRITICAL_SECTION critsec;
00461 #endif
00462 };
00463
00464
00465
00466
00467
00468 class ScopeMutexLock: public NonCopyable
00469 {
00470 protected:
00471 Mutex& mtx;
00472 public:
00473 ScopeMutexLock(Mutex& imtx): mtx(imtx) { mtx.lock (); }
00474 ~ScopeMutexLock() { mtx.unlock(); }
00475 };
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 class Keyword : public NonCopyable
00495 {
00496 private:
00497
00498 hashtype dw;
00499
00500
00501
00502 string strName, strStartElement, strEndElement, strElement, strAttribute;
00503
00504
00505 XMLCh* xmlname;
00506
00507
00508 void check();
00509
00510 public:
00511
00512 typedef map<hashtype,Keyword*> tagtable;
00513
00514
00515
00516 DECLARE_EXPORT Keyword(const string&);
00517
00518
00519
00520
00521
00522
00523 DECLARE_EXPORT Keyword(const string&, const string&);
00524
00525
00526 DECLARE_EXPORT ~Keyword();
00527
00528
00529 hashtype getHash() const {return dw;}
00530
00531
00532 const string& getName() const {return strName;}
00533
00534
00535
00536 const XMLCh* getXMLCharacters() const {return xmlname;}
00537
00538
00539 const string& stringStartElement() const {return strStartElement;}
00540
00541
00542 const string& stringEndElement() const {return strEndElement;}
00543
00544
00545 const string& stringElement() const {return strElement;}
00546
00547
00548 const string& stringAttribute() const {return strAttribute;}
00549
00550
00551
00552
00553
00554
00555
00556
00557 #if !defined(WIN32) || defined(FREPPLE_CORE)
00558 static DECLARE_EXPORT hashtype hash(const char* c)
00559 {return xercesc::XMLString::hash(c,954991);}
00560 #else
00561 static DECLARE_EXPORT hashtype hash(const char* c);
00562 #endif
00563
00564
00565
00566
00567 #if !defined(WIN32) || defined(FREPPLE_CORE)
00568 static DECLARE_EXPORT hashtype hash(const string& c)
00569 {return xercesc::XMLString::hash(c.c_str(),954991);}
00570 #else
00571 static DECLARE_EXPORT hashtype hash(const string& c);
00572 #endif
00573
00574
00575
00576
00577
00578
00579 #if !defined(WIN32) || defined(FREPPLE_CORE)
00580 static DECLARE_EXPORT hashtype hash(const XMLCh* c)
00581 {return xercesc::XMLString::hash(c,954991);}
00582 #else
00583 static DECLARE_EXPORT hashtype hash(const XMLCh* c);
00584 #endif
00585
00586
00587
00588 static DECLARE_EXPORT const Keyword& find(const char*);
00589
00590
00591 static DECLARE_EXPORT tagtable& getTags();
00592
00593
00594
00595
00596
00597
00598 static DECLARE_EXPORT void printTags();
00599 };
00600
00601
00602
00603
00604
00605
00606
00607 class Functor : public NonCopyable
00608 {
00609 public:
00610
00611
00612
00613
00614
00615
00616
00617 virtual bool callback(Object* v, const Signal a) const = 0;
00618
00619
00620 virtual ~Functor() {}
00621 };
00622
00623
00624
00625
00626 extern "C"
00627 {
00628
00629 DECLARE_EXPORT PyObject* getattro_handler (PyObject*, PyObject*);
00630
00631 DECLARE_EXPORT int setattro_handler (PyObject*, PyObject*, PyObject*);
00632
00633 DECLARE_EXPORT int compare_handler (PyObject*, PyObject*);
00634
00635 DECLARE_EXPORT PyObject* iternext_handler (PyObject*);
00636
00637 DECLARE_EXPORT PyObject* call_handler(PyObject*, PyObject*, PyObject*);
00638
00639 DECLARE_EXPORT PyObject* str_handler(PyObject*);
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649 class PythonType : public NonCopyable
00650 {
00651 private:
00652
00653
00654
00655 static const PyTypeObject PyTypeObjectTemplate;
00656
00657
00658 vector<PyMethodDef> methodvector;
00659
00660
00661 PyMethodDef *methods;
00662
00663 public:
00664
00665
00666
00667
00668
00669 static DECLARE_EXPORT void evalException();
00670
00671
00672 DECLARE_EXPORT PythonType(size_t base_size, const type_info*);
00673
00674
00675 PyTypeObject* type_object() const {return const_cast<PyTypeObject*>(&table);}
00676
00677
00678 DECLARE_EXPORT void addMethod(const char*, PyCFunction, int, const char*);
00679
00680
00681 DECLARE_EXPORT void addMethod(const char*, PyCFunctionWithKeywords, int, const char*);
00682
00683
00684 void setName (const string n)
00685 {
00686 name = "frepple." + n;
00687 table.tp_name = const_cast<char*>(name.c_str());
00688 }
00689
00690
00691 void setDoc (const string n)
00692 {
00693 doc = n;
00694 table.tp_doc = const_cast<char*>(doc.c_str());
00695 }
00696
00697
00698 void setBase(PythonType& b)
00699 {
00700 table.tp_base = &b.table;
00701 }
00702
00703
00704 void supportdealloc(void (*f)(PyObject*))
00705 {
00706 table.tp_dealloc = f;
00707 }
00708
00709
00710
00711
00712
00713
00714 void supportgetattro()
00715 {table.tp_getattro = getattro_handler;}
00716
00717
00718
00719
00720
00721
00722 void supportsetattro()
00723 {table.tp_setattro = setattro_handler;}
00724
00725
00726
00727
00728
00729
00730 void supportcompare()
00731 {table.tp_compare = compare_handler;}
00732
00733
00734
00735
00736
00737
00738 void supportiter()
00739 {
00740 table.tp_iter = PyObject_SelfIter;
00741 table.tp_iternext = iternext_handler;
00742 }
00743
00744
00745
00746
00747
00748
00749 void supportcall()
00750 {table.tp_call = call_handler;}
00751
00752
00753
00754
00755
00756
00757 void supportstr()
00758 {table.tp_str = str_handler;}
00759
00760
00761 typedef PyObject* (*createfunc)(PyTypeObject*, PyObject*, PyObject*);
00762
00763
00764 void supportcreate(createfunc c) {table.tp_new = c;}
00765
00766
00767
00768
00769 DECLARE_EXPORT int typeReady(PyObject* m);
00770
00771
00772 bool operator == (const PythonType& i) const
00773 {
00774 return *cppClass == *(i.cppClass);
00775 }
00776
00777
00778 bool operator == (const type_info& i) const
00779 {
00780 return *cppClass == i;
00781 }
00782
00783 private:
00784
00785 PyTypeObject table;
00786
00787
00788 string name;
00789
00790
00791 string doc;
00792
00793
00794 const type_info* cppClass;
00795 };
00796
00797
00798 class MetaCategory;
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 class MetaClass : public NonCopyable
00836 {
00837 friend class MetaCategory;
00838 template <class T, class U> friend class FunctorStatic;
00839 template <class T, class U> friend class FunctorInstance;
00840
00841 public:
00842
00843
00844 typedef Object* (*creatorDefault)();
00845
00846
00847
00848 typedef Object* (*creatorString)(const string&);
00849
00850
00851
00852 typedef void (*processorXMLInstruction)(const char *d);
00853
00854
00855
00856
00857
00858 typedef PyObject* (*creatorPythonProxy)(Object*);
00859
00860
00861
00862 string type;
00863
00864
00865 const Keyword* typetag;
00866
00867
00868 const MetaCategory* category;
00869
00870
00871 union
00872 {
00873 creatorDefault factoryMethodDefault;
00874 creatorString factoryMethodString;
00875 processorXMLInstruction processingInstruction;
00876 };
00877
00878
00879
00880
00881 creatorPythonProxy factoryPythonProxy;
00882
00883
00884 virtual ~MetaClass() {}
00885
00886
00887 DECLARE_EXPORT void registerClass(const string&, const string&,
00888 bool = false, creatorDefault = NULL);
00889
00890
00891 MetaClass (const string& cat, const string& cls, bool def = false)
00892 {
00893 registerClass(cat,cls,def);
00894 }
00895
00896
00897
00898 MetaClass (const string& cat, const string& cls, creatorDefault f,
00899 bool def = false)
00900 {
00901 registerClass(cat,cls,def);
00902 factoryMethodDefault = f;
00903 }
00904
00905
00906
00907 MetaClass (const string& cat, const string& cls, creatorString f,
00908 bool def = false)
00909 {
00910 registerClass(cat,cls,def);
00911 factoryMethodString = f;
00912 }
00913
00914
00915
00916 MetaClass (const string& cat, const string& cls,
00917 processorXMLInstruction f, bool def = false)
00918 {
00919 registerClass(cat,cls,def);
00920 processingInstruction = f;
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932 static DECLARE_EXPORT Action decodeAction(const char*);
00933
00934
00935
00936
00937
00938 static DECLARE_EXPORT Action decodeAction(const AttributeList&);
00939
00940
00941
00942
00943
00944
00945 bool operator < (const MetaClass& b) const
00946 {
00947 return typetag->getHash() < b.typetag->getHash();
00948 }
00949
00950
00951
00952
00953
00954
00955
00956 bool operator == (const MetaClass& b) const
00957 {
00958 return typetag->getHash() == b.typetag->getHash();
00959 }
00960
00961
00962
00963
00964
00965
00966
00967 bool operator != (const MetaClass& b) const
00968 {
00969 return typetag->getHash() != b.typetag->getHash();
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979 DECLARE_EXPORT bool raiseEvent(Object* v, Signal a) const;
00980
00981
00982 void connect(Functor *c, Signal a) const
00983 {const_cast<MetaClass*>(this)->subscribers[a].push_front(c);}
00984
00985
00986 void disconnect(Functor *c, Signal a) const
00987 {const_cast<MetaClass*>(this)->subscribers[a].remove(c);}
00988
00989
00990
00991 static DECLARE_EXPORT void printClasses();
00992
00993
00994
00995 static DECLARE_EXPORT const MetaClass* findClass(const char*);
00996
00997 protected:
00998
00999 MetaClass() : type("unspecified"), typetag(&Keyword::find("unspecified")),
01000 category(NULL), factoryMethodDefault(NULL), factoryPythonProxy(NULL) {}
01001
01002 private:
01003
01004
01005
01006
01007
01008
01009
01010
01011 list<Functor*> subscribers[4];
01012 };
01013
01014
01015 class XMLOutput;
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 class MetaCategory : public MetaClass
01033 {
01034 friend class MetaClass;
01035 template<class T> friend class HasName;
01036 public:
01037
01038 string group;
01039
01040
01041 const Keyword* grouptag;
01042
01043
01044 typedef Object* (*readController)(const MetaClass*, const AttributeList&);
01045
01046
01047 typedef void (*writeController)(const MetaCategory*, XMLOutput *o);
01048
01049
01050
01051
01052 static Object* ControllerDefault (const MetaClass*, const AttributeList&);
01053
01054
01055 virtual ~MetaCategory() {}
01056
01057
01058 DECLARE_EXPORT MetaCategory (const string& t, const string& g,
01059 readController = NULL, writeController = NULL);
01060
01061
01062 typedef map < hashtype, const MetaClass*, less<hashtype> > ClassMap;
01063
01064
01065 typedef map < hashtype, const MetaCategory*, less<hashtype> > CategoryMap;
01066
01067
01068
01069 static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const char*);
01070
01071
01072
01073 static DECLARE_EXPORT const MetaCategory* findCategoryByTag(const hashtype);
01074
01075
01076
01077 static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const char*);
01078
01079
01080
01081 static DECLARE_EXPORT const MetaCategory* findCategoryByGroupTag(const hashtype);
01082
01083
01084
01085
01086 DECLARE_EXPORT const MetaClass* findClass(const char*) const;
01087
01088
01089
01090
01091 DECLARE_EXPORT const MetaClass* findClass(const hashtype) const;
01092
01093
01094
01095
01096
01097 static DECLARE_EXPORT void persist(XMLOutput *);
01098
01099
01100
01101
01102
01103 readController readFunction;
01104
01105 private:
01106
01107 ClassMap classes;
01108
01109
01110
01111 static DECLARE_EXPORT const hashtype defaultHash;
01112
01113
01114
01115
01116 static DECLARE_EXPORT const MetaCategory* firstCategory;
01117
01118
01119 const MetaCategory* nextCategory;
01120
01121
01122
01123
01124
01125 writeController writeFunction;
01126
01127
01128 static DECLARE_EXPORT CategoryMap categoriesByTag;
01129
01130
01131 static DECLARE_EXPORT CategoryMap categoriesByGroupTag;
01132 };
01133
01134
01135
01136
01137
01138
01139
01140 template <class T, class U> class FunctorStatic : public Functor
01141 {
01142 friend class MetaClass;
01143 public:
01144
01145 static void connect(const Signal a)
01146 {T::metadata->connect(new FunctorStatic<T,U>(), a);}
01147
01148
01149 static void disconnect(const Signal a)
01150 {
01151 MetaClass &t =
01152 const_cast<MetaClass&>(static_cast<const MetaClass&>(*T::metadata));
01153
01154 for (list<Functor*>::iterator i = t.subscribers[a].begin();
01155 i != t.subscribers[a].end(); ++i)
01156 {
01157
01158 FunctorStatic<T,U> *f = dynamic_cast< FunctorStatic<T,U>* >(*i);
01159 if (f)
01160 {
01161
01162 delete *i;
01163 t.subscribers[a].erase(i);
01164 return;
01165 }
01166 }
01167
01168 throw LogicException("Subscription doesn't exist");
01169 }
01170
01171 private:
01172
01173
01174
01175 virtual bool callback(Object* v, const Signal a) const
01176 {return U::callback(static_cast<T*>(v),a);}
01177 };
01178
01179
01180
01181
01182
01183
01184
01185 template <class T, class U> class FunctorInstance : public Functor
01186 {
01187 public:
01188
01189
01190
01191
01192
01193 static void connect(U* u, const Signal a)
01194 { if (u) T::metadata.connect(new FunctorInstance(u), a);}
01195
01196
01197 static void disconnect(U *u, const Signal a)
01198 {
01199 MetaClass &t =
01200 const_cast<MetaClass&>(static_cast<const MetaClass&>(T::metadata));
01201
01202 for (list<Functor*>::iterator i = t.subscribers[a].begin();
01203 i != t.subscribers[a].end(); ++i)
01204 {
01205
01206 FunctorInstance<T,U> *f = dynamic_cast< FunctorInstance<T,U>* >(*i);
01207 if (f && f->instance == u)
01208 {
01209
01210 delete *i;
01211 t.subscribers[a].erase(i);
01212 return;
01213 }
01214 }
01215
01216 throw LogicException("Subscription doesn't exist");
01217 }
01218
01219
01220 FunctorInstance(U* u) : instance(u) {}
01221
01222 private:
01223
01224 virtual bool callback(Object* v, const Signal a) const
01225 { return instance ? instance->callback(static_cast<T*>(v),a) : true; }
01226
01227
01228 U* instance;
01229 };
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251 class Timer
01252 {
01253 public:
01254
01255
01256 explicit Timer() : start_time(clock()) {}
01257
01258
01259 void restart() { start_time = clock(); }
01260
01261
01262
01263 double elapsed() const {return double(clock()-start_time)/CLOCKS_PER_SEC;}
01264
01265 private:
01266
01267 clock_t start_time;
01268 };
01269
01270
01271
01272 inline ostream & operator << (ostream& os, const Timer& t)
01273 {
01274 return os << t.elapsed();
01275 }
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 class TimePeriod
01289 {
01290 friend ostream& operator << (ostream &, const TimePeriod &);
01291 public:
01292
01293 TimePeriod(const long l = 0) : lval(l) {}
01294
01295
01296
01297
01298 TimePeriod(const char* s) {parse(s);}
01299
01300
01301 bool operator < (const long& b) const {return lval < b;}
01302
01303
01304 bool operator > (const long& b) const {return lval > b;}
01305
01306
01307 bool operator <= (const long& b) const {return lval <= b;}
01308
01309
01310 bool operator >= (const long& b) const {return lval >= b;}
01311
01312
01313 bool operator < (const TimePeriod& b) const {return lval < b.lval;}
01314
01315
01316 bool operator > (const TimePeriod& b) const {return lval > b.lval;}
01317
01318
01319 bool operator <= (const TimePeriod& b) const {return lval <= b.lval;}
01320
01321
01322 bool operator >= (const TimePeriod& b) const {return lval >= b.lval;}
01323
01324
01325 bool operator == (const TimePeriod& b) const {return lval == b.lval;}
01326
01327
01328 bool operator != (const TimePeriod& b) const {return lval != b.lval;}
01329
01330
01331 void operator += (const TimePeriod& l) {lval += l.lval;}
01332
01333
01334 void operator -= (const TimePeriod& l) {lval -= l.lval;}
01335
01336
01337 bool operator ! () const {return lval == 0L;}
01338
01339
01340 operator long() const {return lval;}
01341
01342
01343 operator string() const
01344 {
01345 char str[20];
01346 toCharBuffer(str);
01347 return string(str);
01348 }
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367 DECLARE_EXPORT void parse(const char*);
01368
01369
01370 DECLARE_EXPORT static const TimePeriod MAX;
01371
01372
01373 DECLARE_EXPORT static const TimePeriod MIN;
01374
01375 private:
01376
01377 long lval;
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 DECLARE_EXPORT void toCharBuffer(char*) const;
01388 };
01389
01390
01391
01392
01393
01394 inline ostream & operator << (ostream & os, const TimePeriod & t)
01395 {
01396 char str[20];
01397 t.toCharBuffer(str);
01398 return os << str;
01399 }
01400
01401
01402
01403
01404 class Date
01405 {
01406 friend ostream& operator << (ostream &, const Date &);
01407 private:
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436 static DECLARE_EXPORT string format;
01437
01438
01439 time_t lval;
01440
01441
01442 DECLARE_EXPORT void checkFinite(long long);
01443
01444
01445
01446 Date(const char* s, bool dummy) {parse(s);}
01447
01448
01449 Date(const time_t l) : lval(l) {checkFinite(lval);}
01450
01451 public:
01452
01453
01454
01455 Date() : lval(infinitePast.lval) {}
01456
01457
01458
01459
01460
01461
01462 Date(const char* s) {parse(s); checkFinite(lval);}
01463
01464
01465
01466
01467 DECLARE_EXPORT Date(int year, int month, int day,
01468 int hr=0, int min=0, int sec=0
01469 );
01470
01471
01472 bool operator < (const Date& b) const {return lval < b.lval;}
01473
01474
01475 bool operator > (const Date& b) const {return lval > b.lval;}
01476
01477
01478 bool operator == (const Date& b) const {return lval == b.lval;}
01479
01480
01481 bool operator != (const Date& b) const {return lval != b.lval;}
01482
01483
01484 bool operator >= (const Date& b) const {return lval >= b.lval;}
01485
01486
01487 bool operator <= (const Date& b) const {return lval <= b.lval;}
01488
01489
01490 void operator = (const Date& b) {lval = b.lval;}
01491
01492
01493 void operator += (const TimePeriod& l)
01494 {checkFinite(static_cast<long long>(l) + lval);}
01495
01496
01497 void operator -= (const TimePeriod& l)
01498 {checkFinite(- static_cast<long long>(l) + lval);}
01499
01500
01501 Date operator + (const TimePeriod& l) const
01502 {
01503 Date d;
01504 d.checkFinite(static_cast<long long>(l) + lval);
01505 return d;
01506 }
01507
01508
01509 Date operator - (const TimePeriod& l) const
01510 {
01511 Date d;
01512 d.checkFinite(- static_cast<long>(l) + lval);
01513 return d;
01514 }
01515
01516
01517
01518 TimePeriod operator - (const Date& l) const
01519 {return static_cast<long>(lval - l.lval);}
01520
01521
01522 bool operator ! () const {return lval == infinitePast.lval;}
01523
01524
01525 operator bool() const {return lval != infinitePast.lval;}
01526
01527
01528
01529 static Date now() {return Date(time(0));}
01530
01531
01532
01533 operator string() const
01534 {
01535 char str[30];
01536 toCharBuffer(str);
01537 return string(str);
01538 }
01539
01540
01541
01542
01543
01544
01545
01546 DECLARE_EXPORT size_t toCharBuffer(char*) const;
01547
01548
01549
01550 time_t getTicks() const {return lval;}
01551
01552
01553 DECLARE_EXPORT void parse(const char*, const string& = format);
01554
01555
01556 static void setFormat(const string& n) {format = n;}
01557
01558
01559 static string getFormat() {return format;}
01560
01561
01562
01563
01564
01565 static DECLARE_EXPORT const Date infinitePast;
01566
01567
01568
01569
01570
01571 static DECLARE_EXPORT const Date infiniteFuture;
01572
01573 #ifndef HAVE_STRPTIME
01574 private:
01575 DECLARE_EXPORT char* strptime(const char *, const char *, struct tm *);
01576 #endif
01577 };
01578
01579
01580
01581 inline ostream & operator << (ostream & os, const Date & d)
01582 {
01583 char str[30];
01584 d.toCharBuffer(str);
01585 return os << str;
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 class DateRange
01598 {
01599 public:
01600
01601
01602
01603 DateRange(const Date& st, const Date& nd) : start(st), end(nd)
01604 {if(st>nd) {start=nd; end=st;}}
01605
01606
01607
01608
01609 DateRange() : start(Date::infinitePast), end(Date::infiniteFuture) {}
01610
01611
01612 DateRange(const DateRange& n) : start(n.start), end(n.end) {}
01613
01614
01615 const Date& getStart() const {return start;}
01616
01617
01618
01619
01620
01621 void setStart(const Date& d) {start=d; if(start>end) end=start;}
01622
01623
01624 const Date & getEnd() const {return end;}
01625
01626
01627
01628
01629
01630 void setEnd(const Date& d) {end=d; if(start>end) start=end;}
01631
01632
01633 void setStartAndEnd(const Date& st, const Date& nd)
01634 {if (st<nd) {start=st; end=nd;} else {start=nd; end=st;}}
01635
01636
01637
01638
01639
01640 TimePeriod getDuration() const {return end - start;}
01641
01642
01643 bool operator == (const DateRange& b) const
01644 {return start==b.start && end==b.end;}
01645
01646
01647 bool operator != (const DateRange& b) const
01648 {return start!=b.start || end!=b.end;}
01649
01650
01651 void operator += (const TimePeriod& l) {start += l; end += l;}
01652
01653
01654 void operator -= (const TimePeriod& l) {start -= l; end -= l;}
01655
01656
01657 void operator = (const DateRange& dr) {start = dr.start; end = dr.end;}
01658
01659
01660
01661
01662
01663
01664
01665 bool intersect(const DateRange& dr) const
01666 {return dr.start<=end && dr.end>start;}
01667
01668
01669 TimePeriod overlap(const DateRange& dr) const
01670 {
01671 long x = (dr.end<end ? dr.end : end)
01672 - (dr.start>start ? dr.start : start);
01673 return x>0 ? x : 0;
01674 }
01675
01676
01677
01678 bool within(const Date& d) const {return d>=start && d<end;}
01679
01680
01681 DECLARE_EXPORT operator string() const;
01682
01683
01684 static void setSeparator(const string& n)
01685 {
01686 separator = n;
01687 separatorlength = n.size();
01688 }
01689
01690
01691 static const string& getSeparator() {return separator;}
01692
01693 private:
01694
01695 Date start;
01696
01697
01698 Date end;
01699
01700
01701 static DECLARE_EXPORT string separator;
01702
01703
01704 static DECLARE_EXPORT size_t separatorlength;
01705 };
01706
01707
01708
01709
01710 inline ostream & operator << (ostream & os, const DateRange & dr)
01711 {
01712 return os << dr.getStart() << DateRange::getSeparator() << dr.getEnd();
01713 }
01714
01715
01716
01717
01718
01719
01720
01721
01722 enum mode
01723 {
01724
01725
01726
01727
01728
01729
01730
01731 DEFAULT = 0,
01732
01733
01734
01735 REFERENCE = 1,
01736
01737
01738
01739
01740
01741 NOHEADER = 2,
01742
01743
01744
01745 FULL = 3
01746 };
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 class XMLEscape
01765 {
01766 friend DECLARE_EXPORT ostream& operator << (ostream&, const XMLEscape&);
01767 private:
01768 const char* data;
01769 public:
01770 XMLEscape(const char* p) {data = p;}
01771 XMLEscape(const string& p) {data = p.c_str();}
01772 };
01773
01774
01775
01776 DECLARE_EXPORT ostream & operator << (ostream&, const XMLEscape&);
01777
01778
01779
01780
01781
01782
01783
01784 class XMLOutput
01785 {
01786 protected:
01787
01788 void setOutput(ostream& o) {m_fp = &o;}
01789
01790 public:
01791
01792
01793
01794
01795
01796 typedef unsigned short content_type;
01797
01798
01799
01800
01801
01802
01803
01804 static DECLARE_EXPORT const content_type STANDARD;
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814 static DECLARE_EXPORT const content_type PLAN;
01815
01816
01817
01818
01819
01820
01821 static DECLARE_EXPORT const content_type PLANDETAIL;
01822
01823
01824
01825
01826
01827
01828
01829 content_type getContentType() const {return content;}
01830
01831
01832
01833
01834
01835
01836 void setContentType(content_type c) {content = c;}
01837
01838
01839
01840
01841
01842
01843 void setHeaderStart(const string& s) {headerStart = s;}
01844
01845
01846
01847 string getHeaderStart() const {return headerStart;}
01848
01849
01850
01851
01852
01853 void setHeaderAtts(const string& s) {headerAtts = s;}
01854
01855
01856
01857 string getHeaderAtts() const {return headerAtts;}
01858
01859
01860 XMLOutput(ostream& os) : m_nIndent(0), numObjects(0),
01861 numParents(0), currentObject(NULL), parentObject(NULL), content(STANDARD),
01862 headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
01863 headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
01864 {m_fp = &os; indentstring[0] = '\0';}
01865
01866
01867 XMLOutput() : m_nIndent(0), numObjects(0), numParents(0),
01868 currentObject(NULL), parentObject(NULL), content(STANDARD),
01869 headerStart("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"),
01870 headerAtts("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"")
01871 {m_fp = &logger; indentstring[0] = '\0';}
01872
01873
01874
01875 void BeginObject(const Keyword& t)
01876 {
01877 *m_fp << indentstring << t.stringElement() << "\n";
01878 incIndent();
01879 }
01880
01881
01882
01883 void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1)
01884 {
01885 *m_fp << indentstring << t.stringStartElement()
01886 << attr1.stringAttribute() << XMLEscape(val1) << "\">\n";
01887 incIndent();
01888 }
01889
01890
01891
01892 void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1,
01893 const Keyword& attr2, const string& val2)
01894 {
01895 *m_fp << indentstring << t.stringStartElement()
01896 << attr1.stringAttribute() << XMLEscape(val1) << "\""
01897 << attr2.stringAttribute() << XMLEscape(val2) << "\">\n";
01898 incIndent();
01899 }
01900
01901
01902
01903 void BeginObject(const Keyword& t, const Keyword& attr1, const string& val1,
01904 const Keyword& attr2, const string& val2,
01905 const Keyword& attr3, const string& val3)
01906 {
01907 *m_fp << indentstring << t.stringStartElement()
01908 << attr1.stringAttribute() << XMLEscape(val1) << "\""
01909 << attr2.stringAttribute() << XMLEscape(val2) << "\""
01910 << attr3.stringAttribute() << XMLEscape(val3) << "\">\n";
01911 incIndent();
01912 }
01913
01914
01915 void BeginObject(const Keyword& t, const string& atts)
01916 {
01917 *m_fp << indentstring << t.stringStartElement() << " " << atts << ">\n";
01918 incIndent();
01919 }
01920
01921
01922
01923 void BeginObject(const Keyword& t, const Keyword& attr1, const long val1)
01924 {
01925 *m_fp << indentstring << t.stringStartElement()
01926 << attr1.stringAttribute() << val1 << "\">\n";
01927 incIndent();
01928 }
01929
01930
01931
01932 void BeginObject(const Keyword& t, const Keyword& attr1, unsigned long val1,
01933 const Keyword& attr2, const string& val2)
01934 {
01935 *m_fp << indentstring << t.stringStartElement()
01936 << attr1.stringAttribute() << val1 << "\""
01937 << attr2.stringAttribute() << XMLEscape(val2) << "\">\n";
01938 incIndent();
01939 }
01940
01941
01942
01943
01944
01945 void EndObject(const Keyword& t)
01946 {
01947 decIndent();
01948 *m_fp << indentstring << t.stringEndElement();
01949 }
01950
01951
01952
01953 void writeString(const string& c)
01954 {
01955 *m_fp << indentstring << c << "\n";
01956 }
01957
01958
01959
01960 void writeElement(const Keyword& t, const long unsigned int val)
01961 {
01962 *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
01963 }
01964
01965
01966
01967 void writeElement(const Keyword& t, const int val)
01968 {
01969 *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
01970 }
01971
01972
01973
01974 void writeElement(const Keyword& t, const double val)
01975 {
01976 *m_fp << indentstring << t.stringElement() << val << t.stringEndElement();
01977 }
01978
01979
01980
01981
01982
01983 void writeElement(const Keyword& t, const bool val)
01984 {
01985 *m_fp << indentstring << t.stringElement()
01986 << (val ? "true" : "false") << t.stringEndElement();
01987 }
01988
01989
01990
01991
01992 void writeElement(const Keyword& t, const string& val)
01993 {
01994 if (!val.empty())
01995 *m_fp << indentstring << t.stringElement()
01996 << XMLEscape(val) << t.stringEndElement();
01997 }
01998
01999
02000
02001 void writeElement(const Keyword& u, const Keyword& t, const string& val)
02002 {
02003 if (val.empty())
02004 *m_fp << indentstring << u.stringStartElement() << "/>\n";
02005 else
02006 *m_fp << indentstring << u.stringStartElement()
02007 << t.stringAttribute() << XMLEscape(val)
02008 << "\"/>\n";
02009 }
02010
02011
02012
02013 void writeElement(const Keyword& u, const Keyword& t, const long val)
02014 {
02015 *m_fp << indentstring << u.stringStartElement()
02016 << t.stringAttribute() << val << "\"/>\n";
02017 }
02018
02019
02020
02021 void writeElement(const Keyword& u, const Keyword& t, const Date& val)
02022 {
02023 *m_fp << indentstring << u.stringStartElement()
02024 << t.stringAttribute() << string(val) << "\"/>\n";
02025 }
02026
02027
02028
02029 void writeElement(const Keyword& u, const Keyword& t1, const string& val1,
02030 const Keyword& t2, const string& val2)
02031 {
02032 if(val1.empty())
02033 *m_fp << indentstring << u.stringStartElement() << "/>\n";
02034 else
02035 *m_fp << indentstring << u.stringStartElement()
02036 << t1.stringAttribute() << XMLEscape(val1.c_str()) << "\""
02037 << t2.stringAttribute() << XMLEscape(val2.c_str())
02038 << "\"/>\n";
02039 }
02040
02041
02042
02043 void writeElement(const Keyword& u, const Keyword& t1, unsigned long val1,
02044 const Keyword& t2, const string& val2)
02045 {
02046 *m_fp << indentstring << u.stringStartElement()
02047 << t1.stringAttribute() << val1 << "\""
02048 << t2.stringAttribute() << XMLEscape(val2.c_str())
02049 << "\"/>\n";
02050 }
02051
02052
02053
02054 void writeElement(const Keyword& t, const char* val)
02055 {
02056 if (val)
02057 *m_fp << indentstring << t.stringElement()
02058 << XMLEscape(val) << t.stringEndElement();
02059 }
02060
02061
02062
02063 void writeElement(const Keyword& t, const TimePeriod d)
02064 {
02065 *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02066 }
02067
02068
02069
02070 void writeElement(const Keyword& t, const Date d)
02071 {
02072 *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02073 }
02074
02075
02076
02077 void writeElement(const Keyword& t, const DateRange& d)
02078 {
02079 *m_fp << indentstring << t.stringElement() << d << t.stringEndElement();
02080 }
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090 DECLARE_EXPORT void writeElement(const Keyword&, const Object*, mode = DEFAULT);
02091
02092
02093 void writeElement(const Keyword& t, const Object& o, mode m = DEFAULT)
02094 {writeElement(t,&o,m);}
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105 DECLARE_EXPORT void writeElementWithHeader(const Keyword& tag, const Object* object);
02106
02107
02108
02109
02110
02111
02112
02113
02114 DECLARE_EXPORT void writeHeader(const Keyword& tag);
02115
02116
02117 Object* getCurrentObject() const
02118 {return const_cast<Object*>(currentObject);}
02119
02120
02121 Object* getPreviousObject() const
02122 {return const_cast<Object*>(parentObject);}
02123
02124
02125 unsigned long countObjects() const {return numObjects;}
02126
02127 private:
02128
02129 ostream* m_fp;
02130
02131
02132
02133
02134 short int m_nIndent;
02135
02136
02137
02138
02139
02140 char indentstring[41];
02141
02142
02143 unsigned long numObjects;
02144
02145
02146 unsigned int numParents;
02147
02148
02149 const Object *currentObject;
02150
02151
02152 const Object *parentObject;
02153
02154
02155
02156 DECLARE_EXPORT void incIndent();
02157
02158
02159 DECLARE_EXPORT void decIndent();
02160
02161
02162 content_type content;
02163
02164
02165
02166
02167
02168 string headerStart;
02169
02170
02171
02172
02173
02174
02175 string headerAtts;
02176 };
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 class XMLOutputFile : public XMLOutput
02187 {
02188 public:
02189
02190
02191 XMLOutputFile(const string& chFilename)
02192 {
02193 of.open(chFilename.c_str(), ios::out);
02194 if(!of) throw RuntimeException("Could not open output file");
02195 setOutput(of);
02196 }
02197
02198
02199 ~XMLOutputFile() {of.close();}
02200
02201 private:
02202 ofstream of;
02203 };
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214 class XMLOutputString : public XMLOutput
02215 {
02216 public:
02217
02218 XMLOutputString(const string& str) : os(str) {setOutput(os);}
02219
02220
02221 XMLOutputString() {setOutput(os);}
02222
02223
02224 const string getData() const {return os.str();}
02225
02226 private:
02227 ostringstream os;
02228 };
02229
02230
02231
02232
02233
02234
02235 class Attribute
02236 {
02237 private:
02238
02239 hashtype hash;
02240
02241
02242
02243
02244
02245 const char* ch;
02246
02247 public:
02248
02249 explicit Attribute() : hash(0), ch(NULL) {}
02250
02251
02252 explicit Attribute(const string& n)
02253 : hash(Keyword::hash(n)), ch(n.c_str()) {}
02254
02255
02256 explicit Attribute(const char* c) : hash(Keyword::hash(c)), ch(c) {}
02257
02258
02259 Attribute(const Attribute& o) : hash(o.hash), ch(o.ch) {}
02260
02261
02262 hashtype getHash() const {return hash;}
02263
02264
02265 void reset(const char *const c)
02266 {
02267 hash = Keyword::hash(c);
02268 ch = c;
02269 }
02270
02271
02272 void reset(const XMLCh *const c)
02273 {
02274 hash = Keyword::hash(c);
02275
02276
02277 ch = NULL;
02278 }
02279
02280
02281
02282
02283
02284
02285 DECLARE_EXPORT const char* getName() const;
02286
02287
02288
02289 bool isA(const Keyword& t) const {return t.getHash() == hash;}
02290
02291
02292
02293 bool isA(const Keyword* t) const {return t->getHash() == hash;}
02294
02295
02296 bool operator < (const Attribute& o) const {return hash < o.hash;}
02297
02298
02299 bool operator == (const string o) const {return o == ch;}
02300 };
02301
02302
02303
02304
02305
02306
02307
02308
02309 class DataElement
02310 {
02311 public:
02312 virtual operator bool() const
02313 {throw LogicException("DataElement is an abstract class");}
02314
02315
02316 virtual ~DataElement() {}
02317
02318 void operator >> (unsigned long int& val) const {val = getUnsignedLong();}
02319
02320 void operator >> (long& val) const {val = getLong();}
02321
02322 void operator >> (TimePeriod& val) const {val = getTimeperiod();}
02323
02324 void operator >> (bool& v) const {v=getBool();}
02325
02326 void operator >> (int& val) const {val = getInt();}
02327
02328 void operator >> (double& val) const {val = getDouble();}
02329
02330 void operator >> (Date& val) const {val = getDate();}
02331
02332 void operator >> (string& val) const {val = getString();}
02333
02334 virtual long getLong() const
02335 {throw LogicException("DataElement is an abstract class");}
02336
02337 virtual unsigned long getUnsignedLong() const
02338 {throw LogicException("DataElement is an abstract class");}
02339
02340 virtual TimePeriod getTimeperiod() const
02341 {throw LogicException("DataElement is an abstract class");}
02342
02343 virtual int getInt() const
02344 {throw LogicException("DataElement is an abstract class");}
02345
02346 virtual double getDouble() const
02347 {throw LogicException("DataElement is an abstract class");}
02348
02349 virtual Date getDate() const
02350 {throw LogicException("DataElement is an abstract class");}
02351
02352 virtual string getString() const
02353 {throw LogicException("DataElement is an abstract class");}
02354
02355 virtual bool getBool() const
02356 {throw LogicException("DataElement is an abstract class");}
02357 };
02358
02359
02360
02361
02362 class XMLElement : public DataElement
02363 {
02364 private:
02365
02366 string m_strData;
02367
02368 public:
02369 virtual operator bool() const {return !m_strData.empty();}
02370
02371
02372 XMLElement() {}
02373
02374
02375 XMLElement(const string& v) : m_strData(v) {}
02376
02377
02378 virtual ~XMLElement() {}
02379
02380
02381
02382
02383
02384 void reset() {m_strData.clear();}
02385
02386
02387
02388
02389
02390 void addData(const char *pData, size_t len) {m_strData.append(pData,len);}
02391
02392
02393 void setData(const char *pData) {m_strData.assign(pData);}
02394
02395
02396 const char *getData() const {return m_strData.c_str();}
02397
02398 virtual long getLong() const {return atol(getData());}
02399
02400 virtual unsigned long getUnsignedLong() const {return atol(getData());}
02401
02402 virtual TimePeriod getTimeperiod() const {return TimePeriod(getData());}
02403
02404 virtual int getInt() const {return atoi(getData());}
02405
02406 virtual double getDouble() const {return atof(getData());}
02407
02408 virtual Date getDate() const {return Date(getData());}
02409
02410
02411
02412 virtual string getString() const {return m_strData;}
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423 DECLARE_EXPORT bool getBool() const;
02424 };
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436 class AttributeList
02437 {
02438 public:
02439 virtual const DataElement* get(const Keyword&) const = 0;
02440
02441
02442
02443 virtual ~AttributeList() {}
02444 };
02445
02446
02447
02448 class XMLAttributeList : public AttributeList
02449 {
02450 private:
02451 const xercesc::Attributes* atts;
02452 XMLElement result;
02453 public:
02454 XMLAttributeList(const xercesc::Attributes* a) : atts(a) {}
02455
02456 const XMLElement* get(const Keyword& key) const
02457 {
02458 char* s = xercesc::XMLString::transcode(atts->getValue(key.getXMLCharacters()));
02459 const_cast<XMLAttributeList*>(this)->result.setData(s ? s : "");
02460 xercesc::XMLString::release(&s);
02461 return &result;
02462 }
02463 };
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478 class Object
02479 {
02480 public:
02481
02482 explicit Object() {}
02483
02484
02485 virtual ~Object() {}
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495 virtual void writeElement(XMLOutput *, const Keyword &, mode=DEFAULT) const
02496 {throw LogicException("Class can't be persisted");}
02497
02498
02499
02500
02501
02502
02503 virtual void beginElement(XMLInput&, const Attribute&) {}
02504
02505
02506
02507
02508
02509 virtual void endElement(XMLInput&, const Attribute&, const DataElement&) = 0;
02510
02511
02512
02513 virtual void setHidden(bool b) {}
02514
02515
02516 virtual bool getHidden() const {return false;}
02517
02518
02519
02520 virtual const MetaClass& getType() const = 0;
02521
02522
02523 virtual size_t getSize() const = 0;
02524
02525
02526
02527 template <class T> static Object* createDefault()
02528 {return new T();}
02529
02530
02531
02532 template <class T> static Object* createString(const string& n)
02533 {return new T(n);}
02534 };
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548 class Tree : public NonCopyable
02549 {
02550 public:
02551
02552
02553
02554
02555
02556 enum NodeColor { red, black, none };
02557
02558
02559
02560
02561
02562
02563 class TreeNode
02564 {
02565 friend class Tree;
02566
02567 public:
02568
02569 virtual ~TreeNode() {}
02570
02571
02572
02573 const string& getName() const {return nm;}
02574
02575
02576 bool operator < (const TreeNode& o) {return nm < o.nm;}
02577
02578
02579 TreeNode(const string& n) : nm(n), color(none)
02580 {
02581 if (n.empty())
02582 throw DataException("Can't create entity without name");
02583 }
02584
02585
02586 TreeNode* increment() const
02587 {
02588 TreeNode *node = const_cast<TreeNode*>(this);
02589 if (node->right != NULL)
02590 {
02591 node = node->right;
02592 while (node->left != NULL) node = node->left;
02593 }
02594 else
02595 {
02596 TreeNode* y = node->parent;
02597 while (node == y->right)
02598 {
02599 node = y;
02600 y = y->parent;
02601 }
02602 if (node->right != y) node = y;
02603 }
02604 return node;
02605 }
02606
02607
02608 TreeNode* decrement() const
02609 {
02610 TreeNode *node = const_cast<TreeNode*>(this);
02611 if (node->color == red && node->parent->parent == node)
02612 node = node->right;
02613 else if (node->left != NULL)
02614 {
02615 TreeNode* y = node->left;
02616 while (y->right != NULL) y = y->right;
02617 node = y;
02618 }
02619 else
02620 {
02621 TreeNode* y = node->parent;
02622 while (node == y->left)
02623 {
02624 node = y;
02625 y = y->parent;
02626 }
02627 node = y;
02628 }
02629 return node;
02630 }
02631
02632 private:
02633
02634 TreeNode() {}
02635
02636
02637 string nm;
02638
02639
02640 NodeColor color;
02641
02642
02643 TreeNode* parent;
02644
02645
02646 TreeNode* left;
02647
02648
02649 TreeNode* right;
02650 };
02651
02652
02653 Tree(bool b = false) : count(0), clearOnDestruct(b)
02654 {
02655
02656 header.color = red;
02657 header.parent = NULL;
02658 header.left = &header;
02659 header.right = &header;
02660 }
02661
02662
02663
02664
02665
02666
02667 ~Tree() { if(clearOnDestruct) clear(); }
02668
02669
02670
02671
02672
02673 TreeNode* begin() const {return const_cast<TreeNode*>(header.left);}
02674
02675
02676
02677
02678
02679 TreeNode* end() const {return const_cast<TreeNode*>(&header);}
02680
02681
02682
02683 bool empty() const
02684 {
02685 ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
02686 return header.parent == NULL;
02687 }
02688
02689
02690 void rename(TreeNode* obj, string newname)
02691 {
02692 bool found;
02693 findLowerBound(newname, &found);
02694 if (found)
02695 throw DataException("Can't rename '" + obj->nm + "' to '"
02696 + newname + "': name already in use");
02697 erase(obj);
02698
02699 obj->nm = newname;
02700 insert(obj);
02701 };
02702
02703
02704
02705
02706
02707 size_t size() const
02708 {
02709 ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
02710 return count;
02711 }
02712
02713
02714
02715
02716
02717 DECLARE_EXPORT void verify() const;
02718
02719
02720 DECLARE_EXPORT void clear();
02721
02722
02723 DECLARE_EXPORT void erase(TreeNode* x);
02724
02725
02726
02727
02728
02729
02730 TreeNode* find(const string& k) const
02731 {
02732 ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
02733 int comp;
02734 for (TreeNode* x = header.parent; x; x = comp<0 ? x->left : x->right)
02735 {
02736 comp = k.compare(x->nm);
02737 if (!comp) return x;
02738 }
02739 TreeNode* result = end();
02740 return result;
02741 }
02742
02743
02744
02745
02746
02747
02748 TreeNode* findLowerBound(const string& k, bool* f) const
02749 {
02750 ScopeMutexLock l(const_cast<Mutex&>(treeaccess));
02751 TreeNode* lower = end();
02752 for (TreeNode* x = header.parent; x;)
02753 {
02754 int comp = k.compare(x->nm);
02755 if (!comp)
02756 {
02757
02758 if (f) *f = true;
02759 return x;
02760 }
02761 if (comp<0) x = x->left;
02762 else lower = x, x = x->right;
02763 }
02764 if (f) *f = false;
02765 return lower;
02766 }
02767
02768
02769 TreeNode* insert(TreeNode* v) {return insert(v, NULL);}
02770
02771
02772
02773
02774
02775
02776
02777 DECLARE_EXPORT TreeNode* insert(TreeNode* v, TreeNode* hint);
02778
02779 private:
02780
02781
02782 inline void rebalance(TreeNode* x);
02783
02784
02785 inline void rotateLeft(TreeNode* x);
02786
02787
02788 inline void rotateRight(TreeNode* x);
02789
02790
02791 unsigned int countBlackNodes(TreeNode* node) const
02792 {
02793 unsigned int sum = 0;
02794 for ( ; node != header.parent; node=node->parent)
02795 if (node->color == black) ++sum;
02796 return sum;
02797 }
02798
02799 TreeNode* minimum(TreeNode* x) const
02800 {
02801 while (x->left) x = x->left;
02802 return x;
02803 }
02804
02805 TreeNode* maximum(TreeNode* x) const
02806 {
02807 while (x->right) x = x->right;
02808 return x;
02809 }
02810
02811
02812
02813
02814
02815
02816
02817 TreeNode header;
02818
02819
02820 size_t count;
02821
02822
02823
02824
02825
02826 Mutex treeaccess;
02827
02828
02829
02830
02831
02832
02833
02834
02835 bool clearOnDestruct;
02836 };
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851 class Command
02852 {
02853 friend class CommandList;
02854 public:
02855
02856
02857
02858
02859
02860
02861 enum inheritableBool {
02862 INHERIT = -1,
02863 YES = 0,
02864 NO = 1
02865 };
02866
02867
02868
02869
02870
02871 Command() : verbose(INHERIT), owner(NULL), next(NULL), prev(NULL) {};
02872
02873
02874
02875
02876
02877
02878
02879 virtual void execute() = 0;
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892 virtual void undo()
02893 {logger << "Warning: Can't undo command" << getDescription() << endl;}
02894
02895
02896 virtual bool undoable() const {return false;}
02897
02898 virtual string getDescription() const {return "No description available";}
02899 virtual ~Command() {};
02900
02901
02902
02903 DECLARE_EXPORT bool getVerbose() const;
02904
02905
02906 void setVerbose(bool b) {verbose = (b ? YES : NO);}
02907
02908
02909 static DECLARE_EXPORT const MetaCategory* metadataInstruction;
02910
02911 private:
02912
02913
02914
02915
02916
02917
02918 inheritableBool verbose;
02919
02920
02921
02922 Command *owner;
02923
02924
02925
02926 Command *next;
02927
02928
02929
02930 Command *prev;
02931 };
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952 class CommandList : public Command
02953 {
02954 private:
02955
02956
02957
02958
02959
02960 Command* firstCommand;
02961
02962
02963 Command* lastCommand;
02964
02965
02966 Command* curCommand;
02967
02968
02969
02970
02971
02972 Mutex lock;
02973
02974
02975 bool can_undo;
02976
02977
02978
02979
02980
02981
02982
02983
02984 int maxparallel;
02985
02986
02987
02988
02989
02990
02991
02992 inheritableBool abortOnError;
02993
02994
02995
02996
02997 #if defined(HAVE_PTHREAD_H) || !defined(MT)
02998 static void* wrapper(void *arg);
02999 #else
03000 static unsigned __stdcall wrapper(void *);
03001 #endif
03002
03003
03004
03005
03006 DECLARE_EXPORT Command* selectCommand();
03007
03008 public:
03009
03010 int getNumberOfCommands() const
03011 {
03012 int cnt = 0;
03013 for(Command *i=firstCommand; i; i=i->next) ++cnt;
03014 return cnt;
03015 }
03016
03017
03018 DECLARE_EXPORT void add(Command* c);
03019
03020
03021 Command* getLastCommand() const {return lastCommand;}
03022
03023
03024
03025
03026
03027 void undo() {undo(NULL);}
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 DECLARE_EXPORT void undo(Command *c);
03038
03039
03040
03041 DECLARE_EXPORT void execute();
03042
03043
03044
03045 DECLARE_EXPORT bool getAbortOnError() const;
03046
03047
03048
03049
03050
03051
03052 void setAbortOnError(bool b) {abortOnError = (b ? YES : NO);}
03053
03054
03055
03056
03057 int getMaxParallel() const {return maxparallel;}
03058
03059
03060
03061 void setMaxParallel(int b)
03062 {
03063 if (b<1)
03064 throw DataException("Invalid number of parallel execution threads");
03065 #ifndef MT
03066 maxparallel = (b>1 ? 1 : b);
03067 #else
03068
03069 int max = Environment::getProcessors() * 2;
03070 maxparallel = (b>max ? max : b);
03071 #endif
03072 }
03073
03074
03075 bool undoable() const {return can_undo;}
03076
03077
03078 DECLARE_EXPORT bool undoable(const Command *c) const;
03079
03080
03081 string getDescription() const {return "Command list";}
03082
03083
03084 bool empty() const {return firstCommand==NULL;}
03085
03086
03087 explicit CommandList() : firstCommand(NULL), lastCommand(NULL),
03088 curCommand(NULL), can_undo(true), maxparallel(1),
03089 abortOnError(INHERIT) {}
03090
03091
03092
03093
03094
03095
03096 virtual DECLARE_EXPORT ~CommandList();
03097 };
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111 class CommandLoadLibrary : public Command
03112 {
03113 public:
03114
03115 static DECLARE_EXPORT void printModules();
03116
03117
03118 typedef map<string,XMLElement> ParameterList;
03119
03120
03121
03122
03123 explicit CommandLoadLibrary(const string& libname) : lib(libname) {};
03124
03125
03126 explicit CommandLoadLibrary() {};
03127
03128
03129
03130
03131 void setLibraryName(const string& libname) {lib = libname;}
03132
03133
03134 string getLibraryName() {return lib;}
03135
03136
03137
03138
03139
03140 DECLARE_EXPORT void execute();
03141
03142
03143 static DECLARE_EXPORT PyObject* executePython(PyObject*, PyObject*, PyObject*);
03144
03145 DECLARE_EXPORT void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement);
03146 string getDescription() const {return "Loading shared library " + lib;}
03147
03148
03149 void addParameter(const string& name, const string& value)
03150 { parameters[name] = value; }
03151
03152
03153 static bool isLoaded(const string& s)
03154 { return registry.find(s) != registry.end(); }
03155
03156 private:
03157
03158 string lib;
03159
03160
03161 ParameterList parameters;
03162
03163
03164 string tempName;
03165
03166
03167 string tempValue;
03168
03169
03170 static set<string> registry;
03171 };
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193 class XMLInput : public NonCopyable, private xercesc::DefaultHandler
03194 {
03195 public:
03196 typedef pair<Attribute,XMLElement> datapair;
03197
03198 private:
03199
03200 xercesc::SAX2XMLReader* parser;
03201
03202
03203 enum state
03204 {
03205
03206 READOBJECT,
03207
03208 IGNOREINPUT,
03209
03210 SHUTDOWN,
03211
03212
03213 INIT
03214 };
03215
03216
03217
03218
03219
03220
03221 const unsigned short maxdepth;
03222
03223
03224
03225 CommandList cmds;
03226
03227
03228 stack <state> states;
03229
03230
03231 Object* prev;
03232
03233
03234
03235
03236
03237
03238
03239 vector< pair<Object*,void*> > m_EHStack;
03240
03241
03242
03243
03244
03245
03246 vector<datapair> m_EStack;
03247
03248
03249
03250
03251
03252 short numElements;
03253
03254
03255
03256
03257
03258 unsigned short ignore;
03259
03260
03261 stack<hashtype> endingHashes;
03262
03263
03264
03265
03266
03267 bool objectEnded;
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281 bool abortOnDataException;
03282
03283
03284
03285
03286
03287 XMLAttributeList attributes;
03288
03289
03290
03291
03292 void startElement (const XMLCh* const, const XMLCh* const,
03293 const XMLCh* const, const xercesc::Attributes&);
03294
03295
03296
03297
03298
03299
03300
03301
03302 void endElement
03303 (const XMLCh* const, const XMLCh* const, const XMLCh* const);
03304
03305
03306
03307
03308 void characters(const XMLCh *const, const unsigned int);
03309
03310
03311
03312 void fatalError (const xercesc::SAXParseException& e) {throw e;}
03313
03314
03315
03316
03317
03318
03319 void processingInstruction (const XMLCh *const, const XMLCh *const);
03320
03321
03322
03323 void error (const xercesc::SAXParseException& e) {throw e;}
03324
03325
03326 void warning (const xercesc::SAXParseException&);
03327
03328
03329
03330 void reset();
03331
03332 public:
03333
03334
03335
03336
03337 XMLInput(unsigned short maxNestedElmnts = 20)
03338 : parser(NULL), maxdepth(maxNestedElmnts), m_EStack(maxNestedElmnts+2),
03339 numElements(-1), ignore(0), objectEnded(false),
03340 abortOnDataException(true), attributes(NULL) {}
03341
03342
03343 virtual ~XMLInput() {reset();}
03344
03345
03346
03347
03348
03349 const AttributeList& getAttributes() const {return attributes;}
03350
03351
03352
03353
03354
03355
03356
03357
03358 DECLARE_EXPORT void readto(Object*);
03359
03360
03361
03362
03363
03364
03365 void shutdown();
03366
03367
03368 void IgnoreElement() {readto(NULL);}
03369
03370
03371
03372 bool isObjectEnd() {return objectEnded;}
03373
03374
03375 Object* getCurrentObject() const
03376 {return m_EHStack.empty() ? NULL : m_EHStack.back().first;}
03377
03378
03379
03380
03381
03382 void invalidateCurrentObject()
03383 {
03384 if (!m_EHStack.empty())
03385 m_EHStack.back().first = NULL;
03386 }
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398 Object* getPreviousObject() const {return prev;}
03399
03400
03401 Object* getParentObject() const
03402 {
03403 int x = m_EHStack.size();
03404 return x>1 ? m_EHStack[x-2].first : NULL;
03405 }
03406
03407
03408 const datapair& getParentElement() const
03409 {return m_EStack[numElements>0 ? numElements : 0];}
03410
03411
03412 const datapair& getCurrentElement() const
03413 {return m_EStack[numElements>-1 ? numElements+1 : 0];}
03414
03415
03416
03417
03418
03419
03420 void parse(xercesc::InputSource&, Object*, bool=false);
03421
03422
03423
03424 void setUserArea(void* v)
03425 {if (!m_EHStack.empty()) m_EHStack.back().second = v;}
03426
03427
03428 void* getUserArea() const
03429 {return m_EHStack.empty() ? NULL : m_EHStack.back().second;}
03430
03431
03432
03433 void setAbortOnDataError(bool i) {abortOnDataException = i;}
03434
03435
03436
03437
03438
03439
03440
03441 bool getAbortOnDataError() const {return abortOnDataException;}
03442
03443
03444 CommandList& getCommands() {return cmds;}
03445
03446 protected:
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457 virtual void parse(Object* s, bool b=false)
03458 {
03459 throw LogicException("Unreachable code reached");
03460 }
03461
03462
03463 DECLARE_EXPORT void executeCommands();
03464 };
03465
03466
03467
03468 class XMLInputString : public XMLInput
03469 {
03470 public:
03471
03472 XMLInputString(const string& s) : data(s) {};
03473
03474
03475 void parse(Object* pRoot, bool v = false)
03476 {
03477
03478
03479
03480
03481
03482 xercesc::MemBufInputSource a(
03483 reinterpret_cast<const XMLByte*>(data.c_str()),
03484 static_cast<const unsigned int>(data.size()),
03485 "memory data",
03486 false);
03487 XMLInput::parse(a,pRoot,v);
03488 }
03489
03490 private:
03491
03492
03493
03494
03495
03496 const string data;
03497 };
03498
03499
03500
03501
03502
03503
03504
03505
03506 class XMLInputFile : public XMLInput
03507 {
03508 public:
03509
03510
03511 XMLInputFile(const string& s) : filename(s) {};
03512
03513
03514 XMLInputFile() {};
03515
03516
03517 void setFileName(const string& s) {filename = s;}
03518
03519
03520 string getFileName() {return filename;}
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532 void parse(Object*, bool=false);
03533
03534 private:
03535
03536 string filename;
03537 };
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552 template <class T> class HasName : public NonCopyable, public Tree::TreeNode
03553 {
03554 private:
03555
03556
03557 static DECLARE_EXPORT Tree st;
03558 typedef T* type;
03559
03560 public:
03561
03562
03563
03564
03565
03566
03567 class iterator
03568 {
03569 public:
03570
03571 iterator(Tree::TreeNode* x) : node(x) {}
03572
03573
03574 iterator(const iterator& it) {node = it.node;}
03575
03576
03577 T& operator*() const {return *static_cast<T*>(node);}
03578
03579
03580 T* operator->() const {return static_cast<T*>(node);}
03581
03582
03583
03584 iterator& operator++() {node = node->increment(); return *this;}
03585
03586
03587
03588 iterator operator++(int)
03589 {
03590 Tree::TreeNode* tmp = node;
03591 node = node->increment();
03592 return tmp;
03593 }
03594
03595
03596
03597 iterator& operator--() {node = node->decrement(); return *this;}
03598
03599
03600
03601 iterator operator--(int)
03602 {
03603 Tree::TreeNode* tmp = node;
03604 node = node->decrement();
03605 return tmp;
03606 }
03607
03608
03609 bool operator==(const iterator& y) const {return node==y.node;}
03610
03611
03612 bool operator!=(const iterator& y) const {return node!=y.node;}
03613
03614 private:
03615 Tree::TreeNode* node;
03616 };
03617
03618
03619 static iterator end() {return st.end();}
03620
03621
03622 static iterator begin() {return st.begin();}
03623
03624
03625 static bool empty() {return st.empty();}
03626
03627
03628 static size_t size() {return st.size();}
03629
03630
03631
03632 static void verify() {st.verify();}
03633
03634
03635 static void clear() {st.clear();}
03636
03637
03638 explicit HasName(const string& n) : Tree::TreeNode(n) {}
03639
03640
03641 explicit HasName(const char* n) : Tree::TreeNode(n) {}
03642
03643
03644 void setName(const string& newname) {st.rename(this, newname);}
03645
03646
03647 ~HasName() {st.erase(this);}
03648
03649
03650
03651 static T* find(const string& k)
03652 {
03653 Tree::TreeNode *i = st.find(k);
03654 return (i!=st.end() ? static_cast<T*>(i) : NULL);
03655 }
03656
03657
03658
03659
03660
03661
03662 static T* findLowerBound(const string& k, bool *f = NULL)
03663 {
03664 Tree::TreeNode *i = st.findLowerBound(k, f);
03665 return (i!=st.end() ? static_cast<T*>(i) : NULL);
03666 }
03667
03668
03669 static T* add(const string& k, const MetaClass& cls)
03670 {
03671 Tree::TreeNode *i = st.find(k);
03672 if (i!=st.end()) return static_cast<T*>(i);
03673 if (*(cls.category) != T::metadata)
03674 throw LogicException("Invalid type " + cls.type +
03675 " for creating an object of category " + T::metadata.type);
03676 T *t = dynamic_cast<T*>(cls.factoryMethodString(k));
03677 st.insert(t);
03678 return t;
03679 }
03680
03681
03682 static T* add(T* t) {return static_cast<T*>(st.insert(t));}
03683
03684
03685
03686
03687
03688 static T* add(T* t, T* hint) {return static_cast<T*>(st.insert(t,hint));}
03689
03690 void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement) {};
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709 static Object* reader (const MetaClass* cat, const AttributeList& in)
03710 {
03711
03712 Action act = MetaClass::decodeAction(in);
03713
03714
03715 const DataElement* nameElement = in.get(Tags::tag_name);
03716 if (!*nameElement) throw DataException("Missing name attribute");
03717 string name = nameElement->getString();
03718
03719
03720 bool found;
03721 T *i = T::findLowerBound(name, &found);
03722
03723
03724 switch (act)
03725 {
03726 case ADD:
03727
03728 if (found)
03729 throw DataException("Object '" + name + "' already exists");
03730 break;
03731
03732 case CHANGE:
03733
03734 if (!found)
03735 throw DataException("Object '" + name + "' doesn't exist");
03736 return i;
03737
03738 case REMOVE:
03739
03740 if (found)
03741 {
03742
03743 if (i->getType().raiseEvent(i,SIG_REMOVE))
03744 {
03745
03746 delete i;
03747 return NULL;
03748 }
03749 else
03750
03751 throw DataException("Can't remove object '" + name + "'");
03752 }
03753 else
03754
03755 throw DataException("Can't find object '" + name + "' for removal");
03756 default:
03757
03758 ;
03759 }
03760
03761
03762 if (found) return i;
03763
03764
03765 const MetaClass* j;
03766 if (cat->category)
03767
03768 j = cat;
03769 else
03770 {
03771
03772 const DataElement* type = in.get(Tags::tag_type);
03773 j = static_cast<const MetaCategory&>(*cat).findClass(*type ? Keyword::hash(type->getString()) : MetaCategory::defaultHash);
03774 if (!j)
03775 {
03776 string t(*type ? type->getString() : "default");
03777 throw DataException("No type " + t + " registered for category " + cat->type);
03778 }
03779 }
03780
03781
03782 T* x = dynamic_cast<T*>(j->factoryMethodString(name));
03783
03784
03785
03786
03787
03788
03789 if (!x->getType().raiseEvent(x,SIG_ADD))
03790 {
03791
03792 delete x;
03793 throw DataException("Can't create object " + name);
03794 }
03795
03796
03797 T::add(x, i);
03798 return x;
03799 }
03800
03801
03802 static void writer(const MetaCategory* c, XMLOutput* o)
03803 {
03804 if (empty()) return;
03805 o->BeginObject(*(c->grouptag));
03806 for (iterator i = begin(); i != end(); ++i)
03807 o->writeElement(*(c->typetag), *i);
03808 o->EndObject(*(c->grouptag));
03809 }
03810 };
03811
03812
03813
03814
03815
03816
03817 class HasDescription
03818 {
03819 public:
03820
03821 string getCategory() const {return cat;}
03822
03823
03824 string getSubCategory() const {return subcat;}
03825
03826
03827 string getDescription() const {return descr;}
03828
03829
03830 void setCategory(const string& f) {cat = f;}
03831
03832
03833 void setSubCategory(const string& f) {subcat = f;}
03834
03835
03836 void setDescription(const string& f) {descr = f;}
03837
03838 void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
03839 void endElement(XMLInput&, const Attribute&, const DataElement&);
03840
03841 protected:
03842
03843 size_t extrasize() const {return cat.size() + subcat.size() + descr.size();}
03844
03845 private:
03846 string cat;
03847 string subcat;
03848 string descr;
03849 };
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863 template <class T> class HasHierarchy : public HasName<T>
03864 {
03865 #if (defined _MSC_VER) || (defined __BORLANDC__)
03866
03867
03868 friend class HasHierarchy<T>;
03869 #endif
03870
03871 public:
03872 class memberIterator;
03873 friend class memberIterator;
03874
03875
03876
03877
03878
03879 class memberIterator
03880 {
03881 public:
03882
03883 memberIterator(HasHierarchy<T>* x) : curmember(x) {}
03884
03885
03886 memberIterator(const memberIterator& it) {curmember = it.curmember;}
03887
03888
03889 T& operator*() const {return *static_cast<T*>(curmember);}
03890
03891
03892 T* operator->() const {return static_cast<T*>(curmember);}
03893
03894
03895
03896 memberIterator& operator++()
03897 {curmember = curmember->next_brother; return *this;}
03898
03899
03900
03901 memberIterator operator++(int)
03902 {
03903 memberIterator tmp = *this;
03904 curmember = curmember->next_brother;
03905 return tmp;
03906 }
03907
03908
03909 bool operator==(const memberIterator& y) const
03910 {return curmember == y.curmember;}
03911
03912
03913 bool operator!=(const memberIterator& y) const
03914 {return curmember != y.curmember;}
03915
03916 private:
03917
03918 HasHierarchy<T>* curmember;
03919 };
03920
03921
03922 HasHierarchy(const string& n) : HasName<T>(n), parent(NULL),
03923 first_child(NULL), next_brother(NULL) {}
03924
03925
03926
03927
03928
03929
03930
03931 ~HasHierarchy();
03932
03933 memberIterator beginMember() const {return first_child;}
03934
03935 memberIterator endMember() const {return NULL;}
03936
03937
03938
03939
03940
03941 bool hasOwner() const {return parent!=NULL;}
03942
03943
03944
03945 bool isGroup() const {return first_child!=NULL;}
03946
03947
03948
03949
03950
03951 void setOwner(T* f);
03952
03953
03954 T* getOwner() const {return parent;}
03955
03956
03957
03958
03959
03960
03961 unsigned short getHierarchyLevel() const;
03962
03963 void beginElement(XMLInput&, const Attribute&);
03964 void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const;
03965 void endElement(XMLInput&, const Attribute&, const DataElement&);
03966
03967 private:
03968
03969 T *parent;
03970
03971
03972 T *first_child;
03973
03974
03975
03976
03977
03978
03979 T *next_brother;
03980 };
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004 template <class A, class B, class C> class Association
04005 {
04006 public:
04007 class Node;
04008 private:
04009
04010
04011
04012 class List
04013 {
04014 friend class Node;
04015 public:
04016 C* first;
04017 public:
04018 List() : first(NULL) {};
04019 bool empty() const {return first==NULL;}
04020 };
04021
04022 public:
04023
04024 class ListA : public List
04025 {
04026 public:
04027 ListA() {};
04028
04029 class iterator
04030 {
04031 protected:
04032 C* nodeptr;
04033 public:
04034 iterator(C* n) : nodeptr(n) {};
04035 C& operator*() const {return *nodeptr;}
04036 C* operator->() const {return nodeptr;}
04037 bool operator==(const iterator& x) const
04038 {return nodeptr == x.nodeptr;}
04039 bool operator!=(const iterator& x) const
04040 {return nodeptr != x.nodeptr;}
04041 iterator& operator++()
04042 {nodeptr = nodeptr->nextA; return *this;}
04043 iterator operator++(int i)
04044 {
04045 iterator j = *this;
04046 nodeptr = nodeptr->nextA;
04047 return j;
04048 }
04049 };
04050
04051 class const_iterator
04052 {
04053 protected:
04054 C* nodeptr;
04055 public:
04056 const_iterator(C* n) : nodeptr(n) {};
04057 const C& operator*() const {return *nodeptr;}
04058 const C* operator->() const {return nodeptr;}
04059 bool operator==(const const_iterator& x) const
04060 {return nodeptr == x.nodeptr;}
04061 bool operator!=(const const_iterator& x) const
04062 {return nodeptr != x.nodeptr;}
04063 const_iterator& operator++()
04064 {nodeptr = nodeptr->nextA; return *this;}
04065 const_iterator operator++(int i)
04066 {
04067 const_iterator j = *this;
04068 nodeptr = nodeptr->nextA;
04069 return j;
04070 }
04071 };
04072 iterator begin() {return iterator(this->first);}
04073 const_iterator begin() const {return const_iterator(this->first);}
04074 iterator end() {return iterator(NULL);}
04075 const_iterator end() const {return const_iterator(NULL);}
04076 ~ListA()
04077 {
04078 C* next;
04079 for (C* p=this->first; p; p=next)
04080 {
04081 next = p->nextA;
04082 delete p;
04083 }
04084 }
04085 void erase(const C* n)
04086 {
04087 if (!n) return;
04088 if (n==this->first)
04089 this->first = n->nextA;
04090 else
04091 for (C* p=this->first; p; p=p->nextA)
04092 if(p->nextA == n)
04093 {
04094 p->nextA = n->nextA;
04095 return;
04096 }
04097 }
04098 size_t size() const
04099 {
04100 size_t i(0);
04101 for (C* p = this->first; p; p=p->nextA) ++i;
04102 return i;
04103 }
04104 C* find(const B* b, Date d = Date::infinitePast) const
04105 {
04106 for (C* p=this->first; p; p=p->nextA)
04107 if (p->ptrB == b && p->effectivity.within(d)) return p;
04108 return NULL;
04109 }
04110 };
04111
04112
04113 class ListB : public List
04114 {
04115 public:
04116 ListB() {};
04117
04118 class iterator
04119 {
04120 protected:
04121 C* nodeptr;
04122 public:
04123 iterator(C* n) : nodeptr(n) {};
04124 C& operator*() const {return *nodeptr;}
04125 C* operator->() const {return nodeptr;}
04126 bool operator==(const iterator& x) const
04127 {return nodeptr == x.nodeptr;}
04128 bool operator!=(const iterator& x) const
04129 {return nodeptr != x.nodeptr;}
04130 iterator& operator++()
04131 {nodeptr = nodeptr->nextB; return *this;}
04132 iterator operator++(int i)
04133 {
04134 iterator j = *this;
04135 nodeptr = nodeptr->nextA;
04136 return j;
04137 }
04138 };
04139
04140 class const_iterator
04141 {
04142 protected:
04143 C* nodeptr;
04144 public:
04145 const_iterator(C* n) : nodeptr(n) {};
04146 const C& operator*() const {return *nodeptr;}
04147 const C* operator->() const {return nodeptr;}
04148 bool operator==(const const_iterator& x) const
04149 {return nodeptr == x.nodeptr;}
04150 bool operator!=(const const_iterator& x) const
04151 {return nodeptr != x.nodeptr;}
04152 const_iterator& operator++()
04153 {nodeptr = nodeptr->nextB; return *this;}
04154 const_iterator operator++(int i)
04155 {
04156 const_iterator j = *this;
04157 nodeptr = nodeptr->nextA;
04158 return j;
04159 }
04160 };
04161 ~ListB()
04162 {
04163 C* next;
04164 for (C* p=this->first; p; p=next)
04165 {
04166 next = p->nextB;
04167 delete p;
04168 }
04169 }
04170 iterator begin() {return iterator(this->first);}
04171 const_iterator begin() const {return const_iterator(this->first);}
04172 iterator end() {return iterator(NULL);}
04173 const_iterator end() const {return const_iterator(NULL);}
04174 void erase(const C* n)
04175 {
04176 if (!n) return;
04177 if (n==this->first)
04178 this->first = n->nextB;
04179 else
04180 for (C* p=this->first; p; p=p->nextB)
04181 if(p->nextB == n)
04182 {
04183 p->nextB = n->nextB;
04184 return;
04185 }
04186 }
04187 size_t size() const
04188 {
04189 size_t i(0);
04190 for (C* p=this->first; p; p=p->nextB) ++i;
04191 return i;
04192 }
04193 C* find(const A* b, Date d = Date::infinitePast) const
04194 {
04195 for (C* p=this->first; p; p=p->nextB)
04196 if (p->ptrA == b && p->effectivity.within(d)) return p;
04197 return NULL;
04198 }
04199 };
04200
04201
04202
04203
04204 class Node
04205 {
04206 public:
04207 A* ptrA;
04208 B* ptrB;
04209 C* nextA;
04210 C* nextB;
04211 DateRange effectivity;
04212 public:
04213 Node() : ptrA(NULL), ptrB(NULL), nextA(NULL), nextB(NULL) {};
04214
04215 Node(A* a, B* b, const ListA& al, const ListB& bl)
04216 : ptrA(a), ptrB(b), nextA(al.first), nextB(bl.first)
04217 {
04218 ((ListA&)al).first = static_cast<C*>(this);
04219 ((ListB&)bl).first = static_cast<C*>(this);
04220 }
04221
04222 void setPtrA(A* a, const ListA& al)
04223 {
04224
04225 if (ptrA) throw DataException("Can't update existing entity");
04226 ptrA = a;
04227 nextA = al.first;
04228 ((ListA&)al).first = static_cast<C*>(this);
04229 }
04230
04231 void setPtrB(B* b, const ListB& bl)
04232 {
04233
04234 if (ptrB) throw DataException("Can't update existing entity");
04235 ptrB = b;
04236 nextB = bl.first;
04237 ((ListB&)bl).first = static_cast<C*>(this);
04238 }
04239
04240 void setPtrAB(A* a, B* b, const ListA& al, const ListB& bl)
04241 {
04242 setPtrA(a, al);
04243 setPtrB(b, bl);
04244 }
04245
04246 A* getPtrA() const {return ptrA;}
04247
04248 B* getPtrB() const {return ptrB;}
04249
04250
04251 void setEffectiveStart(Date d) { effectivity.setStart(d); }
04252
04253
04254 void setEffectiveEnd(Date d) { effectivity.setEnd(d); }
04255
04256
04257 void setEffective(DateRange dr) { effectivity = dr; }
04258
04259
04260
04261
04262 DateRange getEffective() const { return effectivity; }
04263 };
04264 };
04265
04266
04267 #include "frepple/entity.h"
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281 class LibraryUtils
04282 {
04283 public:
04284 static void initialize();
04285 };
04286
04287
04288 }
04289 }
04290
04291 #include "pythonutils.h"
04292
04293 #endif // End of FREPPLE_UTILS_H