/*********************************************************************** * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * * All rights reserved. * * Distributed under the terms of the MIT License (see LICENSE.TXT). * **********************************************************************/ #ifndef ACGL_RESOURCE_FILEMANAGER_HH #define ACGL_RESOURCE_FILEMANAGER_HH /** * The FileManager and MultiFileManager are like the NameManager Singleton- * maps to access resources from everywhere by calling them by name. * In addition to the NameManager, these containers also feature the * functionality to reload all contained resources. For this it is important * that in addition to the resource and the name a Creator is also provided. * * Note that changes to the objects returned by these managers might get * destroyed in case the resource gets reloaded. The update() function * of the Creator should as far as possible transfer the state from the * old object to the new one, but this might not always work. * Note that declaring the object as const isn't always helpful as well * as for OpenGL objects the state often gets altered (e.g. uniforms are being set) * and disalowing the change of OpenGL states is not useful. * * To use one, create a FileManager for the resource: * * typedef Resource::FileManager FooFileManager; * * Then add your resources: * * SharedFoo foo = FooNameManager::the()->get( FooCreator("filename").option1().option2() ); * * And later query the resource: * * SharedFoo foo = FooNameManager::the()->query( "filename" ); * * If get() gets called more than once for the same resource, only one copy gets created. * * Per default the resource name is the filename (FileManager) or the concatenated list of * alphabetically ordered filenames (MultiFileManager). * The resource name can get explicitly set by (Multi)FileBasedCreator.setResourceName(). */ #include #include #include #include #include #include #include namespace ACGL{ namespace Resource{ template class FileManager : public Base::Singleton< FileManager > { ACGL_SINGLETON(FileManager) public: typedef ptr::shared_ptr< SingleFileBasedCreator > SharedController; ACGL_SMARTPOINTER_TYPEDEFS(RESOURCE) struct Resource { SharedController controller; SharedRESOURCE resource; }; typedef std::map ResourceMap; virtual ~FileManager() {} //! returns the resource and creates it if it isn't created yet. template SharedRESOURCE get(const CONTROLLER& _controller); //! returns the resource by name (or NULL if it isn't stored) SharedRESOURCE query(const std::string &_filename); //! test the existance of a resource bool exists(const std::string &_key); bool erase(const std::string &_key); void eraseAll(); //! update a specific resource bool update(const std::string& key); //! update all resources - will only update the resources if the file modification time has changed void updateAll(void); typename ResourceMap::const_iterator begin(void) const { return mResourceMap.begin(); } typename ResourceMap::const_iterator end(void) const { return mResourceMap.end(); } protected: FileManager(void) : mResourceMap() {} private: ResourceMap mResourceMap; }; template template typename FileManager::SharedRESOURCE FileManager::get(const CONTROLLER &_controller) { typename ResourceMap::iterator existingResource = mResourceMap.find(_controller.getResourceName()); if(existingResource != mResourceMap.end()) return existingResource->second.resource; SharedController pController(new CONTROLLER(_controller)); SharedRESOURCE pResource = pController->create(); if(pResource) { Resource resource = { pController, pResource }; mResourceMap[_controller.getResourceName()] = resource; //Utils::debug() << "FileManager::getResource: Resource loaded: " << _controller.getResourceName() << std::endl; return pResource; } else { Utils::error() << "FileManager::getResource: Resource could not be loaded: " << _controller.getResourceName() << std::endl; } return SharedRESOURCE(); } template typename FileManager::SharedRESOURCE FileManager::query(const std::string &_key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return existingResource->second.resource; return ConstSharedRESOURCE(); } template bool FileManager::exists(const std::string &_key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return true; return false; } template bool FileManager::erase(const std::string &_key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) { mResourceMap.erase(existingResource); Utils::debug() << "FileManager::Resource deleted: " << _key << std::endl; return true; } Utils::warning() << "FileManager::Resource not found for deletion! " << std::endl; return false; } template void FileManager::eraseAll() { mResourceMap.clear(); } template bool FileManager::update(const std::string& _key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return existingResource->second.controller->update(existingResource->second.resource); return false; } template void FileManager::updateAll(void) { for(typename ResourceMap::iterator i = mResourceMap.begin(); i != mResourceMap.end(); ++i) i->second.controller->update(i->second.resource); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: merge FileManager & MultiFileManager //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template class MultiFileManager : public Base::Singleton< MultiFileManager > { ACGL_SINGLETON(MultiFileManager) public: typedef ptr::shared_ptr< MultiFileBasedCreator > SharedController; ACGL_SMARTPOINTER_TYPEDEFS(RESOURCE) struct Resource { SharedController controller; SharedRESOURCE resource; }; typedef std::map ResourceMap; virtual ~MultiFileManager(void) {} template SharedRESOURCE get(const CONTROLLER& _controller); SharedRESOURCE query(const std::string& _filename); bool exists(const std::string& _key); bool erase(const std::string& key); void eraseAll(void); bool update(const std::string& key); void updateAll(void); typename ResourceMap::const_iterator begin(void) const { return mResourceMap.begin(); } typename ResourceMap::const_iterator end(void) const { return mResourceMap.end(); } protected: MultiFileManager(void) : mResourceMap() {} private: ResourceMap mResourceMap; }; template template typename MultiFileManager::SharedRESOURCE MultiFileManager::get(const CONTROLLER& _controller) { typename ResourceMap::iterator existingResource = mResourceMap.find(_controller.getResourceName()); if(existingResource != mResourceMap.end()) return existingResource->second.resource; SharedController pController(new CONTROLLER(_controller)); SharedRESOURCE pResource = pController->create(); if(pResource) { Resource resource = { pController, pResource }; mResourceMap[_controller.getResourceName()] = resource; //Utils::debug() << "FileManager::getResource: Resource loaded: " << _controller.getResourceName() << std::endl; return pResource; } else { Utils::error() << "FileManager::getResource: Resource could not be loaded: " << _controller.getResourceName() << std::endl; } return SharedRESOURCE(); } template typename MultiFileManager::SharedRESOURCE MultiFileManager::query(const std::string& _key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return existingResource->second.resource; return ConstSharedRESOURCE(); } template bool MultiFileManager::exists(const std::string& _key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return true; return false; } template bool MultiFileManager::erase(const std::string& _key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) { mResourceMap.erase(existingResource); Utils::debug() << "FileManager::Resource deleted: " << _key << std::endl; return true; } Utils::warning() << "FileManager::Resource not found for deletion! " << std::endl; return false; } template void MultiFileManager::eraseAll(void) { mResourceMap.clear(); } template bool MultiFileManager::update(const std::string& _key) { typename ResourceMap::iterator existingResource = mResourceMap.find(_key); if(existingResource != mResourceMap.end()) return existingResource->second.controller->update(existingResource->second.resource); return false; } template void MultiFileManager::updateAll(void) { for(typename ResourceMap::iterator i = mResourceMap.begin(); i != mResourceMap.end(); ++i) i->second.controller->update(i->second.resource); } } // Resource } // ACGL #endif // ACGL_RESOURCE_NAMEMANAGER_HH