Crazy Eddies GUI System 0.7.5
CEGUINamedXMLResourceManager.h
00001 /***********************************************************************
00002     filename:   CEGUINamedXMLResourceManager.h
00003     created:    Fri Jul 17 2009
00004     author:     Paul D Turner <paul@cegui.org.uk>
00005 *************************************************************************/
00006 /***************************************************************************
00007  *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
00008  *
00009  *   Permission is hereby granted, free of charge, to any person obtaining
00010  *   a copy of this software and associated documentation files (the
00011  *   "Software"), to deal in the Software without restriction, including
00012  *   without limitation the rights to use, copy, modify, merge, publish,
00013  *   distribute, sublicense, and/or sell copies of the Software, and to
00014  *   permit persons to whom the Software is furnished to do so, subject to
00015  *   the following conditions:
00016  *
00017  *   The above copyright notice and this permission notice shall be
00018  *   included in all copies or substantial portions of the Software.
00019  *
00020  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00022  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00023  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00024  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00025  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00026  *   OTHER DEALINGS IN THE SOFTWARE.
00027  ***************************************************************************/
00028 #ifndef _CEGUINamedXMLResourceManager_h_
00029 #define _CEGUINamedXMLResourceManager_h_
00030 
00031 #include "CEGUIEventSet.h"
00032 #include "CEGUIString.h"
00033 #include "CEGUIExceptions.h"
00034 #include "CEGUILogger.h"
00035 #include "CEGUIInputEvent.h"
00036 #include "CEGUISystem.h"
00037 #include <map>
00038 
00039 // Start of CEGUI namespace section
00040 namespace CEGUI
00041 {
00043 enum XMLResourceExistsAction
00044 {
00046     XREA_RETURN,
00048     XREA_REPLACE,
00050     XREA_THROW
00051 };
00052 
00053 //----------------------------------------------------------------------------//
00054 
00056 class CEGUIEXPORT ResourceEventSet : public EventSet
00057 {
00058 public:
00060     static const String EventNamespace;
00067     static const String EventResourceCreated;
00074     static const String EventResourceDestroyed;
00081     static const String EventResourceReplaced;
00082 };
00083 
00084 //----------------------------------------------------------------------------//
00085 
00108 template<typename T, typename U>
00109 class NamedXMLResourceManager : public ResourceEventSet
00110 {
00111 public:
00121     NamedXMLResourceManager(const String& resource_type);
00122 
00124     virtual ~NamedXMLResourceManager();
00125 
00148     T& create(const String& xml_filename, const String& resource_group = "",
00149               XMLResourceExistsAction action = XREA_RETURN);
00150 
00159     void destroy(const String& object_name);
00160 
00170     void destroy(const T& object);
00171 
00173     void destroyAll();
00174 
00185     T& get(const String& object_name) const;
00186 
00188     bool isDefined(const String& object_name) const;
00189 
00191     void createAll(const String& pattern, const String& resource_group);
00192 
00193 protected:
00195     typedef std::map<String, T*, String::FastLessCompare> ObjectRegistry;
00197     void destroyObject(typename ObjectRegistry::iterator ob);
00199     T& doExistingObjectAction(const String object_name, T* object,
00200                               const XMLResourceExistsAction action);
00202     virtual void doPostObjectAdditionAction(T& object);
00204     const String d_resourceType;
00206     ObjectRegistry d_objects;
00207 };
00208 
00209 //----------------------------------------------------------------------------//
00210 template<typename T, typename U>
00211 NamedXMLResourceManager<T, U>::NamedXMLResourceManager(
00212         const String& resource_type) :
00213     d_resourceType(resource_type)
00214 {
00215 }
00216 
00217 //----------------------------------------------------------------------------//
00218 template<typename T, typename U>
00219 NamedXMLResourceManager<T, U>::~NamedXMLResourceManager()
00220 {
00221 }
00222 
00223 //----------------------------------------------------------------------------//
00224 template<typename T, typename U>
00225 T& NamedXMLResourceManager<T, U>::create(const String& xml_filename,
00226                                         const String& resource_group,
00227                                         XMLResourceExistsAction action)
00228 {
00229     U xml_loader(xml_filename, resource_group);
00230     return doExistingObjectAction(xml_loader.getObjectName(),
00231                                   &xml_loader.getObject(), action);
00232 }
00233 
00234 //----------------------------------------------------------------------------//
00235 template<typename T, typename U>
00236 void NamedXMLResourceManager<T, U>::destroy(const String& object_name)
00237 {
00238     typename ObjectRegistry::iterator i(d_objects.find(object_name));
00239 
00240     // exit if no such object.
00241     if (i == d_objects.end())
00242         return;
00243 
00244     destroyObject(i);
00245 }
00246 
00247 //----------------------------------------------------------------------------//
00248 template<typename T, typename U>
00249 void NamedXMLResourceManager<T, U>::destroy(const T& object)
00250 {
00251     // don't want to force a 'getName' function on T here, so we'll look for the
00252     // object the hard way.
00253     typename ObjectRegistry::iterator i(d_objects.begin());
00254     for (; i != d_objects.end(); ++i)
00255         if (i->second == &object)
00256         {
00257             destroyObject(i);
00258             return;
00259         }
00260 }
00261 
00262 //----------------------------------------------------------------------------//
00263 template<typename T, typename U>
00264 void NamedXMLResourceManager<T, U>::destroyAll()
00265 {
00266     while (!d_objects.empty())
00267         destroyObject(d_objects.begin());
00268 }
00269 
00270 //----------------------------------------------------------------------------//
00271 template<typename T, typename U>
00272 T& NamedXMLResourceManager<T, U>::get(const String& object_name) const
00273 {
00274     typename ObjectRegistry::const_iterator i(d_objects.find(object_name));
00275 
00276     if (i == d_objects.end())
00277         CEGUI_THROW(UnknownObjectException("NamedXMLResourceManager::get: "
00278             "No object of type '" + d_resourceType + "' named '" + object_name +
00279             "' is present in the collection."));
00280 
00281     return *i->second;
00282 }
00283 
00284 //----------------------------------------------------------------------------//
00285 template<typename T, typename U>
00286 bool NamedXMLResourceManager<T, U>::isDefined(const String& object_name) const
00287 {
00288     return d_objects.find(object_name) != d_objects.end();
00289 }
00290 
00291 //----------------------------------------------------------------------------//
00292 template<typename T, typename U>
00293 void NamedXMLResourceManager<T, U>::destroyObject(
00294         typename ObjectRegistry::iterator ob)
00295 {
00296     char addr_buff[32];
00297     sprintf(addr_buff, "(%p)", static_cast<void*>(ob->second));
00298     Logger::getSingleton().logEvent("Object of type '" + d_resourceType +
00299         "' named '" + ob->first + "' has been destroyed. " +
00300         addr_buff, Informative);
00301 
00302     // Set up event args for event notification
00303     ResourceEventArgs args(d_resourceType, ob->first);
00304 
00305     delete ob->second;
00306     d_objects.erase(ob);
00307 
00308     // fire event signalling an object has been destroyed
00309     fireEvent(EventResourceDestroyed, args, EventNamespace);
00310 }
00311 
00312 //----------------------------------------------------------------------------//
00313 template<typename T, typename U>
00314 T& NamedXMLResourceManager<T, U>::doExistingObjectAction(
00315     const String object_name,
00316     T* object,
00317     const XMLResourceExistsAction action)
00318 {
00319     String event_name;
00320 
00321     if (isDefined(object_name))
00322     {
00323         switch (action)
00324         {
00325         case XREA_RETURN:
00326             Logger::getSingleton().logEvent("---- Returning existing instance "
00327                 "of " + d_resourceType + " named '" + object_name + "'.");
00328             // delete any new object we already had created
00329             delete object;
00330             // return existing instance of object.
00331             return *d_objects[object_name];
00332 
00333         case XREA_REPLACE:
00334             Logger::getSingleton().logEvent("---- Replacing existing instance "
00335                 "of " + d_resourceType + " named '" + object_name +
00336                 "' (DANGER!).");
00337             destroy(object_name);
00338             event_name = EventResourceReplaced;
00339             break;
00340 
00341         case XREA_THROW:
00342             delete object;
00343             CEGUI_THROW(AlreadyExistsException(
00344                 "NamedXMLResourceManager::checkExistingObjectAction: "
00345                 "an object of type '" + d_resourceType + "' named '" +
00346                 object_name + "' already exists in the collection."));
00347 
00348         default:
00349             delete object;
00350             CEGUI_THROW(InvalidRequestException(
00351                 "NamedXMLResourceManager::checkExistingObjectAction: "
00352                 "Invalid CEGUI::XMLResourceExistsAction was specified."));
00353         }
00354     }
00355     else
00356         event_name = EventResourceCreated;
00357 
00358     d_objects[object_name] = object;
00359     doPostObjectAdditionAction(*object);
00360 
00361     // fire event about this resource change
00362     ResourceEventArgs args(d_resourceType, object_name);
00363     fireEvent(event_name, args, EventNamespace);
00364 
00365     return *object;
00366 }
00367 
00368 //----------------------------------------------------------------------------//
00369 template<typename T, typename U>
00370 void NamedXMLResourceManager<T, U>::doPostObjectAdditionAction(T& /*object*/)
00371 {
00372     // do nothing by default.
00373 }
00374 
00375 //----------------------------------------------------------------------------//
00376 template<typename T, typename U>
00377 void NamedXMLResourceManager<T, U>::createAll(const String& pattern,
00378                                               const String& resource_group)
00379 {
00380     std::vector<String> names;
00381     const size_t num = System::getSingleton().getResourceProvider()->
00382         getResourceGroupFileNames(names, pattern, resource_group);
00383 
00384     for (size_t i = 0; i < num; ++i)
00385         create(names[i], resource_group);
00386 }
00387 
00388 //----------------------------------------------------------------------------//
00389 
00390 } // End of  CEGUI namespace section
00391 
00392 #endif  // end of guard _CEGUINamedXMLResourceManager_h_