PSCF v1.1
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
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()) {
531 factoryPtr_ = newDefaultFactory();
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
Saving archive for binary istream.
Saving / output archive for binary ostream.
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:57
Template container for pointers to objects with a common base class.
Definition: Manager.h:39
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< Data > & factory()
Return a reference to the 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
Manager(bool uniqueNames=false)
Constructor.
Definition: Manager.h:232
static bool echo()
Get echo parameter.
An object that can read multiple parameters from file.
std::string className() const
Get class name string.
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:51
Utility classes for scientific computation.
Definition: accumulators.mod:1