frepple2python.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/modules/python/frepple2python.cpp $
00003   version : $LastChangedRevision: 756 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2008-04-26 08:53:35 +0200 (Sat, 26 Apr 2008) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007 by Johan De Taeye                                    *
00010  *                                                                         *
00011  * This library is free software; you can redistribute it and/or modify it *
00012  * under the terms of the GNU Lesser General Public License as published   *
00013  * by the Free Software Foundation; either version 2.1 of the License, or  *
00014  * (at your option) any later version.                                     *
00015  *                                                                         *
00016  * This library is distributed in the hope that it will be useful,         *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
00019  * General Public License for more details.                                *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Lesser General Public        *
00022  * License along with this library; if not, write to the Free Software     *
00023  * Foundation Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #include "embeddedpython.h"
00028 
00029 namespace module_python
00030 {
00031 
00032 //
00033 // INTERFACE FOR PLAN
00034 //
00035 
00036 
00037 int PythonPlan::initialize(PyObject* m)
00038 {
00039   // Initialize the type
00040   PythonType& x = getType();
00041   x.setName("parameters");
00042   x.setDoc("frePPLe global settings");
00043   x.supportgetattro();
00044   x.supportsetattro();
00045   int tmp =x.typeReady(m);
00046 
00047   // Add access to the information with a global attribute
00048   return PyModule_AddObject(m, "settings", new PythonPlan) + tmp;
00049 }
00050 
00051 
00052 PyObject* PythonPlan::getattro(const Attribute& attr)
00053 {
00054   if (attr.isA(Tags::tag_name))
00055     return PythonObject(Plan::instance().getName());
00056   if (attr.isA(Tags::tag_description))
00057     return PythonObject(Plan::instance().getDescription());
00058   if (attr.isA(Tags::tag_current))
00059     return PythonObject(Plan::instance().getCurrent());
00060   if (attr.isA(Tags::tag_logfile))
00061     return PythonObject(Environment::getLogFile());
00062   return NULL;
00063 }
00064 
00065 
00066 int PythonPlan::setattro(const Attribute& attr, const PythonObject& field)
00067 {
00068   if (attr.isA(Tags::tag_name))
00069     Plan::instance().setName(field.getString());  
00070   else if (attr.isA(Tags::tag_description))
00071     Plan::instance().setDescription(field.getString());
00072   else if (attr.isA(Tags::tag_current))
00073     Plan::instance().setCurrent(field.getDate()); 
00074   else if (attr.isA(Tags::tag_logfile))
00075     Environment::setLogFile(field.getString());
00076   else
00077     return -1; // Error
00078   return 0;  // OK
00079 }
00080 
00081 
00082 //
00083 // INTERFACE FOR BUFFER
00084 //
00085 
00086 
00087 PyObject* PythonBuffer::getattro(const Attribute& attr)
00088 {
00089   if (!obj) return Py_None;
00090   if (attr.isA(Tags::tag_name))
00091     return PythonObject(obj->getName());
00092   if (attr.isA(Tags::tag_description))
00093     return PythonObject(obj->getDescription());
00094   if (attr.isA(Tags::tag_category))
00095     return PythonObject(obj->getCategory());
00096   if (attr.isA(Tags::tag_subcategory))
00097     return PythonObject(obj->getSubCategory());
00098   if (attr.isA(Tags::tag_owner))
00099     return PythonObject(obj->getOwner());
00100   if (attr.isA(Tags::tag_location))
00101     return PythonObject(obj->getLocation());
00102   if (attr.isA(Tags::tag_producing))
00103     return PythonObject(obj->getProducingOperation());
00104   if (attr.isA(Tags::tag_item))
00105     return PythonObject(obj->getItem());
00106   if (attr.isA(Tags::tag_onhand))
00107     return PythonObject(obj->getOnHand());
00108   if (attr.isA(Tags::tag_flowplans))
00109     return new PythonFlowPlanIterator(obj);
00110   if (attr.isA(Tags::tag_maximum))
00111     return PythonObject(obj->getMaximum());
00112   if (attr.isA(Tags::tag_minimum))
00113     return PythonObject(obj->getMinimum());
00114   if (attr.isA(Tags::tag_hidden))
00115     return PythonObject(obj->getHidden());
00116   if (attr.isA(Tags::tag_flows))
00117     return new PythonFlowIterator(obj);
00118   if (attr.isA(Tags::tag_level))
00119     return PythonObject(obj->getLevel());
00120   if (attr.isA(Tags::tag_cluster))
00121     return PythonObject(obj->getCluster());
00122   // @todo support member iteration for buffer, res, dem, item, ...
00123   // PythonBufferIterator becomes an abstract class: defines the pytype and an abstract iternext.
00124   // 2 subclasses then implement it: an iterator over all buffers, and another one over all members.
00125   return NULL;
00126 }
00127 
00128 
00129 int PythonBuffer::setattro(const Attribute& attr, const PythonObject& field)
00130 {
00131   if (attr.isA(Tags::tag_name))
00132     obj->setName(field.getString());
00133   else if (attr.isA(Tags::tag_description))
00134     obj->setDescription(field.getString());
00135   else if (attr.isA(Tags::tag_category))
00136     obj->setCategory(field.getString());
00137   else if (attr.isA(Tags::tag_subcategory))
00138     obj->setSubCategory(field.getString());
00139   else if (attr.isA(Tags::tag_owner))
00140   {
00141     if (!field.check(PythonBuffer::getType()))
00142     {
00143       PyErr_SetString(PythonDataException, "buffer owner must be of type buffer");
00144       return -1;
00145     }
00146     Buffer* y = static_cast<PythonBuffer*>(static_cast<PyObject*>(field))->obj;
00147     obj->setOwner(y);
00148   }
00149   else if (attr.isA(Tags::tag_location))
00150   {
00151     if (!field.check(PythonLocation::getType())) 
00152     {
00153       PyErr_SetString(PythonDataException, "buffer location must be of type location");
00154       return -1;
00155     }
00156     Location* y = static_cast<PythonLocation*>(static_cast<PyObject*>(field))->obj;
00157     obj->setLocation(y);
00158   }
00159   else if (attr.isA(Tags::tag_item))
00160   {
00161     if (!field.check(PythonItem::getType())) 
00162     {
00163       PyErr_SetString(PythonDataException, "buffer item must be of type item");
00164       return -1;
00165     }
00166     Item* y = static_cast<PythonItem*>(static_cast<PyObject*>(field))->obj;
00167     obj->setItem(y);
00168   }
00169   else if (attr.isA(Tags::tag_maximum))
00170   {
00171     if (!field.check(PythonCalendarDouble::getType())) 
00172     {
00173       PyErr_SetString(PythonDataException, "buffer maximum must be of type calendar_double");
00174       return -1;
00175     }
00176     CalendarDouble* y = static_cast<PythonCalendarDouble*>(static_cast<PyObject*>(field))->obj;
00177     obj->setMaximum(y);
00178   }
00179   else if (attr.isA(Tags::tag_minimum))
00180   {
00181     if (!field.check(PythonCalendarDouble::getType())) 
00182     {
00183       PyErr_SetString(PythonDataException, "buffer minimum must be of type calendar_double");
00184       return -1;
00185     }
00186     CalendarDouble* y = static_cast<PythonCalendarDouble*>(static_cast<PyObject*>(field))->obj;
00187     obj->setMinimum(y);
00188   }
00189   else if (attr.isA(Tags::tag_onhand))
00190     obj->setOnHand(field.getDouble());
00191   else if (attr.isA(Tags::tag_producing))
00192   {
00193     if (!field.check(PythonOperation::getType())) 
00194     {
00195       PyErr_SetString(PythonDataException, "buffer producing must be of type operation");
00196       return -1;
00197     }
00198     Operation* y = static_cast<PythonOperation*>(static_cast<PyObject*>(field))->obj;
00199     obj->setProducingOperation(y);
00200   }
00201   else if (attr.isA(Tags::tag_hidden))
00202     obj->setHidden(field.getBool());
00203   else
00204     return -1;  // Error
00205   return 0;  // OK
00206 }
00207 
00208 
00209 PyObject* PythonBufferDefault::getattro(const Attribute& attr)
00210 {
00211   return PythonBuffer(obj).getattro(attr); 
00212 }
00213 
00214 
00215 int PythonBufferDefault::setattro(const Attribute& attr, const PythonObject& field)
00216 {
00217   // @todo avoid constructing a PythonBuffer object to call the base class
00218   // This is currently not really feasible (no casting between the classes is possible)
00219   // When the XML and Python framework will be unified, this will be solved: we'll basically
00220   // have a single call to the getAttribute() method of the default buffer, which can call
00221   // the getAttribute function of the parent class.
00222   return PythonBuffer(obj).setattro(attr, field);  
00223 }
00224 
00225 
00226 PyObject* PythonBufferInfinite::getattro(const Attribute& attr)
00227 {
00228   return PythonBuffer(obj).getattro(attr);
00229 }
00230 
00231 
00232 int PythonBufferInfinite::setattro(const Attribute& attr, const PythonObject& field)
00233 {
00234   return PythonBuffer(obj).setattro(attr, field);
00235 }
00236 
00237 
00238 PyObject* PythonBufferProcure::getattro(const Attribute& attr)
00239 {
00240   if (!obj) return Py_None;
00241   if (attr.isA(Tags::tag_leadtime))
00242     return PythonObject(obj->getLeadtime());
00243   if (attr.isA(Tags::tag_mininventory))
00244     return PythonObject(obj->getMinimumInventory());
00245   if (attr.isA(Tags::tag_maxinventory))
00246     return PythonObject(obj->getMaximumInventory());
00247   if (attr.isA(Tags::tag_mininterval))
00248     return PythonObject(obj->getMinimumInterval());
00249   if (attr.isA(Tags::tag_maxinterval))
00250     return PythonObject(obj->getMaximumInterval());
00251   if (attr.isA(Tags::tag_fence))
00252     return PythonObject(obj->getFence());
00253   if (attr.isA(Tags::tag_size_minimum))
00254     return PythonObject(obj->getSizeMinimum());
00255   if (attr.isA(Tags::tag_size_multiple))
00256     return PythonObject(obj->getSizeMultiple());
00257   if (attr.isA(Tags::tag_size_maximum))
00258     return PythonObject(obj->getSizeMaximum());
00259   return PythonBuffer(obj).getattro(attr);
00260 }
00261 
00262 
00263 int PythonBufferProcure::setattro(const Attribute& attr, const PythonObject& field)
00264 {
00265   if (attr.isA(Tags::tag_leadtime))
00266     obj->setLeadtime(field.getTimeperiod());
00267   else if (attr.isA(Tags::tag_mininventory))
00268     obj->setMinimumInventory(field.getDouble());
00269   else if (attr.isA(Tags::tag_maxinventory))
00270     obj->setMaximumInventory(field.getDouble());
00271   else if (attr.isA(Tags::tag_mininterval))
00272     obj->setMinimumInterval(field.getTimeperiod());
00273   else if (attr.isA(Tags::tag_maxinterval))
00274     obj->setMaximumInterval(field.getTimeperiod());
00275   else if (attr.isA(Tags::tag_size_minimum))
00276     obj->setSizeMinimum(field.getDouble());
00277   else if (attr.isA(Tags::tag_size_multiple))
00278     obj->setSizeMultiple(field.getDouble());
00279   else if (attr.isA(Tags::tag_size_maximum))
00280     obj->setSizeMaximum(field.getDouble());
00281   else if (attr.isA(Tags::tag_fence))
00282     obj->setFence(field.getTimeperiod());
00283   else
00284     return PythonBuffer(obj).setattro(attr, field);
00285   return 0;
00286 }
00287 
00288 
00289 //
00290 // INTERFACE FOR LOCATION
00291 //
00292 
00293 
00294 PyObject* PythonLocation::getattro(const Attribute& attr)
00295 {
00296   if (!obj) return Py_None;
00297   if (attr.isA(Tags::tag_name))
00298     return PythonObject(obj->getName());
00299   if (attr.isA(Tags::tag_description))
00300     return PythonObject(obj->getDescription());
00301   if (attr.isA(Tags::tag_category))
00302     return PythonObject(obj->getCategory());
00303   if (attr.isA(Tags::tag_subcategory))
00304     return PythonObject(obj->getSubCategory());
00305   if (attr.isA(Tags::tag_owner))
00306     return PythonObject(obj->getOwner());
00307   if (attr.isA(Tags::tag_available))
00308     return PythonObject(obj->getAvailable());
00309   if (attr.isA(Tags::tag_hidden))
00310     return PythonObject(obj->getHidden());
00311   return NULL;
00312 }
00313 
00314 
00315 int PythonLocation::setattro(const Attribute& attr, const PythonObject& field)
00316 {
00317   if (attr.isA(Tags::tag_name))
00318     obj->setName(field.getString());
00319   else if (attr.isA(Tags::tag_description))
00320     obj->setDescription(field.getString());
00321   else if (attr.isA(Tags::tag_category))
00322     obj->setCategory(field.getString());
00323   else if (attr.isA(Tags::tag_subcategory))
00324     obj->setSubCategory(field.getString());
00325   else if (attr.isA(Tags::tag_owner))
00326   {
00327     if (!field.check(PythonLocation::getType())) 
00328     {
00329       PyErr_SetString(PythonDataException, "location owner must be of type location");
00330       return -1;
00331     }
00332     Location* y = static_cast<PythonLocation*>(static_cast<PyObject*>(field))->obj;
00333     obj->setOwner(y);
00334   }
00335   else if (attr.isA(Tags::tag_available))
00336   {
00337     if (!field.check(PythonCalendarBool::getType())) 
00338     {
00339       PyErr_SetString(PythonDataException, "location calendar must be of type calendar_bool");
00340       return -1;
00341     }
00342     CalendarBool* y = static_cast<PythonCalendarBool*>(static_cast<PyObject*>(field))->obj;
00343     obj->setAvailable(y);
00344   }
00345   else if (attr.isA(Tags::tag_hidden))
00346     obj->setHidden(field.getBool());
00347   else
00348     return -1;
00349   return 0;
00350 }
00351 
00352 
00353 PyObject* PythonLocationDefault::getattro(const Attribute& attr)
00354 {
00355   return PythonLocation(obj).getattro(attr);
00356 }
00357 
00358 
00359 int PythonLocationDefault::setattro(const Attribute& attr, const PythonObject& field)
00360 {
00361  return PythonLocation(obj).setattro(attr, field);
00362 }
00363 
00364 
00365 
00366 
00367 //
00368 // INTERFACE FOR CUSTOMER
00369 //
00370 
00371 
00372 PyObject* PythonCustomer::getattro(const Attribute& attr)
00373 {
00374   if (!obj) return Py_None;
00375   if (attr.isA(Tags::tag_name))
00376     return PythonObject(obj->getName());
00377   if (attr.isA(Tags::tag_description))
00378     return PythonObject(obj->getDescription());
00379   if (attr.isA(Tags::tag_category))
00380     return PythonObject(obj->getCategory());
00381   if (attr.isA(Tags::tag_subcategory))
00382     return PythonObject(obj->getSubCategory());
00383   if (attr.isA(Tags::tag_owner))
00384     return PythonObject(obj->getOwner());
00385   if (attr.isA(Tags::tag_hidden))
00386     return PythonObject(obj->getHidden());
00387   return NULL;
00388 }
00389 
00390 
00391 int PythonCustomer::setattro(const Attribute& attr, const PythonObject& field)
00392 {
00393   if (attr.isA(Tags::tag_name))
00394     obj->setName(field.getString());
00395   else if (attr.isA(Tags::tag_description))
00396     obj->setDescription(field.getString());
00397   else if (attr.isA(Tags::tag_category))
00398     obj->setCategory(field.getString());
00399   else if (attr.isA(Tags::tag_subcategory))
00400     obj->setSubCategory(field.getString());
00401   else if (attr.isA(Tags::tag_owner))
00402   {
00403     if (!field.check(PythonCustomer::getType())) 
00404     {
00405       PyErr_SetString(PythonDataException, "customer owner must be of type customer");
00406       return -1;
00407     }
00408     Customer* y = static_cast<PythonCustomer*>(static_cast<PyObject*>(field))->obj;
00409     obj->setOwner(y);
00410   }
00411   else if (attr.isA(Tags::tag_hidden))
00412     obj->setHidden(field.getBool());
00413   else
00414     return -1;
00415   return 0;
00416 }
00417 
00418 
00419 PyObject* PythonCustomerDefault::getattro(const Attribute& attr)
00420 {
00421   return PythonCustomer(obj).getattro(attr);
00422 }
00423 
00424 
00425 int PythonCustomerDefault::setattro(const Attribute& attr, const PythonObject& field)
00426 {
00427  return PythonCustomer(obj).setattro(attr, field);
00428 }
00429 
00430 
00431 //
00432 // INTERFACE FOR ITEM
00433 //
00434 
00435 
00436 PyObject* PythonItem::getattro(const Attribute& attr)
00437 {
00438   if (!obj) return Py_None;
00439   if (attr.isA(Tags::tag_name))
00440     return PythonObject(obj->getName());
00441   if (attr.isA(Tags::tag_description))
00442     return PythonObject(obj->getDescription());
00443   if (attr.isA(Tags::tag_category))
00444     return PythonObject(obj->getCategory());
00445   if (attr.isA(Tags::tag_subcategory))
00446     return PythonObject(obj->getSubCategory());
00447   if (attr.isA(Tags::tag_owner))
00448     return PythonObject(obj->getOwner());
00449   if (attr.isA(Tags::tag_operation))
00450     return PythonObject(obj->getOperation());
00451   if (attr.isA(Tags::tag_hidden))
00452     return PythonObject(obj->getHidden());
00453   return NULL;
00454 }
00455 
00456 
00457 int PythonItem::setattro(const Attribute& attr, const PythonObject& field)
00458 {
00459   if (attr.isA(Tags::tag_name))
00460     obj->setName(field.getString());
00461   else if (attr.isA(Tags::tag_description))
00462     obj->setDescription(field.getString());
00463   else if (attr.isA(Tags::tag_category))
00464     obj->setCategory(field.getString());
00465   else if (attr.isA(Tags::tag_subcategory))
00466     obj->setSubCategory(field.getString());
00467   else if (attr.isA(Tags::tag_owner))
00468   {
00469     if (!field.check(PythonItem::getType())) 
00470     {
00471       PyErr_SetString(PythonDataException, "item owner must be of type item");
00472       return -1;
00473     }
00474     Item* y = static_cast<PythonItem*>(static_cast<PyObject*>(field))->obj;
00475     obj->setOwner(y);
00476   }
00477   else if (attr.isA(Tags::tag_operation))
00478   {
00479     if (!field.check(PythonOperation::getType())) 
00480     {
00481       PyErr_SetString(PythonDataException, "item operation must be of type operation");
00482       return -1;
00483     }
00484     Operation* y = static_cast<PythonOperation*>(static_cast<PyObject*>(field))->obj;
00485     obj->setOperation(y);
00486   }
00487   else if (attr.isA(Tags::tag_hidden))
00488     obj->setHidden(field.getBool());
00489   else
00490     return -1;
00491   return 0;
00492 }
00493 
00494 
00495 PyObject* PythonItemDefault::getattro(const Attribute& attr)
00496 {
00497   return PythonItem(obj).getattro(attr);
00498 }
00499 
00500 
00501 int PythonItemDefault::setattro(const Attribute& attr, const PythonObject& field)
00502 {
00503  return PythonItem(obj).setattro(attr, field);
00504 }
00505 
00506 
00507 //
00508 // INTERFACE FOR CALENDAR
00509 //
00510 
00511 
00512 PyObject* PythonCalendar::getattro(const Attribute& attr)
00513 {
00514   if (!obj) return Py_None;
00515   if (attr.isA(Tags::tag_name))
00516     return PythonObject(obj->getName());
00517   if (attr.isA(Tags::tag_buckets))
00518     return new PythonCalendarBucketIterator(obj);
00519   return NULL;
00520 }
00521 
00522 
00523 int PythonCalendar::setattro(const Attribute& attr, const PythonObject& field)
00524 {
00525   if (attr.isA(Tags::tag_name))
00526     obj->setName(field.getString());
00527   else
00528     return -1;  // Error
00529   return 0;  // OK
00530 }
00531 
00532 
00533 PyObject* PythonCalendarVoid::getattro(const Attribute& attr)
00534 {
00535   return PythonCalendar(obj).getattro(attr); 
00536 }
00537 
00538 
00539 int PythonCalendarVoid::setattro(const Attribute& attr, const PythonObject& field)
00540 {
00541    return PythonCalendar(obj).setattro(attr, field);
00542 }
00543 
00544 
00545 PyObject* PythonCalendarBool::getattro(const Attribute& attr)
00546 {
00547   if (!obj) return Py_None;
00548   if (attr.isA(Tags::tag_default))
00549     return PythonObject(obj->getDefault());
00550   return PythonCalendar(obj).getattro(attr); 
00551 }
00552 
00553 
00554 int PythonCalendarBool::setattro(const Attribute& attr, const PythonObject& field)
00555 {
00556   if (attr.isA(Tags::tag_default))
00557     obj->setDefault(field.getBool());
00558   else
00559     return PythonCalendar(obj).setattro(attr, field);
00560   return 0;
00561 }
00562 
00563 
00564 PyObject* PythonCalendarDouble::getattro(const Attribute& attr)
00565 {
00566   if (!obj) return Py_None;
00567   if (attr.isA(Tags::tag_default))
00568     return PythonObject(obj->getDefault());
00569   return PythonCalendar(obj).getattro(attr); 
00570 }
00571 
00572 
00573 int PythonCalendarDouble::setattro(const Attribute& attr, const PythonObject& field)
00574 {
00575   if (attr.isA(Tags::tag_default))
00576     obj->setDefault(field.getDouble());
00577   else
00578     return PythonCalendar(obj).setattro(attr, field);
00579   return 0;
00580 }
00581 
00582 
00583 int PythonCalendarBucketIterator::initialize(PyObject* m)
00584 {
00585   // Initialize the type
00586   PythonType& x = PythonExtension<PythonCalendarBucketIterator>::getType();
00587   x.setName("calendarBucketIterator");
00588   x.setDoc("frePPLe iterator for calendar buckets");
00589   x.supportiter();
00590   return x.typeReady(m);
00591 }
00592 
00593 
00594 PyObject* PythonCalendarBucketIterator::iternext()
00595 {  
00596   if (i == cal->endBuckets()) return NULL;
00597   return new PythonCalendarBucket(cal, &*(i++));
00598 }
00599 
00600 
00601 int PythonCalendarBucket::initialize(PyObject* m)
00602 {
00603   // Initialize the type
00604   PythonType& x = PythonExtension<PythonCalendarBucket>::getType();
00605   x.setName("calendarBucket");
00606   x.setDoc("frePPLe calendar bucket");
00607   x.supportgetattro();
00608   x.supportsetattro();
00609   return x.typeReady(m);
00610 }
00611 
00612 
00613 PyObject* PythonCalendarBucket::getattro(const Attribute& attr)
00614 {
00615   if (!obj) return Py_None;
00616   if (attr.isA(Tags::tag_start))
00617     return PythonObject(obj->getStart());
00618   if (attr.isA(Tags::tag_end))
00619     return PythonObject(obj->getEnd());
00620   if (attr.isA(Tags::tag_value))
00621   {
00622     if (cal->getType() == CalendarDouble::metadata)
00623       return PythonObject(dynamic_cast< CalendarValue<double>::BucketValue* >(obj)->getValue());
00624     if (cal->getType() == CalendarBool::metadata)
00625       return PythonObject(dynamic_cast< CalendarValue<bool>::BucketValue* >(obj)->getValue());
00626     if (cal->getType() == CalendarInt::metadata)
00627       return PythonObject(dynamic_cast< CalendarValue<int>::BucketValue* >(obj)->getValue());
00628     if (cal->getType() == CalendarString::metadata)
00629       return PythonObject(dynamic_cast< CalendarValue<string>::BucketValue* >(obj)->getValue());
00630     if (cal->getType() == CalendarVoid::metadata) return Py_None;
00631     PyErr_SetString(PythonLogicException, "calendar type not recognized");
00632     return NULL;
00633   }
00634   if (attr.isA(Tags::tag_priority))
00635     return PythonObject(obj->getPriority());
00636   if (attr.isA(Tags::tag_name))
00637     return PythonObject(obj->getName());
00638   return NULL; 
00639 }
00640 
00641 
00642 int PythonCalendarBucket::setattro(const Attribute& attr, const PythonObject& field)
00643 {
00644   if (attr.isA(Tags::tag_name))
00645     obj->setName(field.getString());
00646   else if (attr.isA(Tags::tag_start))
00647     obj->setStart(field.getDate());
00648   else if (attr.isA(Tags::tag_end))
00649     obj->setEnd(field.getDate());
00650   else if (attr.isA(Tags::tag_priority))
00651     obj->setPriority(field.getInt());
00652   else if (attr.isA(Tags::tag_value))
00653   {
00654     if (cal->getType() == CalendarDouble::metadata)
00655       dynamic_cast< CalendarValue<double>::BucketValue* >(obj)->setValue(field.getDouble());
00656     else if (cal->getType() == CalendarBool::metadata)
00657       dynamic_cast< CalendarValue<bool>::BucketValue* >(obj)->setValue(field.getBool());
00658     else if (cal->getType() == CalendarInt::metadata)
00659       dynamic_cast< CalendarValue<int>::BucketValue* >(obj)->setValue(field.getInt());
00660     else if (cal->getType() == CalendarString::metadata)
00661       dynamic_cast< CalendarValue<string>::BucketValue* >(obj)->setValue(field.getString());
00662     else if (cal->getType() == CalendarVoid::metadata) 
00663       return -1;
00664     else
00665     {
00666       PyErr_SetString(PythonLogicException, "calendar type not recognized");
00667       return -1;
00668     }
00669   }
00670   else
00671     return -1;
00672   return 0;
00673 }
00674 
00675 
00676 //
00677 // INTERFACE FOR DEMAND
00678 //
00679 
00680 
00681 PyObject* PythonDemand::getattro(const Attribute& attr)
00682 {
00683   if (!obj) return Py_None;
00684   if (attr.isA(Tags::tag_name))
00685     return PythonObject(obj->getName());
00686   if (attr.isA(Tags::tag_quantity))
00687     return PythonObject(obj->getQuantity());
00688   if (attr.isA(Tags::tag_due))
00689     return PythonObject(obj->getDue());
00690   if (attr.isA(Tags::tag_priority))
00691     return PythonObject(obj->getPriority());
00692   if (attr.isA(Tags::tag_owner))
00693     return PythonObject(obj->getOwner());
00694   if (attr.isA(Tags::tag_item))
00695     return PythonObject(obj->getItem());
00696   if (attr.isA(Tags::tag_customer))
00697     return PythonObject(obj->getCustomer());
00698   if (attr.isA(Tags::tag_operation))
00699     return PythonObject(obj->getOperation());
00700   if (attr.isA(Tags::tag_description))
00701     return PythonObject(obj->getDescription());
00702   if (attr.isA(Tags::tag_category))
00703     return PythonObject(obj->getCategory());
00704   if (attr.isA(Tags::tag_subcategory))
00705     return PythonObject(obj->getSubCategory());
00706   if (attr.isA(Tags::tag_minshipment))
00707     return PythonObject(obj->getMinShipment());
00708   if (attr.isA(Tags::tag_maxlateness))
00709     return PythonObject(obj->getMaxLateness());
00710   if (attr.isA(Tags::tag_hidden))
00711     return PythonObject(obj->getHidden());
00712   if (attr.isA(Tags::tag_operationplans))
00713     return new PythonDemandPlanIterator(obj);
00714   if (attr.isA(Tags::tag_pegging))
00715     return new PythonPeggingIterator(obj);
00716   return NULL;
00717 }
00718 
00719 
00720 int PythonDemand::setattro(const Attribute& attr, const PythonObject& field)
00721 {
00722   if (attr.isA(Tags::tag_name))
00723     obj->setName(field.getString());
00724   else if (attr.isA(Tags::tag_priority))
00725     obj->setPriority(field.getInt());
00726   else if (attr.isA(Tags::tag_quantity))
00727     obj->setQuantity(field.getDouble());
00728   else if (attr.isA(Tags::tag_due))
00729     obj->setDue(field.getDate());
00730   else if (attr.isA(Tags::tag_item))
00731   {
00732     if (!field.check(PythonItem::getType())) 
00733     {
00734       PyErr_SetString(PythonDataException, "demand item must be of type item");
00735       return -1;
00736     }
00737     Item* y = static_cast<PythonItem*>(static_cast<PyObject*>(field))->obj;
00738     obj->setItem(y);
00739   }
00740   else if (attr.isA(Tags::tag_customer))
00741   {
00742     if (!field.check(PythonCustomer::getType())) 
00743     {
00744       PyErr_SetString(PythonDataException, "demand customer must be of type customer");
00745       return -1;
00746     }
00747     Customer* y = static_cast<PythonCustomer*>(static_cast<PyObject*>(field))->obj;
00748     obj->setCustomer(y);
00749   }
00750   else if (attr.isA(Tags::tag_description))
00751     obj->setDescription(field.getString());
00752   else if (attr.isA(Tags::tag_category))
00753     obj->setCategory(field.