osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #ifndef OSGEARTH_CONFIG_H 00020 #define OSGEARTH_CONFIG_H 1 00021 00022 #include <osgEarth/Common> 00023 #include <osgEarth/StringUtils> 00024 #include <osgEarth/URI> 00025 #include <osgDB/ReaderWriter> 00026 #include <osg/Version> 00027 #if OSG_MIN_VERSION_REQUIRED(2,9,5) 00028 #include <osgDB/Options> 00029 #endif 00030 #include <list> 00031 #include <stack> 00032 #include <istream> 00033 00034 namespace osgEarth 00035 { 00036 typedef std::list<class Config> ConfigSet; 00037 00038 00039 // general-purpose name/value pair set. 00040 struct Properties : public std::map<std::string,std::string> { 00041 std::string get( const std::string& key ) const { 00042 std::map<std::string,std::string>::const_iterator i = find(key); 00043 return i != end()? i->second : std::string(); 00044 } 00045 }; 00046 00053 class OSGEARTH_EXPORT Config 00054 { 00055 public: 00056 Config() { } 00057 00058 Config( const std::string& key ) : _key(key) { } 00059 00060 Config( const std::string& key, const std::string& value ) : _key( key ), _defaultValue( value ) { } 00061 00062 Config( const Config& rhs ) : _key(rhs._key), _defaultValue(rhs._defaultValue), _attrs(rhs._attrs), _children(rhs._children), _refMap(rhs._refMap), _uriContext(rhs._uriContext) { } 00063 00065 void setURIContext( const URIContext& value ); 00066 const URIContext& uriContext() const { return _uriContext; } 00067 00068 bool loadXML( std::istream& in ); 00069 00070 bool empty() const { 00071 return _key.empty() && _defaultValue.empty() && _children.empty(); 00072 } 00073 00074 std::string& key() { return _key; } 00075 const std::string& key() const { return _key; } 00076 00077 const std::string& value() const { return _defaultValue; } 00078 std::string& value() { return _defaultValue; } 00079 00080 Properties& attrs() { return _attrs; } 00081 const Properties& attrs() const { return _attrs; } 00082 00083 std::string attr( const std::string& name ) const { 00084 Properties::const_iterator i = _attrs.find(name); 00085 return i != _attrs.end()? trim(i->second) : ""; 00086 } 00087 00088 std::string& attr( const std::string& name ) { return _attrs[name]; } 00089 00090 //ConfigSet& children() { return _children; } 00091 const ConfigSet& children() const { return _children; } 00092 00093 const ConfigSet children( const std::string& key ) const { 00094 ConfigSet r; 00095 for(ConfigSet::const_iterator i = _children.begin(); i != _children.end(); i++ ) { 00096 if ( i->key() == key ) 00097 r.push_back( *i ); 00098 } 00099 return r; 00100 } 00101 00102 bool hasChild( const std::string& key ) const { 00103 for(ConfigSet::const_iterator i = _children.begin(); i != _children.end(); i++ ) 00104 if ( i->key() == key ) 00105 return true; 00106 return false; 00107 } 00108 00109 void remove( const std::string& key ) { 00110 _attrs.erase(key); 00111 for(ConfigSet::iterator i = _children.begin(); i != _children.end(); ) { 00112 if ( i->key() == key ) 00113 i = _children.erase( i ); 00114 else 00115 ++i; 00116 } 00117 } 00118 00119 const Config& child( const std::string& key ) const; 00120 00121 void merge( const Config& rhs ); 00122 00123 template<typename T> 00124 void addIfSet( const std::string& key, const optional<T>& opt ) { 00125 if ( opt.isSet() ) { 00126 add( key, osgEarth::toString<T>( opt.value() ) ); 00127 } 00128 } 00129 00130 template<typename T> 00131 void addObjIfSet( const std::string& key, const osg::ref_ptr<T>& opt ) { 00132 if ( opt.valid() ) { 00133 Config conf = opt->getConfig(); 00134 conf.key() = key; 00135 add( conf ); 00136 } 00137 } 00138 00139 template<typename T> 00140 void addObjIfSet( const std::string& key, const optional<T>& obj ) { 00141 if ( obj.isSet() ) { 00142 Config conf = obj->getConfig(); 00143 conf.key() = key; 00144 add( conf ); 00145 } 00146 } 00147 00148 template<typename X, typename Y> 00149 void addIfSet( const std::string& key, const std::string& val, const optional<X>& target, const Y& targetValue ) { 00150 if ( target.isSetTo( targetValue ) ) 00151 add( key, val ); 00152 } 00153 00154 void addChild( const std::string& key, const std::string& value ) { 00155 add( key, value ); 00156 } 00157 00158 void add( const std::string& key, const std::string& value ) { 00159 _children.push_back( Config( key, value ) ); 00160 _children.back().setURIContext( _uriContext ); 00161 } 00162 00163 void addChild( const Config& conf ) { 00164 add( conf ); 00165 } 00166 00167 void add( const Config& conf ) { 00168 _children.push_back( conf ); 00169 _children.back().setURIContext( _uriContext ); 00170 } 00171 00172 void add( const std::string& key, const Config& conf ) { 00173 Config temp = conf; 00174 temp.key() = key; 00175 add( temp ); 00176 } 00177 00178 void add( const ConfigSet& set ) { 00179 for( ConfigSet::const_iterator i = set.begin(); i != set.end(); i++ ) 00180 add( *i ); 00181 } 00182 00183 template<typename T> 00184 void updateIfSet( const std::string& key, const optional<T>& opt ) { 00185 if ( opt.isSet() ) { 00186 remove(key); 00187 add( key, osgEarth::toString<T>( opt.value() ) ); 00188 } 00189 } 00190 00191 template<typename T> 00192 void updateObjIfSet( const std::string& key, const osg::ref_ptr<T>& opt ) { 00193 if ( opt.valid() ) { 00194 remove(key); 00195 Config conf = opt->getConfig(); 00196 conf.key() = key; 00197 add( conf ); 00198 } 00199 } 00200 00201 template<typename T> 00202 void updateObjIfSet( const std::string& key, const optional<T>& obj ) { 00203 if ( obj.isSet() ) { 00204 remove(key); 00205 Config conf = obj->getConfig(); 00206 conf.key() = key; 00207 add( conf ); 00208 } 00209 } 00210 00211 template<typename X, typename Y> 00212 void updateIfSet( const std::string& key, const std::string& val, const optional<X>& target, const Y& targetValue ) { 00213 if ( target.isSetTo( targetValue ) ) { 00214 remove(key); 00215 add( key, val ); 00216 } 00217 } 00218 00219 void updateChild( const std::string& key, const std::string& value ) { 00220 update( key, value ); 00221 } 00222 00223 void update( const std::string& key, const std::string& value ) { 00224 remove(key); 00225 add( Config(key, value) ); 00226 //_children.push_back( Config( key, value ) ); 00227 } 00228 00229 void updateChild( const Config& conf ) { 00230 update( conf ); 00231 } 00232 00233 void update( const Config& conf ) { 00234 remove(conf.key()); 00235 add( conf ); 00236 //_children.push_back( conf ); 00237 } 00238 00239 void update( const std::string& key, const Config& conf ) { 00240 remove(key); 00241 Config temp = conf; 00242 temp.key() = key; 00243 add( temp ); 00244 } 00245 00246 00247 bool hasValue( const std::string& key ) const { 00248 return !value(key).empty(); 00249 } 00250 00251 const std::string value( const std::string& key ) const { 00252 std::string r = trim(child(key).value()); 00253 if ( r.empty() ) 00254 r = attr(key); 00255 return r; 00256 } 00257 00258 // populates a primitive value. 00259 template<typename T> 00260 T value( const std::string& key, T fallback ) const { 00261 std::string r = attr(key); 00262 if ( r.empty() && hasChild( key ) ) 00263 r = child(key).value(); 00264 return osgEarth::as<T>( r, fallback ); 00265 } 00266 00267 bool boolValue( bool fallback ) const { 00268 return osgEarth::as<bool>( _defaultValue, fallback ); 00269 } 00270 00271 // populates the output value iff the Config exists. 00272 template<typename T> 00273 bool getIfSet( const std::string& key, optional<T>& output ) const { 00274 std::string r = attr(key); 00275 if ( r.empty() && hasChild(key) ) 00276 r = child(key).value(); 00277 if ( !r.empty() ) { 00278 output = osgEarth::as<T>( r, output.defaultValue() ); 00279 return true; 00280 } 00281 else 00282 return false; 00283 } 00284 00285 // for Configurable's 00286 template<typename T> 00287 bool getObjIfSet( const std::string& key, optional<T>& output ) const { 00288 if ( hasChild( key ) ) { 00289 output = T( child(key) ); 00290 return true; 00291 } 00292 else 00293 return false; 00294 } 00295 00296 // populates a Referenced that takes a Config in the constructor. 00297 template<typename T> 00298 bool getObjIfSet( const std::string& key, osg::ref_ptr<T>& output ) const { 00299 if ( hasChild( key ) ) { 00300 output = new T( child(key) ); 00301 return true; 00302 } 00303 else 00304 return false; 00305 } 00306 00307 template<typename X, typename Y> 00308 bool getIfSet( const std::string& key, const std::string& val, optional<X>& target, const Y& targetValue ) const { 00309 if ( hasValue( key ) && value( key ) == val ) { 00310 target = targetValue; 00311 return true; 00312 } 00313 else 00314 return false; 00315 } 00316 00317 std::string toString( int indent =0 ) const; 00318 00319 std::string toHashString() const; 00320 00323 typedef std::map<std::string, osg::ref_ptr<osg::Referenced> > RefMap; 00324 00325 void addNonSerializable( const std::string& key, osg::Referenced* obj ) { 00326 _refMap[key] = obj; 00327 } 00328 00329 void updateNonSerializable( const std::string& key, osg::Referenced* obj ) { 00330 _refMap[key] = obj; 00331 } 00332 00333 template<typename X> 00334 X* getNonSerializable( const std::string& key ) const { 00335 RefMap::const_iterator i = _refMap.find(key); 00336 return i == _refMap.end() ? 0 : dynamic_cast<X*>( i->second.get() ); 00337 } 00338 00339 protected: 00340 std::string _key; 00341 std::string _defaultValue; 00342 Properties _attrs; 00343 ConfigSet _children; 00344 URIContext _uriContext; 00345 00346 RefMap _refMap; 00347 }; 00348 00349 // specialization for Config 00350 template <> inline 00351 void Config::addIfSet<Config>( const std::string& key, const optional<Config>& opt ) { 00352 if ( opt.isSet() ) { 00353 Config conf = opt.value(); 00354 conf.key() = key; 00355 add( conf ); 00356 } 00357 } 00358 00359 template<> inline 00360 void Config::updateIfSet<Config>( const std::string& key, const optional<Config>& opt ) { 00361 if ( opt.isSet() ) { 00362 remove(key); 00363 Config conf = opt.value(); 00364 conf.key() = key; 00365 add( conf ); 00366 } 00367 } 00368 00369 template<> inline 00370 bool Config::getIfSet<Config>( const std::string& key, optional<Config>& output ) const { 00371 if ( hasChild( key ) ) { 00372 output = child(key); 00373 return true; 00374 } 00375 else 00376 return false; 00377 } 00378 00379 // specializations for URI: 00380 template <> inline 00381 void Config::addIfSet<URI>( const std::string& key, const optional<URI>& opt ) { 00382 if ( opt.isSet() ) { 00383 add( Config(key, opt->base()) ); 00384 } 00385 } 00386 00387 template<> inline 00388 void Config::updateIfSet<URI>( const std::string& key, const optional<URI>& opt ) { 00389 if ( opt.isSet() ) { 00390 remove(key); 00391 add( Config(key, opt->base()) ); 00392 } 00393 } 00394 00395 template<> inline 00396 bool Config::getIfSet<URI>( const std::string& key, optional<URI>& output ) const { 00397 if ( hasValue( key ) ) { 00398 output = URI( value(key), _uriContext ); 00399 return true; 00400 } 00401 else 00402 return false; 00403 } 00404 00408 class ConfigOptions // header-only (no export required) 00409 { 00410 public: 00411 ConfigOptions( const Config& conf =Config() ) 00412 : _conf( conf ) { } 00413 ConfigOptions( const ConfigOptions& rhs ) 00414 : _conf( rhs.getConfig() ) { } 00415 00416 ConfigOptions& operator = ( const ConfigOptions& rhs ) { 00417 if ( this != &rhs ) { 00418 _conf = rhs.getConfig(); 00419 mergeConfig( _conf ); 00420 } 00421 return *this; 00422 } 00423 00424 void merge( const ConfigOptions& rhs ) { 00425 _conf.merge( rhs._conf ); 00426 mergeConfig( rhs.getConfig() ); 00427 } 00428 00429 virtual Config getConfig() const { return _conf; } 00430 00431 protected: 00432 virtual void mergeConfig( const Config& conf ) { } 00433 00434 Config _conf; 00435 }; 00436 00440 class DriverConfigOptions : public ConfigOptions // header-only (no export required) 00441 { 00442 public: 00443 DriverConfigOptions( const ConfigOptions& rhs =ConfigOptions() ) 00444 : ConfigOptions( rhs ) { fromConfig( _conf ); } 00445 00447 void setDriver( const std::string& value ) { _driver = value; } 00448 const std::string& getDriver() const { return _driver; } 00449 00451 //void setName( const std::string& value ) { _name = value; } 00452 //const std::string& getName() const { return _name; } 00453 00454 public: 00455 virtual Config getConfig() const { 00456 Config conf = ConfigOptions::getConfig(); 00457 //conf.attr("name") = _name; 00458 conf.attr("driver") = _driver; 00459 return conf; 00460 } 00461 00462 virtual void mergeConfig( const Config& conf ) { 00463 ConfigOptions::mergeConfig(conf); 00464 fromConfig(conf); 00465 } 00466 00467 public: 00468 void fromConfig( const Config& conf ) { 00469 //_name = conf.value( "name" ); 00470 _driver = conf.value( "driver" ); 00471 if ( _driver.empty() && conf.hasValue("type") ) 00472 _driver = conf.value("type"); 00473 } 00474 00475 private: 00476 std::string _name, _driver; 00477 }; 00478 } 00479 00480 #endif // OSGEARTH_CONFIG_H 00481