Simpatico  v1.10
Manager.h
1 #ifndef UTIL_MANAGER_H
2 #define UTIL_MANAGER_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/param/ParamComposite.h> // base class
12 #include <util/param/Factory.h> // pointer member, used in implementation
13 #include <util/global.h>
14 
15 #include <string>
16 #include <vector>
17 
18 namespace Util
19 {
20 
37  template <typename Data>
38  class Manager : public ParamComposite
39  {
40 
41  public:
42 
48  Manager(bool uniqueNames = false);
49 
53  virtual ~Manager();
54 
60  void addSubfactory(Factory<Data>& subfactory);
61 
68 
74  void setFactory(Factory<Data>* factoryPtr);
75 
96  virtual void readParam(std::istream &in);
97 
107  virtual void readParamOptional(std::istream &in);
108 
114  virtual void readParameters(std::istream &in);
115 
121  virtual void loadParameters(Serializable::IArchive &ar);
122 
128  virtual void save(Serializable::OArchive &ar);
129 
136  void append(Data& data, const std::string& name);
137 
143  int size() const;
144 
151  std::string className(int i) const;
152 
157 
161  bool hasFactory() const;
162 
169  Data& operator[] (int i) const;
170 
177  Data* findFirst(std::string const & className);
178 
179  protected:
180 
183 
187  void beginReadManager(std::istream& in);
188 
192  void endReadManager();
193 
197  virtual void initFactory();
198 
204  virtual Factory<Data>* newDefaultFactory() const;
205 
206  private:
207 
209  std::vector<Data*> ptrs_;
210 
212  std::vector<std::string> names_;
213 
215  int capacity_;
216 
218  int size_;
219 
221  bool uniqueNames_;
222 
224  bool createdFactory_;
225 
226  };
227 
228  /*
229  * Constructor.
230  */
231  template <typename Data>
232  Manager<Data>::Manager(bool uniqueNames)
233  : factoryPtr_(0),
234  ptrs_(),
235  names_(),
236  capacity_(0),
237  size_(0),
238  uniqueNames_(uniqueNames),
239  createdFactory_(false)
240  {}
241 
242  /*
243  * Destructor.
244  */
245  template <typename Data>
247  {
248  // Delete objects referenced by non-null elements of ptrs_[].
249  for (int i=0; i < size_; ++i) {
250  if (ptrs_[i]) {
251  delete ptrs_[i];
252  }
253  }
254 
255  // Delete Factory if it was created by this Manager.
256  if (factoryPtr_ && createdFactory_) {
257  delete factoryPtr_;
258  }
259  }
260 
261  /*
262  * Return a reference to the factory.
263  */
264  template <typename Data>
266  {
267  initFactory();
268  return *factoryPtr_;
269  }
270 
271  /*
272  * Add a subfactory to the current (or default) Factory.
273  */
274  template <typename Data>
276  {
277  factory().addSubfactory(subfactory);
278  }
279 
280  /*
281  * Associate a Factory with the Manager, pass by reference.
282  */
283  template <typename Data>
285  {
286  if (factoryPtr_ && createdFactory_) {
287  delete factoryPtr_;
288  createdFactory_ = false;
289  }
290  factoryPtr_ = &factory;
291  }
292 
293  /*
294  * Associate a factory with the Manager, passed by pointer.
295  */
296  template <typename Data>
298  {
299  if (factoryPtr_ && createdFactory_) {
300  delete factoryPtr_;
301  createdFactory_ = false;
302  }
303  factoryPtr_ = factoryPtr;
304  }
305 
306  /*
307  * Read Manager parameter block.
308  */
309  template <typename Data>
310  void Manager<Data>::readParam(std::istream &in)
311  {
312  setIsRequired(true);
313  setIsActive(true);
314  beginReadManager(in);
315  readParameters(in);
316  endReadManager();
317  }
318 
319  /*
320  * Attempt to read parameter block for optional Manager.
321  */
322  template <typename Data>
323  void Manager<Data>::readParamOptional(std::istream &in)
324  {
325  setIsRequired(false);
326  setIsActive(false);
327  beginReadManager(in);
328  if (isActive()) {
329  readParameters(in);
330  endReadManager();
331  }
332  }
333 
334  /*
335  * Read (or attempt to read) opening line.
336  */
337  template <typename Data>
338  void Manager<Data>::beginReadManager(std::istream &in)
339  {
340  std::string managerName = ParamComposite::className();
341  Begin* beginPtr = &readBegin(in, managerName.c_str(), isRequired());
342  if (!isRequired()) {
343  if (beginPtr->isActive()) {
344  setIsActive(true);
345  } else {
346  setIsActive(false);
347  delete beginPtr;
348  }
349  }
350  }
351 
352  /*
353  * Read a sequence of child objects, return when closing bracket found.
354  */
355  template <typename Data>
356  void Manager<Data>::readParameters(std::istream &in)
357  {
358  // Check if a Factory exists, create one if necessary.
359  initFactory();
360 
361  // Loop over managed objects
362  std::string name;
363  Data* typePtr;
364  bool isEnd = false;
365  while (!isEnd) {
366 
367  // Read a blank line before each object
368  readBlank(in);
369 
370  // Attempt to read and instantiate a new object *typePtr.
371  // This sets isEnd = true if a closing bracket is encountered.
372  typePtr = factoryPtr_->readObject(in, *this, name, isEnd);
373 
374  if (!isEnd) {
375  if (typePtr) {
376  if (uniqueNames_) {
377  Data* firstPtr = findFirst(name);
378  if (firstPtr) {
379  std::string msg("Non-unique subclass name: ");
380  msg += name;
381  UTIL_THROW(msg.c_str());
382  }
383  }
384  append(*typePtr, name);
385  } else {
386  std::string msg("Unknown subclass name: ");
387  msg += name;
388  UTIL_THROW(msg.c_str());
389  }
390  }
391 
392  }
393  }
394 
395  /*
396  * Add closing bracket.
397  */
398  template <typename Data>
400  {
401  End* endPtr = &addEnd();
402  if (ParamComponent::echo() && isIoProcessor()) {
403  endPtr->writeParam(Log::file());
404  }
405  }
406 
407  /*
408  * Read instructions for creating objects from file.
409  */
410  template <typename Data>
412  {
413  int size = 0;
414  Data* typePtr;
415  std::string name;
416 
417  // Check if a Factory exists, create one if necessary.
418  initFactory();
419 
420  if (isIoProcessor()) {
421  ar >> size;
422  }
423  #ifdef UTIL_MPI
424  if (hasIoCommunicator()) {
425  bcast<int>(ioCommunicator(), size, 0);
426  }
427  #endif
428 
429  for (int i = 0; i < size; ++i) {
430  addBlank();
431  name = "unknown";
432  typePtr = factoryPtr_->loadObject(ar, *this, name);
433  if (typePtr) {
434  append(*typePtr, name);
435  } else {
436  std::string msg("Unknown subclass name: ");
437  msg += name;
438  UTIL_THROW(msg.c_str());
439  }
440  }
441  addBlank();
442  }
443 
444  /*
445  * Read instructions for creating objects from file.
446  */
447  template <typename Data>
449  {
450  int size = ptrs_.size();
451  ar << size;
452  for (int i = 0; i < size; ++i) {
453  ar << names_[i];
454  (ptrs_[i])->save(ar);
455  }
456  }
457 
458  /*
459  * Append an object to the Manager.
460  */
461  template <typename Data>
462  void Manager<Data>::append(Data& data, const std::string& name)
463  {
464  ptrs_.push_back(&data);
465  names_.push_back(name);
466  ++size_;
467  }
468 
469  /*
470  * Return subclass name for object number i.
471  */
472  template <typename Data>
473  std::string Manager<Data>::className(int i) const
474  {
475  if (i >= size_) {
476  UTIL_THROW("Invalid array index\n");
477  }
478  return names_[i];
479  }
480 
481  /*
482  * Does this Manager have an associated Factory?
483  */
484  template <typename Data>
486  {
487  return (factoryPtr_ != 0);
488  }
489 
490  /*
491  * Return logical size (number of objects appended thus far).
492  */
493  template <typename Data>
494  inline int Manager<Data>::size() const
495  { return size_; }
496 
497  /*
498  * Array subscript operator - return a reference.
499  */
500  template <typename Data>
501  inline Data& Manager<Data>::operator[] (int i) const
502  {
503  assert(i >= 0);
504  assert(i < size_);
505  return *ptrs_[i];
506  }
507 
508  /*
509  * Find first object with specified class name.
510  */
511  template <typename Data>
512  Data* Manager<Data>::findFirst(std::string const & className)
513  {
514  for (int i = 0; i < size_; ++i) {
515  if (names_[i] == className) {
516  return ptrs_[i];
517  }
518  }
519  return 0;
520  }
521 
522  // Protected methods
523 
524  /*
525  * Initialize Factory, create if necessary.
526  */
527  template <typename Data>
529  {
530  if (!hasFactory()) {
532  createdFactory_ = true;
533  }
534  assert(factoryPtr_);
535  }
536 
540  template <typename Data>
542  {
543  UTIL_THROW("Call of un-implemented Manager<Data>::newDefaultFactory");
544  return 0;
545  }
546 
547 }
548 #endif
virtual void loadParameters(Serializable::IArchive &ar)
Load a set of objects to an output archive.
Definition: Manager.h:411
Manager(bool uniqueNames=false)
Constructor.
Definition: Manager.h:232
End bracket of a ParamComposite parameter block.
Definition: End.h:24
virtual void save(Serializable::OArchive &ar)
Save a set of objects to an output archive.
Definition: Manager.h:448
void append(Data &data, const std::string &name)
Append a Data object to the end of the sequence.
Definition: Manager.h:462
virtual ~Manager()
Destructor.
Definition: Manager.h:246
bool isRequired() const
Is this ParamComposite required in the input file?
virtual void initFactory()
Create factory if necessary.
Definition: Manager.h:528
Factory< Data > * factoryPtr_
Pointer to an associated Factory<Data> object.
Definition: Manager.h:182
void beginReadManager(std::istream &in)
Read (or attempt to read) opening line: "ManagerName{".
Definition: Manager.h:338
Factory< Data > & factory()
Return a reference to the factory.
Definition: Manager.h:265
Data & operator[](int i) const
Mimic C array subscripting.
Definition: Manager.h:501
virtual void readParamOptional(std::istream &in)
Optionally read and create a set of objects.
Definition: Manager.h:323
File containing preprocessor macros for error handling.
void endReadManager()
Add closing bracket to output format.
Definition: Manager.h:399
void setIsActive(bool isActive)
Set or unset the isActive flag.
Blank & readBlank(std::istream &in)
Add and read a new Blank object, representing a blank line.
virtual void readParam(std::istream &in)
Read and create a set of objects.
Definition: Manager.h:310
End & addEnd()
Add a closing bracket.
bool isActive() const
Is this parameter active?
Saving / output archive for binary ostream.
virtual Factory< Data > * newDefaultFactory() const
Create an instance of the default Factory<Data> class.
Definition: Manager.h:541
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
std::string className() const
Get class name string.
MPI::Intracomm & ioCommunicator() const
Get the MPI communicator by reference.
Definition: MpiFileIo.h:105
Template container for pointers to objects with a common base class.
Definition: Manager.h:38
Data * findFirst(std::string const &className)
Return pointer to first object with specified class name.
Definition: Manager.h:512
Utility classes for scientific computation.
Definition: accumulators.mod:1
static bool echo()
Get echo parameter.
bool isIoProcessor() const
Can this processor do file I/O ?
Definition: MpiFileIo.h:92
virtual void writeParam(std::ostream &out)
Write the closing bracket.
Definition: End.cpp:43
virtual void readParameters(std::istream &in)
Read child blocks, return when closing bracket encountered.
Definition: Manager.h:356
static std::ostream & file()
Get log ostream by reference.
Definition: Log.cpp:57
bool hasIoCommunicator() const
Does this object have an associated MPI communicator?
Definition: MpiFileIo.h:99
Saving archive for binary istream.
void addSubfactory(Factory< Data > &subfactory)
Set a SubFactory for this Manager.
Definition: Manager.h:275
bool isActive() const
Is this an active element (has it been read from file)?
Definition: Begin.h:84
Begin & readBegin(std::istream &in, const char *label, bool isRequired=true)
Add and read a class label and opening bracket.
Factory template.
Definition: Factory.h:32
bool hasFactory() const
Return true if this Manager has a Factory, false otherwise.
Definition: Manager.h:485
int size() const
Get logical size.
Definition: Manager.h:494
An object that can read multiple parameters from file.
Blank & addBlank()
Create and add a new Blank object, representing a blank line.
void setIsRequired(bool isRequired)
Set or unset the isActive flag.
Beginning line of a composite parameter block.
Definition: Begin.h:24
void setFactory(Factory< Data > &factory)
Associate a Factory with this Manager.
Definition: Manager.h:284