Crazy Eddie's GUI System  0.8.4
NamedXMLResourceManager.h
00001 /***********************************************************************
00002     created:    Fri Jul 17 2009
00003     author:     Paul D Turner <paul@cegui.org.uk>
00004 *************************************************************************/
00005 /***************************************************************************
00006  *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
00007  *
00008  *   Permission is hereby granted, free of charge, to any person obtaining
00009  *   a copy of this software and associated documentation files (the
00010  *   "Software"), to deal in the Software without restriction, including
00011  *   without limitation the rights to use, copy, modify, merge, publish,
00012  *   distribute, sublicense, and/or sell copies of the Software, and to
00013  *   permit persons to whom the Software is furnished to do so, subject to
00014  *   the following conditions:
00015  *
00016  *   The above copyright notice and this permission notice shall be
00017  *   included in all copies or substantial portions of the Software.
00018  *
00019  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00020  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00021  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00022  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00023  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00024  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  *   OTHER DEALINGS IN THE SOFTWARE.
00026  ***************************************************************************/
00027 #ifndef _CEGUINamedXMLResourceManager_h_
00028 #define _CEGUINamedXMLResourceManager_h_
00029 
00030 #include "CEGUI/EventSet.h"
00031 #include "CEGUI/String.h"
00032 #include "CEGUI/Exceptions.h"
00033 #include "CEGUI/Logger.h"
00034 #include "CEGUI/InputEvent.h"
00035 #include "CEGUI/System.h"
00036 #include <map>
00037 
00038 // Start of CEGUI namespace section
00039 namespace CEGUI
00040 {
00042 enum XMLResourceExistsAction
00043 {
00045     XREA_RETURN,
00047     XREA_REPLACE,
00049     XREA_THROW
00050 };
00051 
00052 //----------------------------------------------------------------------------//
00053 
00055 class CEGUIEXPORT ResourceEventSet : public EventSet
00056 {
00057 public:
00059     static const String EventNamespace;
00066     static const String EventResourceCreated;
00073     static const String EventResourceDestroyed;
00080     static const String EventResourceReplaced;
00081 };
00082 
00083 //----------------------------------------------------------------------------//
00084 
00107 template<typename T, typename U>
00108 class NamedXMLResourceManager : public ResourceEventSet
00109 {
00110 public:
00120     NamedXMLResourceManager(const String& resource_type);
00121 
00123     virtual ~NamedXMLResourceManager();
00124 
00142     T& createFromContainer(const RawDataContainer& source,
00143                            XMLResourceExistsAction action = XREA_RETURN);
00144 
00167     T& createFromFile(const String& xml_filename, const String& resource_group = "",
00168                       XMLResourceExistsAction action = XREA_RETURN);
00169 
00187     T& createFromString(const String& source,
00188                         XMLResourceExistsAction action = XREA_RETURN);
00189 
00198     void destroy(const String& object_name);
00199 
00209     void destroy(const T& object);
00210 
00212     void destroyAll();
00213 
00224     T& get(const String& object_name) const;
00225 
00227     bool isDefined(const String& object_name) const;
00228 
00230     void createAll(const String& pattern, const String& resource_group);
00231 
00232 protected:
00233     // singleton allocator fits here, resource managers are very likely to be singletons
00235     typedef std::map<String, T*, StringFastLessCompare
00236         CEGUI_MAP_ALLOC(String, T*)> ObjectRegistry;
00238     void destroyObject(typename ObjectRegistry::iterator ob);
00240     T& doExistingObjectAction(const String object_name, T* object,
00241                               const XMLResourceExistsAction action);
00243     virtual void doPostObjectAdditionAction(T& object);
00245     const String d_resourceType;
00247     ObjectRegistry d_objects;
00248 };
00249 
00250 //----------------------------------------------------------------------------//
00251 template<typename T, typename U>
00252 NamedXMLResourceManager<T, U>::NamedXMLResourceManager(
00253         const String& resource_type) :
00254     d_resourceType(resource_type)
00255 {
00256 }
00257 
00258 //----------------------------------------------------------------------------//
00259 template<typename T, typename U>
00260 NamedXMLResourceManager<T, U>::~NamedXMLResourceManager()
00261 {
00262 }
00263 
00264 //----------------------------------------------------------------------------//
00265 template<typename T, typename U>
00266 T& NamedXMLResourceManager<T, U>::createFromContainer(const RawDataContainer& source,
00267                                                       XMLResourceExistsAction action)
00268 {
00269     U xml_loader;
00270 
00271     xml_loader.handleContainer(source);
00272     return doExistingObjectAction(xml_loader.getObjectName(),
00273                                   &xml_loader.getObject(), action);
00274 }
00275 
00276 //----------------------------------------------------------------------------//
00277 template<typename T, typename U>
00278 T& NamedXMLResourceManager<T, U>::createFromFile(const String& xml_filename,
00279                                                  const String& resource_group,
00280                                                  XMLResourceExistsAction action)
00281 {
00282     U xml_loader;
00283 
00284     xml_loader.handleFile(xml_filename, resource_group);
00285     return doExistingObjectAction(xml_loader.getObjectName(),
00286                                   &xml_loader.getObject(), action);
00287 }
00288 
00289 //----------------------------------------------------------------------------//
00290 template<typename T, typename U>
00291 T& NamedXMLResourceManager<T, U>::createFromString(const String& source,
00292                                                    XMLResourceExistsAction action)
00293 {
00294     U xml_loader;
00295 
00296     xml_loader.handleString(source);
00297     return doExistingObjectAction(xml_loader.getObjectName(),
00298                                   &xml_loader.getObject(), action);
00299 }
00300 
00301 //----------------------------------------------------------------------------//
00302 template<typename T, typename U>
00303 void NamedXMLResourceManager<T, U>::destroy(const String& object_name)
00304 {
00305     typename ObjectRegistry::iterator i(d_objects.find(object_name));
00306 
00307     // exit if no such object.
00308     if (i == d_objects.end())
00309         return;
00310 
00311     destroyObject(i);
00312 }
00313 
00314 //----------------------------------------------------------------------------//
00315 template<typename T, typename U>
00316 void NamedXMLResourceManager<T, U>::destroy(const T& object)
00317 {
00318     // don't want to force a 'getName' function on T here, so we'll look for the
00319     // object the hard way.
00320     typename ObjectRegistry::iterator i(d_objects.begin());
00321     for (; i != d_objects.end(); ++i)
00322         if (i->second == &object)
00323         {
00324             destroyObject(i);
00325             return;
00326         }
00327 }
00328 
00329 //----------------------------------------------------------------------------//
00330 template<typename T, typename U>
00331 void NamedXMLResourceManager<T, U>::destroyAll()
00332 {
00333     while (!d_objects.empty())
00334         destroyObject(d_objects.begin());
00335 }
00336 
00337 //----------------------------------------------------------------------------//
00338 template<typename T, typename U>
00339 T& NamedXMLResourceManager<T, U>::get(const String& object_name) const
00340 {
00341     typename ObjectRegistry::const_iterator i(d_objects.find(object_name));
00342 
00343     if (i == d_objects.end())
00344         CEGUI_THROW(UnknownObjectException(
00345             "No object of type '" + d_resourceType + "' named '" + object_name +
00346             "' is present in the collection."));
00347 
00348     return *i->second;
00349 }
00350 
00351 //----------------------------------------------------------------------------//
00352 template<typename T, typename U>
00353 bool NamedXMLResourceManager<T, U>::isDefined(const String& object_name) const
00354 {
00355     return d_objects.find(object_name) != d_objects.end();
00356 }
00357 
00358 //----------------------------------------------------------------------------//
00359 template<typename T, typename U>
00360 void NamedXMLResourceManager<T, U>::destroyObject(
00361         typename ObjectRegistry::iterator ob)
00362 {
00363     char addr_buff[32];
00364     sprintf(addr_buff, "(%p)", static_cast<void*>(ob->second));
00365     Logger::getSingleton().logEvent("Object of type '" + d_resourceType +
00366         "' named '" + ob->first + "' has been destroyed. " +
00367         addr_buff, Informative);
00368 
00369     // Set up event args for event notification
00370     ResourceEventArgs args(d_resourceType, ob->first);
00371 
00372     CEGUI_DELETE_AO ob->second;
00373     d_objects.erase(ob);
00374 
00375     // fire event signalling an object has been destroyed
00376     fireEvent(EventResourceDestroyed, args, EventNamespace);
00377 }
00378 
00379 //----------------------------------------------------------------------------//
00380 template<typename T, typename U>
00381 T& NamedXMLResourceManager<T, U>::doExistingObjectAction(
00382     const String object_name,
00383     T* object,
00384     const XMLResourceExistsAction action)
00385 {
00386     String event_name;
00387 
00388     if (isDefined(object_name))
00389     {
00390         switch (action)
00391         {
00392         case XREA_RETURN:
00393             Logger::getSingleton().logEvent("---- Returning existing instance "
00394                 "of " + d_resourceType + " named '" + object_name + "'.");
00395             // delete any new object we already had created
00396             CEGUI_DELETE_AO object;
00397             // return existing instance of object.
00398             return *d_objects[object_name];
00399 
00400         case XREA_REPLACE:
00401             Logger::getSingleton().logEvent("---- Replacing existing instance "
00402                 "of " + d_resourceType + " named '" + object_name +
00403                 "' (DANGER!).");
00404             destroy(object_name);
00405             event_name = EventResourceReplaced;
00406             break;
00407 
00408         case XREA_THROW:
00409             CEGUI_DELETE_AO object;
00410             CEGUI_THROW(AlreadyExistsException(
00411                 "an object of type '" + d_resourceType + "' named '" +
00412                 object_name + "' already exists in the collection."));
00413 
00414         default:
00415             CEGUI_DELETE_AO object;
00416             CEGUI_THROW(InvalidRequestException(
00417                 "Invalid CEGUI::XMLResourceExistsAction was specified."));
00418         }
00419     }
00420     else
00421         event_name = EventResourceCreated;
00422 
00423     d_objects[object_name] = object;
00424     doPostObjectAdditionAction(*object);
00425 
00426     // fire event about this resource change
00427     ResourceEventArgs args(d_resourceType, object_name);
00428     fireEvent(event_name, args, EventNamespace);
00429 
00430     return *object;
00431 }
00432 
00433 //----------------------------------------------------------------------------//
00434 template<typename T, typename U>
00435 void NamedXMLResourceManager<T, U>::doPostObjectAdditionAction(T& /*object*/)
00436 {
00437     // do nothing by default.
00438 }
00439 
00440 //----------------------------------------------------------------------------//
00441 template<typename T, typename U>
00442 void NamedXMLResourceManager<T, U>::createAll(const String& pattern,
00443                                               const String& resource_group)
00444 {
00445     std::vector<String> names;
00446     const size_t num = System::getSingleton().getResourceProvider()->
00447         getResourceGroupFileNames(names, pattern, resource_group);
00448 
00449     for (size_t i = 0; i < num; ++i)
00450         createFromFile(names[i], resource_group);
00451 }
00452 
00453 //----------------------------------------------------------------------------//
00454 
00455 } // End of  CEGUI namespace section
00456 
00457 #endif  // end of guard _CEGUINamedXMLResourceManager_h_
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends