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 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029
00030 namespace frepple
00031 {
00032
00033 DECLARE_EXPORT bool Plannable::anyChange = false;
00034 DECLARE_EXPORT bool Plannable::computationBusy = false;
00035
00036
00037 DECLARE_EXPORT bool Problem::operator < (const Problem& a) const
00038 {
00039
00040 assert(owner == a.owner);
00041
00042
00043 if (getType() != a.getType()) return getType() < a.getType();
00044
00045
00046 return getDateRange().getStart() < a.getDateRange().getStart();
00047 }
00048
00049
00050 DECLARE_EXPORT void Problem::addProblem()
00051 {
00052 assert(owner);
00053 if ((owner->firstProblem && *this < *(owner->firstProblem))
00054 || !owner->firstProblem)
00055 {
00056
00057 nextProblem = owner->firstProblem;
00058 owner->firstProblem = this;
00059 }
00060 else
00061 {
00062
00063 Problem* curProblem = owner->firstProblem->nextProblem;
00064 Problem* prevProblem = owner->firstProblem;
00065 while (curProblem && !(*this < *curProblem))
00066 {
00067 prevProblem = curProblem;
00068 curProblem = curProblem->nextProblem;
00069 }
00070 nextProblem = curProblem;
00071 prevProblem->nextProblem = this;
00072 }
00073 }
00074
00075
00076 DECLARE_EXPORT void Problem::removeProblem()
00077 {
00078
00079
00080 if (!owner) return;
00081
00082 if (owner->firstProblem == this)
00083
00084 owner->firstProblem = nextProblem;
00085 else
00086 {
00087
00088 Problem *prev = owner->firstProblem;
00089 for (Problem* cur = owner->firstProblem; cur; cur=cur->nextProblem)
00090 {
00091 if (cur == this)
00092 {
00093
00094 prev->nextProblem = nextProblem;
00095 return;
00096 }
00097 prev = cur;
00098 }
00099
00100 throw LogicException("Corrupted problem list");
00101 }
00102 }
00103
00104
00105 DECLARE_EXPORT void Plannable::setDetectProblems(bool b)
00106 {
00107 if (useProblemDetection && !b)
00108
00109 Problem::clearProblems(*this);
00110 else if (!useProblemDetection && b)
00111
00112
00113 setChanged();
00114
00115 useProblemDetection=b;
00116 }
00117
00118
00119 DECLARE_EXPORT void Plannable::computeProblems()
00120 {
00121
00122 if (!anyChange && !computationBusy) return;
00123
00124 computationBusy = true;
00125
00126 static Mutex computationbusy;
00127 {
00128 ScopeMutexLock l(computationbusy);
00129
00130
00131
00132 while (anyChange)
00133 {
00134
00135
00136 anyChange = false;
00137
00138
00139 for (HasProblems::EntityIterator i; i!=HasProblems::endEntity(); ++i)
00140 {
00141 Plannable *e = i->getEntity();
00142 if (e->getChanged() && e->getDetectProblems()) i->updateProblems();
00143 }
00144
00145
00146 for (HasProblems::EntityIterator j; j!=HasProblems::endEntity(); ++j)
00147 {
00148 Plannable *e = j->getEntity();
00149 if (e->getChanged() && e->getDetectProblems()) e->setChanged(false);
00150 }
00151 }
00152
00153
00154 computationBusy = false;
00155 }
00156 }
00157
00158
00159 DECLARE_EXPORT void Plannable::writeElement (XMLOutput* o, const Keyword& tag, mode m) const
00160 {
00161
00162
00163
00164
00165 if (!getDetectProblems()) o->writeElement(Tags::tag_detectproblems, false);
00166 }
00167
00168
00169 DECLARE_EXPORT void Plannable::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00170 {
00171 if (pAttr.isA (Tags::tag_detectproblems))
00172 {
00173 bool b = pElement.getBool();
00174 setDetectProblems(b);
00175 }
00176 }
00177
00178
00179 DECLARE_EXPORT void Problem::clearProblems()
00180 {
00181
00182 for (HasProblems::EntityIterator i = HasProblems::beginEntity();
00183 i != HasProblems::endEntity(); ++i)
00184 {
00185 clearProblems(*i);
00186 i->getEntity()->setChanged(true);
00187 }
00188 }
00189
00190
00191 DECLARE_EXPORT void Problem::clearProblems(HasProblems& p, bool setchanged)
00192 {
00193
00194 if (!p.firstProblem) return;
00195
00196
00197 for (Problem *cur=p.firstProblem; cur; )
00198 {
00199 Problem *del = cur;
00200 cur = cur->nextProblem;
00201 del->owner = NULL;
00202 delete del;
00203 }
00204 p.firstProblem = NULL;
00205
00206
00207 if (setchanged) p.getEntity()->setChanged();
00208 }
00209
00210
00211 DECLARE_EXPORT void Problem::writer(const MetaCategory* c, XMLOutput* o)
00212 {
00213 const_iterator piter = begin();
00214 if (piter != end())
00215 {
00216 o->BeginObject(*c->grouptag);
00217 for (; piter!=end(); ++piter)
00218
00219
00220
00221 piter->writeElement(o, *c->typetag);
00222 o->EndObject(*c->grouptag);
00223 }
00224 }
00225
00226
00227 DECLARE_EXPORT void Problem::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00228 {
00229
00230 o->BeginObject(tag);
00231 o->writeElement(Tags::tag_name, getType().type);
00232 o->writeElement(Tags::tag_description, getDescription());
00233 o->writeElement(Tags::tag_start, getDateRange().getStart());
00234 o->writeElement(Tags::tag_end, getDateRange().getEnd());
00235 o->writeElement(Tags::tag_weight, getWeight());
00236 o->EndObject(tag);
00237 }
00238
00239
00240 DECLARE_EXPORT HasProblems::EntityIterator::EntityIterator() : type(0)
00241 {
00242
00243 bufIter = new Buffer::iterator(Buffer::begin());
00244 if (*bufIter != Buffer::end()) return;
00245
00246
00247 delete bufIter;
00248 type = 1;
00249 resIter = new Resource::iterator(Resource::begin());
00250 if (*resIter != Resource::end()) return;
00251
00252
00253 delete resIter;
00254 type = 2;
00255 operIter = new OperationPlan::iterator(OperationPlan::begin());
00256 if (*operIter != OperationPlan::end()) return;
00257
00258
00259 delete operIter;
00260 type = 3;
00261 demIter = new Demand::iterator(Demand::begin());
00262 if (*demIter == Demand::end())
00263 {
00264
00265 delete demIter;
00266 type = 4;
00267 }
00268 }
00269
00270
00271 DECLARE_EXPORT HasProblems::EntityIterator& HasProblems::EntityIterator::operator++()
00272 {
00273 switch (type)
00274 {
00275 case 0:
00276
00277 if (*bufIter != Buffer::end())
00278 if (++(*bufIter) != Buffer::end()) return *this;
00279 ++type;
00280 delete bufIter;
00281 resIter = new Resource::iterator(Resource::begin());
00282 if (*resIter != Resource::end()) return *this;
00283
00284 case 1:
00285
00286 if (*resIter != Resource::end())
00287 if (++(*resIter) != Resource::end()) return *this;
00288 ++type;
00289 delete resIter;
00290 operIter = new OperationPlan::iterator(OperationPlan::begin());
00291 if (*operIter != OperationPlan::end()) return *this;
00292
00293 case 2:
00294
00295 if (*operIter != OperationPlan::end())
00296 if (++(*operIter) != OperationPlan::end()) return *this;
00297 ++type;
00298 delete operIter;
00299 demIter = new Demand::iterator(Demand::begin());
00300 if (*demIter != Demand::end()) return *this;
00301
00302 case 3:
00303
00304 if (*demIter != Demand::end())
00305 if (++(*demIter) != Demand::end()) return *this;
00306
00307 ++type;
00308 delete demIter;
00309 demIter = NULL;
00310 return *this;
00311 }
00312 throw LogicException("Unreachable code reached");
00313 }
00314
00315
00316 DECLARE_EXPORT HasProblems::EntityIterator::~EntityIterator()
00317 {
00318 switch (type)
00319 {
00320
00321 case 0: delete bufIter; return;
00322
00323 case 1: delete resIter; return;
00324
00325 case 2: delete operIter; return;
00326
00327 case 3: delete demIter; return;
00328 }
00329 }
00330
00331
00332 DECLARE_EXPORT HasProblems::EntityIterator::EntityIterator(const EntityIterator& o)
00333 {
00334
00335 this->~EntityIterator();
00336
00337 type = o.type;
00338 if (type==0) bufIter = new Buffer::iterator(*(o.bufIter));
00339 else if (type==1) resIter = new Resource::iterator(*(o.resIter));
00340 else if (type==2) operIter = new OperationPlan::iterator(*(o.operIter));
00341 else if (type==3) demIter = new Demand::iterator(*(o.demIter));
00342 }
00343
00344
00345 DECLARE_EXPORT HasProblems::EntityIterator&
00346 HasProblems::EntityIterator::operator=(const EntityIterator& o)
00347 {
00348
00349 if (this == &o) return *this;
00350
00351 this->~EntityIterator();
00352
00353 type = o.type;
00354 if (type==0) bufIter = new Buffer::iterator(*(o.bufIter));
00355 else if (type==1) resIter = new Resource::iterator(*(o.resIter));
00356 else if (type==2) operIter = new OperationPlan::iterator(*(o.operIter));
00357 else if (type==3) demIter = new Demand::iterator(*(o.demIter));
00358 return *this;
00359 }
00360
00361
00362 DECLARE_EXPORT bool
00363 HasProblems::EntityIterator::operator != (const EntityIterator& t) const
00364 {
00365
00366 if (type != t.type) return true;
00367
00368
00369 switch (type)
00370 {
00371
00372 case 0: return *bufIter != *(t.bufIter);
00373
00374 case 1: return *resIter != *(t.resIter);
00375
00376 case 2: return *operIter != *(t.operIter);
00377
00378 case 3: return *demIter != *(t.demIter);
00379
00380
00381 default: return false;
00382 }
00383 }
00384
00385
00386 DECLARE_EXPORT HasProblems& HasProblems::EntityIterator::operator*() const
00387 {
00388 switch (type)
00389 {
00390
00391 case 0: return **bufIter;
00392
00393 case 1: return **resIter;
00394
00395 case 2: return **operIter;
00396
00397 case 3: return **demIter;
00398 default: throw LogicException("Unreachable code reached");
00399 }
00400 }
00401
00402
00403 DECLARE_EXPORT HasProblems* HasProblems::EntityIterator::operator->() const
00404 {
00405 switch (type)
00406 {
00407
00408 case 0: return &**bufIter;
00409
00410 case 1: return &**resIter;
00411
00412 case 2: return &**operIter;
00413
00414 case 3: return &**demIter;
00415 default: throw LogicException("Unreachable code reached");
00416 }
00417 }
00418
00419
00420 DECLARE_EXPORT HasProblems::EntityIterator HasProblems::beginEntity()
00421 {
00422 return EntityIterator();
00423 }
00424
00425
00426 DECLARE_EXPORT HasProblems::EntityIterator HasProblems::endEntity()
00427 {
00428
00429
00430 return EntityIterator(4);
00431 }
00432
00433
00434 DECLARE_EXPORT Problem::const_iterator& Problem::const_iterator::operator++()
00435 {
00436
00437 if (!iter) return *this;
00438
00439
00440 iter = iter->nextProblem;
00441
00442
00443
00444 while (!iter && !owner && eiter!=HasProblems::endEntity())
00445 {
00446 ++eiter;
00447 if (eiter!=HasProblems::endEntity()) iter = eiter->firstProblem;
00448 }
00449 return *this;
00450 }
00451
00452
00453 DECLARE_EXPORT Problem::const_iterator Problem::begin()
00454 {
00455 Plannable::computeProblems();
00456 return const_iterator();
00457 }
00458
00459
00460 DECLARE_EXPORT Problem::const_iterator Problem::begin(HasProblems* i, bool refresh)
00461 {
00462
00463 if (!i) return begin();
00464
00465
00466 if (refresh) i->updateProblems();
00467 return const_iterator(i);
00468 }
00469
00470
00471 DECLARE_EXPORT const Problem::const_iterator Problem::end()
00472 {
00473 return const_iterator(NULL);
00474 }
00475
00476
00477 int PythonProblem::initialize(PyObject* m)
00478 {
00479
00480 PythonType& x = getType();
00481 x.setName("problem");
00482 x.setDoc("frePPLe problem");
00483 x.supportgetattro();
00484 x.supportstr();
00485 x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
00486 const_cast<MetaCategory*>(Problem::metadata)->factoryPythonProxy = proxy;
00487 return x.typeReady(m);
00488 }
00489
00490
00491 PyObject* PythonProblem::getattro(const Attribute& attr)
00492 {
00493 if (!obj) return Py_BuildValue("");
00494 if (attr.isA(Tags::tag_name))
00495 return PythonObject(obj->getType().type);
00496 if (attr.isA(Tags::tag_description))
00497 return PythonObject(obj->getDescription());
00498 if (attr.isA(Tags::tag_entity))
00499 return PythonObject(obj->getOwner()->getEntity()->getType().category->group);
00500 if (attr.isA(Tags::tag_start))
00501 return PythonObject(obj->getDateRange().getStart());
00502 if (attr.isA(Tags::tag_end))
00503 return PythonObject(obj->getDateRange().getEnd());
00504 if (attr.isA(Tags::tag_weight))
00505 return PythonObject(obj->getWeight());
00506 return NULL;
00507 }
00508
00509 }