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 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029 namespace frepple
00030 {
00031
00032
00033 DECLARE_EXPORT void Load::validate(Action action)
00034 {
00035
00036 Operation *oper = getOperation();
00037 Resource *res = getResource();
00038 if (!oper || !res)
00039 {
00040
00041 delete this;
00042 if (!oper && !res)
00043 throw DataException("Missing operation and resource on a load");
00044 else if (!oper)
00045 throw DataException("Missing operation on a load on resource '"
00046 + res->getName() + "'");
00047 else if (!res)
00048 throw DataException("Missing resource on a load on operation '"
00049 + oper->getName() + "'");
00050 }
00051
00052
00053
00054 Operation::loadlist::const_iterator i = oper->getLoads().begin();
00055 for (;i != oper->getLoads().end(); ++i)
00056 if (i->getResource() == res
00057 && i->getEffective().overlap(getEffective())
00058 && &*i != this)
00059 break;
00060
00061
00062 switch (action)
00063 {
00064 case ADD:
00065 if (i != oper->getLoads().end())
00066 {
00067 delete this;
00068 throw DataException("Load of '" + oper->getName() + "' and '"
00069 + res->getName() + "' already exists");
00070 }
00071 break;
00072 case CHANGE:
00073 delete this;
00074 throw DataException("Can't update a load");
00075 case ADD_CHANGE:
00076
00077 if (i == oper->getLoads().end()) break;
00078 delete this;
00079 throw DataException("Can't update a load");
00080 case REMOVE:
00081
00082 delete this;
00083 if (i == oper->getLoads().end())
00084
00085 throw DataException("Can't remove nonexistent load of '"
00086 + oper->getName() + "' and '" + res->getName() + "'");
00087 delete &*i;
00088
00089 HasLevel::triggerLazyRecomputation();
00090 return;
00091 }
00092
00093
00094
00095
00096
00097 if (res->hasOwner() && action!=REMOVE) new Load(oper, res->getOwner(), qty);
00098
00099
00100 HasLevel::triggerLazyRecomputation();
00101 }
00102
00103
00104 DECLARE_EXPORT Load::~Load()
00105 {
00106
00107 HasLevel::triggerLazyRecomputation();
00108
00109
00110 if (getOperation() && getResource())
00111 {
00112
00113 for(OperationPlan::iterator i(getOperation()); i != OperationPlan::end(); ++i)
00114
00115 for(OperationPlan::LoadPlanIterator j = i->beginLoadPlans(); j != i->endLoadPlans(); )
00116 if (j->getLoad() == this) j.deleteLoadPlan();
00117 else ++j;
00118 }
00119
00120
00121 if (getOperation()) getOperation()->loaddata.erase(this);
00122 if (getResource()) getResource()->loads.erase(this);
00123 }
00124
00125
00126 DECLARE_EXPORT void Load::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00127 {
00128
00129
00130 if (m == REFERENCE) return;
00131 assert(m != NOHEADER);
00132
00133 o->BeginObject(tag);
00134
00135
00136
00137 if (!dynamic_cast<Operation*>(o->getPreviousObject()))
00138 o->writeElement(Tags::tag_operation, getOperation());
00139
00140
00141
00142 if (!dynamic_cast<Resource*>(o->getPreviousObject()))
00143 o->writeElement(Tags::tag_resource, getResource());
00144
00145
00146 if (qty != 1.0) o->writeElement(Tags::tag_quantity, qty);
00147
00148
00149 if (getEffective().getStart() != Date::infinitePast)
00150 o->writeElement(Tags::tag_effective_start, getEffective().getStart());
00151 if (getEffective().getEnd() != Date::infiniteFuture)
00152 o->writeElement(Tags::tag_effective_end, getEffective().getEnd());
00153
00154 o->EndObject(tag);
00155 }
00156
00157
00158 DECLARE_EXPORT void Load::beginElement (XMLInput& pIn, const Attribute& pAttr)
00159 {
00160 if (pAttr.isA (Tags::tag_resource))
00161 pIn.readto( Resource::reader(Resource::metadata,pIn.getAttributes()) );
00162 else if (pAttr.isA (Tags::tag_operation))
00163 pIn.readto( Operation::reader(Operation::metadata,pIn.getAttributes()) );
00164 }
00165
00166
00167 DECLARE_EXPORT void Load::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00168 {
00169 if (pAttr.isA (Tags::tag_resource))
00170 {
00171 Resource * r = dynamic_cast<Resource*>(pIn.getPreviousObject());
00172 if (r) setResource(r);
00173 else throw LogicException("Incorrect object type during read operation");
00174 }
00175 else if (pAttr.isA (Tags::tag_operation))
00176 {
00177 Operation * o = dynamic_cast<Operation*>(pIn.getPreviousObject());
00178 if (o) setOperation(o);
00179 else throw LogicException("Incorrect object type during read operation");
00180 }
00181 else if (pAttr.isA(Tags::tag_quantity))
00182 setQuantity(pElement.getDouble());
00183 else if (pAttr.isA(Tags::tag_action))
00184 {
00185 delete static_cast<Action*>(pIn.getUserArea());
00186 pIn.setUserArea(
00187 new Action(MetaClass::decodeAction(pElement.getString().c_str()))
00188 );
00189 }
00190 else if (pAttr.isA(Tags::tag_effective_end))
00191 setEffectiveEnd(pElement.getDate());
00192 else if (pAttr.isA(Tags::tag_effective_start))
00193 setEffectiveStart(pElement.getDate());
00194 else if (pIn.isObjectEnd())
00195 {
00196
00197 validate(!pIn.getUserArea() ?
00198 ADD_CHANGE :
00199 *static_cast<Action*>(pIn.getUserArea())
00200 );
00201 delete static_cast<Action*>(pIn.getUserArea());
00202 }
00203 }
00204
00205
00206 int PythonLoad::initialize(PyObject* m)
00207 {
00208
00209 PythonType& x = getType();
00210 x.setName("load");
00211 x.setDoc("frePPLe load");
00212 x.supportgetattro();
00213 x.supportsetattro();
00214 x.supportcreate(create);
00215 x.addMethod("toXML", toXML, METH_VARARGS, "return a XML representation");
00216 const_cast<MetaCategory*>(Load::metadata)->factoryPythonProxy = proxy;
00217 return x.typeReady(m);
00218 }
00219
00220
00221 DECLARE_EXPORT PyObject* PythonLoad::getattro(const Attribute& attr)
00222 {
00223 if (!obj) return Py_BuildValue("");
00224 if (attr.isA(Tags::tag_resource))
00225 return PythonObject(obj->getResource());
00226 if (attr.isA(Tags::tag_operation))
00227 return PythonObject(obj->getOperation());
00228 if (attr.isA(Tags::tag_quantity))
00229 return PythonObject(obj->getQuantity());
00230 if (attr.isA(Tags::tag_effective_end))
00231 return PythonObject(obj->getEffective().getEnd());
00232 if (attr.isA(Tags::tag_effective_start))
00233 return PythonObject(obj->getEffective().getStart());
00234 return NULL;
00235 }
00236
00237
00238 DECLARE_EXPORT int PythonLoad::setattro(const Attribute& attr, const PythonObject& field)
00239 {
00240 if (attr.isA(Tags::tag_resource))
00241 {
00242 if (!field.check(PythonResource::getType()))
00243 {
00244 PyErr_SetString(PythonDataException, "load resource must be of type resource");
00245 return -1;
00246 }
00247 Resource* y = static_cast<PythonResource*>(static_cast<PyObject*>(field))->obj;
00248 obj->setResource(y);
00249 }
00250 else if (attr.isA(Tags::tag_operation))
00251 {
00252 if (!field.check(PythonOperation::getType()))
00253 {
00254 PyErr_SetString(PythonDataException, "load operation must be of type operation");
00255 return -1;
00256 }
00257 Operation* y = static_cast<PythonOperation*>(static_cast<PyObject*>(field))->obj;
00258 obj->setOperation(y);
00259 }
00260 else if (attr.isA(Tags::tag_quantity))
00261 obj->setQuantity(field.getDouble());
00262 else if (attr.isA(Tags::tag_effective_end))
00263 obj->setEffectiveEnd(field.getDate());
00264 else if (attr.isA(Tags::tag_effective_start))
00265 obj->setEffectiveStart(field.getDate());
00266 else
00267 return -1;
00268 return 0;
00269 }
00270
00271
00272
00273 PyObject* PythonLoad::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds)
00274 {
00275 try
00276 {
00277
00278 PyObject* oper = PyDict_GetItemString(kwds,"operation");
00279 if (!PyObject_TypeCheck(oper, PythonOperation::getType().type_object()))
00280 throw DataException("load operation must be of type operation");
00281
00282
00283 PyObject* res = PyDict_GetItemString(kwds,"resource");
00284 if (!PyObject_TypeCheck(res, PythonResource::getType().type_object()))
00285 throw DataException("load resource must be of type resource");
00286
00287
00288 PyObject* q1 = PyDict_GetItemString(kwds,"quantity");
00289 double q2 = q1 ? PythonObject(q1).getDouble() : 1.0;
00290
00291
00292 Load *l = new Load(
00293 static_cast<PythonOperation*>(oper)->obj,
00294 static_cast<PythonResource*>(res)->obj,
00295 q2
00296 );
00297
00298
00299 PyObject* eff_start = PyDict_GetItemString(kwds,"effective_start");
00300 if (eff_start)
00301 {
00302 PythonObject d(eff_start);
00303 l->setEffectiveStart(d.getDate());
00304 }
00305
00306
00307 PyObject* eff_end = PyDict_GetItemString(kwds,"effective_end");
00308 if (eff_end)
00309 {
00310 PythonObject d(eff_end);
00311 l->setEffectiveEnd(d.getDate());
00312 }
00313
00314
00315 return static_cast<PyObject*>(*(new PythonObject(l)));
00316 }
00317 catch (...)
00318 {
00319 PythonType::evalException();
00320 return NULL;
00321 }
00322 }
00323
00324
00325 int PythonLoadIterator::initialize(PyObject* m)
00326 {
00327
00328 PythonType& x = PythonExtension<PythonLoadIterator>::getType();
00329 x.setName("loadIterator");
00330 x.setDoc("frePPLe iterator for loads");
00331 x.supportiter();
00332 return x.typeReady(m);
00333 }
00334
00335
00336 PyObject* PythonLoadIterator::iternext()
00337 {
00338 if (res)
00339 {
00340
00341 if (ir == res->getLoads().end()) return NULL;
00342 return PythonObject(const_cast<Load*>(&*(ir++)));
00343 }
00344 else
00345 {
00346
00347 if (io == oper->getLoads().end()) return NULL;
00348 return PythonObject(const_cast<Load*>(&*(io++)));
00349 }
00350 }
00351
00352 }