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