resource.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.8.0/src/model/resource.cpp $
00003   version : $LastChangedRevision: 1176 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2010-02-14 22:27:13 +0100 (Sun, 14 Feb 2010) $
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., 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 }

Generated on 21 Mar 2010 for frePPLe by  doxygen 1.6.1