00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define FREPPLE_CORE
00029 #include "frepple/model.h"
00030
00031 namespace frepple
00032 {
00033
00034 template<class Demand> DECLARE_EXPORT Tree utils::HasName<Demand>::st;
00035 DECLARE_EXPORT const MetaCategory* Demand::metadata;
00036 DECLARE_EXPORT const MetaClass* DemandDefault::metadata;
00037
00038
00039 int Demand::initialize()
00040 {
00041
00042 metadata = new MetaCategory("demand", "demands", reader, writer);
00043
00044
00045 return FreppleCategory<Demand>::initialize();
00046 }
00047
00048
00049 int DemandDefault::initialize()
00050 {
00051
00052 DemandDefault::metadata = new MetaClass(
00053 "demand",
00054 "demand_default",
00055 Object::createString<DemandDefault>, true);
00056
00057
00058 return FreppleClass<DemandDefault,Demand>::initialize();
00059 }
00060
00061
00062 DECLARE_EXPORT void Demand::setQuantity(double f)
00063 {
00064
00065 double delta(f - qty);
00066 if (f < 0.0 || fabs(delta)<ROUNDING_ERROR) return;
00067
00068
00069 qty = f;
00070 setChanged();
00071 }
00072
00073
00074 DECLARE_EXPORT void Demand::deleteOperationPlans
00075 (bool deleteLocked, CommandList* cmds)
00076 {
00077
00078
00079
00080 while (true)
00081 {
00082
00083 OperationPlan *candidate = NULL;
00084 for (OperationPlan_list::iterator i = deli.begin(); i!=deli.end(); ++i)
00085 if (deleteLocked || !(*i)->getLocked())
00086 {
00087 candidate = *i;
00088 break;
00089 }
00090 if (!candidate) break;
00091 if (cmds)
00092
00093 cmds->add(new CommandDeleteOperationPlan(candidate));
00094 else
00095
00096 delete candidate;
00097 }
00098
00099
00100 setChanged();
00101 }
00102
00103
00104 DECLARE_EXPORT void Demand::removeDelivery(OperationPlan * o)
00105 {
00106
00107 if (!o) return;
00108
00109
00110 if (o->dmd != this)
00111 throw LogicException("Delivery operationplan incorrectly registered");
00112
00113
00114 o->dmd = NULL;
00115 o->setDemand(NULL);
00116
00117
00118 OperationPlan_list::iterator j = deli.begin();
00119 while (j!=deli.end() && *j!=o) ++j;
00120
00121
00122
00123
00124 if (j!=deli.end())
00125 {
00126
00127 deli.erase(j);
00128
00129 setChanged();
00130 }
00131 }
00132
00133
00134 DECLARE_EXPORT const Demand::OperationPlan_list& Demand::getDelivery() const
00135 {
00136
00137
00138
00139
00140
00141 for (bool swapped(!deli.empty()); swapped; swapped=false)
00142 {
00143 OperationPlan_list::iterator j = const_cast<Demand*>(this)->deli.begin();
00144 ++j;
00145 for (OperationPlan_list::iterator i =
00146 const_cast<Demand*>(this)->deli.begin();
00147 j!=const_cast<Demand*>(this)->deli.end(); ++j)
00148 {
00149 if ((*i)->getDates().getEnd() < (*j)->getDates().getEnd())
00150 {
00151
00152 iter_swap(i,j);
00153
00154
00155 swapped = true;
00156 break;
00157 }
00158 ++i;
00159 }
00160 }
00161
00162 return deli;
00163 }
00164
00165
00166 DECLARE_EXPORT OperationPlan* Demand::getLatestDelivery() const
00167 {
00168 const Demand::OperationPlan_list& l = getDelivery();
00169 return l.empty() ? NULL : *(l.begin());
00170 }
00171
00172
00173 DECLARE_EXPORT OperationPlan* Demand::getEarliestDelivery() const
00174 {
00175 const Demand::OperationPlan_list& l = getDelivery();
00176 OperationPlan *last = NULL;
00177 for (Demand::OperationPlan_list::const_iterator i = l.begin(); i!=l.end(); ++i)
00178 last = *i;
00179 return last;
00180 }
00181
00182
00183 DECLARE_EXPORT void Demand::addDelivery (OperationPlan * o)
00184 {
00185
00186 if (!o) return;
00187
00188
00189
00190
00191 for (OperationPlan_list::iterator i = deli.begin(); i!=deli.end(); ++i)
00192 if (*i == o) return;
00193
00194
00195
00196
00197
00198
00199
00200 getDelivery();
00201 OperationPlan_list::iterator j = deli.begin();
00202 while (j!=deli.end() && (*j)->getDates().getEnd()>o->getDates().getEnd()) ++j;
00203 deli.insert(j, o);
00204
00205
00206 setChanged();
00207
00208
00209 o->setDemand(this);
00210
00211
00212 Operation* tmpOper = getDeliveryOperation();
00213 if (tmpOper && tmpOper != o->getOperation())
00214 logger << "Warning: Delivery Operation '" << o->getOperation()
00215 << "' different than expected '" << tmpOper
00216 << "' for demand '" << this << "'" << endl;
00217 }
00218
00219
00220 DECLARE_EXPORT Operation* Demand::getDeliveryOperation() const
00221 {
00222
00223 if (oper) return oper;
00224
00225 if (it) return it->getOperation();
00226
00227 return NULL;
00228 }
00229
00230
00231 DECLARE_EXPORT double Demand::getPlannedQuantity() const
00232 {
00233 double delivered(0.0);
00234 for (OperationPlan_list::const_iterator i=deli.begin(); i!=deli.end(); ++i)
00235 delivered += (*i)->getQuantity();
00236 return delivered;
00237 }
00238
00239
00240 DECLARE_EXPORT void Demand::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00241 {
00242
00243 if (m == REFERENCE)
00244 {
00245 o->writeElement(tag, Tags::tag_name, getName());
00246 return;
00247 }
00248
00249
00250 if (m != NOHEADER) o->BeginObject(tag, Tags::tag_name, getName());
00251
00252
00253 HasDescription::writeElement(o, tag);
00254 HasHierarchy<Demand>::writeElement(o, tag);
00255 o->writeElement(Tags::tag_operation, oper);
00256 o->writeElement(Tags::tag_customer, cust);
00257 Plannable::writeElement(o, tag);
00258
00259 o->writeElement(Tags::tag_quantity, qty);
00260 o->writeElement(Tags::tag_item, it);
00261 o->writeElement(Tags::tag_due, dueDate);
00262 if (getPriority()) o->writeElement(Tags::tag_priority, getPriority());
00263 if (getMaxLateness() != TimePeriod::MAX)
00264 o->writeElement(Tags::tag_maxlateness, getMaxLateness());
00265 if (getMinShipment())
00266 o->writeElement(Tags::tag_minshipment, getMinShipment());
00267
00268
00269 if ((o->getContentType() == XMLOutput::PLAN
00270 || o->getContentType() == XMLOutput::PLANDETAIL) && !deli.empty())
00271 {
00272 o->BeginObject(Tags::tag_operationplans);
00273 for (OperationPlan_list::const_iterator i=deli.begin(); i!=deli.end(); ++i)
00274 o->writeElement(Tags::tag_operationplan, *i, FULL);
00275 o->EndObject(Tags::tag_operationplans);
00276 }
00277 o->EndObject(tag);
00278 }
00279
00280
00281 DECLARE_EXPORT void Demand::beginElement(XMLInput& pIn, const Attribute& pAttr)
00282 {
00283 if (pAttr.isA (Tags::tag_item))
00284 pIn.readto( Item::reader(Item::metadata,pIn.getAttributes()) );
00285 else if (pAttr.isA (Tags::tag_operation))
00286 pIn.readto( Operation::reader(Operation::metadata,pIn.getAttributes()) );
00287 else if (pAttr.isA (Tags::tag_customer))
00288 pIn.readto( Customer::reader(Customer::metadata,pIn.getAttributes()) );
00289 else if (pAttr.isA(Tags::tag_operationplan))
00290 pIn.readto(OperationPlan::createOperationPlan(OperationPlan::metadata,pIn.getAttributes()));
00291 else
00292 HasHierarchy<Demand>::beginElement(pIn, pAttr);
00293 }
00294
00295
00296 DECLARE_EXPORT void Demand::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00297 {
00298 if (pAttr.isA (Tags::tag_quantity))
00299 setQuantity (pElement.getDouble());
00300 else if (pAttr.isA (Tags::tag_priority))
00301 setPriority (pElement.getInt());
00302 else if (pAttr.isA (Tags::tag_due))
00303 setDue(pElement.getDate());
00304 else if (pAttr.isA (Tags::tag_operation))
00305 {
00306 Operation *o = dynamic_cast<Operation*>(pIn.getPreviousObject());
00307 if (o) setOperation(o);
00308 else throw LogicException("Incorrect object type during read operation");
00309 }
00310 else if (pAttr.isA (Tags::tag_customer))
00311 {
00312 Customer *c = dynamic_cast<Customer*>(pIn.getPreviousObject());
00313 if (c) setCustomer(c);
00314 else throw LogicException("Incorrect object type during read operation");
00315 }
00316 else if (pAttr.isA (Tags::tag_item))
00317 {
00318 Item *i = dynamic_cast<Item*>(pIn.getPreviousObject());
00319 if (i) setItem(i);
00320 else throw LogicException("Incorrect object type during read operation");
00321 }
00322 else if (pAttr.isA (Tags::tag_maxlateness))
00323 setMaxLateness(pElement.getTimeperiod());
00324 else if (pAttr.isA (Tags::tag_minshipment))
00325 setMinShipment(pElement.getDouble());
00326 else if (pAttr.isA(Tags::tag_operationplan))
00327 {
00328 OperationPlan* opplan
00329 = dynamic_cast<OperationPlan*>(pIn.getPreviousObject());
00330 if (opplan) addDelivery(opplan);
00331 else throw LogicException("Incorrect object type during read operation");
00332 }
00333 else
00334 {
00335 Plannable::endElement(pIn, pAttr, pElement);
00336 HasDescription::endElement(pIn, pAttr, pElement);
00337 HasHierarchy<Demand>::endElement (pIn, pAttr, pElement);
00338 }
00339 }
00340
00341
00342 DECLARE_EXPORT PyObject* Demand::getattro(const Attribute& attr)
00343 {
00344 if (attr.isA(Tags::tag_name))
00345 return PythonObject(getName());
00346 if (attr.isA(Tags::tag_quantity))
00347 return PythonObject(getQuantity());
00348 if (attr.isA(Tags::tag_due))
00349 return PythonObject(getDue());
00350 if (attr.isA(Tags::tag_priority))
00351 return PythonObject(getPriority());
00352 if (attr.isA(Tags::tag_owner))
00353 return PythonObject(getOwner());
00354 if (attr.isA(Tags::tag_item))
00355 return PythonObject(getItem());
00356 if (attr.isA(Tags::tag_customer))
00357 return PythonObject(getCustomer());
00358 if (attr.isA(Tags::tag_operation))
00359 return PythonObject(getOperation());
00360 if (attr.isA(Tags::tag_description))
00361 return PythonObject(getDescription());
00362 if (attr.isA(Tags::tag_category))
00363 return PythonObject(getCategory());
00364 if (attr.isA(Tags::tag_subcategory))
00365 return PythonObject(getSubCategory());
00366 if (attr.isA(Tags::tag_minshipment))
00367 return PythonObject(getMinShipment());
00368 if (attr.isA(Tags::tag_maxlateness))
00369 return PythonObject(getMaxLateness());
00370 if (attr.isA(Tags::tag_hidden))
00371 return PythonObject(getHidden());
00372 if (attr.isA(Tags::tag_operationplans))
00373 return new DemandPlanIterator(this);
00374 if (attr.isA(Tags::tag_pegging))
00375 return new PeggingIterator(this);
00376 return NULL;
00377 }
00378
00379
00380 DECLARE_EXPORT int Demand::setattro(const Attribute& attr, const PythonObject& field)
00381 {
00382 if (attr.isA(Tags::tag_name))
00383 setName(field.getString());
00384 else if (attr.isA(Tags::tag_priority))
00385 setPriority(field.getInt());
00386 else if (attr.isA(Tags::tag_quantity))
00387 setQuantity(field.getDouble());
00388 else if (attr.isA(Tags::tag_due))
00389 setDue(field.getDate());
00390 else if (attr.isA(Tags::tag_item))
00391 {
00392 if (!field.check(Item::metadata))
00393 {
00394 PyErr_SetString(PythonDataException, "demand item must be of type item");
00395 return -1;
00396 }
00397 Item* y = static_cast<Item*>(static_cast<PyObject*>(field));
00398 setItem(y);
00399 }
00400 else if (attr.isA(Tags::tag_customer))
00401 {
00402 if (!field.check(Customer::metadata))
00403 {
00404 PyErr_SetString(PythonDataException, "demand customer must be of type customer");
00405 return -1;
00406 }
00407 Customer* y = static_cast<Customer*>(static_cast<PyObject*>(field));
00408 setCustomer(y);
00409 }
00410 else if (attr.isA(Tags::tag_description))
00411 setDescription(field.getString());
00412 else if (attr.isA(Tags::tag_category))
00413 setCategory(field.getString());
00414 else if (attr.isA(Tags::tag_subcategory))
00415 setSubCategory(field.getString());
00416 else if (attr.isA(Tags::tag_minshipment))
00417 setMinShipment(field.getDouble());
00418 else if (attr.isA(Tags::tag_maxlateness))
00419 setMaxLateness(field.getTimeperiod());
00420 else if (attr.isA(Tags::tag_owner))
00421 {
00422 if (!field.check(Demand::metadata))
00423 {
00424 PyErr_SetString(PythonDataException, "demand owner must be of type demand");
00425 return -1;
00426 }
00427 Demand* y = static_cast<Demand*>(static_cast<PyObject*>(field));
00428 setOwner(y);
00429 }
00430 else if (attr.isA(Tags::tag_operation))
00431 {
00432 if (!field.check(Operation::metadata))
00433 {
00434 PyErr_SetString(PythonDataException, "demand operation must be of type operation");
00435 return -1;
00436 }
00437 Operation* y = static_cast<Operation*>(static_cast<PyObject*>(field));
00438 setOperation(y);
00439 }
00440 else if (attr.isA(Tags::tag_hidden))
00441 setHidden(field.getBool());
00442 else
00443 return -1;
00444 return 0;
00445 }
00446
00447
00448 int DemandPlanIterator::initialize()
00449 {
00450
00451 PythonType& x = PythonExtension<DemandPlanIterator>::getType();
00452 x.setName("demandplanIterator");
00453 x.setDoc("frePPLe iterator for demand delivery operationplans");
00454 x.supportiter();
00455 return x.typeReady();
00456 }
00457
00458
00459 PyObject* DemandPlanIterator::iternext()
00460 {
00461 if (i == dem->getDelivery().end()) return NULL;
00462 PyObject* result = const_cast<OperationPlan*>(&**(i++));
00463 Py_INCREF(result);
00464 return result;
00465 }
00466
00467 }