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