Parasol Planning Library (PPL)
MethodSet.h
Go to the documentation of this file.
1 #ifndef PMPL_METHOD_SET_H_
2 #define PMPL_METHOD_SET_H_
3 
4 #include <functional>
5 #include <iostream>
6 #include <map>
7 #include <memory>
8 #include <string>
9 
10 #include <boost/mpl/list.hpp>
11 #include <boost/mpl/next_prior.hpp>
12 
13 #include "IOUtils.h"
14 #include "XMLNode.h"
15 
16 class MPLibrary;
17 
18 
22 template <typename Method>
23 struct MethodFactory final {
24 
27 
28  typedef std::shared_ptr<Method> OwningPointer;
29 
33 
35  return OwningPointer(new Method(_node));
36  }
37 
39 
40 };
41 
42 
57 template <typename Method>
58 class MethodSet final {
59 
60  public:
61 
64 
65  typedef Method* MethodPointer;
66  typedef std::shared_ptr<Method> OwningPointer;
67  typedef typename std::map<std::string, OwningPointer> MethodMap;
68 
69  typedef std::function<OwningPointer(XMLNode&)> FactoryType;
70  typedef typename std::map<std::string, FactoryType> FactoryMap;
71 
72  typedef typename MethodMap::iterator iterator;
73  typedef typename MethodMap::const_iterator const_iterator;
74 
78 
82  template <typename MethodTypeList>
83  MethodSet(MPLibrary* const _p, const MethodTypeList& _mtl,
84  const std::string& _name);
85 
89 
91  void ParseXML(XMLNode& _node);
92 
93  void AddMethod(XMLNode& _node);
94 
95  void AddMethod(MethodPointer _e, const std::string& _label);
96 
97  void AddMethod(OwningPointer _e, const std::string& _label);
98 
102  MethodPointer GetMethod(const std::string& _label);
103 
106  void Initialize();
107 
109  void Print(std::ostream& _os) const;
110 
115 
116  iterator begin() noexcept;
117  iterator end() noexcept;
118  const_iterator begin() const noexcept;
119  const_iterator end() const noexcept;
120 
122 
123  private:
124 
129 
131  template <typename First, typename Last>
132  void AddToUniverse(First, Last);
133 
135  template <typename Last>
136  void AddToUniverse(Last, Last);
137 
141 
142  MPLibrary* const m_library;
143 
144  std::string m_name;
145 
146  FactoryMap m_universe;
147  MethodMap m_elements;
148 
150 
151 };
152 
153 /*------------------------------- Method Set ---------------------------------*/
154 
155 template <typename Method>
156 template <typename MethodTypeList>
157 MethodSet<Method>::
158 MethodSet(MPLibrary* const _p, const MethodTypeList& _mtl,
159  const std::string& _name) : m_library(_p), m_name(_name) {
160  AddToUniverse(typename boost::mpl::begin<MethodTypeList>::type(),
161  typename boost::mpl::end<MethodTypeList>::type());
162 }
163 
164 
165 template <typename Method>
166 void
168 ParseXML(XMLNode& _node) {
169  for(auto& child : _node)
170  AddMethod(child);
171 }
172 
173 
174 template <typename Method>
175 void
177 AddMethod(XMLNode& _node) {
178  auto iter = m_universe.find(_node.Name());
179 
180  // Skip if method isn't in universe.
181  if(iter == m_universe.end())
182  return;
183 
184  OwningPointer e = iter->second(_node);
185  AddMethod(e, e->m_label);
186 }
187 
188 
189 template <typename Method>
190 void
192 AddMethod(MethodPointer _e, const std::string& _label) {
193  AddMethod(OwningPointer(_e), _label);
194 }
195 
196 
197 template <typename Method>
198 void
200 AddMethod(OwningPointer _e, const std::string& _label) {
201  auto iter = m_universe.find(_e->m_name);
202 
203  // Throw exception if method isn't in universe.
204  if(iter == m_universe.end())
205  throw ParseException(WHERE) << "Method set '" << m_name << "' has no "
206  << "method type '" << _e->m_name << "'.";
207  // Also throw if the label already exists.
208  if(m_elements.count(_label))
209  throw ParseException(WHERE) << "Method set '" << m_name << "' already has "
210  << "label '" << _label << "'.";
211  // And also for empty labels.
212  if(_label.empty())
213  throw ParseException(WHERE) << "Method label cannot be empty.";
214 
215  _e->SetMPLibrary(m_library);
216  _e->SetLabel(_label);
217  m_elements[_label] = _e;
218 }
219 
220 
221 template <typename Method>
224 GetMethod(const std::string& _label) {
225  // Find the method and ensure it exists.
226  auto iter = m_elements.find(_label);
227 
228  if(iter == m_elements.end()) {
229  std::ostringstream choices;
230  Print(choices);
231  throw RunTimeException(WHERE) << "Method '" << _label << "' does not exist "
232  << "in set " << m_name << "."
233  << choices.str();
234  }
235 
236  return iter->second.get();
237 }
238 
239 
240 template <typename Method>
241 void
243 Initialize() {
244  for(auto& elem : m_elements)
245  elem.second->Initialize();
246 }
247 
248 
249 template <typename Method>
250 void
252 Print(std::ostream& _os) const {
253  size_t count = 0;
254 
255  _os << "\n" << m_name << " has these methods available:";
256  for(const auto& elem : m_elements)
257  _os << "\n\t"
258  << ++count << ") '" << elem.first << "' (" << elem.second->m_name << ")";
259  _os << std::endl;
260 }
261 
262 /*--------------------------------- Iteration --------------------------------*/
263 
264 template <typename Method>
265 inline
268 begin() noexcept {
269  return m_elements.begin();
270 }
271 
272 
273 template <typename Method>
274 inline
277 end() noexcept {
278  return m_elements.end();
279 }
280 
281 
282 template <typename Method>
283 inline
286 begin() const noexcept {
287  return m_elements.begin();
288 }
289 
290 
291 template <typename Method>
292 inline
295 end() const noexcept {
296  return m_elements.end();
297 }
298 
299 /*-------------------------- Initialization Helpers --------------------------*/
300 
301 template <typename Method>
302 template <typename First, typename Last>
303 void
305 AddToUniverse(First, Last) {
306  using FirstType = typename boost::mpl::deref<First>::type;
307  FirstType first;
308  m_universe[first.m_name] = MethodFactory<FirstType>();
309  AddToUniverse(typename boost::mpl::next<First>::type(), Last());
310 }
311 
312 
313 template <typename Method>
314 template <typename Last>
315 void
317 AddToUniverse(Last, Last) {}
318 
319 /*----------------------------------------------------------------------------*/
320 
321 #endif
#define WHERE
Macro for retrieving info about file, function, and line number.
Definition: RuntimeUtils.h:32
Definition: MPLibrary.h:47
Definition: MethodSet.h:58
void Initialize()
Definition: MethodSet.h:243
std::map< std::string, OwningPointer > MethodMap
Definition: MethodSet.h:67
MethodPointer GetMethod(const std::string &_label)
Definition: MethodSet.h:224
void AddMethod(XMLNode &_node)
Definition: MethodSet.h:177
std::map< std::string, FactoryType > FactoryMap
Definition: MethodSet.h:70
void Print(std::ostream &_os) const
Display the instantiated methods.
Definition: MethodSet.h:252
MethodSet(MPLibrary *const _p, const MethodTypeList &_mtl, const std::string &_name)
Definition: MethodSet.h:158
MethodMap::iterator iterator
Definition: MethodSet.h:72
std::shared_ptr< Method > OwningPointer
Definition: MethodSet.h:66
Method * MethodPointer
Definition: MethodSet.h:65
MethodMap::const_iterator const_iterator
Definition: MethodSet.h:73
std::function< OwningPointer(XMLNode &)> FactoryType
Definition: MethodSet.h:69
iterator end() noexcept
Definition: MethodSet.h:277
void ParseXML(XMLNode &_node)
Add the appropriate methods from an XML node.
Definition: MethodSet.h:168
iterator begin() noexcept
Definition: MethodSet.h:268
Definition: XMLNode.h:27
const std::string & Name() const
Get the XMLNode name.
Definition: XMLNode.cpp:90
Creates new method instances from an XML node.
Definition: MethodSet.h:23
OwningPointer operator()(XMLNode &_node) const
Definition: MethodSet.h:34
std::shared_ptr< Method > OwningPointer
Definition: MethodSet.h:28
Definition: PMPLExceptions.h:38
Definition: PMPLExceptions.h:62