calendar.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/calendar.cpp $
00003   version : $LastChangedRevision: 1315 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2010-07-17 18:08:53 +0200 (Sat, 17 Jul 2010) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 *
00024  * USA                                                                     *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 #define FREPPLE_CORE
00029 #include "frepple/model.h"
00030 
00031 namespace frepple
00032 {
00033 
00034 template<class Calendar> DECLARE_EXPORT Tree utils::HasName<Calendar>::st;
00035 DECLARE_EXPORT const MetaCategory* Calendar::metadata;
00036 DECLARE_EXPORT const MetaCategory* Calendar::Bucket::metadata;
00037 DECLARE_EXPORT const MetaClass *CalendarVoid::metadata,
00038   *CalendarDouble::metadata,
00039   *CalendarInt::metadata,
00040   *CalendarBool::metadata,
00041   *CalendarString::metadata,
00042   *CalendarOperation::metadata;
00043 
00044 
00045 int Calendar::initialize()
00046 {
00047   // Initialize the metadata
00048   metadata = new MetaCategory("calendar", "calendars", reader, writer);
00049 
00050   // Initialize the Python class
00051   return Calendar::Bucket::initialize() +
00052     FreppleCategory<Calendar>::initialize() +
00053     CalendarBucketIterator::initialize() +
00054     CalendarEventIterator::initialize();
00055 }
00056 
00057 
00058 int Calendar::Bucket::initialize()
00059 {
00060   // Initialize the metadata
00061   metadata = new MetaCategory("bucket", "buckets");
00062 
00063   // Initialize the Python class
00064   PythonType& x = PythonExtension<Calendar::Bucket>::getType();
00065   x.setName("calendarBucket");
00066   x.setDoc("frePPLe calendar bucket");
00067   x.supportgetattro();
00068   x.supportsetattro();
00069   const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object();
00070   return x.typeReady();
00071 }
00072 
00073 
00074 int CalendarVoid::initialize()
00075 {
00076   // Initialize the metadata
00077   metadata = new MetaClass("calendar", "calendar_void",
00078     Object::createString<CalendarVoid>);
00079 
00080   // Initialize the Python class
00081   FreppleClass<CalendarVoid,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00082   FreppleClass<CalendarVoid,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00083   return FreppleClass<CalendarVoid,Calendar>::initialize();
00084 }
00085 
00086 
00087 int CalendarDouble::initialize()
00088 {
00089   // Initialize the metadata
00090   metadata = new MetaClass("calendar", "calendar_double",
00091     Object::createString<CalendarDouble>, true);
00092 
00093   // Initialize the Python class
00094   FreppleClass<CalendarDouble,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00095   FreppleClass<CalendarDouble,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00096   return FreppleClass<CalendarDouble,Calendar>::initialize();
00097 }
00098 
00099 
00100 int CalendarInt::initialize()
00101 {
00102   // Initialize the metadata
00103   metadata = new MetaClass("calendar", "calendar_integer",
00104     Object::createString<CalendarInt>);
00105 
00106   // Initialize the Python class
00107   FreppleClass<CalendarInt,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00108   FreppleClass<CalendarInt,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00109   return FreppleClass<CalendarInt,Calendar>::initialize();
00110 }
00111 
00112 
00113 int CalendarBool::initialize()
00114 {
00115   // Initialize the metadata
00116   metadata = new MetaClass("calendar", "calendar_boolean",
00117     Object::createString<CalendarBool>);
00118 
00119   // Initialize the Python class
00120   FreppleClass<CalendarBool,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00121   FreppleClass<CalendarBool,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00122   return FreppleClass<CalendarBool,Calendar>::initialize();
00123 }
00124 
00125 
00126 int CalendarString::initialize()
00127 {
00128   // Initialize the metadata
00129   metadata = new MetaClass("calendar", "calendar_string",
00130     Object::createString<CalendarString>);
00131 
00132   // Initialize the Python class
00133   FreppleClass<CalendarString,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00134   FreppleClass<CalendarString,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00135   return FreppleClass<CalendarString,Calendar>::initialize();
00136 }
00137 
00138 
00139 int CalendarOperation::initialize()
00140 {
00141   // Initialize the metadata
00142   metadata = new MetaClass("calendar", "calendar_operation",
00143     Object::createString<CalendarOperation>);
00144 
00145   // Initialize the Python class
00146   FreppleClass<CalendarOperation,Calendar>::getType().addMethod("setValue", setPythonValue, METH_KEYWORDS, "update the value in a date range");
00147   FreppleClass<CalendarOperation,Calendar>::getType().addMethod("events", getEvents, METH_VARARGS, "return an event iterator");
00148   return FreppleClass<CalendarOperation,Calendar>::initialize();
00149 }
00150 
00151 
00152 // Specialised template functions
00153 template <> DECLARE_EXPORT bool CalendarValue<string>::getBool() const
00154   {return defaultValue.empty();}
00155 template <> DECLARE_EXPORT bool CalendarValue<string>::BucketValue::getBool() const
00156   {return val.empty();}
00157 
00158 
00159 DECLARE_EXPORT Calendar::~Calendar()
00160 {
00161   // De-allocate all the dynamic memory used for the bucket objects
00162   while (firstBucket)
00163   {
00164     Bucket* tmp = firstBucket;
00165     firstBucket = firstBucket->nextBucket;
00166     delete tmp;
00167   }
00168 }
00169 
00170 
00171 DECLARE_EXPORT CalendarDouble::~CalendarDouble()
00172 {
00173   // Remove all references from buffers
00174   for (Buffer::iterator b = Buffer::begin(); b != Buffer::end(); ++b)
00175   {
00176     if (b->getMinimum()==this) b->setMinimum(NULL);
00177     if (b->getMaximum()==this) b->setMaximum(NULL);
00178   }
00179 
00180   // Remove all references from resources
00181   for (Resource::iterator r = Resource::begin(); r != Resource::end(); ++r)
00182     if (r->getMaximum()==this) r->setMaximum(NULL);
00183 }
00184 
00185 
00186 DECLARE_EXPORT CalendarBool::~CalendarBool()
00187 {
00188   // Remove all references from locations
00189   for (Location::iterator l = Location::begin(); l != Location::end(); ++l)
00190   {
00191     if (l->getAvailable() == this)
00192       l->setAvailable(NULL);
00193   }
00194 }
00195 
00196 
00197 DECLARE_EXPORT Calendar::Bucket* Calendar::addBucket
00198   (Date start, Date end, string name)
00199 {
00200   // Assure the start is before the end.
00201   if (start > end)
00202   {
00203     // Switch arguments
00204     Date tmp = end;
00205     end = start;
00206     start = end;
00207   }
00208 
00209   // Create new bucket and insert in the list
00210   Bucket *next = firstBucket, *prev = NULL;
00211   while (next && next->startdate < start)
00212   {
00213     prev = next;
00214     next = next->nextBucket;
00215   }
00216 
00217   // Create the new bucket
00218   Bucket *c = createNewBucket(start,end,name);
00219   c->nextBucket = next;
00220   c->prevBucket = prev;
00221 
00222   // Maintain linked list
00223   if (prev) prev->nextBucket = c;
00224   else firstBucket = c;
00225   if (next) next->prevBucket = c;
00226 
00227   // Return the new bucket
00228   return c;
00229 }
00230 
00231 
00232 DECLARE_EXPORT void Calendar::removeBucket(Calendar::Bucket* bkt)
00233 {
00234   // Verify the bucket is on this calendar indeed
00235   Bucket *b = firstBucket;
00236   while (b && b != bkt) b = b->nextBucket;
00237 
00238   // Error
00239   if (!b)
00240     throw DataException("Trying to remove unavailable bucket from calendar '"
00241         + getName() + "'");
00242 
00243   // Update the list
00244   if (bkt->prevBucket)
00245     // Previous bucket links to a new next bucket
00246     bkt->prevBucket->nextBucket = bkt->nextBucket;
00247   else
00248     // New head for the bucket list
00249     firstBucket = bkt->nextBucket;
00250   if (bkt->nextBucket)
00251     // Update the reference prevBucket of the next bucket
00252     bkt->nextBucket->prevBucket = bkt->prevBucket;
00253 
00254   // Delete the bucket
00255   delete bkt;
00256 }
00257 
00258 
00259 DECLARE_EXPORT Calendar::Bucket* Calendar::findBucket(Date d, bool fwd) const
00260 {
00261   Calendar::Bucket *curBucket = NULL;
00262   double curPriority = DBL_MAX;
00263   for (Bucket *b = firstBucket; b; b = b->nextBucket)
00264   {
00265     if (b->getStart() > d)
00266       // Buckets are sorted by the start date. Other entries definately
00267       // won't be effective.
00268       break;
00269     else if (curPriority > b->getPriority() && b->checkValid(d)
00270       && ( (fwd && d >= b->getStart() && d < b->getEnd()) ||
00271            (!fwd && d > b->getStart() && d <= b->getEnd())
00272       ))
00273     {
00274       // Bucket is effective and has lower priority than other effective ones.
00275       curPriority = b->getPriority();
00276       curBucket = &*b;
00277     }
00278   }
00279   return curBucket;
00280 }
00281 
00282 
00283 DECLARE_EXPORT Calendar::Bucket* Calendar::findBucket(const string& d) const
00284 {
00285   for (Bucket *b = firstBucket; b; b = b->nextBucket)
00286     if (b->getName() == d) return b;
00287   return NULL;
00288 }
00289 
00290 
00291 DECLARE_EXPORT void Calendar::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00292 {
00293   // Writing a reference
00294   if (m == REFERENCE)
00295   {
00296     o->writeElement
00297       (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00298     return;
00299   }
00300 
00301   // Write the complete object
00302   if (m != NOHEADER) o->BeginObject
00303     (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00304 
00305   // Write all buckets
00306   o->BeginObject (Tags::tag_buckets);
00307   for (BucketIterator i = beginBuckets(); i != endBuckets(); ++i)
00308     // We use the FULL mode, to force the buckets being written regardless
00309     // of the depth in the XML tree.
00310     o->writeElement(Tags::tag_bucket, *i, FULL);
00311   o->EndObject(Tags::tag_buckets);
00312 
00313   o->EndObject(tag);
00314 }
00315 
00316 
00317 DECLARE_EXPORT Calendar::Bucket* Calendar::createBucket(const AttributeList& atts)
00318 {
00319   // Pick up the start, end and name attributes
00320   Date startdate = atts.get(Tags::tag_start)->getDate();
00321   const DataElement* d = atts.get(Tags::tag_end);
00322   Date enddate = *d ? d->getDate() : Date::infiniteFuture;
00323   string name = atts.get(Tags::tag_name)->getString();
00324 
00325   // Check for existence of the bucket: same name, start date and end date
00326   Calendar::Bucket* result = NULL;
00327   for (BucketIterator x = beginBuckets(); x!=endBuckets(); ++x)
00328   {
00329     if ((!name.empty() && x->nm==name)
00330       || (name.empty() && x->startdate==startdate && x->enddate==enddate))
00331     {
00332       // Found!
00333       result = &*x;
00334       break;
00335     }
00336   }
00337 
00338   // Pick up the action attribute and update the bucket accordingly
00339   switch (MetaClass::decodeAction(atts))
00340   {
00341     case ADD:
00342       // Only additions are allowed
00343       if (result)
00344         throw DataException("Bucket " + string(startdate) + " "
00345             + string(enddate) + " " + name
00346             + " already exists in calendar '" + getName() + "'");
00347       result = addBucket(startdate, enddate, name);
00348       return result;
00349     case CHANGE:
00350       // Only changes are allowed
00351       if (!result)
00352         throw DataException("Bucket " + string(startdate) + " " + string(enddate)
00353             + " " + name + " doesn't exist in calendar '" + getName() + "'");
00354       return result;
00355     case REMOVE:
00356       // Delete the entity
00357       if (!result)
00358         throw DataException("Bucket " + string(startdate) + " " + string(enddate)
00359             + " " + name + " doesn't exist in calendar '" + getName() + "'");
00360       else
00361       {
00362         // Delete it
00363         removeBucket(result);
00364         return NULL;
00365       }
00366     case ADD_CHANGE:
00367       if (!result)
00368         // Adding a new bucket
00369         result = addBucket(startdate, enddate, name);
00370       return result;
00371   }
00372 
00373   // This part of the code isn't expected not be reached
00374   throw LogicException("Unreachable code reached");
00375 }
00376 
00377 
00378 DECLARE_EXPORT void Calendar::beginElement(XMLInput& pIn, const Attribute& pAttr)
00379 {
00380   if (pAttr.isA (Tags::tag_bucket)
00381       && pIn.getParentElement().first.isA(Tags::tag_buckets))
00382     // A new bucket
00383     pIn.readto(createBucket(pIn.getAttributes()));
00384 }
00385 
00386 
00387 DECLARE_EXPORT void Calendar::Bucket::writeHeader(XMLOutput *o, const Keyword& tag) const
00388 {
00389   // The header line has a variable number of attributes: start, end and/or name
00390   if (startdate != Date::infinitePast)
00391   {
00392     if (enddate != Date::infiniteFuture)
00393     {
00394       if (!nm.empty())
00395         o->BeginObject(tag, Tags::tag_start, string(startdate), Tags::tag_end, string(enddate), Tags::tag_name, nm);
00396       else
00397         o->BeginObject(tag, Tags::tag_start, string(startdate), Tags::tag_end, string(enddate));
00398     }
00399     else
00400     {
00401       if (!nm.empty())
00402         o->BeginObject(tag, Tags::tag_start, string(startdate), Tags::tag_name, nm);
00403       else
00404         o->BeginObject(tag, Tags::tag_start, string(startdate));
00405     }
00406   }
00407   else
00408   {
00409     if (enddate != Date::infiniteFuture)
00410     {
00411       if (!nm.empty())
00412         o->BeginObject(tag, Tags::tag_end, string(enddate), Tags::tag_name, nm);
00413       else
00414         o->BeginObject(tag, Tags::tag_end, string(enddate));
00415     }
00416     else
00417     {
00418       if (!nm.empty())
00419         o->BeginObject(tag, Tags::tag_name, nm);
00420       else
00421         o->BeginObject(tag);
00422     }
00423   }
00424 }
00425 
00426 
00427 DECLARE_EXPORT void Calendar::Bucket::writeElement
00428 (XMLOutput *o, const Keyword& tag, mode m) const
00429 {
00430   assert(m == DEFAULT || m == FULL);
00431   writeHeader(o,tag);
00432   if (priority) o->writeElement(Tags::tag_priority, priority);
00433   o->EndObject(tag);
00434 }
00435 
00436 
00437 DECLARE_EXPORT void Calendar::Bucket::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00438 {
00439   if (pAttr.isA(Tags::tag_priority))
00440     pElement >> priority;
00441 }
00442 
00443 
00444 DECLARE_EXPORT Calendar::EventIterator& Calendar::EventIterator::operator++()
00445 {
00446   // Go over all entries and ask them to update the iterator
00447   Date d = curDate;
00448   curDate = Date::infiniteFuture;  // Cause end date is not included
00449   curBucket = NULL;
00450   curPriority = DBL_MAX;
00451   for (const Calendar::Bucket *b = theCalendar->firstBucket; b; b = b->nextBucket)
00452     b->nextEvent(this, d);
00453   return *this;
00454 }
00455 
00456 
00457 DECLARE_EXPORT Calendar::EventIterator& Calendar::EventIterator::operator--()
00458 {
00459   // Go over all entries and ask them to update the iterator
00460   Date d = curDate;
00461   curDate = Date::infinitePast;
00462   curBucket = NULL;
00463   curPriority = DBL_MAX;
00464   for (const Calendar::Bucket *b = theCalendar->firstBucket; b; b = b->nextBucket)
00465     b->prevEvent(this, d);
00466   return *this;
00467 }
00468 
00469 
00470 DECLARE_EXPORT void Calendar::Bucket::nextEvent(EventIterator* iter, Date refDate) const
00471 {
00472   if (iter->curPriority < priority)
00473     // Priority isn't low enough to overrule current date
00474     return;
00475 
00476   if (refDate < startdate && startdate <= iter->curDate)
00477   {
00478     // Next event is the start date of the bucket
00479     iter->curDate = startdate;
00480     iter->curBucket = this;
00481     iter->curPriority = priority;
00482     return;
00483   }
00484 
00485   if (refDate < enddate && enddate < iter->curDate)
00486   {
00487     // Next event is the end date of the bucket
00488     iter->curDate = enddate;
00489     iter->curBucket = iter->theCalendar->findBucket(enddate);
00490     iter->curPriority = priority;
00491     return;
00492   }
00493 }
00494 
00495 
00496 DECLARE_EXPORT void Calendar::Bucket::prevEvent(EventIterator* iter, Date refDate) const
00497 {
00498   if (iter->curPriority < priority)
00499     // Priority isn't low enough to overrule current date
00500     return;
00501 
00502   if (refDate > enddate && enddate >= iter->curDate)
00503   {
00504     // Previous event is the end date of the bucket
00505     iter->curDate = enddate;
00506     iter->curBucket = this;
00507     iter->curPriority = priority;
00508     return;
00509   }
00510 
00511   if (refDate > startdate && startdate > iter->curDate)
00512   {
00513     // Previous event is the start date of the bucket
00514     iter->curDate = startdate;
00515     iter->curBucket = iter->theCalendar->findBucket(startdate,false);
00516     iter->curPriority = priority;
00517     return;
00518   }
00519 
00520 }
00521 
00522 
00523 DECLARE_EXPORT PyObject* Calendar::getattro(const Attribute& attr)
00524 {
00525   if (attr.isA(Tags::tag_name))
00526     return PythonObject(getName());
00527   if (attr.isA(Tags::tag_buckets))
00528     return new CalendarBucketIterator(this);
00529   return NULL;
00530 }
00531 
00532 
00533 DECLARE_EXPORT int Calendar::setattro(const Attribute& attr, const PythonObject& field)
00534 {
00535   if (attr.isA(Tags::tag_name))
00536     setName(field.getString());
00537   else
00538     return -1;  // Error
00539   return 0;  // OK
00540 }
00541 
00542 
00543 DECLARE_EXPORT PyObject* CalendarVoid::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00544 {
00545   try
00546   {
00547     // Pick up the calendar
00548     CalendarVoid *cal = static_cast<CalendarVoid*>(self);
00549     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00550 
00551     // Parse the arguments
00552     PyObject *pystart, *pyend, *pyval = NULL;
00553     if (!PyArg_ParseTuple(args, "OO|O:setValue", &pystart, &pyend, &pyval))
00554       return NULL;
00555 
00556     // Update the calendar
00557     PythonObject start(pystart), end(pyend);
00558     cal->addBucket(start.getDate(), end.getDate(), "");
00559   }
00560   catch(...)
00561   {
00562     PythonType::evalException();
00563     return NULL;
00564   }
00565   return Py_BuildValue("");
00566 }
00567 
00568 
00569 DECLARE_EXPORT PyObject* CalendarBool::getattro(const Attribute& attr)
00570 {
00571   if (attr.isA(Tags::tag_default))
00572     return PythonObject(getDefault());
00573   return Calendar::getattro(attr);
00574 }
00575 
00576 
00577 DECLARE_EXPORT int CalendarBool::setattro(const Attribute& attr, const PythonObject& field)
00578 {
00579   if (attr.isA(Tags::tag_default))
00580     setDefault(field.getBool());
00581   else
00582     return Calendar::setattro(attr, field);
00583   return 0;
00584 }
00585 
00586 
00587 DECLARE_EXPORT PyObject* CalendarBool::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00588 {
00589   try
00590   {
00591     // Pick up the calendar
00592     CalendarBool *cal = static_cast<CalendarBool*>(self);
00593     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00594 
00595     // Parse the arguments
00596     PyObject *pystart, *pyend, *pyval;
00597     if (!PyArg_ParseTuple(args, "OOO:setValue", &pystart, &pyend, &pyval))
00598       return NULL;
00599 
00600     // Update the calendar
00601     PythonObject start(pystart), end(pyend), val(pyval);
00602     cal->setValue(start.getDate(), end.getDate(), val.getBool());
00603   }
00604   catch(...)
00605   {
00606     PythonType::evalException();
00607     return NULL;
00608   }
00609   return Py_BuildValue("");
00610 }
00611 
00612 
00613 DECLARE_EXPORT PyObject* CalendarDouble::getattro(const Attribute& attr)
00614 {
00615   if (attr.isA(Tags::tag_default))
00616     return PythonObject(getDefault());
00617   return Calendar::getattro(attr);
00618 }
00619 
00620 
00621 DECLARE_EXPORT int CalendarDouble::setattro(const Attribute& attr, const PythonObject& field)
00622 {
00623   if (attr.isA(Tags::tag_default))
00624     setDefault(field.getDouble());
00625   else
00626     return Calendar::setattro(attr, field);
00627   return 0;
00628 }
00629 
00630 
00631 DECLARE_EXPORT PyObject* CalendarDouble::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00632 {
00633   try
00634   {
00635     // Pick up the calendar
00636     CalendarDouble *cal = static_cast<CalendarDouble*>(self);
00637     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00638 
00639     // Parse the arguments
00640     PyObject *pystart, *pyend, *pyval;
00641     if (!PyArg_ParseTuple(args, "OOO:setValue", &pystart, &pyend, &pyval))
00642       return NULL;
00643 
00644     // Update the calendar
00645     PythonObject start(pystart), end(pyend), val(pyval);
00646     cal->setValue(start.getDate(), end.getDate(), val.getDouble());
00647   }
00648   catch(...)
00649   {
00650     PythonType::evalException();
00651     return NULL;
00652   }
00653   return Py_BuildValue("");
00654 }
00655 
00656 
00657 DECLARE_EXPORT PyObject* CalendarString::getattro(const Attribute& attr)
00658 {
00659   if (attr.isA(Tags::tag_default))
00660     return PythonObject(getDefault());
00661   return Calendar::getattro(attr);
00662 }
00663 
00664 
00665 DECLARE_EXPORT int CalendarString::setattro(const Attribute& attr, const PythonObject& field)
00666 {
00667   if (attr.isA(Tags::tag_default))
00668     setDefault(field.getString());
00669   else
00670     return Calendar::setattro(attr, field);
00671   return 0;
00672 }
00673 
00674 
00675 DECLARE_EXPORT PyObject* CalendarString::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00676 {
00677   try
00678   {
00679     // Pick up the calendar
00680     CalendarString *cal = static_cast<CalendarString*>(self);
00681     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00682 
00683     // Parse the arguments
00684     PyObject *pystart, *pyend, *pyval;
00685     if (!PyArg_ParseTuple(args, "OOO:setValue", &pystart, &pyend, &pyval))
00686       return NULL;
00687 
00688     // Update the calendar
00689     PythonObject start(pystart), end(pyend), val(pyval);
00690     cal->setValue(start.getDate(), end.getDate(), val.getString());
00691   }
00692   catch(...)
00693   {
00694     PythonType::evalException();
00695     return NULL;
00696   }
00697   return Py_BuildValue("");
00698 }
00699 
00700 
00701 DECLARE_EXPORT PyObject* CalendarInt::getattro(const Attribute& attr)
00702 {
00703   if (attr.isA(Tags::tag_default))
00704     return PythonObject(getDefault());
00705   return Calendar::getattro(attr);
00706 }
00707 
00708 
00709 DECLARE_EXPORT int CalendarInt::setattro(const Attribute& attr, const PythonObject& field)
00710 {
00711   if (attr.isA(Tags::tag_default))
00712     setDefault(field.getInt());
00713   else
00714     return Calendar::setattro(attr, field);
00715   return 0;
00716 }
00717 
00718 
00719 DECLARE_EXPORT PyObject* CalendarInt::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00720 {
00721   try
00722   {
00723     // Pick up the calendar
00724     CalendarInt *cal = static_cast<CalendarInt*>(self);
00725     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00726 
00727     // Parse the arguments
00728     PyObject *pystart, *pyend, *pyval;
00729     if (!PyArg_ParseTuple(args, "OOO:setValue", &pystart, &pyend, &pyval))
00730       return NULL;
00731 
00732     // Update the calendar
00733     PythonObject start(pystart), end(pyend), val(pyval);
00734     cal->setValue(start.getDate(), end.getDate(), val.getInt());
00735   }
00736   catch(...)
00737   {
00738     PythonType::evalException();
00739     return NULL;
00740   }
00741   return Py_BuildValue("");
00742 }
00743 
00744 
00745 DECLARE_EXPORT PyObject* CalendarOperation::getattro(const Attribute& attr)
00746 {
00747   if (attr.isA(Tags::tag_default))
00748     return PythonObject(getDefault());
00749   return Calendar::getattro(attr);
00750 }
00751 
00752 
00753 DECLARE_EXPORT int CalendarOperation::setattro(const Attribute& attr, const PythonObject& field)
00754 {
00755   if (attr.isA(Tags::tag_default))
00756   {
00757     if (!field.check(Operation::metadata))
00758     {
00759       PyErr_SetString(PythonDataException, "calendar_operation stores values of type operation");
00760       return -1;
00761     }
00762     Operation* y = static_cast<Operation*>(static_cast<PyObject*>(field));
00763     setDefault(y);
00764   }
00765   else
00766     return Calendar::setattro(attr, field);
00767   return 0;
00768 }
00769 
00770 
00771 DECLARE_EXPORT PyObject* CalendarOperation::setPythonValue(PyObject* self, PyObject* args, PyObject* kwdict)
00772 {
00773   try
00774   {
00775     // Pick up the calendar
00776     CalendarOperation *cal = static_cast<CalendarOperation*>(self);
00777     if (!cal) throw LogicException("Can't set value of a NULL calendar");
00778 
00779     // Parse the arguments
00780     PyObject *pystart, *pyend, *pyval;
00781     if (!PyArg_ParseTuple(args, "OOO:setValue", &pystart, &pyend, &pyval))
00782       return NULL;
00783 
00784     // Update the calendar
00785     PythonObject start(pystart), end(pyend), val(pyval);
00786     if (!val.check(Operation::metadata))
00787     {
00788       PyErr_SetString(PythonDataException, "calendar_operation stores values of type operation");
00789       return NULL;
00790     }
00791     Operation* y = static_cast<Operation*>(static_cast<PyObject*>(val));
00792     cal->setValue(start.getDate(), end.getDate(), y);
00793   }
00794   catch(...)
00795   {
00796     PythonType::evalException();
00797     return NULL;
00798   }
00799   return Py_BuildValue("");
00800 }
00801 
00802 
00803 int CalendarBucketIterator::initialize()
00804 {
00805   // Initialize the type
00806   PythonType& x = PythonExtension<CalendarBucketIterator>::getType();
00807   x.setName("calendarBucketIterator");
00808   x.setDoc("frePPLe iterator for calendar buckets");
00809   x.supportiter();
00810   return x.typeReady();
00811 }
00812 
00813 
00814 PyObject* CalendarBucketIterator::iternext()
00815 {
00816   if (i == cal->endBuckets()) return NULL;
00817   PyObject *result = &*(i++);
00818   Py_INCREF(result);
00819   return result;
00820 }
00821 
00822 
00823 DECLARE_EXPORT PyObject* Calendar::Bucket::getattro(const Attribute& attr)
00824 {
00825   if (attr.isA(Tags::tag_start))
00826     return PythonObject(getStart());
00827   if (attr.isA(Tags::tag_end))
00828     return PythonObject(getEnd());
00829   if (attr.isA(Tags::tag_value))
00830   {
00831     if (cal->getType() == *CalendarDouble::metadata)
00832       return PythonObject(dynamic_cast< CalendarValue<double>::BucketValue* >(this)->getValue());
00833     if (cal->getType() == *CalendarBool::metadata)
00834       return PythonObject(dynamic_cast< CalendarValue<bool>::BucketValue* >(this)->getValue());
00835     if (cal->getType() == *CalendarInt::metadata)
00836       return PythonObject(dynamic_cast< CalendarValue<int>::BucketValue* >(this)->getValue());
00837     if (cal->getType() == *CalendarString::metadata)
00838       return PythonObject(dynamic_cast< CalendarValue<string>::BucketValue* >(this)->getValue());
00839     if (cal->getType() == *CalendarOperation::metadata)
00840       return PythonObject(dynamic_cast< CalendarPointer<Operation>::BucketPointer* >(this)->getValue());
00841     if (cal->getType() == *CalendarVoid::metadata)
00842       return Py_BuildValue("");
00843     PyErr_SetString(PythonLogicException, "calendar type not recognized");
00844     return NULL;
00845   }
00846   if (attr.isA(Tags::tag_priority))
00847     return PythonObject(getPriority());
00848   if (attr.isA(Tags::tag_name))
00849     return PythonObject(getName());
00850   return NULL;
00851 }
00852 
00853 
00854 DECLARE_EXPORT int Calendar::Bucket::setattro(const Attribute& attr, const PythonObject& field)
00855 {
00856   if (attr.isA(Tags::tag_name))
00857     setName(field.getString());
00858   else if (attr.isA(Tags::tag_start))
00859     setStart(field.getDate());
00860   else if (attr.isA(Tags::tag_end))
00861     setEnd(field.getDate());
00862   else if (attr.isA(Tags::tag_priority))
00863     setPriority(field.getInt());
00864   else if (attr.isA(Tags::tag_value))
00865   {
00866     if (cal->getType() == *CalendarDouble::metadata)
00867       dynamic_cast< CalendarValue<double>::BucketValue* >(this)->setValue(field.getDouble());
00868     else if (cal->getType() == *CalendarBool::metadata)
00869       dynamic_cast< CalendarValue<bool>::BucketValue* >(this)->setValue(field.getBool());
00870     else if (cal->getType() == *CalendarInt::metadata)
00871       dynamic_cast< CalendarValue<int>::BucketValue* >(this)->setValue(field.getInt());
00872     else if (cal->getType() == *CalendarString::metadata)
00873       dynamic_cast< CalendarValue<string>::BucketValue* >(this)->setValue(field.getString());
00874     else if (cal->getType() == *CalendarOperation::metadata)
00875     {
00876       if (!field.check(Operation::metadata))
00877       {
00878         PyErr_SetString(PythonDataException, "calendar_operation stores values of type operation");
00879         return -1;
00880       }
00881       Operation* y = static_cast<Operation*>(static_cast<PyObject*>(field));
00882       dynamic_cast< CalendarPointer<Operation>::BucketPointer* >(this)->setValue(y);
00883     }
00884     else if (cal->getType() == *CalendarVoid::metadata)
00885       return -1;
00886     else
00887     {
00888       PyErr_SetString(PythonLogicException, "calendar type not recognized");
00889       return -1;
00890     }
00891   }
00892   else
00893     return -1;
00894   return 0;
00895 }
00896 
00897 
00898 DECLARE_EXPORT PyObject* Calendar::getEvents(
00899   PyObject* self, PyObject* args, PyObject* kwdict
00900   )
00901 {
00902   try
00903   {
00904     // Pick up the calendar
00905     Calendar *cal = NULL;
00906     PythonObject c(self);
00907     if (c.check(CalendarBool::metadata))
00908       cal = static_cast<CalendarBool*>(self);
00909     else if (c.check(CalendarDouble::metadata))
00910       cal = static_cast<CalendarDouble*>(self);
00911     else if (c.check(CalendarInt::metadata))
00912       cal = static_cast<CalendarInt*>(self);
00913     else if (c.check(CalendarOperation::metadata))
00914       cal = static_cast<CalendarOperation*>(self);
00915     else if (c.check(CalendarString::metadata))
00916       cal = static_cast<CalendarString*>(self);
00917     else if (c.check(CalendarVoid::metadata))
00918       cal = static_cast<CalendarVoid*>(self);
00919     else
00920       throw LogicException("Invalid calendar type");
00921 
00922     // Parse the arguments
00923     PyObject* pystart = NULL;
00924     PyObject* pydirection = NULL;
00925     if (!PyArg_ParseTuple(args, "|OO:setvalue", &pystart, &pydirection))
00926       return NULL;
00927     Date startdate = pystart ? PythonObject(pystart).getDate() : Date::infinitePast;
00928     bool forward = pydirection ? PythonObject(pydirection).getBool() : true;
00929 
00930     // Return the iterator
00931     return new CalendarEventIterator(cal, startdate, forward);
00932   }
00933   catch(...)
00934   {
00935     PythonType::evalException();
00936     return NULL;
00937   }
00938 }
00939 
00940 
00941 int CalendarEventIterator::initialize()
00942 {
00943   // Initialize the type
00944   PythonType& x = PythonExtension<CalendarEventIterator>::getType();
00945   x.setName("calendarEventIterator");
00946   x.setDoc("frePPLe iterator for calendar events");
00947   x.supportiter();
00948   return x.typeReady();
00949 }
00950 
00951 
00952 PyObject* CalendarEventIterator::iternext()
00953 {
00954   if ((forward && eventiter.getDate() == Date::infiniteFuture)
00955    || (!forward && eventiter.getDate() == Date::infinitePast))
00956    return NULL;
00957   PythonObject x;
00958   if (dynamic_cast<CalendarBool*>(cal))
00959   {
00960     if (eventiter.getBucket())
00961       x = PythonObject(dynamic_cast<const CalendarBool::BucketValue*>(eventiter.getBucket())->getValue());
00962     else
00963       x = PythonObject(dynamic_cast<CalendarBool*>(cal)->getDefault());
00964   }
00965   else if (dynamic_cast<CalendarDouble*>(cal))
00966   {
00967     if (eventiter.getBucket())
00968       x = PythonObject(dynamic_cast<const CalendarDouble::BucketValue*>(eventiter.getBucket())->getValue());
00969     else
00970       x = PythonObject(dynamic_cast<CalendarDouble*>(cal)->getDefault());
00971   }
00972   else if (dynamic_cast<CalendarInt*>(cal))
00973   {
00974     if (eventiter.getBucket())
00975       x = PythonObject(dynamic_cast<const CalendarInt::BucketValue*>(eventiter.getBucket())->getValue());
00976     else
00977       x = PythonObject(dynamic_cast<CalendarInt*>(cal)->getDefault());
00978   }
00979   else if (dynamic_cast<CalendarOperation*>(cal))
00980   {
00981     if (eventiter.getBucket())
00982       x = PythonObject(dynamic_cast<const CalendarOperation::BucketPointer*>(eventiter.getBucket())->getValue());
00983     else
00984       x = PythonObject(dynamic_cast<CalendarOperation*>(cal)->getDefault());
00985   }
00986   else if (dynamic_cast<CalendarString*>(cal))
00987   {
00988     if (eventiter.getBucket())
00989       x = PythonObject(dynamic_cast<const CalendarString::BucketValue*>(eventiter.getBucket())->getValue());
00990     else
00991       x = PythonObject(dynamic_cast<CalendarString*>(cal)->getDefault());
00992   }
00993   PyObject* result = Py_BuildValue("(N,N)",
00994     static_cast<PyObject*>(PythonObject(eventiter.getDate())),
00995     static_cast<PyObject*>(x)
00996     );
00997   if (forward)
00998     ++eventiter;
00999   else
01000     --eventiter;
01001   return result;
01002 }
01003 
01004 } // end namespace

Documentation generated for frePPLe by  doxygen