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 #include <math.h>
00031
00032
00033
00034 #define INVENTORY_OPERATION "Inventory of buffer '" + string(getName()) + "'"
00035
00036
00037 #define PROCURE_OPERATION "Procure for buffer '" + string(getName()) + "'"
00038
00039 namespace frepple
00040 {
00041
00042 template<class Buffer> DECLARE_EXPORT Tree utils::HasName<Buffer>::st;
00043 DECLARE_EXPORT const MetaCategory* Buffer::metadata;
00044 DECLARE_EXPORT const MetaClass* BufferDefault::metadata,
00045 *BufferInfinite::metadata,
00046 *BufferProcure::metadata;
00047
00048
00049 int Buffer::initialize()
00050 {
00051
00052 metadata = new MetaCategory("buffer", "buffers", reader, writer);
00053
00054
00055 return FreppleCategory<Buffer>::initialize();
00056 }
00057
00058
00059 int BufferDefault::initialize()
00060 {
00061
00062 BufferDefault::metadata = new MetaClass(
00063 "buffer",
00064 "buffer_default",
00065 Object::createString<BufferDefault>, true);
00066
00067
00068 return FreppleClass<BufferDefault,Buffer>::initialize();
00069 }
00070
00071
00072 int BufferInfinite::initialize()
00073 {
00074
00075 BufferInfinite::metadata = new MetaClass(
00076 "buffer",
00077 "buffer_infinite",
00078 Object::createString<BufferInfinite>);
00079
00080
00081 return FreppleClass<BufferInfinite,Buffer>::initialize();
00082 }
00083
00084
00085 int BufferProcure::initialize()
00086 {
00087
00088 BufferProcure::metadata = new MetaClass(
00089 "buffer",
00090 "buffer_procure",
00091 Object::createString<BufferProcure>);
00092
00093
00094 return FreppleClass<BufferProcure,Buffer>::initialize();
00095 }
00096
00097
00098 DECLARE_EXPORT void Buffer::setOnHand(double f)
00099 {
00100
00101 Operation *o = Operation::find(INVENTORY_OPERATION);
00102 Flow *fl;
00103 if (!o)
00104 {
00105
00106
00107 o = new OperationFixedTime(INVENTORY_OPERATION);
00108 Operation::add(o);
00109 o->setHidden(true);
00110 o->setDetectProblems(false);
00111 fl = new FlowEnd(o, this, 1);
00112 }
00113 else
00114
00115 fl = const_cast<Flow*>(&*(o->getFlows().begin()));
00116
00117
00118 if (!fl || !o)
00119 throw LogicException("Failed creating inventory operation for '"
00120 + getName() + "'");
00121
00122
00123 fl->setQuantity(f>=0.0 ? 1.0 : -1.0);
00124
00125
00126 OperationPlan::iterator i(o);
00127 if (i == OperationPlan::end())
00128 {
00129
00130 OperationPlan *opplan = o->createOperationPlan(
00131 fabs(f), Date::infinitePast, Date::infinitePast);
00132 opplan->setLocked(true);
00133 opplan->instantiate();
00134 }
00135 else
00136 {
00137
00138 i->setLocked(false);
00139 i->setQuantity(fabs(f));
00140 i->setLocked(true);
00141 }
00142 setChanged();
00143 }
00144
00145
00146 DECLARE_EXPORT double Buffer::getOnHand(Date d) const
00147 {
00148 double tmp(0.0);
00149 for (flowplanlist::const_iterator oo=flowplans.begin();
00150 oo!=flowplans.end(); ++oo)
00151 {
00152 if (oo->getDate() > d)
00153
00154
00155 return tmp;
00156 tmp = oo->getOnhand();
00157 }
00158
00159
00160 return tmp;
00161 }
00162
00163
00164 DECLARE_EXPORT double Buffer::getOnHand(Date d1, Date d2, bool min) const
00165 {
00166
00167 if (d2 < d1)
00168 {
00169 Date x(d1);
00170 d2 = d1;
00171 d2 = x;
00172 }
00173
00174
00175 double tmp(0.0), record(0.0);
00176 Date d, prev_Date;
00177 for (flowplanlist::const_iterator oo=flowplans.begin(); true; ++oo)
00178 {
00179 if (oo==flowplans.end() || oo->getDate() > d)
00180 {
00181
00182
00183
00184 if (prev_Date < d1)
00185
00186 record = tmp;
00187 else
00188 {
00189
00190
00191 if (min) {if (tmp < record) record = tmp;}
00192 else {if (tmp > record) record = tmp;}
00193 }
00194
00195
00196 if (prev_Date > d2 || oo==flowplans.end()) return record;
00197
00198
00199 d = oo->getDate();
00200 }
00201 tmp = oo->getOnhand();
00202 prev_Date = oo->getDate();
00203 }
00204
00205 throw LogicException("Unreachable code reached");
00206 }
00207
00208
00209 DECLARE_EXPORT void Buffer::writeElement(XMLOutput *o, const Keyword &tag, mode m) const
00210 {
00211
00212 if (m == REFERENCE)
00213 {
00214 o->writeElement(tag, Tags::tag_name, getName());
00215 return;
00216 }
00217
00218
00219 if (m!= NOHEADER) o->BeginObject(tag, Tags::tag_name, getName());
00220
00221
00222 HasDescription::writeElement(o, tag);
00223 HasHierarchy<Buffer>::writeElement(o, tag);
00224 o->writeElement(Tags::tag_producing, producing_operation);
00225 o->writeElement(Tags::tag_item, it);
00226 o->writeElement(Tags::tag_location, loc);
00227 Plannable::writeElement(o, tag);
00228
00229
00230 flowplanlist::const_iterator i = flowplans.begin();
00231
00232 for (; i!=flowplans.end() && i->getType()!=1 && !i->getDate(); ++i) ;
00233 if (i!=flowplans.end() && i->getType()==1)
00234 {
00235
00236 const FlowPlan *fp = dynamic_cast<const FlowPlan*>(&*i);
00237 if (fp
00238 && fp->getFlow()->getOperation()->getName() == string(INVENTORY_OPERATION)
00239 && fabs(fp->getQuantity()) > ROUNDING_ERROR)
00240 o->writeElement(Tags::tag_onhand, fp->getQuantity());
00241 }
00242
00243
00244 o->writeElement(Tags::tag_minimum, min_cal);
00245 o->writeElement(Tags::tag_maximum, max_cal);
00246 if (getCarryingCost()!= 0.0)
00247 o->writeElement(Tags::tag_carrying_cost, getCarryingCost());
00248
00249
00250 i = flowplans.begin();
00251 if ((o->getContentType() == XMLOutput::PLAN
00252 || o->getContentType() == XMLOutput::PLANDETAIL) && i!=flowplans.end())
00253 {
00254 o->BeginObject(Tags::tag_flowplans);
00255 for (; i!=flowplans.end(); ++i)
00256 if (i->getType()==1)
00257 dynamic_cast<const FlowPlan*>(&*i)->writeElement(o, Tags::tag_flowplan);
00258 o->EndObject(Tags::tag_flowplans);
00259 }
00260
00261
00262 o->EndObject(tag);
00263 }
00264
00265
00266 DECLARE_EXPORT void Buffer::beginElement(XMLInput& pIn, const Attribute& pAttr)
00267 {
00268 if (pAttr.isA(Tags::tag_flow)
00269 && pIn.getParentElement().first.isA(Tags::tag_flows))
00270 {
00271 Flow *f =
00272 dynamic_cast<Flow*>(MetaCategory::ControllerDefault(Flow::metadata,pIn.getAttributes()));
00273 if (f) f->setBuffer(this);
00274 pIn.readto (f);
00275 }
00276 else if (pAttr.isA(Tags::tag_producing))
00277 pIn.readto( Operation::reader(Operation::metadata,pIn.getAttributes()) );
00278 else if (pAttr.isA(Tags::tag_item))
00279 pIn.readto( Item::reader(Item::metadata,pIn.getAttributes()) );
00280 else if (pAttr.isA(Tags::tag_minimum) || pAttr.isA(Tags::tag_maximum))
00281 pIn.readto( Calendar::reader(Calendar::metadata,pIn.getAttributes()) );
00282 else if (pAttr.isA(Tags::tag_location))
00283 pIn.readto( Location::reader(Location::metadata,pIn.getAttributes()) );
00284 else if (pAttr.isA(Tags::tag_flowplans))
00285 pIn.IgnoreElement();
00286 else
00287 HasHierarchy<Buffer>::beginElement(pIn, pAttr);
00288 }
00289
00290
00291 DECLARE_EXPORT void Buffer::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00292 {
00293 if (pAttr.isA(Tags::tag_producing))
00294 {
00295 Operation *b = dynamic_cast<Operation*>(pIn.getPreviousObject());
00296 if (b) setProducingOperation(b);
00297 else throw LogicException("Incorrect object type during read operation");
00298 }
00299 else if (pAttr.isA(Tags::tag_item))
00300 {
00301 Item *a = dynamic_cast<Item*>(pIn.getPreviousObject());
00302 if (a) setItem(a);
00303 else throw LogicException("Incorrect object type during read operation");
00304 }
00305 else if (pAttr.isA(Tags::tag_onhand))
00306 setOnHand(pElement.getDouble());
00307 else if (pAttr.isA(Tags::tag_minimum))
00308 {
00309 CalendarDouble *mincal =
00310 dynamic_cast<CalendarDouble*>(pIn.getPreviousObject());
00311 if (mincal)
00312 setMinimum(mincal);
00313 else
00314 {
00315 Calendar *c = dynamic_cast<Calendar*>(pIn.getPreviousObject());
00316 if (!c)
00317 throw LogicException("Incorrect object type during read operation");
00318 throw DataException("Calendar '" + c->getName() +
00319 "' has invalid type for use as buffer min calendar");
00320 }
00321 }
00322 else if (pAttr.isA(Tags::tag_maximum))
00323 {
00324 CalendarDouble *maxcal =
00325 dynamic_cast<CalendarDouble*>(pIn.getPreviousObject());
00326 if (maxcal)
00327 setMaximum(maxcal);
00328 else
00329 {
00330 Calendar *c = dynamic_cast<Calendar*>(pIn.getPreviousObject());
00331 if (!c)
00332 throw LogicException("Incorrect object type during read operation");
00333 throw DataException("Calendar '" + c->getName() +
00334 "' has invalid type for use as buffer max calendar");
00335 }
00336 }
00337 else if (pAttr.isA(Tags::tag_location))
00338 {
00339 Location * d = dynamic_cast<Location*>(pIn.getPreviousObject());
00340 if (d) setLocation(d);
00341 else throw LogicException("Incorrect object type during read operation");
00342 }
00343 else if (pAttr.isA(Tags::tag_carrying_cost))
00344 setCarryingCost(pElement.getDouble());
00345 else
00346 {
00347 Plannable::endElement(pIn, pAttr, pElement);
00348 HasDescription::endElement(pIn, pAttr, pElement);
00349 HasHierarchy<Buffer>::endElement(pIn, pAttr, pElement);
00350 }
00351 }
00352
00353
00354 DECLARE_EXPORT void Buffer::setMinimum(CalendarDouble *cal)
00355 {
00356
00357 if (min_cal == cal) return;
00358
00359
00360 setChanged();
00361
00362
00363 if (min_cal)
00364 {
00365 for (flowplanlist::iterator oo=flowplans.begin(); oo!=flowplans.end(); )
00366 if (oo->getType() == 3)
00367 {
00368 flowplans.erase(&(*oo));
00369 delete &(*(oo++));
00370 }
00371 else ++oo;
00372 }
00373
00374
00375 if (!cal) return;
00376
00377
00378
00379 min_cal = const_cast< CalendarDouble* >(cal);
00380 double curMin = 0.0;
00381 for (CalendarDouble::EventIterator x(min_cal); x.getDate()<Date::infiniteFuture; ++x)
00382 if (curMin != x.getValue())
00383 {
00384 curMin = x.getValue();
00385 flowplanlist::EventMinQuantity *newBucket =
00386 new flowplanlist::EventMinQuantity(x.getDate(), curMin);
00387 flowplans.insert(newBucket);
00388 }
00389 }
00390
00391
00392 DECLARE_EXPORT void Buffer::setMaximum(CalendarDouble *cal)
00393 {
00394
00395 if (max_cal == cal) return;
00396
00397
00398 setChanged();
00399
00400
00401 if (max_cal)
00402 {
00403 for (flowplanlist::iterator oo=flowplans.begin(); oo!=flowplans.end(); )
00404 if (oo->getType() == 4)
00405 {
00406 flowplans.erase(&(*oo));
00407 delete &(*(oo++));
00408 }
00409 else ++oo;
00410 }
00411
00412
00413 if (!cal) return;
00414
00415
00416
00417 max_cal = const_cast<CalendarDouble*>(cal);
00418 double curMax = 0.0;
00419 for (CalendarDouble::EventIterator x(min_cal); x.getDate()<Date::infiniteFuture; ++x)
00420 if (curMax != x.getValue())
00421 {
00422 curMax = x.getValue();
00423 flowplanlist::EventMaxQuantity *newBucket =
00424 new flowplanlist::EventMaxQuantity(x.getDate(), curMax);
00425 flowplans.insert(newBucket);
00426 }
00427 }
00428
00429
00430 DECLARE_EXPORT void Buffer::deleteOperationPlans(bool deleteLocked)
00431 {
00432
00433 for (flowlist::iterator i=flows.begin(); i!=flows.end(); ++i)
00434 OperationPlan::deleteOperationPlans(i->getOperation(),deleteLocked);
00435
00436
00437 setChanged();
00438 }
00439
00440
00441 DECLARE_EXPORT Buffer::~Buffer()
00442 {
00443
00444
00445
00446
00447 deleteOperationPlans(true);
00448
00449
00450
00451
00452
00453 Operation *invoper = Operation::find(INVENTORY_OPERATION);
00454 if (invoper) delete invoper;
00455 }
00456
00457
00458 DECLARE_EXPORT void Buffer::followPegging
00459 (PeggingIterator& iter, FlowPlan* curflowplan, short nextlevel, double curqty, double curfactor)
00460 {
00461
00462 double peggedQty(0);
00463 Buffer::flowplanlist::const_iterator f = getFlowPlans().begin(curflowplan);
00464
00465 if (curflowplan->getQuantity() < -ROUNDING_ERROR && !iter.isDownstream())
00466 {
00467
00468
00469
00470 double endQty = f->getCumulativeConsumed();
00471 double startQty = endQty + f->getQuantity();
00472 if (f->getCumulativeProduced() <= startQty)
00473 {
00474
00475 while (f!=getFlowPlans().end()
00476 && f->getCumulativeProduced() <= startQty) ++f;
00477 while (f!=getFlowPlans().end()
00478 && ( (f->getQuantity()<=0 && f->getCumulativeProduced() < endQty)
00479 || (f->getQuantity()>0
00480 && f->getCumulativeProduced()-f->getQuantity() < endQty))
00481 )
00482 {
00483 if (f->getQuantity() > ROUNDING_ERROR)
00484 {
00485 double newqty = f->getQuantity();
00486 if (f->getCumulativeProduced()-f->getQuantity() < startQty)
00487 newqty -= startQty - (f->getCumulativeProduced()-f->getQuantity());
00488 if (f->getCumulativeProduced() > endQty)
00489 newqty -= f->getCumulativeProduced() - endQty;
00490 peggedQty += newqty;
00491 const FlowPlan *x = dynamic_cast<const FlowPlan*>(&(*f));
00492 iter.updateStack(nextlevel,
00493 -curqty*newqty/curflowplan->getQuantity(),
00494 curfactor*newqty/f->getQuantity(),
00495 curflowplan, x);
00496 }
00497 ++f;
00498 }
00499 }
00500 else
00501 {
00502
00503 while ( f!=getFlowPlans().end()
00504 && ((f->getQuantity()<=0 && f->getCumulativeProduced() > endQty)
00505 || (f->getQuantity()>0
00506 && f->getCumulativeProduced()-f->getQuantity() > endQty))) --f;
00507 while (f!=getFlowPlans().end() && f->getCumulativeProduced() > startQty)
00508 {
00509 if (f->getQuantity() > ROUNDING_ERROR)
00510 {
00511 double newqty = f->getQuantity();
00512 if (f->getCumulativeProduced()-f->getQuantity() < startQty)
00513 newqty -= startQty - (f->getCumulativeProduced()-f->getQuantity());
00514 if (f->getCumulativeProduced() > endQty)
00515 newqty -= f->getCumulativeProduced() - endQty;
00516 peggedQty += newqty;
00517 const FlowPlan *x = dynamic_cast<const FlowPlan*>(&(*f));
00518 iter.updateStack(nextlevel,
00519 -curqty*newqty/curflowplan->getQuantity(),
00520 curfactor*newqty/f->getQuantity(),
00521 curflowplan, x);
00522 }
00523 --f;
00524 }
00525 }
00526 if (peggedQty < endQty - startQty - ROUNDING_ERROR)
00527
00528
00529 iter.updateStack(nextlevel,
00530 curqty*(peggedQty - endQty + startQty)/curflowplan->getQuantity(),
00531 curfactor,
00532 curflowplan,
00533 NULL,
00534 false);
00535 return;
00536 }
00537
00538 if (curflowplan->getQuantity() > ROUNDING_ERROR && iter.isDownstream())
00539 {
00540
00541
00542
00543 double endQty = f->getCumulativeProduced();
00544 double startQty = endQty - f->getQuantity();
00545 if (f->getCumulativeConsumed() <= startQty)
00546 {
00547
00548 while (f!=getFlowPlans().end()
00549 && f->getCumulativeConsumed() <= startQty) ++f;
00550 while (f!=getFlowPlans().end()
00551 && ( (f->getQuantity()<=0
00552 && f->getCumulativeConsumed()+f->getQuantity() < endQty)
00553 || (f->getQuantity()>0 && f->getCumulativeConsumed() < endQty))
00554 )
00555 {
00556 if (f->getQuantity() < -ROUNDING_ERROR)
00557 {
00558 double newqty = - f->getQuantity();
00559 if (f->getCumulativeConsumed()+f->getQuantity() < startQty)
00560 newqty -= startQty - (f->getCumulativeConsumed()+f->getQuantity());
00561 if (f->getCumulativeConsumed() > endQty)
00562 newqty -= f->getCumulativeConsumed() - endQty;
00563 peggedQty += newqty;
00564 const FlowPlan *x = dynamic_cast<const FlowPlan*>(&(*f));
00565 iter.updateStack(nextlevel,
00566 curqty*newqty/curflowplan->getQuantity(),
00567 -curfactor*newqty/f->getQuantity(),
00568 x, curflowplan);
00569 }
00570 ++f;
00571 }
00572 }
00573 else
00574 {
00575
00576 while ( f!=getFlowPlans().end()
00577 && ((f->getQuantity()<=0 && f->getCumulativeConsumed()+f->getQuantity() < endQty)
00578 || (f->getQuantity()>0 && f->getCumulativeConsumed() < endQty))) --f;
00579 while (f!=getFlowPlans().end() && f->getCumulativeConsumed() > startQty)
00580 {
00581 if (f->getQuantity() < -ROUNDING_ERROR)
00582 {
00583 double newqty = - f->getQuantity();
00584 if (f->getCumulativeConsumed()+f->getQuantity() < startQty)
00585 newqty -= startQty - (f->getCumulativeConsumed()+f->getQuantity());
00586 if (f->getCumulativeConsumed() > endQty)
00587 newqty -= f->getCumulativeConsumed() - endQty;
00588 peggedQty += newqty;
00589 const FlowPlan *x = dynamic_cast<const FlowPlan*>(&(*f));
00590 iter.updateStack(nextlevel,
00591 curqty*newqty/curflowplan->getQuantity(),
00592 -curfactor*newqty/f->getQuantity(),
00593 x, curflowplan);
00594 }
00595 --f;
00596 }
00597 }
00598 if (peggedQty < endQty - startQty)
00599
00600
00601 iter.updateStack(nextlevel,
00602 curqty*(endQty - startQty - peggedQty)/curflowplan->getQuantity(),
00603 curfactor,
00604 NULL, curflowplan,
00605 false);
00606 return;
00607 }
00608 }
00609
00610
00611 DECLARE_EXPORT void BufferInfinite::writeElement
00612 (XMLOutput *o, const Keyword &tag, mode m) const
00613 {
00614
00615 if (m == REFERENCE)
00616 {
00617 o->writeElement
00618 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00619 return;
00620 }
00621
00622
00623 if (m != NOHEADER) o->BeginObject
00624 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00625
00626
00627 Buffer::writeElement(o, tag, NOHEADER);
00628 }
00629
00630
00631 DECLARE_EXPORT void BufferProcure::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00632 {
00633 if (pAttr.isA(Tags::tag_leadtime))
00634 setLeadtime(pElement.getTimeperiod());
00635 else if (pAttr.isA(Tags::tag_fence))
00636 setFence(pElement.getTimeperiod());
00637 else if (pAttr.isA(Tags::tag_size_maximum))
00638 setSizeMaximum(pElement.getDouble());
00639 else if (pAttr.isA(Tags::tag_size_minimum))
00640 setSizeMinimum(pElement.getDouble());
00641 else if (pAttr.isA(Tags::tag_size_multiple))
00642 setSizeMultiple(pElement.getDouble());
00643 else if (pAttr.isA(Tags::tag_mininterval))
00644 setMinimumInterval(pElement.getTimeperiod());
00645 else if (pAttr.isA(Tags::tag_maxinterval))
00646 setMaximumInterval(pElement.getTimeperiod());
00647 else if (pAttr.isA(Tags::tag_mininventory))
00648 setMinimumInventory(pElement.getDouble());
00649 else if (pAttr.isA(Tags::tag_maxinventory))
00650 setMaximumInventory(pElement.getDouble());
00651 else
00652 Buffer::endElement(pIn, pAttr, pElement);
00653 }
00654
00655
00656 DECLARE_EXPORT void BufferProcure::writeElement(XMLOutput *o, const Keyword &tag, mode m) const
00657 {
00658
00659 if (m == REFERENCE)
00660 {
00661 o->writeElement
00662 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00663 return;
00664 }
00665
00666
00667 if (m != NOHEADER) o->BeginObject
00668 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00669
00670
00671 if (leadtime) o->writeElement(Tags::tag_leadtime, leadtime);
00672 if (fence) o->writeElement(Tags::tag_fence, fence);
00673 if (size_maximum != DBL_MAX) o->writeElement(Tags::tag_size_maximum, size_maximum);
00674 if (size_minimum) o->writeElement(Tags::tag_size_minimum, size_minimum);
00675 if (size_multiple) o->writeElement(Tags::tag_size_multiple, size_multiple);
00676 if (min_interval) o->writeElement(Tags::tag_mininterval, min_interval);
00677 if (max_interval) o->writeElement(Tags::tag_maxinterval, max_interval);
00678 if (min_inventory) o->writeElement(Tags::tag_mininventory, min_inventory);
00679 if (max_inventory) o->writeElement(Tags::tag_maxinventory, max_inventory);
00680
00681
00682 Buffer::writeElement(o, tag, NOHEADER);
00683 }
00684
00685
00686 DECLARE_EXPORT Operation* BufferProcure::getOperation() const
00687 {
00688 if (!oper)
00689 {
00690 Operation *o = Operation::find(PROCURE_OPERATION);
00691 if (!o)
00692 {
00693
00694 o = new OperationFixedTime(PROCURE_OPERATION);
00695 static_cast<OperationFixedTime*>(o)->setDuration(leadtime);
00696
00697
00698
00699
00700 Operation::add(o);
00701 new FlowEnd(o, const_cast<BufferProcure*>(this), 1);
00702 }
00703 const_cast<BufferProcure*>(this)->oper = o;
00704 }
00705 return oper;
00706 }
00707
00708
00709 DECLARE_EXPORT PyObject* Buffer::getattro(const Attribute& attr)
00710 {
00711 if (attr.isA(Tags::tag_name))
00712 return PythonObject(getName());
00713 if (attr.isA(Tags::tag_description))
00714 return PythonObject(getDescription());
00715 if (attr.isA(Tags::tag_category))
00716 return PythonObject(getCategory());
00717 if (attr.isA(Tags::tag_subcategory))
00718 return PythonObject(getSubCategory());
00719 if (attr.isA(Tags::tag_owner))
00720 return PythonObject(getOwner());
00721 if (attr.isA(Tags::tag_location))
00722 return PythonObject(getLocation());
00723 if (attr.isA(Tags::tag_producing))
00724 return PythonObject(getProducingOperation());
00725 if (attr.isA(Tags::tag_item))
00726 return PythonObject(getItem());
00727 if (attr.isA(Tags::tag_onhand))
00728 return PythonObject(getOnHand());
00729 if (attr.isA(Tags::tag_flowplans))
00730 return new FlowPlanIterator(this);
00731 if (attr.isA(Tags::tag_maximum))
00732 return PythonObject(getMaximum());
00733 if (attr.isA(Tags::tag_minimum))
00734 return PythonObject(getMinimum());
00735 if (attr.isA(Tags::tag_carrying_cost))
00736 return PythonObject(getCarryingCost());
00737 if (attr.isA(Tags::tag_hidden))
00738 return PythonObject(getHidden());
00739 if (attr.isA(Tags::tag_flows))
00740 return new FlowIterator(this);
00741 if (attr.isA(Tags::tag_level))
00742 return PythonObject(getLevel());
00743 if (attr.isA(Tags::tag_cluster))
00744 return PythonObject(getCluster());
00745
00746
00747
00748 return NULL;
00749 }
00750
00751
00752 DECLARE_EXPORT int Buffer::setattro(const Attribute& attr, const PythonObject& field)
00753 {
00754 if (attr.isA(Tags::tag_name))
00755 setName(field.getString());
00756 else if (attr.isA(Tags::tag_description))
00757 setDescription(field.getString());
00758 else if (attr.isA(Tags::tag_category))
00759 setCategory(field.getString());
00760 else if (attr.isA(Tags::tag_subcategory))
00761 setSubCategory(field.getString());
00762 else if (attr.isA(Tags::tag_owner))
00763 {
00764 if (!field.check(Buffer::metadata))
00765 {
00766 PyErr_SetString(PythonDataException, "buffer owner must be of type buffer");
00767 return -1;
00768 }
00769 Buffer* y = static_cast<Buffer*>(static_cast<PyObject*>(field));
00770 setOwner(y);
00771 }
00772 else if (attr.isA(Tags::tag_location))
00773 {
00774 if (!field.check(Location::metadata))
00775 {
00776 PyErr_SetString(PythonDataException, "buffer location must be of type location");
00777 return -1;
00778 }
00779 Location* y = static_cast<Location*>(static_cast<PyObject*>(field));
00780 setLocation(y);
00781 }
00782 else if (attr.isA(Tags::tag_item))
00783 {
00784 if (!field.check(Item::metadata))
00785 {
00786 PyErr_SetString(PythonDataException, "buffer item must be of type item");
00787 return -1;
00788 }
00789 Item* y = static_cast<Item*>(static_cast<PyObject*>(field));
00790 setItem(y);
00791 }
00792 else if (attr.isA(Tags::tag_maximum))
00793 {
00794 if (!field.check(CalendarDouble::metadata))
00795 {
00796 PyErr_SetString(PythonDataException, "buffer maximum must be of type calendar_double");
00797 return -1;
00798 }
00799 CalendarDouble* y = static_cast<CalendarDouble*>(static_cast<PyObject*>(field));
00800 setMaximum(y);
00801 }
00802 else if (attr.isA(Tags::tag_minimum))
00803 {
00804 if (!field.check(CalendarDouble::metadata))
00805 {
00806 PyErr_SetString(PythonDataException, "buffer minimum must be of type calendar_double");
00807 return -1;
00808 }
00809 CalendarDouble* y = static_cast<CalendarDouble*>(static_cast<PyObject*>(field));
00810 setMinimum(y);
00811 }
00812 else if (attr.isA(Tags::tag_onhand))
00813 setOnHand(field.getDouble());
00814 else if (attr.isA(Tags::tag_carrying_cost))
00815 setCarryingCost(field.getDouble());
00816 else if (attr.isA(Tags::tag_producing))
00817 {
00818 if (!field.check(Operation::metadata))
00819 {
00820 PyErr_SetString(PythonDataException, "buffer producing must be of type operation");
00821 return -1;
00822 }
00823 Operation* y = static_cast<Operation*>(static_cast<PyObject*>(field));
00824 setProducingOperation(y);
00825 }
00826 else if (attr.isA(Tags::tag_hidden))
00827 setHidden(field.getBool());
00828 else
00829 return -1;
00830 return 0;
00831 }
00832
00833
00834 DECLARE_EXPORT PyObject* BufferProcure::getattro(const Attribute& attr)
00835 {
00836 if (attr.isA(Tags::tag_leadtime))
00837 return PythonObject(getLeadtime());
00838 if (attr.isA(Tags::tag_mininventory))
00839 return PythonObject(getMinimumInventory());
00840 if (attr.isA(Tags::tag_maxinventory))
00841 return PythonObject(getMaximumInventory());
00842 if (attr.isA(Tags::tag_mininterval))
00843 return PythonObject(getMinimumInterval());
00844 if (attr.isA(Tags::tag_maxinterval))
00845 return PythonObject(getMaximumInterval());
00846 if (attr.isA(Tags::tag_fence))
00847 return PythonObject(getFence());
00848 if (attr.isA(Tags::tag_size_minimum))
00849 return PythonObject(getSizeMinimum());
00850 if (attr.isA(Tags::tag_size_multiple))
00851 return PythonObject(getSizeMultiple());
00852 if (attr.isA(Tags::tag_size_maximum))
00853 return PythonObject(getSizeMaximum());
00854 return Buffer::getattro(attr);
00855 }
00856
00857
00858 DECLARE_EXPORT int BufferProcure::setattro(const Attribute& attr, const PythonObject& field)
00859 {
00860 if (attr.isA(Tags::tag_leadtime))
00861 setLeadtime(field.getTimeperiod());
00862 else if (attr.isA(Tags::tag_mininventory))
00863 setMinimumInventory(field.getDouble());
00864 else if (attr.isA(Tags::tag_maxinventory))
00865 setMaximumInventory(field.getDouble());
00866 else if (attr.isA(Tags::tag_mininterval))
00867 setMinimumInterval(field.getTimeperiod());
00868 else if (attr.isA(Tags::tag_maxinterval))
00869 setMaximumInterval(field.getTimeperiod());
00870 else if (attr.isA(Tags::tag_size_minimum))
00871 setSizeMinimum(field.getDouble());
00872 else if (attr.isA(Tags::tag_size_multiple))
00873 setSizeMultiple(field.getDouble());
00874 else if (attr.isA(Tags::tag_size_maximum))
00875 setSizeMaximum(field.getDouble());
00876 else if (attr.isA(Tags::tag_fence))
00877 setFence(field.getTimeperiod());
00878 else
00879 return Buffer::setattro(attr, field);
00880 return 0;
00881 }
00882
00883 }