PSCF v1.3
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
18namespace 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
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
193
197 virtual void initFactory();
198
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>
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 }
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);
315 readParameters(in);
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);
328 if (isActive()) {
329 readParameters(in);
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();
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
Beginning line of a composite parameter block.
Definition Begin.h:25
bool isActive() const
Is this an active element (has it been read from file)?
Definition Begin.h:84
End bracket of a ParamComposite parameter block.
Definition End.h:25
virtual void writeParam(std::ostream &out) const
Write the closing bracket.
Definition End.cpp:43
Factory template.
Definition Factory.h:34
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
Factory< Data > * factoryPtr_
Pointer to an associated Factory<Data> object.
Definition Manager.h:182
void setFactory(Factory< Data > &factory)
Associate a Factory with this Manager.
Definition Manager.h:284
virtual void readParam(std::istream &in)
Read and create a set of objects.
Definition Manager.h:310
Factory< Analyzer< D > > & factory()
Definition Manager.h:265
virtual void initFactory()
Create factory if necessary.
Definition Manager.h:528
Data * findFirst(std::string const &className)
Return pointer to first object with specified class name.
Definition Manager.h:512
virtual Factory< Data > * newDefaultFactory() const
Create an instance of the default Factory<Data> class.
Definition Manager.h:541
virtual ~Manager()
Destructor.
Definition Manager.h:246
bool hasFactory() const
Return true if this Manager has a Factory, false otherwise.
Definition Manager.h:485
virtual void readParameters(std::istream &in)
Read child blocks, return when closing bracket encountered.
Definition Manager.h:356
virtual void loadParameters(Serializable::IArchive &ar)
Load a set of objects to an output archive.
Definition Manager.h:411
virtual void save(Serializable::OArchive &ar)
Save a set of objects to an output archive.
Definition Manager.h:448
void beginReadManager(std::istream &in)
Read (or attempt to read) opening line: "ManagerName{".
Definition Manager.h:338
virtual void readParamOptional(std::istream &in)
Optionally read and create a set of objects.
Definition Manager.h:323
Data & operator[](int i) const
Mimic C array subscripting.
Definition Manager.h:501
void addSubfactory(Factory< Data > &subfactory)
Set a SubFactory for this Manager.
Definition Manager.h:275
int size() const
Get logical size.
Definition Manager.h:494
void append(Data &data, const std::string &name)
Append a Data object to the end of the sequence.
Definition Manager.h:462
void endReadManager()
Add closing bracket to output format.
Definition Manager.h:399
std::string className(int i) const
Get the subclass name for object number i.
Definition Manager.h:473
Manager(bool uniqueNames=false)
Constructor.
Definition Manager.h:232
bool isIoProcessor() const
Can this processor do file I/O ?
Definition MpiFileIo.h:94
static bool echo()
Get echo parameter.
Begin & readBegin(std::istream &in, const char *label, bool isRequired=true)
Add and read a class label and opening bracket.
void setIsRequired(bool isRequired)
Set or unset the isActive flag.
void setIsActive(bool isActive)
Set or unset the isActive flag.
Blank & addBlank()
Create and add a new Blank object, representing a blank line.
bool isActive() const
Is this parameter active?
End & addEnd()
Add a closing bracket.
ParamComposite()
Constructor.
std::string className() const
Get class name string.
Blank & readBlank(std::istream &in)
Add and read a new Blank object, representing a blank line.
bool isRequired() const
Is this ParamComposite required in the input file?
BinaryFileIArchive IArchive
Type of input archive used by load method.
BinaryFileOArchive OArchive
Type of output archive used by save method.
File containing preprocessor macros for error handling.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
Utility classes for scientific computation.