DECLARE_EXPORT void Flow::validate(Action action) { // Catch null operation and buffer pointers Operation* oper = getOperation(); Buffer* buf = getBuffer(); if (!oper || !buf) { // This flow is not a valid one since it misses essential information if (!oper && !buf) throw DataException("Missing operation and buffer on a flow"); else if (!oper) throw DataException("Missing operation on a flow with buffer '" + buf->getName() + "'"); else throw DataException("Missing buffer on a flow with operation '" + oper->getName() + "'"); } // Check if a flow with 1) identical buffer, 2) identical operation and // 3) overlapping effectivity dates already exists, and 4) same // flow type. Operation::flowlist::const_iterator i = oper->getFlows().begin(); for (; i != oper->getFlows().end(); ++i) if (i->getBuffer() == buf && i->getEffective().overlap(getEffective()) && i->getType() == getType() && &*i != this) break; // Apply the appropriate action switch (action) { case ADD: if (i != oper->getFlows().end()) throw DataException("Flow of '" + oper->getName() + "' and '" + buf->getName() + "' already exists"); break; case CHANGE: throw DataException("Can't update a flow"); case ADD_CHANGE: // ADD is handled in the code after the switch statement if (i == oper->getFlows().end()) break; throw DataException("Can't update a flow between '" + oper->getName() + "' and '" + buf->getName() + "')"); case REMOVE: // Delete the temporary flow object delete this; // Nothing to delete if (i == oper->getFlows().end()) throw DataException("Can't remove nonexistent flow of '" + oper->getName() + "' and '" + buf->getName() + "'"); // Delete delete &*i; } // Set a flag to make sure the level computation is triggered again HasLevel::triggerLazyRecomputation(); }
Object* Flow::finder(const DataValueDict& d) { // Check operation const DataValue* tmp = d.get(Tags::operation); if (!tmp) return nullptr; Operation* oper = static_cast<Operation*>(tmp->getObject()); // Check buffer field tmp = d.get(Tags::buffer); if (!tmp) return nullptr; Buffer* buf = static_cast<Buffer*>(tmp->getObject()); // Walk over all flows of the operation, and return // the first one with matching const DataValue* hasEffectiveStart = d.get(Tags::effective_start); Date effective_start; if (hasEffectiveStart) effective_start = hasEffectiveStart->getDate(); const DataValue* hasEffectiveEnd = d.get(Tags::effective_end); Date effective_end; if (hasEffectiveEnd) effective_end = hasEffectiveEnd->getDate(); const DataValue* hasPriority = d.get(Tags::priority); int priority = 1; if (hasPriority) priority = hasPriority->getInt(); const DataValue* hasName = d.get(Tags::name); string name; if (hasName) name = hasName->getString(); for (Operation::flowlist::const_iterator fl = oper->getFlows().begin(); fl != oper->getFlows().end(); ++fl) { if (fl->getBuffer() != buf) continue; if (hasEffectiveStart && fl->getEffectiveStart() != effective_start) continue; if (hasEffectiveEnd && fl->getEffectiveEnd() != effective_end) continue; if (hasPriority && fl->getPriority() != priority) continue; if (hasName && fl->getName() != name) continue; return const_cast<Flow*>(&*fl); } return nullptr; }
DECLARE_EXPORT void Buffer::setOnHand(double f) { // The dummy operation to model the inventory may need to be created Operation *o = Operation::find(INVENTORY_OPERATION); Flow *fl; if (!o) { // Create a fixed time operation with zero leadtime, hidden from the xml // output, hidden for the solver, and without problem detection. o = new OperationFixedTime(); o->setName(INVENTORY_OPERATION); o->setHidden(true); o->setDetectProblems(false); fl = new FlowEnd(o, this, 1); } else // Find the flow of this operation fl = const_cast<Flow*>(&*(o->getFlows().begin())); // Check valid pointers if (!fl || !o) throw LogicException("Failed creating inventory operation for '" + getName() + "'"); // Make sure the sign of the flow is correct: +1 or -1. fl->setQuantity(f>=0.0 ? 1.0 : -1.0); // Create a dummy operationplan on the inventory operation OperationPlan::iterator i(o); if (i == OperationPlan::end()) { // No operationplan exists yet OperationPlan *opplan = o->createOperationPlan( fabs(f), Date::infinitePast, Date::infinitePast); opplan->setLocked(true); opplan->activate(); } else { // Update the existing operationplan i->setLocked(false); i->setQuantity(fabs(f)); i->setLocked(true); } setChanged(); }