resource.cpp
Go to the documentation of this file.00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/resource.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 Resource> DECLARE_EXPORT Tree utils::HasName<Resource>::st; 00035 DECLARE_EXPORT const MetaCategory* Resource::metadata; 00036 DECLARE_EXPORT const MetaClass* ResourceDefault::metadata; 00037 DECLARE_EXPORT const MetaClass* ResourceInfinite::metadata; 00038 00039 00040 int Resource::initialize() 00041 { 00042 // Initialize the metadata 00043 metadata = new MetaCategory("resource", "resources", reader, writer); 00044 00045 // Initialize the Python class 00046 return FreppleCategory<Resource>::initialize(); 00047 } 00048 00049 00050 int ResourceDefault::initialize() 00051 { 00052 // Initialize the metadata 00053 ResourceDefault::metadata = new MetaClass( 00054 "resource", 00055 "resource_default", 00056 Object::createString<ResourceDefault>, 00057 true); 00058 00059 // Initialize the Python class 00060 return FreppleClass<ResourceDefault,Resource>::initialize(); 00061 } 00062 00063 00064 int ResourceInfinite::initialize() 00065 { 00066 // Initialize the metadata 00067 ResourceInfinite::metadata = new MetaClass( 00068 "resource", 00069 "resource_infinite", 00070 Object::createString<ResourceInfinite>); 00071 00072 // Initialize the Python class 00073 return FreppleClass<ResourceInfinite,Resource>::initialize(); 00074 } 00075 00076 00077 DECLARE_EXPORT void Resource::setMaximum(CalendarDouble* c) 00078 { 00079 // Resetting the same calendar 00080 if (max_cal == c) return; 00081 00082 // Mark as changed 00083 setChanged(); 00084 00085 // Calendar is already set. Need to remove the current max events. 00086 if (max_cal) 00087 { 00088 for (loadplanlist::iterator oo=loadplans.begin(); oo!=loadplans.end(); ) 00089 if (oo->getType() == 4) 00090 { 00091 loadplans.erase(&(*oo)); 00092 delete &(*(oo++)); 00093 } 00094 else ++oo; 00095 } 00096 00097 // Null pointer passed 00098 if (!c) return; 00099 00100 // Create timeline structures for every bucket. 00101 max_cal = c; 00102 double curMax = 0.0; 00103 for (CalendarDouble::EventIterator x(max_cal); x.getDate()<Date::infiniteFuture; ++x) 00104 if (curMax != x.getValue()) 00105 { 00106 curMax = x.getValue(); 00107 loadplanlist::EventMaxQuantity *newBucket = 00108 new loadplanlist::EventMaxQuantity(x.getDate(), curMax); 00109 loadplans.insert(newBucket); 00110 } 00111 } 00112 00113 00114 DECLARE_EXPORT void Resource::writeElement(XMLOutput *o, const Keyword& tag, mode m) const 00115 { 00116 // Write a reference 00117 if (m == REFERENCE) 00118 { 00119 o->writeElement(tag, Tags::tag_name, getName()); 00120 return; 00121 } 00122 00123 // Write the complete object 00124 if (m != NOHEADER) o->BeginObject(tag, Tags::tag_name, getName()); 00125 00126 // Write my fields 00127 HasDescription::writeElement(o, tag); 00128 HasHierarchy<Resource>::writeElement(o, tag); 00129 o->writeElement(Tags::tag_maximum, max_cal); 00130 if (getMaxEarly() != TimePeriod(defaultMaxEarly)) 00131 o->writeElement(Tags::tag_maxearly, getMaxEarly()); 00132 if (getCost() != 0.0) o->writeElement(Tags::tag_cost, getCost()); 00133 o->writeElement(Tags::tag_location, loc); 00134 if (!getSetup().empty()) o->writeElement(Tags::tag_setup, getSetup()); 00135 if (getSetupMatrix()) 00136 o->writeElement(Tags::tag_setupmatrix, getSetupMatrix()); 00137 Plannable::writeElement(o, tag); 00138 00139 // Write extra plan information 00140 loadplanlist::const_iterator i = loadplans.begin(); 00141 if (o->getContentType() == XMLOutput::PLAN && i!=loadplans.end()) 00142 { 00143 o->BeginObject(Tags::tag_loadplans); 00144 for (; i!=loadplans.end(); ++i) 00145 if (i->getType()==1) 00146 { 00147 const LoadPlan *lp = dynamic_cast<const LoadPlan*>(&*i); 00148 o->BeginObject(Tags::tag_loadplan); 00149 o->writeElement(Tags::tag_date, lp->getDate()); 00150 o->writeElement(Tags::tag_quantity, lp->getQuantity()); 00151 o->writeElement(Tags::tag_onhand, lp->getOnhand()); 00152 o->writeElement(Tags::tag_minimum, lp->getMin()); 00153 o->writeElement(Tags::tag_maximum, lp->getMax()); 00154 o->writeElement(Tags::tag_operationplan, &*(lp->getOperationPlan()), FULL); 00155 o->EndObject(Tags::tag_loadplan); 00156 } 00157 o->EndObject(Tags::tag_loadplans); 00158 } 00159 00160 // That was it 00161 o->EndObject(tag); 00162 } 00163 00164 00165 DECLARE_EXPORT void Resource::beginElement(XMLInput& pIn, const Attribute& pAttr) 00166 { 00167 if (pAttr.isA (Tags::tag_load) 00168 && pIn.getParentElement().first.isA(Tags::tag_loads)) 00169 { 00170 Load* l = new Load(); 00171 l->setResource(this); 00172 pIn.readto(&*l); 00173 } 00174 else if (pAttr.isA (Tags::tag_maximum)) 00175 pIn.readto( Calendar::reader(Calendar::metadata,pIn.getAttributes()) ); 00176 else if (pAttr.isA(Tags::tag_loadplans)) 00177 pIn.IgnoreElement(); 00178 else if (pAttr.isA(Tags::tag_location)) 00179 pIn.readto( Location::reader(Location::metadata,pIn.getAttributes()) ); 00180 else if (pAttr.isA(Tags::tag_setupmatrix)) 00181 pIn.readto( SetupMatrix::reader(SetupMatrix::metadata,pIn.getAttributes()) ); 00182 else 00183 HasHierarchy<Resource>::beginElement(pIn, pAttr); 00184 } 00185 00186 00187 DECLARE_EXPORT void Resource::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement) 00188 { 00189 /* Note that while restoring the size, the parent's size is NOT 00190 automatically updated. The getDescription of the 'set_size' function may 00191 suggest this would be the case... */ 00192 if (pAttr.isA (Tags::tag_maximum)) 00193 { 00194 CalendarDouble * c = dynamic_cast<CalendarDouble*>(pIn.getPreviousObject()); 00195 if (c) 00196 setMaximum(c); 00197 else 00198 { 00199 Calendar *c = dynamic_cast<Calendar*>(pIn.getPreviousObject()); 00200 if (!c) 00201 throw LogicException("Incorrect object type during read operation"); 00202 throw DataException("Calendar '" + c->getName() + 00203 "' has invalid type for use as resource max calendar"); 00204 } 00205 } 00206 else if (pAttr.isA (Tags::tag_maxearly)) 00207 setMaxEarly(pElement.getTimeperiod()); 00208 else if (pAttr.isA (Tags::tag_cost)) 00209 setCost(pElement.getDouble()); 00210 else if (pAttr.isA(Tags::tag_location)) 00211 { 00212 Location * d = dynamic_cast<Location*>(pIn.getPreviousObject()); 00213 if (d) setLocation(d); 00214 else throw LogicException("Incorrect object type during read operation"); 00215 } 00216 else if (pAttr.isA (Tags::tag_setup)) 00217 setSetup(pElement.getString()); 00218 else if (pAttr.isA(Tags::tag_setupmatrix)) 00219 { 00220 SetupMatrix * d = dynamic_cast<SetupMatrix*>(pIn.getPreviousObject()); 00221 if (d) setSetupMatrix(d); 00222 else throw LogicException("Incorrect object type during read operation"); 00223 } 00224 else 00225 { 00226 Plannable::endElement(pIn, pAttr, pElement); 00227 HasDescription::endElement(pIn, pAttr, pElement); 00228 HasHierarchy<Resource>::endElement (pIn, pAttr, pElement); 00229 } 00230 } 00231 00232 00233 DECLARE_EXPORT void Resource::deleteOperationPlans(bool deleteLocked) 00234 { 00235 // Delete the operationplans 00236 for (loadlist::iterator i=loads.begin(); i!=loads.end(); ++i) 00237 OperationPlan::deleteOperationPlans(i->getOperation(),deleteLocked); 00238 00239 // Mark to recompute the problems 00240 setChanged(); 00241 } 00242 00243 00244 DECLARE_EXPORT Resource::~Resource() 00245 { 00246 // Delete all operationplans 00247 // An alternative logic would be to delete only the loadplans for this 00248 // resource and leave the rest of the plan untouched. The currently 00249 // implemented method is way more drastic... 00250 deleteOperationPlans(true); 00251 00252 // The Load objects are automatically deleted by the destructor 00253 // of the Association list class. 00254 } 00255 00256 00257 DECLARE_EXPORT void Resource::updateSetups(const LoadPlan* ldplan) 00258 { 00259 // No updating required this resource 00260 if (!getSetupMatrix() || (ldplan && ldplan->getOperationPlan()->getOperation() != OperationSetup::setupoperation)) 00261 return; 00262 00263 // Update later setup opplans 00264 OperationPlan *opplan = ldplan ? ldplan->getOperationPlan() : NULL; 00265 loadplanlist::const_iterator i = ldplan ? 00266 getLoadPlans().begin(ldplan) : 00267 getLoadPlans().begin(); 00268 string prevsetup = ldplan ? ldplan->getSetup() : getSetup(); 00269 Date latestCheckDate = ldplan ? ldplan->getDate() : Date::infiniteFuture; 00270 for (; i != getLoadPlans().end(); ++i) 00271 { 00272 const LoadPlan* l = dynamic_cast<const LoadPlan*>(&*i); 00273 if (l && !l->getLoad()->getSetup().empty() 00274 && l->getOperationPlan()->getOperation() == OperationSetup::setupoperation 00275 && l->getOperationPlan() != opplan 00276 && !l->isStart()) 00277 { 00278 // Next conversion operation 00279 OperationPlanState x = l->getOperationPlan()->getOperation()->setOperationPlanParameters( 00280 l->getOperationPlan(), 00281 l->getOperationPlan()->getQuantity(), 00282 Date::infinitePast, 00283 l->getOperationPlan()->getDates().getEnd(), 00284 true, 00285 false); 00286 if (x.start != l->getOperationPlan()->getDates().getStart()) 00287 // We need to change a setup plan 00288 l->getOperationPlan()->restore(x); 00289 else if (ldplan && x.start == l->getOperationPlan()->getDates().getStart()) 00290 // We found a setup plan that doesn't need updating. Later setup plans 00291 // won't require updating either 00292 return; 00293 } 00294 } 00295 } 00296 00297 00298 DECLARE_EXPORT void ResourceInfinite::writeElement 00299 (XMLOutput *o, const Keyword &tag, mode m) const 00300 { 00301 // Writing a reference 00302 if (m == REFERENCE) 00303 { 00304 o->writeElement 00305 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type); 00306 return; 00307 } 00308 00309 // Write the complete object 00310 if (m != NOHEADER) o->BeginObject 00311 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type); 00312 00313 // Write the fields 00314 Resource::writeElement(o, tag, NOHEADER); 00315 } 00316 00317 00318 DECLARE_EXPORT PyObject* Resource::getattro(const Attribute& attr) 00319 { 00320 if (attr.isA(Tags::tag_name)) 00321 return PythonObject(getName()); 00322 if (attr.isA(Tags::tag_description)) 00323 return PythonObject(getDescription()); 00324 if (attr.isA(Tags::tag_category)) 00325 return PythonObject(getCategory()); 00326 if (attr.isA(Tags::tag_subcategory)) 00327 return PythonObject(getSubCategory()); 00328 if (attr.isA(Tags::tag_owner)) 00329 return PythonObject(getOwner()); 00330 if (attr.isA(Tags::tag_location)) 00331 return PythonObject(getLocation()); 00332 if (attr.isA(Tags::tag_maximum)) 00333 return PythonObject(getMaximum()); 00334 if (attr.isA(Tags::tag_maxearly)) 00335 return PythonObject(getMaxEarly()); 00336 if (attr.isA(Tags::tag_cost)) 00337 return PythonObject(getCost()); 00338 if (attr.isA(Tags::tag_hidden)) 00339 return PythonObject(getHidden()); 00340 if (attr.isA(Tags::tag_loadplans)) 00341 return new LoadPlanIterator(this); 00342 if (attr.isA(Tags::tag_loads)) 00343 return new LoadIterator(this); 00344 if (attr.isA(Tags::tag_setup)) 00345 return PythonObject(getSetup()); 00346 if (attr.isA(Tags::tag_setupmatrix)) 00347 return PythonObject(getSetupMatrix()); 00348 if (attr.isA(Tags::tag_level)) 00349 return PythonObject(getLevel()); 00350 if (attr.isA(Tags::tag_cluster)) 00351 return PythonObject(getCluster()); 00352 return NULL; 00353 } 00354 00355 00356 DECLARE_EXPORT int Resource::setattro(const Attribute& attr, const PythonObject& field) 00357 { 00358 if (attr.isA(Tags::tag_name)) 00359 setName(field.getString()); 00360 else if (attr.isA(Tags::tag_description)) 00361 setDescription(field.getString()); 00362 else if (attr.isA(Tags::tag_category)) 00363 setCategory(field.getString()); 00364 else if (attr.isA(Tags::tag_subcategory)) 00365 setSubCategory(field.getString()); 00366 else if (attr.isA(Tags::tag_owner)) 00367 { 00368 if (!field.check(PythonExtension<Resource>::getType())) 00369 { 00370 PyErr_SetString(PythonDataException, "resource owner must be of type resource"); 00371 return -1; 00372 } 00373 Resource* y = static_cast<Resource*>(static_cast<PyObject*>(field)); 00374 setOwner(y); 00375 } 00376 else if (attr.isA(Tags::tag_location)) 00377 { 00378 if (!field.check(Location::metadata)) 00379 { 00380 PyErr_SetString(PythonDataException, "buffer location must be of type location"); 00381 return -1; 00382 } 00383 Location* y = static_cast<Location*>(static_cast<PyObject*>(field)); 00384 setLocation(y); 00385 } 00386 else if (attr.isA(Tags::tag_maximum)) 00387 { 00388 if (!field.check(CalendarDouble::metadata)) 00389 { 00390 PyErr_SetString(PythonDataException, "resource maximum must be of type calendar_double"); 00391 return -1; 00392 } 00393 CalendarDouble* y = static_cast<CalendarDouble*>(static_cast<PyObject*>(field)); 00394 setMaximum(y); 00395 } 00396 else if (attr.isA(Tags::tag_hidden)) 00397 setHidden(field.getBool()); 00398 else if (attr.isA(Tags::tag_cost)) 00399 setCost(field.getDouble()); 00400 else if (attr.isA(Tags::tag_maxearly)) 00401 setMaxEarly(field.getTimeperiod()); 00402 else if (attr.isA(Tags::tag_setup)) 00403 setSetup(field.getString()); 00404 else if (attr.isA(Tags::tag_setupmatrix)) 00405 { 00406 if (!field.check(SetupMatrix::metadata)) 00407 { 00408 PyErr_SetString(PythonDataException, "resource setup_matrix must be of type setup_matrix"); 00409 return -1; 00410 } 00411 SetupMatrix* y = static_cast<SetupMatrix*>(static_cast<PyObject*>(field)); 00412 setSetupMatrix(y); 00413 } 00414 else 00415 return -1; // Error 00416 return 0; // OK 00417 } 00418 00419 }
Documentation generated for frePPLe by
