00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.8.0/src/model/problems_operationplan.cpp $ 00003 version : $LastChangedRevision: 1152 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2010-01-13 00:19:05 +0100 (Wed, 13 Jan 2010) $ 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., 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 00034 DECLARE_EXPORT void Operation::updateProblems() 00035 { 00036 // Find all operationplans, and delegate the problem detection to them 00037 for (OperationPlan *o = first_opplan; o; o = o->next) o->updateProblems(); 00038 } 00039 00040 00041 // 00042 // BEFORECURRENT, BEFOREFENCE, PRECEDENCE 00043 // 00044 00045 00046 void OperationPlan::updateProblems() 00047 { 00048 // A flag for each problem type that may need to be created 00049 bool needsBeforeCurrent(false); 00050 bool needsBeforeFence(false); 00051 bool needsPrecedence(false); 00052 00053 // The following categories of operation plans can't have problems: 00054 // - locked opplans 00055 // - opplans of hidden operations 00056 if (!getLocked() && getOperation()->getDetectProblems()) 00057 { 00058 if (!getOwner() || getOperation() == OperationSetup::setupoperation) 00059 { 00060 // Avoid duplicating problems on child and owner operationplans 00061 // Check if a BeforeCurrent problem is required. 00062 if (dates.getStart() < Plan::instance().getCurrent()) 00063 needsBeforeCurrent = true; 00064 00065 // Check if a BeforeFence problem is required. 00066 // Note that we either detect of beforeCurrent or a beforeFence problem, 00067 // never both simultaneously. 00068 else if 00069 (dates.getStart() < Plan::instance().getCurrent() + oper->getFence()) 00070 needsBeforeFence = true; 00071 } 00072 if (nextsubopplan && getDates().getEnd() > nextsubopplan->getDates().getStart()) 00073 needsPrecedence = true; 00074 } 00075 00076 // Loop through the existing problems 00077 for (Problem::const_iterator j = Problem::begin(this, false); 00078 j!=Problem::end();) 00079 { 00080 // Need to increment now and define a pointer to the problem, since the 00081 // problem can be deleted soon (which invalidates the iterator). 00082 Problem& curprob = *j; 00083 ++j; 00084 // The if-statement keeps the problem detection code concise and 00085 // concentrated. However, a drawback of this design is that a new problem 00086 // subclass will also require a new demand subclass. I think such a link 00087 // is acceptable. 00088 if (typeid(curprob) == typeid(ProblemBeforeCurrent)) 00089 { 00090 // if: problem needed and it exists already 00091 if (needsBeforeCurrent) needsBeforeCurrent = false; 00092 // else: problem not needed but it exists already 00093 else delete &curprob; 00094 } 00095 else if (typeid(curprob) == typeid(ProblemBeforeFence)) 00096 { 00097 if (needsBeforeFence) needsBeforeFence = false; 00098 else delete &curprob; 00099 } 00100 else if (typeid(curprob) == typeid(ProblemPrecedence)) 00101 { 00102 if (needsPrecedence) needsPrecedence = false; 00103 else delete &curprob; 00104 } 00105 } 00106 00107 // Create the problems that are required but aren't existing yet. 00108 // There is a little trick involved here... Normally problems are owned 00109 // by objects of the Plannable class. OperationPlan isn't a subclass of 00110 // Plannable, so we need a dirty cast. 00111 if (needsBeforeCurrent) new ProblemBeforeCurrent(this); 00112 if (needsBeforeFence) new ProblemBeforeFence(this); 00113 if (needsPrecedence) new ProblemPrecedence(this); 00114 } 00115 00116 }