EGSnrc C++ class library  Report PIRS-898 (2021)
Iwan Kawrakow, Ernesto Mainegra-Hing, Frederic Tessier, Reid Townson and Blake Walters
egs_object_factory.cpp
Go to the documentation of this file.
1 /*
2 ###############################################################################
3 #
4 # EGSnrc egs++ object factory
5 # Copyright (C) 2015 National Research Council Canada
6 #
7 # This file is part of EGSnrc.
8 #
9 # EGSnrc is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU Affero General Public License as published by the
11 # Free Software Foundation, either version 3 of the License, or (at your
12 # option) any later version.
13 #
14 # EGSnrc is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
17 # more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with EGSnrc. If not, see <http://www.gnu.org/licenses/>.
21 #
22 ###############################################################################
23 #
24 # Author: Iwan Kawrakow, 2005
25 #
26 # Contributors: Ernesto Mainegra-Hing
27 # Hubert Ho
28 #
29 ###############################################################################
30 */
31 
32 
38 #include <cstdio>
39 #include <cstdlib>
40 
41 #include "egs_object_factory.h"
42 #include "egs_library.h"
43 #include "egs_input.h"
44 
45 static unsigned int object_count = 0;
46 
47 EGS_Object::EGS_Object(const string &Name, EGS_ObjectFactory *f) :
48  name(Name), otype("EGS_Object"), nref(0), factory(f) {
49  object_count++;
50  if (!name.size()) {
51  name = getUniqueName(this);
52  }
53  //if( factory ) factory->addObject(this);
54 }
55 
57  name(""), otype("EGS_Object"), nref(0), factory(f) {
58  object_count++;
59  setName(input);
60  //if( factory ) factory->addObject(this);
61 }
62 
63 EGS_Object::~EGS_Object() {
64  //egsWarning("Destruncting object of type %s with name %s\n",
65  // otype.c_str(),name.c_str());
66  if (factory) {
67  factory->removeObject(this);
68  }
69 }
70 
72  if (f && f != factory) {
73  if (factory) {
74  factory->removeObject(this);
75  }
76  factory = f;
77  factory->addObject(this);
78  }
79 }
80 
82  char buf[256];
83  if (o) {
84  sprintf(buf,"%s_%d",o->getObjectType().c_str(),object_count);
85  }
86  else {
87  sprintf(buf,"object_%d",object_count);
88  }
89  string result(buf);
90  return result;
91 }
92 
94  int err = 1;
95  if (input) {
96  err = input->getInput("name",name);
97  }
98  if (err) {
99  name = getUniqueName(this);
100  }
101 }
102 
103 EGS_ObjectFactory::EGS_ObjectFactory(const string &dsoPath, int where) {
104  //egsWarning("Creating object factory at 0x%x\n",this);
105  if (egsIsAbsolutePath(dsoPath)) {
106  dso_path = dsoPath;
107  }
108  else {
109  static const char *locations[] = {"HEN_HOUSE","EGS_HOME"};
110  int i = !where ? 0 : 1;
111  char *loc = getenv(locations[i]);
112  if (!loc)
113  egsFatal("EGS_ObjectFactory: the environment variable "
114  "%s must be defined\n",locations[i]);
115  dso_path = egsJoinPath(loc,dsoPath);
116  }
117 }
118 
120  unsigned int j;
121  //egsWarning("Destructing object factory at 0x%x\n",this);
122  //egsWarning(" - destructing known objects\n");
123  for (j=0; j<known_objects.size(); j++) {
125  }
126  //egsWarning(" - destructing added objects, objects size is %d\n",
127  // objects.size());
128  for (j=0; j<objects.size(); j++) {
129  EGS_Object *o = objects[j];
130  //egsWarning("Deleting object at 0x%x of type %s with name %s\n",
131  // o,o->getObjectType().c_str(),o->getObjectName().c_str());
133  }
134  //egsWarning(" - unloading libraries\n");
135  for (j=0; j<libs.size(); j++) {
136  delete libs[j];
137  }
138 }
139 
141  for (vector<EGS_Object *>::iterator i = objects.begin();
142  i != objects.end(); i++) {
143  if (o == *i) {
144  // why not calling o->deref() here ?
145  objects.erase(i);
146  break;
147  }
148  }
149 }
150 
151 typedef EGS_Object *(*EGS_ObjectCreationFunction)(EGS_Input *,
153 
155  const string &section_delimeter, const string &object_delimeter,
156  const string &select_key, const char *funcname, bool unique) {
157  if (!i) {
158  egsWarning("EGS_ObjectFactory::createObjects(): null input?\n");
159  return 0;
160  }
161  EGS_Input *input = i;
162  if (!i->isA(section_delimeter)) {
163  input = i->takeInputItem(section_delimeter);
164  if (!input) {
165  egsWarning("EGS_ObjectFactory::createObjects(): the input is"
166  " not of type %s and also does not have items of this type\n",
167  section_delimeter.c_str());
168  return 0;
169  }
170  }
171  EGS_Input *ij;
172  int errors = 0;
173  while ((ij = input->takeInputItem(object_delimeter)) != 0) {
174  EGS_Object *o = createSingleObject(ij,funcname,unique);
175  if (!o) {
176  errors++;
177  }
178  delete ij;
179  }
180  if (errors) egsWarning("EGS_ObjectFactory::createObjects(): %d errors"
181  " occured while creating objects\n",errors);
182  string sought_object;
183  EGS_Object *o = 0;
184  if (objects.size() > 0) {
185  o = objects[objects.size()-1];
186  }
187  int err = input->getInput(select_key,sought_object);
188  if (!err) {
189  o = getObject(sought_object);
190  if (!o) egsWarning("EGS_ObjectFactory::createObjects(): an object "
191  "with the name %s does not exist\n",sought_object.c_str());
192  }
193  delete input;
194  return o;
195 }
196 
198  const char *funcname, bool unique) {
199  if (!i) {
200  egsWarning("EGS_ObjectFactory::createSingleObject(): null input?\n");
201  return 0;
202  }
203  string type;
204  int err = i->getInput("type",type);
205  if (!err) {
206  for (unsigned int j=0; j<known_objects.size(); j++) {
207  if (i->compare(type,known_objects[j]->getObjectType())) {
208  EGS_Object *o = known_objects[j]->createObject(i);
209  if (addObject(o,unique)) {
210  return o;
211  }
213  return 0;
214  }
215  }
216  }
217  string libname;
218  int error = i->getInput("library",libname);
219  if (error) {
220  if (err) egsWarning("EGS_ObjectFactory::createObject(): \n"
221  " input item %s does not define an object type or an object "
222  "library\n",i->name());
223  else egsWarning("EGS_ObjectFactory::createObject(): input item %s\n"
224  " don't know anything about object type %s and no object"
225  "library defined\n",i->name(),type.c_str());
226  return 0;
227  }
228  EGS_Library *lib = 0;
229  for (unsigned int j=0; j<libs.size(); j++) {
230  if (libname == libs[j]->libraryName()) {
231  lib = libs[j];
232  break;
233  }
234  }
235  if (!lib) {
236  lib = new EGS_Library(libname.c_str(),dso_path.c_str());
237  lib->load();
238  if (!lib->isLoaded()) {
239  egsWarning("EGS_ObjectFactory::createObject(): "
240  "failed to load the library %s from %s\n",
241  libname.c_str(),dso_path.c_str());
242  return 0;
243  }
244  libs.push_back(lib);
245  }
246  EGS_ObjectCreationFunction create;
247  const char *fname = funcname ? funcname : "createObject";
248  create = (EGS_ObjectCreationFunction) lib->resolve(fname);
249  if (!create) {
250  egsWarning("EGS_ObjectFactory::createObject():\n"
251  " failed to resolve the '%s' function in the library %s\n",
252  fname,lib->libraryName());
253  return 0;
254  }
255  EGS_Object *o = create(i,this);
256  if (addObject(o,unique)) {
257  return o;
258  }
260  return 0;
261 }
262 
264  if (!o) {
265  egsWarning("EGS_ObjectFactory::addObject(): attempt to add a null"
266  " object\n");
267  return false;
268  }
269  for (unsigned int j=0; j<objects.size(); j++) {
270  if (objects[j] == o) {
271  return true;
272  }
273  }
274  if (unique) {
275  for (unsigned int j=0; j<objects.size(); j++) {
276  if (o->getObjectName() == objects[j]->getObjectName()) {
277  egsWarning("EGS_ObjectFactory::addObject(): an object with "
278  "the name %s already exists\n",o->getObjectName().c_str());
279  //if( o->deref() == -1 ) delete o;
280  return false;
281  }
282  }
283  }
284  //egsWarning("adding an object with name '%s' of type '%s' at 0x%x\n",
285  // o->getObjectName().c_str(),o->getObjectType().c_str(),o);
286  objects.push_back(o);
287  o->setFactory(this);
288  return true;
289 }
290 
292  for (unsigned int j=0; j<objects.size(); j++) {
293  if (objects[j] == o) {
294  return true;
295  }
296  }
297  return false;
298 }
299 
301  for (unsigned int j=0; j<objects.size(); j++) {
302  if (name == objects[j]->getObjectName()) {
303  return objects[j];
304  }
305  }
306  return 0;
307 }
308 
310  for (vector<EGS_Object *>::iterator i = objects.begin();
311  i != objects.end(); i++) {
312  if ((*i)->getObjectName() == name) {
313  (*i)->deref();
314  objects.erase(i);
315  return *i;
316  }
317  }
318  return 0;
319 }
320 
321 void EGS_ObjectFactory::addKnownTypeId(const char *typeid_name) {
322  if (!typeid_name) {
323  return;
324  }
325  for (int j=0; j<known_typeids.size(); j++)
326  if (known_typeids[j] == typeid_name) {
327  return;
328  }
329  known_typeids.push_back(typeid_name);
330 }
virtual EGS_Object * createSingleObject(EGS_Input *inp, const char *funcname=0, bool unique=true)
Create a single object from the information pointed to by inp.
bool haveObject(const EGS_Object *o) const
Does the factory own the object pointed to by o?
Base egspp object.
void removeObject(EGS_Object *o)
Remove o from the list of objects.
EGS_Object(const string &Name="", EGS_ObjectFactory *f=0)
Create an EGS_Object named Name belonging to the object factory f.
A class for dynamically loading shared libraries.
Definition: egs_library.h:52
virtual ~EGS_ObjectFactory()
Destructor.
bool egsIsAbsolutePath(const string &path)
Does the string path represent an absolute path name?
vector< EGS_Library * > libs
DSOs loaded so far.
const string & getObjectName() const
Get the object name.
bool isA(const string &key) const
Definition: egs_input.cpp:278
const char * libraryName() const
Returns the name of the library object as given in the constructor.
static string getUniqueName(const EGS_Object *o=0)
Create and return a unique object name.
EGS_Input class header file.
string egsJoinPath(const string &first, const string &second)
Join two path variables (or a path and a file name) using the platform specific directory separator a...
static void deleteObject(EGS_Object *o)
Delete an object.
EGS_ObjectFactory * factory
The factory this object belongs to.
vector< string > known_typeids
Known typeid&#39;s.
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
EGS_ObjectFactory(const string &dsoPath, int where=0)
Create an object factory that will load shared libraries from the directory dsoPath.
EGS_Object * createObjects(EGS_Input *inp, const string &section_delimeter, const string &object_delimeter, const string &select_key, const char *funcname=0, bool unique=true)
Create all objects specified by the information inp.
void setFactory(EGS_ObjectFactory *f)
Set the factory to which the object belongs.
EGS_Library class header file.
An object factory.
int deref()
Decrease the reference count to this object.
EGS_Object * takeObject(const string &Name)
Take the object named Name from the list of objects.
const char * name() const
Get the name of this property.
Definition: egs_input.cpp:271
void setName(EGS_Input *inp)
Set the name of the object from the information provided by inp.
const string & getObjectType() const
Get the object type.
virtual bool addObject(EGS_Object *o, bool unique=true)
Add the object o to the factory&#39;s list of objects.
bool load()
Loads the library.
void addKnownTypeId(const char *typeid_name)
Add a known typeid to this factory.
string name
The object name.
EGS_Object and EGS_ObjectFactory class header file.
A class for storing information in a tree-like structure of key-value pairs. This class is used throu...
Definition: egs_input.h:182
static bool compare(const string &s1, const string &s2)
Definition: egs_input.cpp:1170
void * resolve(const char *func)
Returns the address of the exported symbol func.
EGS_Object * getObject(const string &Name)
Get the object named Name.
EGS_Input * takeInputItem(const string &key, bool self=true)
Get the property named key.
Definition: egs_input.cpp:226
string dso_path
The path to look for DSOs.
vector< EGS_Object * > known_objects
known Objects
int getInput(const string &key, vector< string > &values) const
Assign values to an array of strings from an input identified by key.
Definition: egs_input.cpp:338
vector< EGS_Object * > objects
Created objects.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.
bool isLoaded() const
Returns true if the library is loaded, false otherwise.