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
