Go to the documentation of this file.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 #define FREPPLE_CORE
00029 #include "frepple/utils.h"
00030 #include <sys/stat.h>
00031
00032
00033 namespace frepple
00034 {
00035 namespace utils
00036 {
00037
00038
00039 DECLARE_EXPORT const MetaCategory* MetaCategory::firstCategory = NULL;
00040 DECLARE_EXPORT MetaCategory::CategoryMap MetaCategory::categoriesByTag;
00041 DECLARE_EXPORT MetaCategory::CategoryMap MetaCategory::categoriesByGroupTag;
00042
00043
00044 set<string> CommandLoadLibrary::registry;
00045
00046
00047 DECLARE_EXPORT const MetaCategory* Command::metadataInstruction;
00048
00049
00050
00051 DECLARE_EXPORT int Environment::processors = 1;
00052
00053
00054
00055 DECLARE_EXPORT ostream logger(cout.rdbuf());
00056
00057
00058 DECLARE_EXPORT ofstream Environment::logfile;
00059
00060
00061 DECLARE_EXPORT string Environment::logfilename;
00062
00063
00064 DECLARE_EXPORT const hashtype MetaCategory::defaultHash(Keyword::hash("default"));
00065
00066 vector<PythonType*> PythonExtensionBase::table;
00067
00068
00069 DECLARE_EXPORT string Environment::searchFile(const string filename)
00070 {
00071 #ifdef _MSC_VER
00072 static char pathseperator = '\\';
00073 #else
00074 static char pathseperator = '/';
00075 #endif
00076
00077
00078 struct stat stat_p;
00079 int result = stat(filename.c_str(), &stat_p);
00080 if (!result && stat_p.st_mode & S_IREAD)
00081 return filename;
00082
00083
00084 string fullname;
00085 char * envvar = getenv("FREPPLE_HOME");
00086 if (envvar)
00087 {
00088 fullname = envvar;
00089 if (*fullname.rbegin() != pathseperator)
00090 fullname += pathseperator;
00091 fullname += filename;
00092 result = stat(fullname.c_str(), &stat_p);
00093 if (!result && stat_p.st_mode & S_IREAD)
00094 return fullname;
00095 }
00096
00097 #ifdef DATADIRECTORY
00098
00099 fullname = DATADIRECTORY;
00100 if (*fullname.rbegin() != pathseperator)
00101 fullname += pathseperator;
00102 fullname.append(filename);
00103 result = stat(fullname.c_str(), &stat_p);
00104 if (!result && stat_p.st_mode & S_IREAD)
00105 return fullname;
00106 #endif
00107
00108 #ifdef LIBDIRECTORY
00109
00110 fullname = LIBDIRECTORY;
00111 if (*fullname.rbegin() != pathseperator)
00112 fullname += pathseperator;
00113 fullname += "frepple/";
00114 fullname += filename;
00115 result = stat(fullname.c_str(), &stat_p);
00116 if (!result && stat_p.st_mode & S_IREAD)
00117 return fullname;
00118 #endif
00119
00120
00121 return "";
00122 }
00123
00124
00125 DECLARE_EXPORT void Environment::setLogFile(const string& x)
00126 {
00127
00128 if (!logfilename.empty())
00129 logger << "Stop logging at " << Date::now() << endl;
00130
00131
00132 if (logfile.is_open()) logfile.close();
00133
00134
00135 if (x.empty() || x == "+")
00136 {
00137 logfilename = x;
00138 logger.rdbuf(cout.rdbuf());
00139 return;
00140 }
00141
00142
00143 if (x[0] != '+') logfile.open(x.c_str(), ios::out);
00144 else logfile.open(x.c_str()+1, ios::app);
00145 if (!logfile.good())
00146 {
00147
00148 if (logfile.is_open()) logfile.close();
00149 logfile.open(logfilename.c_str(), ios::app);
00150 logger.rdbuf(logfile.is_open() ? logfile.rdbuf() : cout.rdbuf());
00151
00152 throw RuntimeException("Could not open log file '" + x + "'");
00153 }
00154
00155
00156 logfilename = x;
00157
00158
00159 logger.rdbuf(logfile.rdbuf());
00160
00161
00162 logger << "Start logging frePPLe " << PACKAGE_VERSION << " ("
00163 << __DATE__ << ") at " << Date::now() << endl;
00164 }
00165
00166
00167 void LibraryUtils::initialize()
00168 {
00169
00170 static bool init = false;
00171 if (init)
00172 {
00173 logger << "Warning: Calling frepple::LibraryUtils::initialize() more "
00174 << "than once." << endl;
00175 return;
00176 }
00177 init = true;
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 #if defined(HAVE_SETLOCALE) || defined(_MSC_VER)
00189 setlocale(LC_ALL, "" );
00190 #endif
00191
00192
00193 xercesc::XMLPlatformUtils::Initialize();
00194
00195
00196 Command::metadataInstruction = new MetaCategory
00197 ("instruction", "");
00198
00199
00200 CommandPython::metadata2 = new MetaClass(
00201 "instruction", "python", CommandPython::processorXMLInstruction);
00202
00203
00204 PythonInterpreter::initialize();
00205
00206
00207
00208
00209
00210
00211 const char *c = getenv("NUMBER_OF_PROCESSORS");
00212 if (c)
00213 {
00214 int p = atoi(c);
00215 Environment::setProcessors(p);
00216 }
00217 }
00218
00219
00220 DECLARE_EXPORT void MetaClass::registerClass (const string& a, const string& b,
00221 bool def, creatorDefault f)
00222 {
00223
00224 MetaCategory* cat
00225 = const_cast<MetaCategory*>(MetaCategory::findCategoryByTag(a.c_str()));
00226
00227
00228 if (!cat)
00229 throw LogicException("Category " + a
00230 + " not found when registering class " + b);
00231
00232
00233 type = b.empty() ? "unspecified" : b;
00234 typetag = &Keyword::find(type.c_str());
00235 category = cat;
00236
00237
00238 cat->classes[Keyword::hash(b)] = this;
00239
00240
00241 if (def) cat->classes[Keyword::hash("default")] = this;
00242
00243
00244 factoryMethodDefault = f;
00245 }
00246
00247
00248 DECLARE_EXPORT MetaCategory::MetaCategory (const string& a, const string& gr,
00249 readController f, writeController w)
00250 {
00251
00252 if (!a.empty()) categoriesByTag[Keyword::hash(a)] = this;
00253 if (!gr.empty()) categoriesByGroupTag[Keyword::hash(gr)] = this;
00254
00255
00256 readFunction = f;
00257 writeFunction = w;
00258 type = a.empty() ? "unspecified" : a;
00259 typetag = &Keyword::find(type.c_str());
00260 group = gr.empty() ? "unspecified" : gr;
00261 grouptag = &Keyword::find(group.c_str());
00262
00263
00264 nextCategory = NULL;
00265 if (!firstCategory)
00266 firstCategory = this;
00267 else
00268 {
00269 const MetaCategory *i = firstCategory;
00270 while (i->nextCategory) i = i->nextCategory;
00271 const_cast<MetaCategory*>(i)->nextCategory = this;
00272 }
00273 }
00274
00275
00276 DECLARE_EXPORT const MetaCategory* MetaCategory::findCategoryByTag(const char* c)
00277 {
00278
00279 CategoryMap::const_iterator i = categoriesByTag.find(Keyword::hash(c));
00280 return (i!=categoriesByTag.end()) ? i->second : NULL;
00281 }
00282
00283
00284 DECLARE_EXPORT const MetaCategory* MetaCategory::findCategoryByTag(const hashtype h)
00285 {
00286
00287 CategoryMap::const_iterator i = categoriesByTag.find(h);
00288 return (i!=categoriesByTag.end()) ? i->second : NULL;
00289 }
00290
00291
00292 DECLARE_EXPORT const MetaCategory* MetaCategory::findCategoryByGroupTag(const char* c)
00293 {
00294
00295 CategoryMap::const_iterator i = categoriesByGroupTag.find(Keyword::hash(c));
00296 return (i!=categoriesByGroupTag.end()) ? i->second : NULL;
00297 }
00298
00299
00300 DECLARE_EXPORT const MetaCategory* MetaCategory::findCategoryByGroupTag(const hashtype h)
00301 {
00302
00303 CategoryMap::const_iterator i = categoriesByGroupTag.find(h);
00304 return (i!=categoriesByGroupTag.end()) ? i->second : NULL;
00305 }
00306
00307
00308 DECLARE_EXPORT const MetaClass* MetaCategory::findClass(const char* c) const
00309 {
00310
00311 MetaCategory::ClassMap::const_iterator j = classes.find(Keyword::hash(c));
00312 return (j == classes.end()) ? NULL : j->second;
00313 }
00314
00315
00316 DECLARE_EXPORT const MetaClass* MetaCategory::findClass(const hashtype h) const
00317 {
00318
00319 MetaCategory::ClassMap::const_iterator j = classes.find(h);
00320 return (j == classes.end()) ? NULL : j->second;
00321 }
00322
00323
00324 DECLARE_EXPORT void MetaCategory::persist(XMLOutput *o)
00325 {
00326 for (const MetaCategory *i = firstCategory; i; i = i->nextCategory)
00327 if (i->writeFunction) i->writeFunction(i, o);
00328 }
00329
00330
00331 DECLARE_EXPORT const MetaClass* MetaClass::findClass(const char* c)
00332 {
00333
00334 for (MetaCategory::CategoryMap::const_iterator i = MetaCategory::categoriesByTag.begin();
00335 i != MetaCategory::categoriesByTag.end(); ++i)
00336 {
00337
00338 MetaCategory::ClassMap::const_iterator j
00339 = i->second->classes.find(Keyword::hash(c));
00340 if (j != i->second->classes.end()) return j->second;
00341 }
00342
00343 return NULL;
00344 }
00345
00346
00347 DECLARE_EXPORT void MetaClass::printClasses()
00348 {
00349 logger << "Registered classes:" << endl;
00350
00351 for (MetaCategory::CategoryMap::const_iterator i = MetaCategory::categoriesByTag.begin();
00352 i != MetaCategory::categoriesByTag.end(); ++i)
00353 {
00354 logger << " " << i->second->type << endl;
00355
00356 for (MetaCategory::ClassMap::const_iterator
00357 j = i->second->classes.begin();
00358 j != i->second->classes.end();
00359 ++j)
00360 if (j->first == Keyword::hash("default"))
00361 logger << " default ( = " << j->second->type << " )" << j->second << endl;
00362 else
00363 logger << " " << j->second->type << j->second << endl;
00364 }
00365 }
00366
00367
00368 DECLARE_EXPORT Action MetaClass::decodeAction(const char *x)
00369 {
00370
00371 if (!x) throw LogicException("Invalid action NULL");
00372 else if (!strcmp(x,"AC")) return ADD_CHANGE;
00373 else if (!strcmp(x,"A")) return ADD;
00374 else if (!strcmp(x,"C")) return CHANGE;
00375 else if (!strcmp(x,"R")) return REMOVE;
00376 else throw LogicException("Invalid action '" + string(x) + "'");
00377 }
00378
00379
00380 DECLARE_EXPORT Action MetaClass::decodeAction(const AttributeList& atts)
00381 {
00382
00383 const DataElement* c = atts.get(Tags::tag_action);
00384 return *c ? decodeAction(c->getString().c_str()) : ADD_CHANGE;
00385 }
00386
00387
00388 DECLARE_EXPORT bool MetaClass::raiseEvent(Object* v, Signal a) const
00389 {
00390 bool result(true);
00391 for (list<Functor*>::const_iterator i = subscribers[a].begin();
00392 i != subscribers[a].end(); ++i)
00393
00394
00395
00396 if (!(*i)->callback(v,a)) result = false;
00397
00398
00399 return (category && category!=this) ?
00400 (result && category->raiseEvent(v,a)) :
00401 result;
00402 }
00403
00404
00405 Object* MetaCategory::ControllerDefault (const MetaClass* cat, const AttributeList& in)
00406 {
00407 Action act = ADD;
00408 switch (act)
00409 {
00410 case REMOVE:
00411 throw DataException
00412 ("Entity " + cat->type + " doesn't support REMOVE action");
00413 case CHANGE:
00414 throw DataException
00415 ("Entity " + cat->type + " doesn't support CHANGE action");
00416 default:
00417
00418 const MetaClass* j;
00419 if (cat->category)
00420
00421 j = cat;
00422 else
00423 {
00424
00425 const DataElement* type = in.get(Tags::tag_type);
00426 j = static_cast<const MetaCategory&>(*cat).findClass(*type ? Keyword::hash(type->getString()) : MetaCategory::defaultHash);
00427 if (!j)
00428 {
00429 string t(*type ? type->getString() : "default");
00430 throw LogicException("No type " + t + " registered for category " + cat->type);
00431 }
00432 }
00433
00434
00435 Object* result = j->factoryMethodDefault();
00436
00437
00438 if (!result->getType().raiseEvent(result, SIG_ADD))
00439 {
00440
00441 delete result;
00442 throw DataException("Can't create object");
00443 }
00444
00445
00446 return result;
00447 }
00448 throw LogicException("Unreachable code reached");
00449 return NULL;
00450 }
00451
00452
00453 void HasDescription::writeElement(XMLOutput *o, const Keyword &t, mode m) const
00454 {
00455
00456
00457
00458 o->writeElement(Tags::tag_category, cat);
00459 o->writeElement(Tags::tag_subcategory, subcat);
00460 o->writeElement(Tags::tag_description, descr);
00461 }
00462
00463
00464 void HasDescription::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00465 {
00466 if (pAttr.isA(Tags::tag_category))
00467 setCategory(pElement.getString());
00468 else if (pAttr.isA(Tags::tag_subcategory))
00469 setSubCategory(pElement.getString());
00470 else if (pAttr.isA(Tags::tag_description))
00471 setDescription(pElement.getString());
00472 }
00473
00474
00475 DECLARE_EXPORT bool matchWildcard(const char* wild, const char *str)
00476 {
00477
00478 if (!wild || !str) return 1;
00479
00480 const char *cp = NULL, *mp = NULL;
00481
00482 while ((*str) && *wild != '*')
00483 {
00484 if (*wild != *str && *wild != '?')
00485
00486 return 0;
00487 wild++;
00488 str++;
00489 }
00490
00491 while (*str)
00492 {
00493 if (*wild == '*')
00494 {
00495 if (!*++wild) return 1;
00496 mp = wild;
00497 cp = str+1;
00498 }
00499 else if (*wild == *str || *wild == '?')
00500 {
00501 wild++;
00502 str++;
00503 }
00504 else
00505 {
00506 wild = mp;
00507 str = cp++;
00508 }
00509 }
00510
00511 while (*wild == '*') wild++;
00512 return !*wild;
00513 }
00514
00515 }
00516 }
00517