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