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