Panda3D
factoryBase.cxx
1 // Filename: factoryBase.cxx
2 // Created by: drose (08May00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "factoryBase.h"
16 #include "indent.h"
17 #include "config_util.h"
18 
19 ////////////////////////////////////////////////////////////////////
20 // Function: FactoryBase::Constructor
21 // Access: Public
22 // Description:
23 ////////////////////////////////////////////////////////////////////
24 FactoryBase::
25 FactoryBase() {
26 }
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: FactoryBase::Destructor
30 // Access: Public
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 FactoryBase::
34 ~FactoryBase() {
35 }
36 
37 ////////////////////////////////////////////////////////////////////
38 // Function: FactoryBase::make_instance
39 // Access: Public
40 // Description: Attempts to create a new instance of some class of
41 // the indicated type, or some derivative if necessary.
42 // If an instance of the exact type cannot be created,
43 // the specified preferred will specify which derived
44 // class will be preferred.
45 ////////////////////////////////////////////////////////////////////
47 make_instance(TypeHandle handle, const FactoryParams &params) {
48  TypedObject *instance = (TypedObject *)NULL;
49 
50  instance = make_instance_exact(handle, params);
51  if (instance == (TypedObject *)NULL) {
52  // Can't create an exact instance; try for a derived type.
53  instance = make_instance_more_specific(handle, params);
54  }
55 
56  if (util_cat.is_debug()) {
57  util_cat.debug()
58  << "make_instance(" << handle << ", params) returns "
59  << (void *)instance;
60  if (instance != (TypedObject *)NULL) {
61  util_cat.debug(false)
62  << ", of type " << instance->get_type();
63  }
64  util_cat.debug(false) << "\n";
65  }
66  return instance;
67 }
68 
69 ////////////////////////////////////////////////////////////////////
70 // Function: FactoryBase::make_instance_more_general
71 // Access: Public
72 // Description: Attempts to create an instance of the type requested,
73 // or some base type of the type requested. Returns the
74 // new instance created, or NULL if the instance could
75 // not be created.
76 ////////////////////////////////////////////////////////////////////
79  TypedObject *object = make_instance_exact(handle, params);
80 
81  if (object == (TypedObject *)NULL) {
82  // Recursively search through the entire inheritance tree until we
83  // find something we know about.
84  if (handle.get_num_parent_classes() == 0) {
85  return NULL;
86  }
87 
88  int num_parents = handle.get_num_parent_classes();
89  for (int i = 0; i < num_parents && object == (TypedObject *)NULL; i++) {
90  object = make_instance_more_general(handle.get_parent_class(i), params);
91  }
92  }
93 
94  if (util_cat.is_debug()) {
95  util_cat.debug()
96  << "make_instance(" << handle << ", params) returns "
97  << (void *)object;
98  if (object != (TypedObject *)NULL) {
99  util_cat.debug(false)
100  << ", of type " << object->get_type();
101  }
102  util_cat.debug(false) << "\n";
103  }
104 
105  return object;
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: FactoryBase::find_registered_type
110 // Access: Public
111 // Description: Returns the TypeHandle given, if it is a registered
112 // type, or if it is not registered, searches for the
113 // nearest ancestor of the indicated type that is
114 // registered and returns it. If no ancestor of the
115 // indicated type is registered, returns
116 // TypeHandle::none().
117 ////////////////////////////////////////////////////////////////////
120  Creators::const_iterator ci = _creators.find(handle);
121  if (ci != _creators.end()) {
122  // This type is registered.
123  return handle;
124  }
125 
126  // Recursively search through the entire inheritance tree until we
127  // find something we know about.
128  if (handle.get_num_parent_classes() == 0) {
129  return TypeHandle::none();
130  }
131 
132  int num_parents = handle.get_num_parent_classes();
133  for (int i = 0; i < num_parents; i++) {
135  if (result != TypeHandle::none()) {
136  return result;
137  }
138  }
139 
140  // No known types.
141  return TypeHandle::none();
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: FactoryBase::register_factory
146 // Access: Public
147 // Description: Registers a new kind of thing the Factory will be
148 // able to create.
149 ////////////////////////////////////////////////////////////////////
150 void FactoryBase::
151 register_factory(TypeHandle handle, BaseCreateFunc *func) {
152  nassertv(handle != TypeHandle::none());
153  nassertv(func != (BaseCreateFunc *)NULL);
154  _creators[handle] = func;
155 }
156 
157 ////////////////////////////////////////////////////////////////////
158 // Function: FactoryBase::get_num_types
159 // Access: Public
160 // Description: Returns the number of different types the Factory
161 // knows how to create.
162 ////////////////////////////////////////////////////////////////////
163 int FactoryBase::
164 get_num_types() const {
165  return _creators.size();
166 }
167 
168 ////////////////////////////////////////////////////////////////////
169 // Function: FactoryBase::get_type
170 // Access: Public
171 // Description: Returns the nth type the Factory knows how to create.
172 // This is not a terribly efficient function; it's
173 // included primarily for debugging output. Normally
174 // you wouldn't need to traverse the list of the
175 // Factory's types.
176 ////////////////////////////////////////////////////////////////////
178 get_type(int n) const {
179  nassertr(n >= 0 && n < get_num_types(), TypeHandle::none());
180  Creators::const_iterator ci;
181  for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
182  if (n == 0) {
183  return (*ci).first;
184  }
185  n--;
186  }
187 
188  // We shouldn't get here.
189  nassertr(false, TypeHandle::none());
190  return TypeHandle::none();
191 }
192 
193 ////////////////////////////////////////////////////////////////////
194 // Function: FactoryBase::clear_preferred
195 // Access: Public
196 // Description: Empties the list of preferred types.
197 ////////////////////////////////////////////////////////////////////
198 void FactoryBase::
200  _preferred.clear();
201 }
202 
203 ////////////////////////////////////////////////////////////////////
204 // Function: FactoryBase::add_preferred
205 // Access: Public
206 // Description: Adds the indicated type to the end of the list of
207 // preferred types. On the next call to
208 // make_instance(), if the exact type requested cannot
209 // be created, the preferred types are first tried in
210 // the order specified.
211 ////////////////////////////////////////////////////////////////////
212 void FactoryBase::
214  nassertv(handle != TypeHandle::none());
215  _preferred.push_back(handle);
216 }
217 
218 ////////////////////////////////////////////////////////////////////
219 // Function: FactoryBase::get_num_preferred
220 // Access: Public
221 // Description: Returns the number of types added to the
222 // preferred-type list.
223 ////////////////////////////////////////////////////////////////////
224 int FactoryBase::
226  return _preferred.size();
227 }
228 
229 ////////////////////////////////////////////////////////////////////
230 // Function: FactoryBase::get_preferred
231 // Access: Public
232 // Description: Returns the nth type added to the preferred-type
233 // list.
234 ////////////////////////////////////////////////////////////////////
236 get_preferred(int n) const {
237  nassertr(n >= 0 && n < get_num_preferred(), TypeHandle::none());
238  return _preferred[n];
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: FactoryBase::write_types
243 // Access: Public
244 // Description: Writes a list of all known types the Factory can
245 // create to the indicated output stream, one per line.
246 ////////////////////////////////////////////////////////////////////
247 void FactoryBase::
248 write_types(ostream &out, int indent_level) const {
249  Creators::const_iterator ci;
250  for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
251  indent(out, indent_level) << (*ci).first << "\n";
252  }
253 }
254 
255 
256 ////////////////////////////////////////////////////////////////////
257 // Function: FactoryBase::Copy Constructor
258 // Access: Private
259 // Description: Don't copy Factories.
260 ////////////////////////////////////////////////////////////////////
261 FactoryBase::
262 FactoryBase(const FactoryBase &) {
263 }
264 
265 ////////////////////////////////////////////////////////////////////
266 // Function: FactoryBase::Copy Assignment Operator
267 // Access: Private
268 // Description: Don't copy Factories.
269 ////////////////////////////////////////////////////////////////////
270 void FactoryBase::
271 operator = (const FactoryBase &) {
272 }
273 
274 ////////////////////////////////////////////////////////////////////
275 // Function: FactoryBase::make_instance_exact
276 // Access: Private
277 // Description: Attempts to create an instance of the exact type
278 // requested by the given handle. Returns the new
279 // instance created, or NULL if the instance could not
280 // be created.
281 ////////////////////////////////////////////////////////////////////
282 TypedObject *FactoryBase::
283 make_instance_exact(TypeHandle handle, const FactoryParams &params) {
284  Creators::const_iterator ci = _creators.find(handle);
285  if (ci == _creators.end()) {
286  return NULL;
287  }
288 
289  BaseCreateFunc *func = (BaseCreateFunc *)((*ci).second);
290  nassertr(func != (BaseCreateFunc *)NULL, NULL);
291  return (*func)(params);
292 }
293 
294 ////////////////////////////////////////////////////////////////////
295 // Function: FactoryBase::make_instance_more_specific
296 // Access: Private
297 // Description: Attempts to create an instance of some derived type
298 // of the type requested by the given handle. Returns
299 // the new instance created, or NULL if the instance
300 // could not be created.
301 ////////////////////////////////////////////////////////////////////
302 TypedObject *FactoryBase::
303 make_instance_more_specific(TypeHandle handle, const FactoryParams &params) {
304  // First, walk through the established preferred list. Maybe one
305  // of these qualifies.
306 
307  Preferred::const_iterator pi;
308  for (pi = _preferred.begin(); pi != _preferred.end(); ++pi) {
309  TypeHandle ptype = (*pi);
310  if (ptype.is_derived_from(handle)) {
311  TypedObject *object = make_instance_exact(ptype, params);
312  if (object != (TypedObject *)NULL) {
313  return object;
314  }
315  }
316  }
317 
318  // No, we couldn't create anything on the preferred list, so create
319  // the first thing we know about that derives from the indicated
320  // type.
321  Creators::const_iterator ci;
322  for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
323  TypeHandle ctype = (*ci).first;
324  if (ctype.is_derived_from(handle)) {
325  BaseCreateFunc *func = (BaseCreateFunc *)((*ci).second);
326  nassertr(func != (BaseCreateFunc *)NULL, NULL);
327  TypedObject *object = (*func)(params);
328  if (object != (TypedObject *)NULL) {
329  return object;
330  }
331  }
332  }
333 
334  return NULL;
335 }
336 
TypedObject * make_instance(TypeHandle handle, const FactoryParams &params)
Attempts to create a new instance of some class of the indicated type, or some derivative if necessar...
Definition: factoryBase.cxx:47
void register_factory(TypeHandle handle, BaseCreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
bool is_derived_from(TypeHandle parent, TypedObject *object=(TypedObject *) NULL) const
Returns true if this type is derived from the indicated type, false otherwise.
Definition: typeHandle.I:152
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:98
TypeHandle get_type(int n) const
Returns the nth type the Factory knows how to create.
int get_num_types() const
Returns the number of different types the Factory knows how to create.
void clear_preferred()
Empties the list of preferred types.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
A Factory can be used to create an instance of a particular subclass of some general base class...
Definition: factoryBase.h:42
int get_num_parent_classes(TypedObject *object=(TypedObject *) NULL) const
Returns the number of parent classes that this type is known to have.
Definition: typeHandle.I:173
TypeHandle get_preferred(int n) const
Returns the nth type added to the preferred-type list.
void write_types(ostream &out, int indent_level=0) const
Writes a list of all known types the Factory can create to the indicated output stream, one per line.
int get_num_preferred() const
Returns the number of types added to the preferred-type list.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void add_preferred(TypeHandle handle)
Adds the indicated type to the end of the list of preferred types.
TypeHandle get_parent_class(int index) const
Returns the nth parent class of this type.
Definition: typeHandle.I:185
TypeHandle find_registered_type(TypeHandle handle)
Returns the TypeHandle given, if it is a registered type, or if it is not registered, searches for the nearest ancestor of the indicated type that is registered and returns it.
TypedObject * make_instance_more_general(TypeHandle handle, const FactoryParams &params)
Attempts to create an instance of the type requested, or some base type of the type requested...
Definition: factoryBase.cxx:78