problems_operationplan.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2007-2012 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 
26 
28 {
29  // Find all operationplans, and delegate the problem detection to them
30  if (getDetectProblems())
31  for (OperationPlan *o = first_opplan; o; o = o->next) o->updateProblems();
32 }
33 
34 
35 //
36 // BEFORECURRENT, BEFOREFENCE, PRECEDENCE
37 //
38 
39 
41 {
42  // A flag for each problem type that may need to be created
43  bool needsBeforeCurrent(false);
44  bool needsBeforeFence(false);
45  bool needsPrecedence(false);
46 
47  // The following categories of operation plans can't have problems:
48  // - locked opplans
49  // - opplans of hidden operations
50  if (!getLocked() && getOperation()->getDetectProblems())
51  {
53  {
54  // Avoid duplicating problems on child and owner operationplans
55  // Check if a BeforeCurrent problem is required.
56  if (dates.getStart() < Plan::instance().getCurrent())
57  needsBeforeCurrent = true;
58 
59  // Check if a BeforeFence problem is required.
60  // Note that we either detect of beforeCurrent or a beforeFence problem,
61  // never both simultaneously.
62  else if
63  (dates.getStart() < Plan::instance().getCurrent() + oper->getFence())
64  needsBeforeFence = true;
65  }
66  if (nextsubopplan && getDates().getEnd() > nextsubopplan->getDates().getStart())
67  needsPrecedence = true;
68  }
69 
70  // Loop through the existing problems
71  for (Problem::const_iterator j = Problem::begin(this, false);
72  j!=Problem::end();)
73  {
74  // Need to increment now and define a pointer to the problem, since the
75  // problem can be deleted soon (which invalidates the iterator).
76  Problem& curprob = *j;
77  ++j;
78  // The if-statement keeps the problem detection code concise and
79  // concentrated. However, a drawback of this design is that a new problem
80  // subclass will also require a new demand subclass. I think such a link
81  // is acceptable.
82  if (typeid(curprob) == typeid(ProblemBeforeCurrent))
83  {
84  // if: problem needed and it exists already
85  if (needsBeforeCurrent) needsBeforeCurrent = false;
86  // else: problem not needed but it exists already
87  else delete &curprob;
88  }
89  else if (typeid(curprob) == typeid(ProblemBeforeFence))
90  {
91  if (needsBeforeFence) needsBeforeFence = false;
92  else delete &curprob;
93  }
94  else if (typeid(curprob) == typeid(ProblemPrecedence))
95  {
96  if (needsPrecedence) needsPrecedence = false;
97  else delete &curprob;
98  }
99  }
100 
101  // Create the problems that are required but aren't existing yet.
102  // There is a little trick involved here... Normally problems are owned
103  // by objects of the Plannable class. OperationPlan isn't a subclass of
104  // Plannable, so we need a dirty cast.
105  if (needsBeforeCurrent) new ProblemBeforeCurrent(this);
106  if (needsBeforeFence) new ProblemBeforeFence(this);
107  if (needsPrecedence) new ProblemPrecedence(this);
108 }
109 
110 }