Panda3D

factoryBase.cxx
Go to the documentation of this file.
1 /**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file factoryBase.cxx
10 * @author drose
11 * @date 2000-05-08
12 */
13
14 #include "factoryBase.h"
15 #include "indent.h"
16 #include "config_putil.h"
17
18 /**
19 * Attempts to create a new instance of some class of the indicated type, or
20 * some derivative if necessary. If an instance of the exact type cannot be
21 * created, the specified preferred will specify which derived class will be
22 * preferred.
23 */
24 TypedObject *FactoryBase::
25 make_instance(TypeHandle handle, const FactoryParams &params) {
26 TypedObject *instance = nullptr;
27
28 instance = make_instance_exact(handle, params);
29 if (instance == nullptr) {
30 // Can't create an exact instance; try for a derived type.
31 instance = make_instance_more_specific(handle, params);
32 }
33
34 if (util_cat.is_debug()) {
35 util_cat.debug()
36 << "make_instance(" << handle << ", params) returns "
37 << (void *)instance;
38 if (instance != nullptr) {
39 util_cat.debug(false)
40 << ", of type " << instance->get_type();
41 }
42 util_cat.debug(false) << "\n";
43 }
44 return instance;
45 }
46
47 /**
48 * Attempts to create an instance of the type requested, or some base type of
49 * the type requested. Returns the new instance created, or NULL if the
50 * instance could not be created.
51 */
52 TypedObject *FactoryBase::
53 make_instance_more_general(TypeHandle handle, const FactoryParams &params) {
54 TypedObject *object = make_instance_exact(handle, params);
55
56 if (object == nullptr) {
57 // Recursively search through the entire inheritance tree until we find
58 // something we know about.
59 if (handle.get_num_parent_classes() == 0) {
60 return nullptr;
61 }
62
63 int num_parents = handle.get_num_parent_classes();
64 for (int i = 0; i < num_parents && object == nullptr; i++) {
65 object = make_instance_more_general(handle.get_parent_class(i), params);
66 }
67 }
68
69 if (util_cat.is_debug()) {
70 util_cat.debug()
71 << "make_instance(" << handle << ", params) returns "
72 << (void *)object;
73 if (object != nullptr) {
74 util_cat.debug(false)
75 << ", of type " << object->get_type();
76 }
77 util_cat.debug(false) << "\n";
78 }
79
80 return object;
81 }
82
83 /**
84 * Returns the TypeHandle given, if it is a registered type, or if it is not
85 * registered, searches for the nearest ancestor of the indicated type that is
86 * registered and returns it. If no ancestor of the indicated type is
87 * registered, returns TypeHandle::none().
88 */
89 TypeHandle FactoryBase::
90 find_registered_type(TypeHandle handle) {
91 Creators::const_iterator ci = _creators.find(handle);
92 if (ci != _creators.end()) {
93 // This type is registered.
94 return handle;
95 }
96
97 // Recursively search through the entire inheritance tree until we find
98 // something we know about.
99 if (handle.get_num_parent_classes() == 0) {
100 return TypeHandle::none();
101 }
102
103 int num_parents = handle.get_num_parent_classes();
104 for (int i = 0; i < num_parents; i++) {
105 TypeHandle result = find_registered_type(handle.get_parent_class(i));
106 if (result != TypeHandle::none()) {
107 return result;
108 }
109 }
110
111 // No known types.
112 return TypeHandle::none();
113 }
114
115 /**
116 * Registers a new kind of thing the Factory will be able to create.
117 *
118 * @param user_data an optional pointer to be passed along to the function.
119 */
120 void FactoryBase::
121 register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data) {
122 nassertv(handle != TypeHandle::none());
123 nassertv(func != nullptr);
124
125 Creator creator;
126 creator._func = func;
127 creator._user_data = user_data;
128 _creators[handle] = creator;
129 }
130
131 /**
132 * Returns the number of different types the Factory knows how to create.
133 */
134 size_t FactoryBase::
135 get_num_types() const {
136 return _creators.size();
137 }
138
139 /**
140 * Returns the nth type the Factory knows how to create. This is not a
141 * terribly efficient function; it's included primarily for debugging output.
142 * Normally you wouldn't need to traverse the list of the Factory's types.
143 */
144 TypeHandle FactoryBase::
145 get_type(size_t n) const {
146 nassertr(n < get_num_types(), TypeHandle::none());
147 Creators::const_iterator ci;
148 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
149 if (n == 0) {
150 return (*ci).first;
151 }
152 n--;
153 }
154
155 // We shouldn't get here.
156 nassertr(false, TypeHandle::none());
157 return TypeHandle::none();
158 }
159
160 /**
161 * Empties the list of preferred types.
162 */
163 void FactoryBase::
164 clear_preferred() {
165 _preferred.clear();
166 }
167
168 /**
169 * Adds the indicated type to the end of the list of preferred types. On the
170 * next call to make_instance(), if the exact type requested cannot be
171 * created, the preferred types are first tried in the order specified.
172 */
173 void FactoryBase::
174 add_preferred(TypeHandle handle) {
175 nassertv(handle != TypeHandle::none());
176 _preferred.push_back(handle);
177 }
178
179 /**
180 * Returns the number of types added to the preferred-type list.
181 */
182 size_t FactoryBase::
183 get_num_preferred() const {
184 return _preferred.size();
185 }
186
187 /**
188 * Returns the nth type added to the preferred-type list.
189 */
190 TypeHandle FactoryBase::
191 get_preferred(size_t n) const {
192 nassertr(n < get_num_preferred(), TypeHandle::none());
193 return _preferred[n];
194 }
195
196 /**
197 * Writes a list of all known types the Factory can create to the indicated
198 * output stream, one per line.
199 */
200 void FactoryBase::
201 write_types(std::ostream &out, int indent_level) const {
202 Creators::const_iterator ci;
203 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
204 indent(out, indent_level) << (*ci).first << "\n";
205 }
206 }
207
208 /**
209 * Attempts to create an instance of the exact type requested by the given
210 * handle. Returns the new instance created, or NULL if the instance could
211 * not be created.
212 */
213 TypedObject *FactoryBase::
214 make_instance_exact(TypeHandle handle, FactoryParams params) {
215 Creators::const_iterator ci = _creators.find(handle);
216 if (ci == _creators.end()) {
217 return nullptr;
218 }
219
220 Creator creator = (*ci).second;
221 nassertr(creator._func != nullptr, nullptr);
222 params._user_data = creator._user_data;
223 return (*creator._func)(params);
224 }
225
226 /**
227 * Attempts to create an instance of some derived type of the type requested
228 * by the given handle. Returns the new instance created, or NULL if the
229 * instance could not be created.
230 */
231 TypedObject *FactoryBase::
232 make_instance_more_specific(TypeHandle handle, FactoryParams params) {
233 // First, walk through the established preferred list. Maybe one of these
234 // qualifies.
235
236 for (TypeHandle ptype : _preferred) {
237 if (ptype.is_derived_from(handle)) {
238 TypedObject *object = make_instance_exact(ptype, params);
239 if (object != nullptr) {
240 return object;
241 }
242 }
243 }
244
245 // No, we couldn't create anything on the preferred list, so create the
246 // first thing we know about that derives from the indicated type.
247 Creators::const_iterator ci;
248 for (ci = _creators.begin(); ci != _creators.end(); ++ci) {
249 TypeHandle ctype = (*ci).first;
250 if (ctype.is_derived_from(handle)) {
251 Creator creator = (*ci).second;
252 nassertr(creator._func != nullptr, nullptr);
253 params._user_data = creator._user_data;
254 TypedObject *object = (*creator._func)(params);
255 if (object != nullptr) {
256 return object;
257 }
258 }
259 }
260
261 return nullptr;
262 }
FactoryBase::register_factory
void register_factory(TypeHandle handle, BaseCreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factoryBase.cxx:121
FactoryBase::find_registered_type
TypeHandle find_registered_type(TypeHandle handle)
Returns the TypeHandle given, if it is a registered type, or if it is not registered,...
Definition: factoryBase.cxx:90
FactoryBase::write_types
void write_types(std::ostream &out, int indent_level=0) const
Writes a list of all known types the Factory can create to the indicated output stream,...
Definition: factoryBase.cxx:201
FactoryBase::get_type
TypeHandle get_type(size_t n) const
Returns the nth type the Factory knows how to create.
Definition: factoryBase.cxx:145
FactoryBase::make_instance
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:25
FactoryBase::get_num_preferred
size_t get_num_preferred() const
Returns the number of types added to the preferred-type list.
Definition: factoryBase.cxx:183
FactoryBase::add_preferred
void add_preferred(TypeHandle handle)
Adds the indicated type to the end of the list of preferred types.
Definition: factoryBase.cxx:174
FactoryBase::get_preferred
TypeHandle get_preferred(size_t n) const
Returns the nth type added to the preferred-type list.
Definition: factoryBase.cxx:191
FactoryBase::clear_preferred
void clear_preferred()
Empties the list of preferred types.
Definition: factoryBase.cxx:164
FactoryBase::make_instance_more_general
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:53
FactoryBase::get_num_types
size_t get_num_types() const
Returns the number of different types the Factory knows how to create.
Definition: factoryBase.cxx:135
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypeHandle::get_parent_class
get_parent_class
Returns the nth parent class of this type.
Definition: typeHandle.h:137
TypeHandle::is_derived_from
bool is_derived_from(TypeHandle parent, TypedObject *object=nullptr) const
Returns true if this type is derived from the indicated type, false otherwise.
Definition: typeHandle.I:105
TypeHandle::get_num_parent_classes
get_num_parent_classes
Returns the number of parent classes that this type is known to have.
Definition: typeHandle.h:137
TypedObject
This is an abstract class that all classes which use TypeHandle, and also provide virtual functions t...
Definition: typedObject.h:88
config_putil.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
factoryBase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
indent
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.