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/model.h"
00030
00031 namespace frepple
00032 {
00033
00034 DECLARE_EXPORT const MetaClass* OperationPlan::metadata;
00035 DECLARE_EXPORT const MetaCategory* OperationPlan::metacategory;
00036 DECLARE_EXPORT unsigned long OperationPlan::counter = 1;
00037
00038
00039 int OperationPlan::initialize()
00040 {
00041
00042 OperationPlan::metacategory = new MetaCategory("operationplan", "operationplans",
00043 OperationPlan::createOperationPlan, OperationPlan::writer);
00044 OperationPlan::metadata = new MetaClass("operationplan", "operationplan");
00045
00046
00047 PythonType& x = FreppleCategory<OperationPlan>::getType();
00048 x.setName("operationplan");
00049 x.setDoc("frePPLe operationplan");
00050 x.supportgetattro();
00051 x.supportsetattro();
00052 x.supportstr();
00053 x.supportcreate(create);
00054 x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
00055 const_cast<MetaClass*>(metadata)->pythonClass = x.type_object();
00056 return x.typeReady();
00057 }
00058
00059
00060 void DECLARE_EXPORT OperationPlan::setChanged(bool b)
00061 {
00062 if (owner)
00063 owner->setChanged(b);
00064 else
00065 {
00066 oper->setChanged(b);
00067 if (dmd) dmd->setChanged();
00068 }
00069 }
00070
00071
00072 DECLARE_EXPORT Object* OperationPlan::createOperationPlan
00073 (const MetaClass* cat, const AttributeList& in)
00074 {
00075
00076 Action action = MetaClass::decodeAction(in);
00077
00078
00079 const DataElement* opnameElement = in.get(Tags::tag_operation);
00080 if (!*opnameElement && action!=REMOVE)
00081 throw DataException("Missing operation attribute");
00082 string opname = *opnameElement ? opnameElement->getString() : "";
00083
00084
00085 unsigned long id = 0;
00086 const DataElement* idfier = in.get(Tags::tag_id);
00087 if (*idfier) id = idfier->getUnsignedLong();
00088
00089
00090 OperationPlan* opplan = NULL;
00091 if (idfier)
00092 {
00093 opplan = OperationPlan::findId(id);
00094 if (opplan && !opname.empty()
00095 && opplan->getOperation()->getName()==opname)
00096 {
00097
00098 ostringstream ch;
00099 ch << "Operationplan id " << id
00100 << " defined multiple times with different operations: '"
00101 << opplan->getOperation() << "' & '" << opname << "'";
00102 throw DataException(ch.str());
00103 }
00104 }
00105
00106
00107 switch (action)
00108 {
00109 case REMOVE:
00110 if (opplan)
00111 {
00112
00113 if (opplan->getType().raiseEvent(opplan, SIG_REMOVE))
00114
00115 delete opplan;
00116 else
00117 {
00118
00119 ostringstream ch;
00120 ch << "Can't delete operationplan with id " << id;
00121 throw DataException(ch.str());
00122 }
00123 }
00124 else
00125 {
00126 ostringstream ch;
00127 ch << "Can't find operationplan with identifier "
00128 << id << " for removal";
00129 throw DataException(ch.str());
00130 }
00131 return NULL;
00132 case ADD:
00133 if (opplan)
00134 {
00135 ostringstream ch;
00136 ch << "Operationplan with identifier " << id
00137 << " already exists and can't be added again";
00138 throw DataException(ch.str());
00139 }
00140 if (opname.empty())
00141 throw DataException
00142 ("Operation name missing for creating an operationplan");
00143 break;
00144 case CHANGE:
00145 if (!opplan)
00146 {
00147 ostringstream ch;
00148 ch << "Operationplan with identifier " << id << " doesn't exist";
00149 throw DataException(ch.str());
00150 }
00151 break;
00152 case ADD_CHANGE: ;
00153 }
00154
00155
00156 if (opplan) return opplan;
00157
00158
00159 Operation* oper = Operation::find(opname);
00160 if (!oper)
00161 {
00162
00163 throw DataException("Operation '" + opname + "' doesn't exist");
00164 }
00165 else
00166 {
00167
00168 opplan = oper->createOperationPlan(0.0,Date::infinitePast,Date::infinitePast,NULL,NULL,id,false);
00169 if (!opplan->getType().raiseEvent(opplan, SIG_ADD))
00170 {
00171 delete opplan;
00172 throw DataException("Can't create operationplan");
00173 }
00174 return opplan;
00175 }
00176 }
00177
00178
00179 DECLARE_EXPORT OperationPlan* OperationPlan::findId(unsigned long l)
00180 {
00181
00182
00183
00184 if (l >= counter) return NULL;
00185
00186
00187 for (OperationPlan::iterator i = begin(); i != end(); ++i)
00188 if (i->id == l) return &*i;
00189
00190
00191 return NULL;
00192 }
00193
00194
00195 DECLARE_EXPORT bool OperationPlan::instantiate()
00196 {
00197
00198 if (!oper) throw LogicException("Initializing an invalid operationplan");
00199
00200
00201 if (getQuantity() <= 0.0 && !owner)
00202 {
00203 delete this;
00204 return false;
00205 }
00206
00207
00208 if (!oper->extraInstantiate(this))
00209 {
00210 delete this;
00211 return false;
00212 }
00213
00214
00215 for (OperationPlan::iterator x(this); x != end(); ++x)
00216 x->instantiate();
00217
00218
00219
00220
00221
00222
00223
00224
00225 static Mutex onlyOne;
00226 {
00227 ScopeMutexLock l(onlyOne);
00228 if (id)
00229 {
00230
00231 if (id < counter)
00232 {
00233
00234
00235 OperationPlan* opplan = findId(id);
00236 if (opplan && opplan->getOperation()!=oper)
00237 {
00238 ostringstream ch;
00239 ch << "Operationplan id " << id
00240 << " defined multiple times with different operations: '"
00241 << opplan->getOperation() << "' & '" << oper << "'";
00242 delete this;
00243 throw DataException(ch.str());
00244 }
00245 }
00246 else
00247
00248
00249
00250 counter = id+1;
00251 }
00252 else
00253
00254 id = counter++;
00255 }
00256
00257
00258 insertInOperationplanList();
00259
00260
00261
00262 createFlowLoads();
00263
00264
00265 if (getDemand() && getDemand()->getDeliveryOperation() == oper)
00266 dmd->addDelivery(this);
00267
00268
00269
00270
00271
00272
00273
00274 oper->setChanged();
00275
00276
00277 return true;
00278 }
00279
00280
00281 DECLARE_EXPORT void OperationPlan::insertInOperationplanList()
00282 {
00283
00284
00285 if (prev || oper->first_opplan == this) return;
00286
00287 if (!oper->first_opplan)
00288 {
00289
00290 oper->first_opplan = this;
00291 oper->last_opplan = this;
00292 }
00293 else if (*this < *(oper->first_opplan))
00294 {
00295
00296 next = oper->first_opplan;
00297 next->prev = this;
00298 oper->first_opplan = this;
00299 }
00300 else if (*(oper->last_opplan) < *this)
00301 {
00302
00303 prev = oper->last_opplan;
00304 prev->next = this;
00305 oper->last_opplan = this;
00306 }
00307 else
00308 {
00309
00310 OperationPlan *x = oper->last_opplan;
00311 OperationPlan *y = NULL;
00312 while (!(*x < *this))
00313 {
00314 y = x;
00315 x = x->prev;
00316 }
00317 next = y;
00318 prev = x;
00319 if (x) x->next = this;
00320 if (y) y->prev = this;
00321 }
00322 }
00323
00324
00325 DECLARE_EXPORT void OperationPlan::addSubOperationPlan(OperationPlan* o)
00326 {
00327
00328 if (!o) throw LogicException("Adding null suboperationplan");
00329
00330
00331 if (o->owner == this) return;
00332
00333
00334 if (o->owner) o->owner->eraseSubOperationPlan(o);
00335
00336
00337 if (!firstsubopplan)
00338 {
00339
00340 firstsubopplan = o;
00341 lastsubopplan = o;
00342 }
00343 else if (firstsubopplan->getOperation() != OperationSetup::setupoperation)
00344 {
00345
00346 o->nextsubopplan = firstsubopplan;
00347 firstsubopplan->prevsubopplan = o;
00348 firstsubopplan = o;
00349 }
00350 else
00351 {
00352
00353 OperationPlan *s = firstsubopplan->nextsubopplan;
00354 o->nextsubopplan = s;
00355 if (s) s->nextsubopplan = o;
00356 else lastsubopplan = o;
00357 }
00358
00359 o->owner = this;
00360
00361
00362 update();
00363 }
00364
00365
00366 DECLARE_EXPORT void OperationPlan::eraseSubOperationPlan(OperationPlan* o)
00367 {
00368
00369 if (!o) return;
00370
00371
00372 if (o->owner != this)
00373 throw LogicException("Operationplan isn't a suboperationplan");
00374
00375
00376 o->owner = NULL;
00377
00378
00379 if (o->prevsubopplan)
00380 o->prevsubopplan->nextsubopplan = o->nextsubopplan;
00381 else
00382 firstsubopplan = o->nextsubopplan;
00383 if (o->nextsubopplan)
00384 o->nextsubopplan->prevsubopplan = o->prevsubopplan;
00385 else
00386 lastsubopplan = o->prevsubopplan;
00387 };
00388
00389
00390 DECLARE_EXPORT bool OperationPlan::operator < (const OperationPlan& a) const
00391 {
00392
00393 if (oper != a.oper)
00394 return *oper < *(a.oper);
00395
00396
00397 if (dates.getStart() != a.dates.getStart())
00398 return dates.getStart() < a.dates.getStart();
00399
00400
00401 return quantity >= a.quantity;
00402 }
00403
00404
00405 DECLARE_EXPORT void OperationPlan::createFlowLoads()
00406 {
00407
00408 if (firstflowplan || firstloadplan) return;
00409
00410
00411 for (Operation::loadlist::const_iterator g=oper->getLoads().begin();
00412 g!=oper->getLoads().end(); ++g)
00413 if (!g->getAlternate())
00414 {
00415 new LoadPlan(this, &*g);
00416 if (!g->getSetup().empty() && g->getResource()->getSetupMatrix())
00417 OperationSetup::setupoperation->createOperationPlan(
00418 1, getDates().getStart(), getDates().getStart(), NULL, this);
00419 }
00420
00421
00422 for (Operation::flowlist::const_iterator h=oper->getFlows().begin();
00423 h!=oper->getFlows().end(); ++h)
00424 if (!h->getAlternate()) new FlowPlan(this, &*h);
00425 }
00426
00427
00428 DECLARE_EXPORT OperationPlan::~OperationPlan()
00429 {
00430
00431 FlowPlanIterator e = beginFlowPlans();
00432 LoadPlanIterator f = beginLoadPlans();
00433 OperationPlan *x = firstsubopplan;
00434
00435
00436 firstflowplan = NULL;
00437 firstloadplan = NULL;
00438 firstsubopplan = NULL;
00439 lastsubopplan = NULL;
00440
00441
00442 while (e != endFlowPlans()) delete &*(e++);
00443 while (f != endLoadPlans()) delete &*(f++);
00444
00445
00446 while (x)
00447 {
00448 OperationPlan *y = x->nextsubopplan;
00449 x->owner = NULL;
00450 delete x;
00451 x = y;
00452 }
00453
00454
00455 if (owner)
00456 {
00457 const OperationPlan* o = owner;
00458 setOwner(NULL);
00459 delete o;
00460 }
00461
00462
00463 if (id && dmd) dmd->removeDelivery(this);
00464
00465
00466 if (prev)
00467
00468 prev->next = next;
00469 else if (oper->first_opplan == this)
00470
00471 oper->first_opplan = next;
00472 if (next)
00473
00474 next->prev = prev;
00475 else if (oper->last_opplan == this)
00476
00477 oper->last_opplan = prev;
00478 }
00479
00480
00481 void DECLARE_EXPORT OperationPlan::setOwner(OperationPlan* o)
00482 {
00483
00484 if (owner == o) return;
00485
00486 if (owner) owner->eraseSubOperationPlan(this);
00487
00488 if (o) o->addSubOperationPlan(this);
00489 }
00490
00491
00492 void DECLARE_EXPORT OperationPlan::setStart (Date d)
00493 {
00494
00495 if (getLocked()) return;
00496
00497 if (!lastsubopplan || lastsubopplan->getOperation() == OperationSetup::setupoperation)
00498
00499 oper->setOperationPlanParameters(this,quantity,d,Date::infinitePast);
00500 else
00501 {
00502
00503 bool firstMove = true;
00504 for (OperationPlan* i = firstsubopplan; i; i = i->nextsubopplan)
00505 {
00506 if (i->getOperation() == OperationSetup::setupoperation) continue;
00507 if (i->getDates().getStart() < d || firstMove)
00508 {
00509 i->setStart(d);
00510
00511 d = i->getDates().getEnd();
00512 }
00513 else
00514
00515 break;
00516 }
00517 }
00518
00519
00520 update();
00521 }
00522
00523
00524 void DECLARE_EXPORT OperationPlan::setEnd(Date d)
00525 {
00526
00527 if (getLocked()) return;
00528
00529 if (!lastsubopplan || lastsubopplan->getOperation() == OperationSetup::setupoperation)
00530
00531 oper->setOperationPlanParameters(this,quantity,Date::infinitePast,d);
00532 else
00533 {
00534
00535 bool firstMove = true;
00536 for (OperationPlan* i = lastsubopplan; i; i = i->prevsubopplan)
00537 {
00538 if (i->getOperation() == OperationSetup::setupoperation) break;
00539 if (i->getDates().getEnd() > d || firstMove)
00540 {
00541 i->setEnd(d);
00542
00543 d = i->getDates().getStart();
00544 }
00545 else
00546
00547 break;
00548 }
00549 }
00550
00551
00552 update();
00553 }
00554
00555
00556 DECLARE_EXPORT double OperationPlan::setQuantity (double f, bool roundDown, bool upd, bool execute)
00557 {
00558
00559 if (getLocked()) return quantity;
00560
00561
00562 if (f < 0)
00563 throw DataException("Operationplans can't have negative quantities");
00564
00565
00566
00567
00568 if (owner && owner->getOperation()->getType() != *OperationAlternate::metadata)
00569 return owner->setQuantity(f,roundDown,upd,execute);
00570
00571
00572 if (f!=0.0 && getOperation()->getSizeMinimum()>0.0
00573 && f < getOperation()->getSizeMinimum())
00574 {
00575 if (roundDown)
00576 {
00577
00578 if (!execute) return 0.0;
00579 quantity = 0.0;
00580
00581 if (upd) update();
00582 return 0.0;
00583 }
00584 f = getOperation()->getSizeMinimum();
00585 }
00586 if (f!=0.0 && f > getOperation()->getSizeMaximum())
00587 {
00588 roundDown = true;
00589 f = getOperation()->getSizeMaximum();
00590 }
00591 if (f!=0.0 && getOperation()->getSizeMultiple()>0.0)
00592 {
00593 int mult = static_cast<int> (f / getOperation()->getSizeMultiple()
00594 + (roundDown ? 0.0 : 0.99999999));
00595 if (!execute) return mult * getOperation()->getSizeMultiple();
00596 quantity = mult * getOperation()->getSizeMultiple();
00597 }
00598 else
00599 {
00600 if (!execute) return f;
00601 quantity = f;
00602 }
00603
00604
00605 if (execute && owner
00606 && owner->getOperation()->getType() == *OperationAlternate::metadata)
00607 {
00608 owner->quantity = quantity;
00609 if (upd) owner->resizeFlowLoadPlans();
00610 }
00611
00612
00613 if (execute && firstsubopplan)
00614 for (OperationPlan *i = firstsubopplan; i; i = i->nextsubopplan)
00615 if (i->getOperation() != OperationSetup::setupoperation)
00616 {
00617 i->quantity = quantity;
00618 if (upd) i->resizeFlowLoadPlans();
00619 }
00620
00621
00622 if (upd) update();
00623 return quantity;
00624 }
00625
00626
00627 DECLARE_EXPORT void OperationPlan::resizeFlowLoadPlans()
00628 {
00629
00630 for (FlowPlanIterator ee = beginFlowPlans(); ee != endFlowPlans(); ++ee)
00631 ee->update();
00632
00633
00634 for (LoadPlanIterator e = beginLoadPlans(); e != endLoadPlans(); ++e)
00635 e->update();
00636
00637
00638 if (firstsubopplan && firstsubopplan->getOperation() == OperationSetup::setupoperation
00639 && firstsubopplan->getDates().getEnd() != getDates().getStart())
00640 firstsubopplan->setEnd(getDates().getStart());
00641 else if (getOperation() == OperationSetup::setupoperation
00642 && getDates().getEnd() != getOwner()->getDates().getStart())
00643 getOwner()->setStart(getDates().getEnd());
00644
00645
00646
00647
00648
00649
00650
00651
00652 for (OperationPlan *j = firstsubopplan; j; j = j->nextsubopplan)
00653 if (j->getOperation() != OperationSetup::setupoperation)
00654 {
00655 j->quantity = quantity;
00656 j->resizeFlowLoadPlans();
00657 }
00658
00659
00660 if (dmd) dmd->setChanged();
00661 }
00662
00663
00664 DECLARE_EXPORT void OperationPlan::update()
00665 {
00666 if (lastsubopplan && lastsubopplan->getOperation() != OperationSetup::setupoperation)
00667 {
00668
00669 OperationPlan *tmp = firstsubopplan;
00670 if (tmp->getOperation() == OperationSetup::setupoperation)
00671 tmp = tmp->nextsubopplan;
00672 dates.setStartAndEnd(
00673 tmp->getDates().getStart(),
00674 lastsubopplan->getDates().getEnd()
00675 );
00676
00677 flags &= ~IS_LOCKED;
00678 for (OperationPlan* i = firstsubopplan; i; i = i->nextsubopplan)
00679 if (i->flags & IS_LOCKED)
00680 {
00681 flags |= IS_LOCKED;
00682 break;
00683 }
00684 }
00685
00686
00687 resizeFlowLoadPlans();
00688
00689
00690 if (owner) owner->update();
00691
00692
00693 setChanged();
00694 }
00695
00696
00697 DECLARE_EXPORT void OperationPlan::deleteOperationPlans(Operation* o, bool deleteLockedOpplans)
00698 {
00699 if (!o) return;
00700 for (OperationPlan *opplan = o->first_opplan; opplan; )
00701 {
00702 OperationPlan *tmp = opplan;
00703 opplan = opplan->next;
00704
00705 if (deleteLockedOpplans || !tmp->getLocked()) delete tmp;
00706 }
00707 }
00708
00709
00710 DECLARE_EXPORT double OperationPlan::getPenalty() const
00711 {
00712 double penalty = 0;
00713 for (OperationPlan::LoadPlanIterator i = beginLoadPlans();
00714 i != endLoadPlans(); ++i)
00715 if (i->isStart() && !i->getLoad()->getSetup().empty() && i->getResource()->getSetupMatrix())
00716 {
00717 SetupMatrix::Rule *rule = i->getResource()->getSetupMatrix()
00718 ->calculateSetup(i->getSetup(false), i->getSetup(true));
00719 if (rule) penalty += rule->getCost();
00720 }
00721 return penalty;
00722 }
00723
00724
00725 DECLARE_EXPORT TimePeriod OperationPlan::getUnavailable() const
00726 {
00727 TimePeriod x;
00728 DateRange y = getOperation()->calculateOperationTime(dates.getStart(), dates.getEnd(), &x);
00729 return dates.getDuration() - x;
00730 }
00731
00732
00733 DECLARE_EXPORT void OperationPlan::writer(const MetaCategory* c, XMLOutput* o)
00734 {
00735 if (!empty())
00736 {
00737 o->BeginObject(*c->grouptag);
00738 for (iterator i=begin(); i!=end(); ++i)
00739 o->writeElement(*c->typetag, *i);
00740 o->EndObject(*c->grouptag);
00741 }
00742 }
00743
00744
00745 DECLARE_EXPORT void OperationPlan::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00746 {
00747
00748 if (oper->getHidden()) return;
00749
00750
00751 if (m == REFERENCE)
00752 {
00753 o->writeElement
00754 (tag, Tags::tag_id, id, Tags::tag_operation, oper->getName());
00755 return;
00756 }
00757
00758 if (m != NOHEADER)
00759 o->BeginObject(tag, Tags::tag_id, id, Tags::tag_operation,oper->getName());
00760
00761
00762
00763
00764 if (dmd && !dynamic_cast<Demand*>(o->getPreviousObject()))
00765 o->writeElement(Tags::tag_demand, dmd);
00766
00767 o->writeElement(Tags::tag_start, dates.getStart());
00768 o->writeElement(Tags::tag_end, dates.getEnd());
00769 o->writeElement(Tags::tag_quantity, quantity);
00770 if (getLocked()) o->writeElement (Tags::tag_locked, getLocked());
00771 o->writeElement(Tags::tag_owner, owner);
00772
00773
00774 if (o->getContentType() == XMLOutput::PLANDETAIL)
00775 {
00776 o->BeginObject(Tags::tag_flowplans);
00777 for (FlowPlanIterator qq = beginFlowPlans(); qq != endFlowPlans(); ++qq)
00778 qq->writeElement(o, Tags::tag_flowplan);
00779 o->EndObject(Tags::tag_flowplans);
00780 }
00781
00782 o->EndObject(tag);
00783 }
00784
00785
00786 DECLARE_EXPORT void OperationPlan::beginElement(XMLInput& pIn, const Attribute& pAttr)
00787 {
00788 if (pAttr.isA (Tags::tag_demand))
00789 pIn.readto( Demand::reader(Demand::metadata,pIn.getAttributes()) );
00790 else if (pAttr.isA(Tags::tag_owner))
00791 pIn.readto(createOperationPlan(metadata,pIn.getAttributes()));
00792 else if (pAttr.isA(Tags::tag_flowplans))
00793 pIn.IgnoreElement();
00794 }
00795
00796
00797 DECLARE_EXPORT void OperationPlan::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00798 {
00799
00800
00801
00802
00803 if (pAttr.isA(Tags::tag_quantity))
00804 pElement >> quantity;
00805 else if (pAttr.isA(Tags::tag_start))
00806 dates.setStart(pElement.getDate());
00807 else if (pAttr.isA(Tags::tag_end))
00808 dates.setEnd(pElement.getDate());
00809 else if (pAttr.isA(Tags::tag_owner) && !pIn.isObjectEnd())
00810 {
00811 OperationPlan* o = dynamic_cast<OperationPlan*>(pIn.getPreviousObject());
00812 if (o) setOwner(o);
00813 }
00814 else if (pIn.isObjectEnd())
00815 {
00816
00817 if (!instantiate())
00818
00819 pIn.invalidateCurrentObject();
00820 }
00821 else if (pAttr.isA (Tags::tag_demand))
00822 {
00823 Demand * d = dynamic_cast<Demand*>(pIn.getPreviousObject());
00824 if (d) d->addDelivery(this);
00825 else throw LogicException("Incorrect object type during read operation");
00826 }
00827 else if (pAttr.isA(Tags::tag_locked))
00828 setLocked(pElement.getBool());
00829 }
00830
00831
00832 DECLARE_EXPORT void OperationPlan::setLocked(bool b)
00833 {
00834 if (b)
00835 flags |= IS_LOCKED;
00836 else
00837 flags &= ~IS_LOCKED;
00838 for (OperationPlan *x = firstsubopplan; x; x = x->nextsubopplan)
00839 x->setLocked(b);
00840 update();
00841 }
00842
00843
00844 DECLARE_EXPORT void OperationPlan::setDemand(Demand* l)
00845 {
00846
00847 if (l==dmd) return;
00848
00849
00850 if (dmd) dmd->removeDelivery(this);
00851
00852
00853 dmd = l;
00854 if (l) l->setChanged();
00855 }
00856
00857
00858 PyObject* OperationPlan::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds)
00859 {
00860 try
00861 {
00862
00863 PythonAttributeList atts(kwds);
00864 Object* x = createOperationPlan(OperationPlan::metadata,atts);
00865
00866
00867 if (x)
00868 {
00869 PyObject *key, *value;
00870 Py_ssize_t pos = 0;
00871 while (PyDict_Next(kwds, &pos, &key, &value))
00872 {
00873 PythonObject field(value);
00874 Attribute attr(PyString_AsString(key));
00875 if (!attr.isA(Tags::tag_operation) && !attr.isA(Tags::tag_id) && !attr.isA(Tags::tag_action))
00876 {
00877 int result = x->setattro(attr, field);
00878 if (result && !PyErr_Occurred())
00879 PyErr_Format(PyExc_AttributeError,
00880 "attribute '%s' on '%s' can't be updated",
00881 PyString_AsString(key), x->ob_type->tp_name);
00882 }
00883 };
00884 }
00885
00886 if (x && !static_cast<OperationPlan*>(x)->instantiate())
00887 return NULL;
00888 return x;
00889 }
00890 catch (...)
00891 {
00892 PythonType::evalException();
00893 return NULL;
00894 }
00895 }
00896
00897
00898 DECLARE_EXPORT PyObject* OperationPlan::getattro(const Attribute& attr)
00899 {
00900 if (attr.isA(Tags::tag_id))
00901 return PythonObject(getIdentifier());
00902 if (attr.isA(Tags::tag_operation))
00903 return PythonObject(getOperation());
00904 if (attr.isA(Tags::tag_flowplans))
00905 return new frepple::FlowPlanIterator(this);
00906 if (attr.isA(Tags::tag_loadplans))
00907 return new frepple::LoadPlanIterator(this);
00908 if (attr.isA(Tags::tag_quantity))
00909 return PythonObject(getQuantity());
00910 if (attr.isA(Tags::tag_start))
00911 return PythonObject(getDates().getStart());
00912 if (attr.isA(Tags::tag_end))
00913 return PythonObject(getDates().getEnd());
00914 if (attr.isA(Tags::tag_demand))
00915 return PythonObject(getDemand());
00916 if (attr.isA(Tags::tag_locked))
00917 return PythonObject(getLocked());
00918 if (attr.isA(Tags::tag_owner))
00919 return PythonObject(getOwner());
00920 if (attr.isA(Tags::tag_operationplans))
00921 return new OperationPlanIterator(this);
00922 if (attr.isA(Tags::tag_hidden))
00923 return PythonObject(getHidden());
00924 if (attr.isA(Tags::tag_unavailable))
00925 return PythonObject(getUnavailable());
00926 return NULL;
00927 }
00928
00929
00930 DECLARE_EXPORT int OperationPlan::setattro(const Attribute& attr, const PythonObject& field)
00931 {
00932 if (attr.isA(Tags::tag_quantity))
00933 setQuantity(field.getDouble());
00934 else if (attr.isA(Tags::tag_start))
00935 setStart(field.getDate());
00936 else if (attr.isA(Tags::tag_end))
00937 setEnd(field.getDate());
00938 else if (attr.isA(Tags::tag_locked))
00939 setLocked(field.getBool());
00940 else if (attr.isA(Tags::tag_demand))
00941 {
00942 if (!field.check(Demand::metadata))
00943 {
00944 PyErr_SetString(PythonDataException, "operationplan demand must be of type demand");
00945 return -1;
00946 }
00947 Demand* y = static_cast<Demand*>(static_cast<PyObject*>(field));
00948 setDemand(y);
00949 }
00950 else if (attr.isA(Tags::tag_owner))
00951 {
00952 if (!field.check(OperationPlan::metadata))
00953 {
00954 PyErr_SetString(PythonDataException, "operationplan demand must be of type demand");
00955 return -1;
00956 }
00957 OperationPlan* y = static_cast<OperationPlan*>(static_cast<PyObject*>(field));
00958 setOwner(y);
00959 }
00960 else
00961 return -1;
00962 return 0;
00963 }
00964
00965 }