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 00093 public: 00094 00095 00096 00107 explicit Loadable( const std::string & contentFilePath ) ; 00108 00109 00110 00112 virtual ~Loadable() throw() ; 00113 00114 00115 00125 virtual bool load() = 0 ; 00126 00127 00128 00138 virtual bool unload() = 0 ; 00139 00140 00141 00146 virtual const std::string & getContentPath() const ; 00147 00148 00149 00150 protected: 00151 00152 00154 std::string _contentPath ; 00155 00156 00157 00158 private: 00159 00160 00168 Loadable( const Loadable & source ) ; 00169 00170 00178 Loadable & operator = ( const Loadable & source ) ; 00179 00180 00181 } ; 00182 00183 00184 00185 00198 template <typename Content> 00199 class LoadableWithContent : public Loadable 00200 { 00201 00202 00203 public: 00204 00205 00206 00214 explicit LoadableWithContent( const std::string & contentFilePath ); 00215 00216 00217 00225 virtual ~LoadableWithContent() throw() ; 00226 00227 00228 00244 virtual bool load() = 0 ; 00245 00246 00247 00260 virtual bool unload() = 0 ; 00261 00262 00263 00279 virtual bool reload( bool forceLoad = false ) ; 00280 00281 00282 00287 virtual bool hasContent() const ; 00288 00289 00290 00301 virtual Content & getExistingContent() ; 00302 00303 00304 00315 virtual const Content & getExistingContentAsConst() const ; 00316 00317 00318 00328 virtual Content & getContent() ; 00329 00330 00331 00347 virtual const Content & getContentAsConst() ; 00348 00349 00350 00351 protected: 00352 00353 00355 Content * _content ; 00356 00357 00358 00359 private: 00360 00361 00369 LoadableWithContent( const LoadableWithContent & source ) ; 00370 00371 00379 LoadableWithContent & operator = ( 00380 const LoadableWithContent & source ) ; 00381 00382 00383 } ; 00384 00385 00386 00387 00388 // Implementation of the LoadableWithContent template. 00389 00390 00391 template <typename Content> 00392 LoadableWithContent<Content>::LoadableWithContent( 00393 const std::string & contentFilePath ) : 00394 Loadable( contentFilePath ), 00395 _content( 0 ) 00396 { 00397 00398 /* 00399 * Cannot preload here as the load method is abstract. 00400 * Instanciable child classes should offer to preload: 00401 00402 if ( preLoad ) 00403 load() ; 00404 00405 */ 00406 00407 } 00408 00409 00410 00411 template <typename Content> 00412 LoadableWithContent<Content>::~LoadableWithContent() throw() 00413 { 00414 00415 00416 /* 00417 * Cannot unload here as the unload method is abstract. 00418 * Instanciable child classes should deallocate any loaded content: 00419 00420 if ( hasContent() ) 00421 unload() ; 00422 00423 */ 00424 00425 // Cannot deallocate, but can warn: 00426 if ( _content != 0 ) 00427 Ceylan::Log::LogPlug::error( 00428 "LoadableWithContent<Content> destructor: " 00429 "still existing content has been found" ) ; 00430 00431 } 00432 00433 00434 00435 template <typename Content> 00436 bool LoadableWithContent<Content>::reload( bool forceLoad ) 00437 { 00438 00439 if ( hasContent() ) 00440 { 00441 00442 // Does not depend on forceLoad: 00443 unload() ; 00444 load() ; 00445 00446 return true ; 00447 00448 } 00449 else 00450 { 00451 00452 // No prior content. 00453 if ( forceLoad ) 00454 load() ; 00455 00456 return forceLoad ; 00457 00458 } 00459 00460 } 00461 00462 00463 00464 template <typename Content> 00465 bool LoadableWithContent<Content>::hasContent() const 00466 { 00467 00468 return ( _content != 0 ) ; 00469 00470 } 00471 00472 00473 00474 template <typename Content> 00475 Content & LoadableWithContent<Content>::getExistingContent() 00476 { 00477 00478 if ( ! hasContent() ) 00479 throw LoadableException( 00480 "LoadableWithContent<Content>::getExistingContent failed: " 00481 "no content available" ) ; 00482 00483 return * _content ; 00484 00485 } 00486 00487 00488 00489 template <typename Content> 00490 const Content & LoadableWithContent<Content>::getExistingContentAsConst() 00491 const 00492 { 00493 00494 if ( ! hasContent() ) 00495 throw LoadableException( 00496 "LoadableWithContent<Content>::getExistingContentAsConst " 00497 "failed: no content available" ) ; 00498 00499 return * _content ; 00500 00501 } 00502 00503 00504 00505 template <typename Content> 00506 Content & LoadableWithContent<Content>::getContent() 00507 { 00508 00509 if ( ! hasContent() ) 00510 load() ; 00511 00512 return * _content ; 00513 00514 } 00515 00516 00517 00518 template <typename Content> 00519 const Content & LoadableWithContent<Content>::getContentAsConst() 00520 { 00521 00522 if ( ! hasContent() ) 00523 load() ; 00524 00525 return * _content ; 00526 00527 } 00528 00529 00530 00531 } 00532 00533 00534 00535 #endif // CEYLAN_LOADABLE_H_ 00536