Panda3D
 All Classes Functions Variables Enumerations
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 
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
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
TypeHandle get_parent_class(int index) const
Returns the nth parent class of this type.
Definition: typeHandle.I:185
int get_num_preferred() const
Returns the number of types added to the preferred-type list.
int get_num_types() const
Returns the number of different types the Factory knows how to create.
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:98
void clear_preferred()
Empties the list of preferred types.
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.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
TypeHandle get_type(int n) const
Returns the nth type the Factory knows how to create.
A Factory can be used to create an instance of a particular subclass of some general base class...
Definition: factoryBase.h:42
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.
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 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