00001 /*************************************************************************** 00002 * * 00003 * (c) Art Tevs, MPI Informatik Saarbruecken * 00004 * mailto: <tevs@mpi-sb.mpg.de> * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 2 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 ***************************************************************************/ 00012 00013 00014 #ifndef _NR_RESOURCE_FACTORY_H_ 00015 #define _NR_RESOURCE_FACTORY_H_ 00016 00017 00018 //---------------------------------------------------------------------------------- 00019 // Includes 00020 //---------------------------------------------------------------------------------- 00021 #include "Prerequisities.h" 00022 #include "ResourceSystem.h" 00023 #include <boost/enable_shared_from_this.hpp> 00024 00025 namespace nrEngine{ 00026 00027 00028 //! Factory class to built instances of resources 00029 /** 00030 * Resource factory is used to create instances of resource objects. 00031 * Each resource factory has a list of supported resources types. The resource 00032 * manager can access the previously registered factories to create instances 00033 * of resources. 00034 * 00035 * Loading of resource itself is done in the resource class. Factories are 00036 * only used to create instances. Factories should also be able to create instances 00037 * of empty resources. 00038 * 00039 * Resource factory should be registered by the resource manager to give him a 00040 * possibility to create or to delete resource instances. 00041 * system on compiling layer/level. 00042 * 00043 * Factories have got a method which says to the manager what kind of resource types 00044 * it supports. By creating of a resource, you should specify the type of to be 00045 * created resource. Manager will look in the database, wich factory can create an instance 00046 * of such a type and will force it to create an instance. 00047 * 00048 * Factories are strongly associated within created resources. This means that if factory 00049 * is removed from the memory, then also all created resource will be removed. This behaviour 00050 * is needed, because otherwise we could get segmentation faults if you use resources from 00051 * plugins ala dynamic libraries. 00052 * 00053 * Resource factory can also let you know which file types are supported by the supported 00054 * resource types. So you can find out if resource factory can handle resources 00055 * @note File types and resource types are case sensitive. So *.png and *.PNG are different file types. 00056 * 00057 * \ingroup resource 00058 **/ 00059 class _NRExport ResourceFactory : public boost::enable_shared_from_this<ResourceFactory>{ 00060 public: 00061 00062 /** 00063 * Remove factory instance. Removing will cause created resources also to be removed 00064 **/ 00065 virtual ~ResourceFactory(); 00066 00067 /** 00068 * Create an instance of appropriate resource object. Like <code>new ResourceType()</code> 00069 * 00070 * @param resourceType Unique name of the resource type to be created 00071 * @param params Default is NULL, so no parameters. Specify here pairs of string that 00072 * represents the parameters for the creating functions. The derived 00073 * resource loader should know how to handle with them. 00074 * @return Instance of such a resource 00075 * 00076 * @note When creating there also will be a check if an empty resource of such a 00077 * type already exists. If no, then empty resource will be created and registered in the 00078 * database. 00079 **/ 00080 SharedPtr<IResource> createResource(const std::string& resourceType, PropertyList* params = NULL); 00081 00082 /** 00083 * @copydoc ResourceFactory::createResource() 00084 * @param name Unique name of the resource 00085 * @param group Unique group name of the resource 00086 **/ 00087 SharedPtr<IResource> createResource(const std::string& name, const std::string& group, const std::string& resourceType, PropertyList* params = NULL); 00088 00089 /** 00090 * @return A vector of strings containing all supported resource types 00091 **/ 00092 NR_FORCEINLINE const std::vector<std::string>& getSupportedResourceTypes(){return mSupportedResourceTypes;} 00093 00094 /** 00095 * @return A vector of string cotntainign all supported file types 00096 **/ 00097 NR_FORCEINLINE const std::vector<std::string>& getSupportedFileTypes(){return mSupportedFileTypes;} 00098 00099 /** 00100 * Check if the factory does support creating of resource of the given 00101 * resource type. 00102 * 00103 * @param resourceType Unique name of the resource type 00104 * @return <b>true</b> if resource type is supported, otherwise false 00105 **/ 00106 bool supportResourceType(const std::string& resourceType) const; 00107 00108 /** 00109 * Check whenever the factory can handle given file types. 00110 * 00111 * @param fileType File type name 00112 * @return <b>true</b> if resource instances of this file type are supported 00113 **/ 00114 bool supportFileType(const std::string& fileType) const ; 00115 00116 /** 00117 * Unload the given resource. Unloading of a resource does not mean that the 00118 * resource is removed from the memory. It just release almost all used 00119 * memory and an empty resource will be used instead. To remove it completly 00120 * from the memory call remove() instead. 00121 * 00122 * This method will be called by the manager or the resource, as soon as a resource must 00123 * be unloaded. 00124 **/ 00125 Result unload(SharedPtr<IResource> resource); 00126 00127 /** 00128 * Remove the resource from the memory. This method will be called 00129 * by the resource manager, so the loader can do the stuff needed 00130 * to remove the resource. 00131 **/ 00132 Result remove(SharedPtr<IResource> resource); 00133 00134 /** 00135 * Reload a certain resource again. A resource object has to be created before. 00136 * If the resource object is loaded, so it will be unloaded and loaded again. Also 00137 * the resource object will be notified about this event, so it can react on this. 00138 * No new instancies will be created. 00139 **/ 00140 Result reload(SharedPtr<IResource> resource); 00141 00142 00143 protected: 00144 00145 /** 00146 * Unload a certain resource from the memory. 00147 * To unload a resource the IResource::unloadRes() method will be called. Herefor 00148 * each resource should know how to release it's data. However you can overwrite 00149 * this method in derived classes to change this default behaviour. 00150 * 00151 * @param res Pointer to the resource which should be unloaded 00152 * 00153 **/ 00154 virtual Result unloadResourceImpl(IResource* res); 00155 00156 /** 00157 * Each derived class has to implement a bahaviour of reloading 00158 * of a resource. This method will be called to reload a given 00159 * resource object from the file again. All according data is already 00160 * stored in the resource only the data from the file must be reloaded. 00161 * 00162 * The default behaviour of this method is to call loadImpl() again 00163 * with the given resource object and a file name (as user parameters the 00164 * NULL will be passed). 00165 * @param res Resource to be reloaded 00166 **/ 00167 virtual Result reloadResourceImpl(IResource* res); 00168 00169 /** 00170 * Derived classes must overload this function. This method 00171 * should load a resource for a given file name 00172 * 00173 * @param res Resource instance created before with create() 00174 * @param fileName Name of the file containing the resource 00175 * @param param Specific parameters specified by the user 00176 **/ 00177 virtual Result loadResourceImpl(IResource* res, const std::string& fileName, PropertyList* param = NULL) = 0; 00178 00179 /** 00180 * Implement this function to provide functionaliy 00181 * of creating resources of certain types. In this function you do not 00182 * have to check whenever the given resourceType string is valid. This 00183 * method can only be called from the base class, which does already 00184 * have checked this. 00185 * 00186 **/ 00187 virtual IResource* createResourceImpl(const std::string& resourceType, PropertyList* params = NULL) = 0; 00188 00189 /** 00190 * Creating of an empty resource object. An empty resource object can be used in 00191 * normal way but contains no data. 00192 * 00193 * @param resourceType Unique name of the resource type to be created 00194 * @return Instance of empty resource 00195 **/ 00196 virtual IResource* createEmptyResource(const std::string& resourceType) = 0; 00197 00198 /** 00199 * Call this function to initilize the loader. Usually initialization of the 00200 * loader does declare supported file and resource types. So because this function 00201 * is pure virtual it must overloaded by derived classes. 00202 * 00203 * This method should be called from the constructor, to declare supported types. 00204 **/ 00205 virtual Result initializeResourceLoader() = 0; 00206 00207 /** 00208 * 00209 **/ 00210 IResourceLoader(const std::string& name); 00211 00212 /** 00213 * Map a certain file type to the resource type. Call this method if 00214 * you want to find out resources of which types will be created 00215 * if you use this filetype. 00216 * 00217 * @param fileType Type of the file (ending *.so, *.bmp, ...) 00218 * @return resource type name which will be create for this file type. If 00219 * the given file type is not supported empty string will be given back 00220 **/ 00221 NR_FORCEINLINE std::string mapFileTypeToResourceType(const std::string& fileType) 00222 { 00223 std::map<std::string, std::string>::const_iterator it = mTypeMap.find(fileType); 00224 if (it == mTypeMap.end()) return std::string(); 00225 return it->second; 00226 } 00227 00228 /** 00229 * Declare the mapping of file types to resource types. 00230 * NOTE: You have to specify supported types before 00231 **/ 00232 NR_FORCEINLINE void declareTypeMap(const std::string& fileType, const std::string& resourceType) 00233 { 00234 if (supportResourceType(resourceType) && supportFileType(fileType)) 00235 mTypeMap[fileType] = resourceType; 00236 } 00237 00238 /** 00239 * Internal function which must be called by all derived classes to 00240 * setup all supported resource types. 00241 * @param name Unique name of supported resource type 00242 */ 00243 NR_FORCEINLINE void declareSupportedResourceType(const std::string& name){ 00244 mSupportedResourceTypes.push_back(name); 00245 } 00246 00247 /** 00248 * Internal function which must be called by all derived classes to 00249 * setup all supported file types. 00250 * @param name Unique name of file type which is supported by the derived loader 00251 */ 00252 NR_FORCEINLINE void declareSupportedFileType(const std::string& name) 00253 { 00254 mSupportedFileTypes.push_back(name); 00255 } 00256 00257 /** 00258 * This method will return back a proper suffix according to the resource type. 00259 * Derived classes should overwrite this method, because they know which suffix 00260 * are proper to use. The suffix does not contain dot. Empty suffixes are possible. 00261 * @param resType Resource type for which one suffix is generated 00262 **/ 00263 virtual std::string getSuffix(const std::string& resType){return std::string();} 00264 00265 00266 private: 00267 00268 //! List of supported resource types 00269 std::vector< std::string > mSupportedResourceTypes; 00270 00271 //! List of supported file types 00272 std::vector< std::string > mSupportedFileTypes; 00273 00274 //! Mapping from file type to resource type 00275 std::map<std::string, std::string> mTypeMap; 00276 00277 //! Unuque name of the loader 00278 std::string mName; 00279 00280 typedef std::list< SharedPtr<IResource> > ResourceList; 00281 00282 //! List of resources managed by this loader 00283 ResourceList mHandledResources; 00284 00285 /** 00286 * Get shared pointer from this class 00287 **/ 00288 SharedPtr<IResourceLoader> getSharedPtrFromThis() 00289 { 00290 return shared_from_this(); 00291 } 00292 00293 /** 00294 * Notify the resource loader that a certain resource object 00295 * will be removed from the memory now. 00296 **/ 00297 void notifyRemoveResource(SharedPtr<IResource>); 00298 00299 /** 00300 * Notify unload resource. The method can be called either 00301 * from resource manager or by the resource itself 00302 **/ 00303 void notifyUnloadResource(SharedPtr<IResource>); 00304 00305 }; 00306 00307 }; 00308 00309 #endif