00001 /* 00002 * Copyright (C) 2003-2009 Olivier Boudeville 00003 * 00004 * This file is part of the Ceylan library. 00005 * 00006 * The Ceylan library is free software: you can redistribute it and/or modify 00007 * it under the terms of either the GNU Lesser General Public License or 00008 * the GNU General Public License, as they are published by the Free Software 00009 * Foundation, either version 3 of these Licenses, or (at your option) 00010 * any later version. 00011 * 00012 * The Ceylan library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License and the GNU General Public License 00016 * for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License and the GNU General Public License along with the Ceylan library. 00020 * If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 * Author: Olivier Boudeville (olivier.boudeville@esperide.com) 00023 * 00024 */ 00025 00026 00027 #ifndef CEYLAN_LOADABLE_H_ 00028 #define CEYLAN_LOADABLE_H_ 00029 00030 00031 #include "CeylanException.h" // for inheritance 00032 #include "CeylanFile.h" // for File 00033 #include "CeylanLogPlug.h" // for LogPlug 00034 00035 00036 #include <string> 00037 00038 00039 00040 namespace Ceylan 00041 { 00042 00043 00044 00046 class CEYLAN_DLL LoadableException : public Ceylan::Exception 00047 { 00048 00049 public: 00050 00051 explicit LoadableException( const std::string & message ) ; 00052 00053 virtual ~LoadableException() throw() ; 00054 00055 } ; 00056 00057 00058 00059 00060 /* 00061 * The overall goal is to rely on a Loadable mother class, that can be 00062 * used simply, while, thanks to the Loadable<Content> template, to be 00063 * able to retrieve the content directly, with its correct type. 00064 * 00065 * User is expected to subclass the template, so that she can rely on a 00066 * useful abstraction: 00067 * 00068 * @example class MyOwnContent: public Loadable<MyContent> {...} ; 00069 * MyOwnContent anExample( aPath ) ; 00070 * anExample.getContent() etc. 00071 * std::list<Loadable> myList ; 00072 * myList.push_back( anExample ) ; 00073 * 00074 * @see testCeylanLoadable.cc 00075 * 00076 */ 00077 00078 00079 00089 class CEYLAN_DLL Loadable 00090 { 00091 00092 public: 00093 00094 00095 00106 explicit Loadable( const std::string & contentFilePath ) ; 00107 00108 00109 00111 virtual ~Loadable() throw() ; 00112 00113 00114 00124 virtual bool load() = 0 ; 00125 00126 00127 00137 virtual bool unload() = 0 ; 00138 00139 00140 00145 virtual const std::string & getContentPath() const ; 00146 00147 00148 00149 protected: 00150 00151 00153 std::string _contentPath ; 00154 00155 00156 00157 private: 00158 00159 00167 Loadable( const Loadable & source ) ; 00168 00169 00177 Loadable & operator = ( const Loadable & source ) ; 00178 00179 00180 } ; 00181 00182 00183 00184 00197 template <typename Content> 00198 class LoadableWithContent: public Loadable 00199 { 00200 00201 00202 public: 00203 00204 00205 00213 explicit LoadableWithContent( const std::string & contentFilePath ); 00214 00215 00216 00224 virtual ~LoadableWithContent() throw() ; 00225 00226 00227 00243 virtual bool load() = 0 ; 00244 00245 00246 00259 virtual bool unload() = 0 ; 00260 00261 00262 00278 virtual bool reload( bool forceLoad = false ) ; 00279 00280 00281 00286 virtual bool hasContent() const ; 00287 00288 00289 00300 virtual Content & getExistingContent() ; 00301 00302 00303 00314 virtual const Content & getExistingContentAsConst() const ; 00315 00316 00317 00327 virtual Content & getContent() ; 00328 00329 00330 00346 virtual const Content & getContentAsConst() ; 00347 00348 00349 00350 protected: 00351 00352 00354 Content * _content ; 00355 00356 00357 00358 private: 00359 00360 00368 LoadableWithContent( const LoadableWithContent & source ) ; 00369 00370 00378 LoadableWithContent & operator = ( 00379 const LoadableWithContent & source ) ; 00380 00381 00382 } ; 00383 00384 00385 00386 00387 // Implementation of the LoadableWithContent template. 00388 00389 00390 template <typename Content> 00391 LoadableWithContent<Content>::LoadableWithContent( 00392 const std::string & contentFilePath ) : 00393 Loadable( contentFilePath ), 00394 _content( 0 ) 00395 { 00396 00397 /* 00398 * Cannot preload here as the load method is abstract. 00399 * Instanciable child classes should offer to preload: 00400 00401 if ( preLoad ) 00402 load() ; 00403 00404 */ 00405 00406 } 00407 00408 00409 00410 template <typename Content> 00411 LoadableWithContent<Content>::~LoadableWithContent() throw() 00412 { 00413 00414 00415 /* 00416 * Cannot unload here as the unload method is abstract. 00417 * Instanciable child classes should deallocate any loaded content: 00418 00419 if ( hasContent() ) 00420 unload() ; 00421 00422 */ 00423 00424 // Cannot deallocate, but can warn: 00425 if ( _content != 0 ) 00426 Ceylan::Log::LogPlug::error( 00427 "LoadableWithContent<Content> destructor: " 00428 "still existing content has been found" ) ; 00429 00430 } 00431 00432 00433 00434 template <typename Content> 00435 bool LoadableWithContent<Content>::reload( bool forceLoad ) 00436 { 00437 00438 if ( hasContent() ) 00439 { 00440 00441 // Does not depend on forceLoad: 00442 unload() ; 00443 load() ; 00444 00445 return true ; 00446 00447 } 00448 else 00449 { 00450 00451 // No prior content. 00452 if ( forceLoad ) 00453 load() ; 00454 00455 return forceLoad ; 00456 00457 } 00458 00459 } 00460 00461 00462 00463 template <typename Content> 00464 bool LoadableWithContent<Content>::hasContent() const 00465 { 00466 00467 return ( _content != 0 ) ; 00468 00469 } 00470 00471 00472 00473 template <typename Content> 00474 Content & LoadableWithContent<Content>::getExistingContent() 00475 { 00476 00477 if ( ! hasContent() ) 00478 throw LoadableException( 00479 "LoadableWithContent<Content>::getExistingContent failed: " 00480 "no content available" ) ; 00481 00482 return * _content ; 00483 00484 } 00485 00486 00487 00488 template <typename Content> 00489 const Content & LoadableWithContent<Content>::getExistingContentAsConst() 00490 const 00491 { 00492 00493 if ( ! hasContent() ) 00494 throw LoadableException( 00495 "LoadableWithContent<Content>::getExistingContentAsConst " 00496 "failed: no content available" ) ; 00497 00498 return * _content ; 00499 00500 } 00501 00502 00503 00504 template <typename Content> 00505 Content & LoadableWithContent<Content>::getContent() 00506 { 00507 00508 if ( ! hasContent() ) 00509 load() ; 00510 00511 return * _content ; 00512 00513 } 00514 00515 00516 00517 template <typename Content> 00518 const Content & LoadableWithContent<Content>::getContentAsConst() 00519 { 00520 00521 if ( ! hasContent() ) 00522 load() ; 00523 00524 return * _content ; 00525 00526 } 00527 00528 00529 00530 } 00531 00532 00533 00534 #endif // CEYLAN_LOADABLE_H_ 00535