Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

TypeFactory.cc

Go to the documentation of this file.
00001 // -*- C++ -*- 00002 00003 // TypeFactory.cc 00004 // Copyright (c) 2001 by Nicolas Chapados 00005 // Copyright (c) 2003 Pascal Vincent 00006 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 00036 #include "Object.h" 00037 #include "stringutils.h" 00038 #include "TypeFactory.h" 00039 00040 namespace PLearn { 00041 using namespace std; 00042 00043 //##### TypeFactory ######################################################### 00044 00045 void TypeFactory::register_type(const string& type_name, 00046 const string& parent_class, 00047 NEW_OBJECT constructor, 00048 GETOPTIONLIST_METHOD getoptionlist_method, 00049 ISA_METHOD isa_method, 00050 const string& one_line_descr, 00051 const string& multi_line_help) 00052 { 00053 TypeMapEntry entry(type_name, 00054 parent_class, 00055 constructor, 00056 getoptionlist_method, 00057 isa_method, 00058 one_line_descr, 00059 multi_line_help); 00060 00061 instance().registerType(entry); 00062 } 00063 00064 void TypeFactory::registerType(const TypeMapEntry& entry) 00065 { 00066 type_map_.insert( pair<string,TypeMapEntry>(entry.type_name, entry) ); 00067 //cout << "register type " << type_name << endl; 00068 } 00069 00070 void TypeFactory::unregisterType(string type_name) 00071 { 00072 type_map_.erase(type_name); // ok even if does not exist 00073 } 00074 00075 bool TypeFactory::isRegistered(string type_name) const 00076 { 00077 return type_map_.find(type_name)!=type_map_.end(); 00078 } 00079 00080 Object* TypeFactory::newObject(string type_name) const 00081 { 00082 TypeMap::const_iterator it = type_map_.find(type_name); 00083 if (it == type_map_.end()) 00084 PLERROR("In TypeFactory::newObject(\"%s\"): %s not registered in type map.", type_name.c_str(), type_name.c_str()); 00085 if (!(*it->second.constructor)) 00086 PLERROR("In TypeFactory::newObject(\"%s\"): %s does not have a factory constructor!", type_name.c_str(), type_name.c_str()); 00087 return (*it->second.constructor)(); 00088 } 00089 00090 bool TypeFactory::isAbstract(string type_name) const 00091 { 00092 TypeMap::const_iterator it = type_map_.find(type_name); 00093 if (it == type_map_.end()) 00094 PLERROR("In TypeFactory: %s not registered in type map.", type_name.c_str(), type_name.c_str()); 00095 return it->second.constructor == 0; 00096 } 00097 00098 TypeFactory& TypeFactory::instance() 00099 { 00100 static TypeFactory instance_; 00101 return instance_; 00102 } 00103 00104 00105 void displayObjectHelp(ostream& out, const string& classname) 00106 { 00107 const TypeMap& type_map = TypeFactory::instance().getTypeMap(); 00108 TypeMap::const_iterator it = type_map.find(classname); 00109 TypeMap::const_iterator itend = type_map.end(); 00110 00111 if(it==itend) 00112 PLERROR("Object type %s unknown.\n" 00113 "Did you #include it, does it call the IMPLEMENT_NAME_AND_DEEPCOPY macro?\n" 00114 "and has it indeed been linked with your program?", classname.c_str()); 00115 00116 const TypeMapEntry& entry = it->second; 00117 Object* obj = 0; 00118 00119 out << "****************************************************************** \n" 00120 << "** " << classname << "\n" 00121 << "****************************************************************** \n" << endl; 00122 00123 // Display basic help 00124 out << entry.one_line_descr << endl << endl; 00125 out << entry.multi_line_help << endl << endl; 00126 00127 if(entry.constructor) // it's an instantiable class 00128 obj = (*entry.constructor)(); 00129 else 00130 out << "Note: " << classname << " is a base-class with pure virtual methods that cannot be instantiated directly.\n" 00131 << "(default values for build options can only be displayed for instantiable classes, \n" 00132 << " so you'll only see question marks here.)\n" << endl; 00133 00134 out << "****************************************************************** \n" 00135 << "** Build Options ** \n" 00136 << "** (including those inherited from parent and ancestor classes) ** \n" 00137 << "****************************************************************** \n" << endl; 00138 00139 out << classname + "( \n"; 00140 OptionList& options = (*entry.getoptionlist_method)(); 00141 00142 for( OptionList::iterator olIt = options.begin(); olIt!=options.end(); ++olIt ) 00143 { 00144 OptionBase::flag_t flags = (*olIt)->flags(); 00145 if(flags & OptionBase::buildoption) 00146 { 00147 string descr = (*olIt)->description(); 00148 string optname = (*olIt)->optionname(); 00149 string opttype = (*olIt)->optiontype(); 00150 string defaultval = "?"; 00151 if(obj) // it's an instantiable class 00152 { 00153 defaultval = (*olIt)->defaultval(); 00154 if(defaultval=="") 00155 defaultval = (*olIt)->writeIntoString(obj); 00156 } 00157 // string holderclass = (*olIt)->optionHolderClassName(this); 00158 out << addprefix("# ", opttype + ": " + descr); 00159 out << optname + " = " + defaultval + " ;\n\n"; 00160 } 00161 } 00162 out << ");\n\n"; 00163 00164 if(obj) 00165 delete obj; 00166 00167 out << "****************************************************************** \n" 00168 << "** Subclasses of " << classname << " \n" 00169 << "** (only those that can be instantiated) \n" 00170 << "****************************************************************** \n" << endl; 00171 for(it = type_map.begin(); it!=itend; ++it) 00172 { 00173 // cerr << "Attempting to instantiate: " << it->first << endl; 00174 const TypeMapEntry& e = it->second; 00175 if(e.constructor && it->first!=classname) 00176 { 00177 Object* o = (*e.constructor)(); 00178 if( (*entry.isa_method)(o) ) 00179 out << it->first << " "; 00180 if(o) 00181 delete o; 00182 } 00183 } 00184 00185 out << "\n\n------------------------------------------------------------------ \n" << endl; 00186 00187 } 00188 00189 00190 00191 } // end of namespace PLearn

Generated on Tue Aug 17 16:09:14 2004 for PLearn by doxygen 1.3.7