flowplan.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2007-2013 by Johan De Taeye, frePPLe bvba *
4  * *
5  * This library is free software; you can redistribute it and/or modify it *
6  * under the terms of the GNU Affero General Public License as published *
7  * by the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This library is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU Affero General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Affero General Public *
16  * License along with this program. *
17  * If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  ***************************************************************************/
20 
21 #define FREPPLE_CORE
22 #include "frepple/model.h"
23 namespace frepple
24 {
25 
27 
28 
30 {
31  // Initialize the metadata
32  metadata = new MetaCategory("flowplan", "flowplans");
33 
34  // Initialize the Python type
36  x.setName("flowplan");
37  x.setDoc("frePPLe flowplan");
38  x.supportgetattro();
39  const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object();
40  return x.typeReady();
41 }
42 
43 
45 {
46  assert(opplan && f);
47  fl = const_cast<Flow*>(f);
48 
49  // Initialize the Python type
51 
52  // Link the flowplan to the operationplan
53  oper = opplan;
54  nextFlowPlan = NULL;
55  if (opplan->firstflowplan)
56  {
57  // Append to the end
58  FlowPlan *c = opplan->firstflowplan;
59  while (c->nextFlowPlan) c = c->nextFlowPlan;
60  c->nextFlowPlan = this;
61  }
62  else
63  // First in the list
64  opplan->firstflowplan = this;
65 
66  // Compute the flowplan quantity
67  fl->getBuffer()->flowplans.insert(
68  this,
69  fl->getFlowplanQuantity(this),
70  fl->getFlowplanDate(this)
71  );
72 
73  // Mark the operation and buffer as having changed. This will trigger the
74  // recomputation of their problems
75  fl->getBuffer()->setChanged();
76  fl->getOperation()->setChanged();
77 }
78 
79 
81 {
82  // Update the timeline data structure
83  fl->getBuffer()->flowplans.update(
84  this,
85  fl->getFlowplanQuantity(this),
86  fl->getFlowplanDate(this)
87  );
88 
89  // Mark the operation and buffer as having changed. This will trigger the
90  // recomputation of their problems
91  fl->getBuffer()->setChanged();
92  fl->getOperation()->setChanged();
93 }
94 
95 
97 {
98  // No change
99  if (newfl == fl) return;
100 
101  // Verify the data
102  if (!newfl) throw LogicException("Can't switch to NULL flow");
103 
104  // Remove from the old buffer, if there is one
105  if (fl)
106  {
107  if (fl->getOperation() != newfl->getOperation())
108  throw LogicException("Only switching to a flow on the same operation is allowed");
109  fl->getBuffer()->flowplans.erase(this);
110  fl->getBuffer()->setChanged();
111  }
112 
113  // Insert in the new buffer
114  fl = newfl;
115  fl->getBuffer()->flowplans.insert(
116  this,
117  fl->getFlowplanQuantity(this),
118  fl->getFlowplanDate(this)
119  );
120  fl->getBuffer()->setChanged();
121  fl->getOperation()->setChanged();
122 }
123 
124 
125 // Remember that this method only superficially looks like a normal
126 // writeElement() method.
128 {
129  o->BeginObject(tag);
135  if (!dynamic_cast<OperationPlan*>(o->getCurrentObject()))
137 
138  // Write pegging info
139  if (o->getContentType() == XMLOutput::PLANDETAIL)
140  {
141  // Write the upstream pegging
142  PeggingIterator k(this, false);
143  if (k) --k;
144  for (; k; --k)
145  {
149  if (!k.getPegged()) o->writeElement(Tags::tag_id, "unpegged");
161  }
162 
163  // Write the downstream pegging
164  PeggingIterator l(this, true);
165  if (l) ++l;
166  for (; l; ++l)
167  {
171  if (!l.getPegged()) o->writeElement(Tags::tag_id, "unpegged");
183  }
184  }
185 
186  o->EndObject(tag);
187 }
188 
189 
190 PyObject* FlowPlan::getattro(const Attribute& attr)
191 {
192  if (attr.isA(Tags::tag_operationplan))
193  return PythonObject(getOperationPlan());
194  if (attr.isA(Tags::tag_quantity))
195  return PythonObject(getQuantity());
196  if (attr.isA(Tags::tag_flow))
197  return PythonObject(getFlow());
198  if (attr.isA(Tags::tag_date))
199  return PythonObject(getDate());
200  if (attr.isA(Tags::tag_onhand))
201  return PythonObject(getOnhand());
202  if (attr.isA(Tags::tag_buffer)) // Convenient shortcut
203  return PythonObject(getFlow()->getBuffer());
204  if (attr.isA(Tags::tag_operation)) // Convenient shortcut
205  return PythonObject(getFlow()->getOperation());
206  return NULL;
207 }
208 
209 
211 {
212  // Initialize the type
214  x.setName("flowplanIterator");
215  x.setDoc("frePPLe iterator for flowplan");
216  x.supportiter();
217  return x.typeReady();
218 }
219 
220 
221 PyObject* FlowPlanIterator::iternext()
222 {
223  FlowPlan* fl;
224  if (buffer_or_opplan)
225  {
226  // Skip uninteresting entries
227  while (*bufiter != buf->getFlowPlans().end() && (*bufiter)->getQuantity()==0.0)
228  ++(*bufiter);
229  if (*bufiter == buf->getFlowPlans().end()) return NULL;
230  fl = const_cast<FlowPlan*>(static_cast<const FlowPlan*>(&*((*bufiter)++)));
231  }
232  else
233  {
234  // Skip uninteresting entries
235  while (*opplaniter != opplan->endFlowPlans() && (*opplaniter)->getQuantity()==0.0)
236  ++(*opplaniter);
237  if (*opplaniter == opplan->endFlowPlans()) return NULL;
238  fl = static_cast<FlowPlan*>(&*((*opplaniter)++));
239  }
240  Py_INCREF(fl);
241  return const_cast<FlowPlan*>(fl);
242 }
243 
244 } // end namespace