flowplan.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   file : $URL: http://svn.code.sf.net/p/frepple/code/trunk/src/model/flowplan.cpp $
00003   version : $LastChangedRevision: 1713 $  $LastChangedBy: jdetaeye $
00004   date : $LastChangedDate: 2012-07-18 11:46:01 +0200 (Wed, 18 Jul 2012) $
00005  ***************************************************************************/
00006 
00007 /***************************************************************************
00008  *                                                                         *
00009  * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba                 *
00010  *                                                                         *
00011  * This library is free software; you can redistribute it and/or modify it *
00012  * under the terms of the GNU Affero General Public License as published   *
00013  * by the Free Software Foundation; either version 3 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            *
00019  * GNU Affero General Public License for more details.                     *
00020  *                                                                         *
00021  * You should have received a copy of the GNU Affero General Public        *
00022  * License along with this program.                                        *
00023  * If not, see <http://www.gnu.org/licenses/>.                             *
00024  *                                                                         *
00025  ***************************************************************************/
00026 
00027 #define FREPPLE_CORE
00028 #include "frepple/model.h"
00029 namespace frepple
00030 {
00031 
00032 DECLARE_EXPORT const MetaCategory* FlowPlan::metadata;
00033 
00034 
00035 int FlowPlan::initialize()
00036 {
00037   // Initialize the metadata
00038   metadata = new MetaCategory("flowplan", "flowplans");
00039 
00040   // Initialize the Python type
00041   PythonType& x = FreppleCategory<FlowPlan>::getType();
00042   x.setName("flowplan");
00043   x.setDoc("frePPLe flowplan");
00044   x.supportgetattro();
00045   const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object();
00046   return x.typeReady();
00047 }
00048 
00049 
00050 DECLARE_EXPORT FlowPlan::FlowPlan (OperationPlan *opplan, const Flow *f)
00051 {
00052   assert(opplan && f);
00053   fl = const_cast<Flow*>(f);
00054 
00055   // Initialize the Python type
00056   initType(metadata);
00057 
00058   // Link the flowplan to the operationplan
00059   oper = opplan;
00060   nextFlowPlan = NULL;
00061   if (opplan->firstflowplan)
00062   {
00063     // Append to the end
00064     FlowPlan *c = opplan->firstflowplan;
00065     while (c->nextFlowPlan) c = c->nextFlowPlan;
00066     c->nextFlowPlan = this;
00067   }
00068   else
00069     // First in the list
00070     opplan->firstflowplan = this;
00071 
00072   // Compute the flowplan quantity
00073   fl->getBuffer()->flowplans.insert(
00074     this,
00075     fl->getFlowplanQuantity(this),
00076     fl->getFlowplanDate(this)
00077   );
00078 
00079   // Mark the operation and buffer as having changed. This will trigger the
00080   // recomputation of their problems
00081   fl->getBuffer()->setChanged();
00082   fl->getOperation()->setChanged();
00083 }
00084 
00085 
00086 DECLARE_EXPORT void FlowPlan::update()
00087 {
00088   // Update the timeline data structure
00089   fl->getBuffer()->flowplans.update(
00090     this,
00091     fl->getFlowplanQuantity(this),
00092     fl->getFlowplanDate(this)
00093   );
00094 
00095   // Mark the operation and buffer as having changed. This will trigger the
00096   // recomputation of their problems
00097   fl->getBuffer()->setChanged();
00098   fl->getOperation()->setChanged();
00099 }
00100 
00101 
00102 DECLARE_EXPORT void FlowPlan::setFlow(const Flow* newfl)
00103 {
00104   // No change
00105   if (newfl == fl) return;
00106 
00107   // Verify the data
00108   if (!newfl) throw LogicException("Can't switch to NULL flow");
00109 
00110   // Remove from the old buffer, if there is one
00111   if (fl)
00112   {
00113     if (fl->getOperation() != newfl->getOperation())
00114       throw LogicException("Only switching to a flow on the same operation is allowed");
00115     fl->getBuffer()->flowplans.erase(this);
00116     fl->getBuffer()->setChanged();
00117   }
00118 
00119   // Insert in the new buffer
00120   fl = newfl;
00121   fl->getBuffer()->flowplans.insert(
00122     this,
00123     fl->getFlowplanQuantity(this),
00124     fl->getFlowplanDate(this)
00125   );
00126   fl->getBuffer()->setChanged();
00127   fl->getOperation()->setChanged();
00128 }
00129 
00130 
00131 // Remember that this method only superficially looks like a normal
00132 // writeElement() method.
00133 DECLARE_EXPORT void FlowPlan::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00134 {
00135   o->BeginObject(tag);
00136   o->writeElement(Tags::tag_date, getDate());
00137   o->writeElement(Tags::tag_quantity, getQuantity());
00138   o->writeElement(Tags::tag_onhand, getOnhand());
00139   o->writeElement(Tags::tag_minimum, getMin());
00140   o->writeElement(Tags::tag_maximum, getMax());
00141   if (!dynamic_cast<OperationPlan*>(o->getCurrentObject()))
00142     o->writeElement(Tags::tag_operationplan, &*getOperationPlan());
00143 
00144   // Write pegging info
00145   if (o->getContentType() == XMLOutput::PLANDETAIL)
00146   {
00147     // Write the upstream pegging
00148     PeggingIterator k(this, false);
00149     if (k) --k;
00150     for (; k; --k)
00151     {
00152       o->BeginObject(Tags::tag_pegging, Tags::tag_level, k.getLevel());
00153       o->writeElement(Tags::tag_quantity, k.getQuantityDemand());
00154       o->writeElement(Tags::tag_factor, k.getFactor());
00155       if (!k.getPegged()) o->writeElement(Tags::tag_id, "unpegged");
00156       o->writeElement(Tags::tag_buffer, Tags::tag_name, k.getBuffer()->getName());
00157       if (k.getConsumingOperationplan())
00158         o->writeElement(Tags::tag_consuming,
00159             Tags::tag_id, k.getConsumingOperationplan()->getIdentifier(),
00160             Tags::tag_operation, k.getConsumingOperationplan()->getOperation()->getName());
00161       if (k.getProducingOperationplan())
00162         o->writeElement(Tags::tag_producing,
00163             Tags::tag_id, k.getProducingOperationplan()->getIdentifier(),
00164             Tags::tag_operation, k.getProducingOperationplan()->getOperation()->getName());
00165       o->writeElement(Tags::tag_dates, DateRange(k.getProducingDate(),k.getConsumingDate()));
00166       o->EndObject(Tags::tag_pegging);
00167     }
00168 
00169     // Write the downstream pegging
00170     PeggingIterator l(this, true);
00171     if (l) ++l;
00172     for (; l; ++l)
00173     {
00174       o->BeginObject(Tags::tag_pegging, Tags::tag_level, l.getLevel());
00175       o->writeElement(Tags::tag_quantity, l.getQuantityDemand());
00176       o->writeElement(Tags::tag_factor, l.getFactor());
00177       if (!l.getPegged()) o->writeElement(Tags::tag_id, "unpegged");
00178       o->writeElement(Tags::tag_buffer, Tags::tag_name, l.getBuffer()->getName());
00179       if (l.getConsumingOperationplan())
00180         o->writeElement(Tags::tag_consuming,
00181             Tags::tag_id, l.getConsumingOperationplan()->getIdentifier(),
00182             Tags::tag_operation, l.getConsumingOperationplan()->getOperation()->getName());
00183       if (l.getProducingOperationplan())
00184         o->writeElement(Tags::tag_producing,
00185             Tags::tag_id, l.getProducingOperationplan()->getIdentifier(),
00186             Tags::tag_operation, l.getProducingOperationplan()->getOperation()->getName());
00187       o->writeElement(Tags::tag_dates, DateRange(l.getProducingDate(),l.getConsumingDate()));
00188       o->EndObject(Tags::tag_pegging);
00189     }
00190   }
00191 
00192   o->EndObject(tag);
00193 }
00194 
00195 
00196 PyObject* FlowPlan::getattro(const Attribute& attr)
00197 {
00198   if (attr.isA(Tags::tag_operationplan))
00199     return PythonObject(getOperationPlan());
00200   if (attr.isA(Tags::tag_quantity))
00201     return PythonObject(getQuantity());
00202   if (attr.isA(Tags::tag_flow))
00203     return PythonObject(getFlow());
00204   if (attr.isA(Tags::tag_date))
00205     return PythonObject(getDate());
00206   if (attr.isA(Tags::tag_onhand))
00207     return PythonObject(getOnhand());
00208   if (attr.isA(Tags::tag_buffer)) // Convenient shortcut
00209     return PythonObject(getFlow()->getBuffer());
00210   if (attr.isA(Tags::tag_operation)) // Convenient shortcut
00211     return PythonObject(getFlow()->getOperation());
00212   return NULL;
00213 }
00214 
00215 
00216 int FlowPlanIterator::initialize()
00217 {
00218   // Initialize the type
00219   PythonType& x = PythonExtension<FlowPlanIterator>::getType();
00220   x.setName("flowplanIterator");
00221   x.setDoc("frePPLe iterator for flowplan");
00222   x.supportiter();
00223   return x.typeReady();
00224 }
00225 
00226 
00227 PyObject* FlowPlanIterator::iternext()
00228 {
00229   FlowPlan* fl;
00230   if (buffer_or_opplan)
00231   {
00232     // Skip uninteresting entries
00233     while (*bufiter != buf->getFlowPlans().end() && (*bufiter)->getQuantity()==0.0)
00234       ++(*bufiter);
00235     if (*bufiter == buf->getFlowPlans().end()) return NULL;
00236     fl = const_cast<FlowPlan*>(static_cast<const FlowPlan*>(&*((*bufiter)++)));
00237   }
00238   else
00239   {
00240     // Skip uninteresting entries
00241     while (*opplaniter != opplan->endFlowPlans() && (*opplaniter)->getQuantity()==0.0)
00242       ++(*opplaniter);
00243     if (*opplaniter == opplan->endFlowPlans()) return NULL;
00244     fl = static_cast<FlowPlan*>(&*((*opplaniter)++));
00245   }
00246   Py_INCREF(fl);
00247   return const_cast<FlowPlan*>(fl);
00248 }
00249 
00250 } // end namespace

Documentation generated for frePPLe by  doxygen