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