flow.cpp
Go to the documentation of this file.00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/flow.cpp $ 00003 version : $LastChangedRevision: 746 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2008-04-19 11:23:51 +0200 (Sat, 19 Apr 2008) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007 by Johan De Taeye * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * 00024 * * 00025 ***************************************************************************/ 00026 00027 00028 #define FREPPLE_CORE 00029 #include "frepple/model.h" 00030 namespace frepple 00031 { 00032 00033 00034 DECLARE_EXPORT void Flow::validate(Action action) 00035 { 00036 // Catch null operation and buffer pointers 00037 Operation* oper = getOperation(); 00038 Buffer* buf = getBuffer(); 00039 if (!oper || !buf) 00040 { 00041 // This flow is not a valid one since it misses essential information 00042 delete this; 00043 if (!oper && !buf) 00044 throw DataException("Missing operation and buffer on a flow"); 00045 else if (!oper) 00046 throw DataException("Missing operation on a flow with buffer '" 00047 + buf->getName() + "'"); 00048 else 00049 throw DataException("Missing buffer on a flow with operation '" 00050 + oper->getName() + "'"); 00051 } 00052 00053 // Check if a flow with 1) identical buffer, 2) identical operation and 00054 // 3) overlapping effectivity dates already exists 00055 Operation::flowlist::const_iterator i = oper->getFlows().begin(); 00056 for (; i != oper->getFlows().end(); ++i) 00057 if (i->getBuffer() == buf 00058 && i->getEffective().overlap(getEffective()) 00059 && &*i != this) 00060 break; 00061 00062 // Apply the appropriate action 00063 switch (action) 00064 { 00065 case ADD: 00066 if (i != oper->getFlows().end()) 00067 { 00068 delete this; 00069 throw DataException("Flow of '" + oper->getName() + "' and '" + 00070 buf->getName() + "' already exists."); 00071 } 00072 break; 00073 case CHANGE: 00074 delete this; 00075 throw DataException("Can't update a flow"); 00076 case ADD_CHANGE: 00077 // ADD is handled in the code after the switch statement 00078 if (i == oper->getFlows().end()) break; 00079 delete this; 00080 throw DataException("Can't update a flow"); 00081 case REMOVE: 00082 // Delete the temporary flow object 00083 delete this; 00084 // Nothing to delete 00085 if (i == oper->getFlows().end()) 00086 throw DataException("Can't remove nonexistent flow of '" 00087 + oper->getName() + "' and '" + buf->getName() + "'"); 00088 // Delete 00089 delete &*i; 00090 } 00091 00092 // Attach to buffers higher up in the hierarchy 00093 // Note that the owner can create more loads if it has an owner too. 00094 if (buf->hasOwner() && action!=REMOVE) new Flow(oper, buf->getOwner(), quantity); 00095 00096 // Set a flag to make sure the level computation is triggered again 00097 HasLevel::triggerLazyRecomputation(); 00098 } 00099 00100 00101 DECLARE_EXPORT Flow::~Flow() 00102 { 00103 // Set a flag to make sure the level computation is triggered again 00104 HasLevel::triggerLazyRecomputation(); 00105 00106 // Delete existing flowplans 00107 if (getOperation() && getBuffer()) 00108 { 00109 // Loop over operationplans 00110 for(OperationPlan::iterator i(getOperation()); i != OperationPlan::end(); ++i) 00111 // Loop over flowplans 00112 for(OperationPlan::FlowPlanIterator j = i->beginFlowPlans(); j != i->endFlowPlans(); ) 00113 if (j->getFlow() == this) j.deleteFlowPlan(); 00114 else ++j; 00115 } 00116 00117 // Delete the flow from the operation and the buffer 00118 if (getOperation()) getOperation()->flowdata.erase(this); 00119 if (getBuffer()) getBuffer()->flows.erase(this); 00120 } 00121 00122 00123 DECLARE_EXPORT void Flow::writeElement (XMLOutput *o, const Keyword& tag, mode m) const 00124 { 00125 // If the flow has already been saved, no need to repeat it again 00126 // A 'reference' to a flow is not useful to be saved. 00127 if (m == REFERENCE) return; 00128 assert(m != NOHEADER); 00129 00130 // Write the header 00131 o->BeginObject(tag, Tags::tag_type, getType().type); 00132 00133 // If the flow is defined inside of an operation tag, we don't need to save 00134 // the operation. Otherwise we do save it... 00135 if (!dynamic_cast<Operation*>(o->getPreviousObject())) 00136 o->writeElement(Tags::tag_operation, getOperation()); 00137 00138 // If the flow is defined inside of an buffer tag, we don't need to save 00139 // the buffer. Otherwise we do save it... 00140 if (!dynamic_cast<Buffer*>(o->getPreviousObject())) 00141 o->writeElement(Tags::tag_buffer, getBuffer()); 00142 00143 // Write the quantity 00144 o->writeElement(Tags::tag_quantity, quantity); 00145 00146 // Write the effective daterange 00147 if (getEffective().getStart() != Date::infinitePast) 00148 o->writeElement(Tags::tag_effective_start, getEffective().getStart()); 00149 if (getEffective().getEnd() != Date::infiniteFuture) 00150 o->writeElement(Tags::tag_effective_end, getEffective().getEnd()); 00151 00152 // End of flow object 00153 o->EndObject(tag); 00154 } 00155 00156 00157 DECLARE_EXPORT void Flow::beginElement (XMLInput& pIn, const Attribute& pAttr) 00158 { 00159 if (pAttr.isA (Tags::tag_buffer)) 00160 pIn.readto( Buffer::reader(Buffer::metadata,pIn.getAttributes()) ); 00161 else if (pAttr.isA (Tags::tag_operation)) 00162 pIn.readto( Operation::reader(Operation::metadata,pIn.getAttributes()) ); 00163 } 00164 00165 00166 DECLARE_EXPORT void Flow::endElement (XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement) 00167 { 00168 if (pAttr.isA (Tags::tag_buffer)) 00169 { 00170 Buffer * b = dynamic_cast<Buffer*>(pIn.getPreviousObject()); 00171 if (b) setBuffer(b); 00172 else throw LogicException("Incorrect object type during read operation"); 00173 } 00174 else if (pAttr.isA (Tags::tag_operation)) 00175 { 00176 Operation * o = dynamic_cast<Operation*>(pIn.getPreviousObject()); 00177 if (o) setOperation(o); 00178 else throw LogicException("Incorrect object type during read operation"); 00179 } 00180 else if (pAttr.isA(Tags::tag_quantity)) 00181 setQuantity(pElement.getDouble()); 00182 else if (pAttr.isA(Tags::tag_action)) 00183 { 00184 delete static_cast<Action*>(pIn.getUserArea()); 00185 pIn.setUserArea( 00186 new Action(MetaClass::decodeAction(pElement.getString().c_str())) 00187 ); 00188 } 00189 else if (pAttr.isA(Tags::tag_effective_end)) 00190 setEffectiveEnd(pElement.getDate()); 00191 else if (pAttr.isA(Tags::tag_effective_start)) 00192 setEffectiveStart(pElement.getDate()); 00193 else if (pIn.isObjectEnd()) 00194 { 00195 // The flow data are now all read in. See if it makes sense now... 00196 Action a = pIn.getUserArea() ? 00197 *static_cast<Action*>(pIn.getUserArea()) : 00198 ADD_CHANGE; 00199 delete static_cast<Action*>(pIn.getUserArea()); 00200 validate(a); 00201 } 00202 } 00203 00204 00205 DECLARE_EXPORT void FlowEnd::writeElement 00206 (XMLOutput *o, const Keyword& tag, mode m) const 00207 { 00208 // If the flow has already been saved, no need to repeat it again 00209 // A 'reference' to a flow is not useful to be saved. 00210 if (m == REFERENCE) return; 00211 assert(m != NOHEADER); 00212 00213 // Write the header 00214 o->BeginObject(tag, Tags::tag_type, getType().type); 00215 00216 // If the flow is defined inside of an operation tag, we don't need to save 00217 // the operation. Otherwise we do save it... 00218 if (!dynamic_cast<Operation*>(o->getPreviousObject())) 00219 o->writeElement(Tags::tag_operation, getOperation()); 00220 00221 // If the flow is defined inside of an buffer tag, we don't need to save 00222 // the buffer. Otherwise we do save it... 00223 if (!dynamic_cast<Buffer*>(o->getPreviousObject())) 00224 o->writeElement(Tags::tag_buffer, getBuffer()); 00225 00226 // Write the quantity 00227 o->writeElement(Tags::tag_quantity, getQuantity()); 00228 00229 // End of flow object 00230 o->EndObject(tag); 00231 } 00232 00233 00234 }
Documentation generated by
