Teuchos - Trilinos Tools Package Version of the Day
Teuchos_ObjectBuilder.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef Teuchos_OBJECT_BUILDER_H
00043 #define Teuchos_OBJECT_BUILDER_H
00044 
00045 #include "Teuchos_ParameterList.hpp"
00046 #include "Teuchos_ParameterListAcceptor.hpp"
00047 #include "Teuchos_AbstractFactoryStd.hpp"
00048 #include "Teuchos_StandardParameterEntryValidators.hpp"
00049 
00050 
00051 namespace Teuchos {
00052 
00053 
00088 template<class ObjectType>
00089 class ObjectBuilder : virtual public ParameterListAcceptor
00090 {
00091 public:
00092 
00094   ObjectBuilder();
00095 
00097   ~ObjectBuilder();
00098 
00100   void setObjectName(
00101       const std::string &objectName
00102       );
00103 
00105   void setObjectTypeName(
00106       const std::string &objectTypeName
00107       );
00108 
00110   void setObjectFactory(
00111     const RCP<const AbstractFactory<ObjectType> > &objectFactory,
00112     const std::string &objectFactoryName
00113     );
00114 
00118   std::string getObjectName() const;
00119 
00124   void setDefaultObject( const std::string &defaultObject_name );
00125 
00127   RCP<ObjectType> create(
00128     const std::string &objectName = ""
00129     ) const;
00130   
00133 
00135   void setParameterList(const RCP<ParameterList> & paramList);
00136   
00138   RCP<ParameterList> getNonconstParameterList();
00139   
00141   RCP<ParameterList> unsetParameterList();
00142   
00144   RCP<const ParameterList> getParameterList() const;
00145 
00147   RCP<const ParameterList> getValidParameters() const;
00148  
00150   
00151 private:
00152 
00153   // //////////////////////////////////////
00154   // Private types
00155 
00156   typedef RCP<const AbstractFactory<ObjectType > > object_fcty_t;
00157 
00158   // //////////////////////////////////////
00159   // Private data members
00160 
00161   RCP<ParameterList> paramList_;
00162   mutable RCP<const ParameterList> validParamList_;
00163   mutable RCP<const StringToIntegralParameterEntryValidator<int> > objectValidator_;
00164 
00165   std::string object_name_;
00166   std::string objectType_name_;
00167 
00168   Array<std::string> validObjectNames_;
00169   Array<object_fcty_t> objectArray_;
00170   std::string defaultObject_name_;
00171 
00172   // //////////////////////////////////////
00173   // Private member functions
00174 
00175   void initializeDefaults_();
00176 
00177 };
00178 
00179 
00180 // Nonmember constructors
00181 
00182 
00183 template<class ObjectType>
00184 RCP<ObjectBuilder<ObjectType> > objectBuilder()
00185 {
00186   RCP<ObjectBuilder<ObjectType> > ob = rcp(new ObjectBuilder<ObjectType>() );
00187   return ob;
00188 }
00189 
00190 
00191 template<class ObjectType>
00192 RCP<ObjectBuilder<ObjectType> >
00193 objectBuilder(const std::string& objectName, const std::string& objectTypeName)
00194 {
00195   RCP<ObjectBuilder<ObjectType> > ob = rcp(new ObjectBuilder<ObjectType>() );
00196   ob->setObjectName(objectName);
00197   ob->setObjectTypeName(objectTypeName);
00198   return ob;
00199 }
00200 
00201 
00202 //
00203 // Implementation
00204 //
00205 
00206 
00207 template<class ObjectType>
00208 ObjectBuilder<ObjectType>::ObjectBuilder()
00209 {
00210   this->initializeDefaults_();
00211 }
00212 
00213 
00214 template<class ObjectType>
00215 ObjectBuilder<ObjectType>::~ObjectBuilder()
00216 {
00217 #ifdef TEUCHOS_DEBUG
00218   // Validate that we read the parameters correctly!
00219   if(!is_null(paramList_)) {
00220     paramList_->validateParameters(*this->getValidParameters());
00221   }
00222 #endif    
00223 }
00224 
00225 
00226 template<class ObjectType>
00227 void ObjectBuilder<ObjectType>::setObjectFactory(
00228   const RCP<const AbstractFactory<ObjectType > > &objectFactory,
00229   const std::string &objectName
00230   )
00231 {
00232   TEUCHOS_TEST_FOR_EXCEPT( objectName.length() == 0 );
00233   validObjectNames_.push_back(objectName);
00234   objectArray_.push_back(objectFactory);
00235   defaultObject_name_ = objectName;
00236   validParamList_ = null;
00237 #ifdef TEUCHOS_DEBUG
00238   this->getValidParameters();
00239 #endif // TEUCHOS_DEBUG
00240 }
00241 
00242 
00243 template<class ObjectType>
00244 std::string
00245 ObjectBuilder<ObjectType>::getObjectName() const
00246 {
00247   if(is_null(validParamList_)) {
00248     this->getValidParameters();
00249   }
00250   // If the user has not specified a ParameterList, then use the ValidParameterList.
00251   RCP<ParameterList> pl = null;
00252   if (!is_null(paramList_)) {
00253     pl = paramList_;
00254   } else {
00255     pl = parameterList();
00256     pl->setParameters(*this->getValidParameters());
00257   }
00258   return objectValidator_->getStringValue(*pl, objectType_name_, defaultObject_name_);
00259 }
00260 
00261 
00262 template<class ObjectType>
00263 void ObjectBuilder<ObjectType>::setParameterList(
00264   RCP<ParameterList> const& paramList
00265   )
00266 {
00267   if (!is_null(paramList)) {
00268     paramList->validateParameters(*this->getValidParameters());
00269     paramList_ = paramList;
00270   }
00271 }
00272 
00273 
00274 template<class ObjectType>
00275 RCP<ParameterList>
00276 ObjectBuilder<ObjectType>::getNonconstParameterList()
00277 {
00278   return paramList_;
00279 }
00280 
00281 
00282 template<class ObjectType>
00283 RCP<ParameterList>
00284 ObjectBuilder<ObjectType>::unsetParameterList()
00285 {
00286 #ifdef TEUCHOS_DEBUG
00287   // Validate that we read the parameters correctly!
00288   if(!is_null(paramList_))
00289     paramList_->validateParameters(*this->getValidParameters());
00290 #endif    
00291   RCP<ParameterList> _paramList = paramList_;
00292   paramList_ = null;
00293   return _paramList;
00294 }
00295 
00296 
00297 template<class ObjectType>
00298 RCP<const ParameterList>
00299 ObjectBuilder<ObjectType>::getParameterList() const
00300 {
00301   return paramList_;
00302 }
00303 
00304 
00305 template<class ObjectType>
00306 RCP<const ParameterList>
00307 ObjectBuilder<ObjectType>::getValidParameters() const
00308 {
00309   if(!validParamList_.get()) {
00310     RCP<ParameterList> validParamList = parameterList();
00311     // Object Types
00312     objectValidator_ = rcp(
00313       new StringToIntegralParameterEntryValidator<int>(
00314         validObjectNames_, objectType_name_
00315         )
00316       );
00317     objectValidator_->validateString(defaultObject_name_,objectType_name_);
00318     validParamList->set(
00319       objectType_name_, defaultObject_name_,
00320       (std::string("Determines the type of " + object_name_ + " object that will be built.\n")
00321         + "The parameters for each " + objectType_name_ + " are specified in this sublist" 
00322         ).c_str(),
00323       objectValidator_
00324       );
00325     for( int i = 0; i < static_cast<int>(objectArray_.size()); ++i ) {
00326       const std::string
00327         &sname = validObjectNames_[i+1];
00328       const RCP<ObjectType >
00329         object = objectArray_[i]->create();
00330       validParamList->sublist(sname).setParameters(
00331         *object->getValidParameters()).disableRecursiveValidation();
00332     }
00333     validParamList_ = validParamList;
00334   }
00335   return validParamList_;
00336 }
00337 
00338 template<class ObjectType>
00339 void ObjectBuilder<ObjectType>::setDefaultObject(
00340     const std::string &defaultObject_name
00341     )
00342 {
00343 #ifdef TEUCHOS_DEBUG
00344   if (is_null(validParamList_)) { // We need the objectValidator_
00345     this->getValidParameters();
00346   }
00347   objectValidator_->validateString(defaultObject_name,objectType_name_);
00348 #endif // TEUCHOS_DEBUG
00349   defaultObject_name_ = defaultObject_name;
00350   // This is necessary to change the default in the valid parameter list 
00351   validParamList_ = null; 
00352 }
00353 
00354 template<class ObjectType>
00355 RCP<ObjectType >
00356 ObjectBuilder<ObjectType>::create(
00357   const std::string &objectName
00358   ) const
00359 {
00360   if (is_null(validParamList_)) { // We need the objectValidator_
00361     this->getValidParameters();
00362   }
00363   const std::string
00364     sname = ( objectName.length()
00365              ? objectName
00366              : this->getObjectName() );
00367   RCP<ObjectType> object = null; 
00368   // Get the index of this object factory (this will validate!)
00369   const int
00370     s_idx = objectValidator_->getIntegralValue(sname, objectType_name_);
00371   if (s_idx != 0) {
00372     // Create the uninitialized object
00373     object = objectArray_[s_idx-1]->create(); 
00374     TEUCHOS_TEST_FOR_EXCEPTION( is_null(object), std::logic_error,
00375         (std::string("Error!  ObjectBuilder attempted to create an object of type ") 
00376          + validObjectNames_[s_idx] + " and it came back as a null RCP!").c_str()
00377         );
00378     // Allow the user to not set a parameterlist (this requires copying the
00379     // parameters in the valid parameter list into a new parameter list:
00380     RCP<ParameterList> pl = null;
00381     if (is_null(paramList_)) {
00382       pl = parameterList();
00383       pl->setParameters(this->getValidParameters()->sublist(sname));
00384     } else {
00385 #ifdef TEUCHOS_DEBUG
00386       // We're validating the parameter list here again because we're storing a
00387       // pointer to it and the user could have changed it.
00388       paramList_->validateParameters(*this->getValidParameters());
00389 #endif // TEUCHOS_DEBUG
00390       pl = sublist(paramList_,sname);
00391     }
00392     // Now set the parameters for the object 
00393     object->setParameterList(pl);
00394   }
00395   return object;
00396 }
00397 
00398 
00399 template<class ObjectType>
00400 void ObjectBuilder<ObjectType>::setObjectName(
00401     const std::string &objectName
00402     )
00403 {
00404   TEUCHOS_TEST_FOR_EXCEPT(objectName.length() == 0);
00405   object_name_ = objectName;
00406   validParamList_ = null;
00407 }
00408 
00409 
00410 template<class ObjectType>
00411 void ObjectBuilder<ObjectType>::setObjectTypeName(
00412     const std::string &objectTypeName
00413     )
00414 {
00415   TEUCHOS_TEST_FOR_EXCEPT(objectTypeName.length() == 0);
00416   objectType_name_ = objectTypeName;
00417   validParamList_ = null;
00418 }
00419 
00420 
00421 template<class ObjectType>
00422 void ObjectBuilder<ObjectType>::initializeDefaults_()
00423 {
00424 
00425   object_name_ = "Object";
00426   objectType_name_ = "Object Type";
00427 
00428   defaultObject_name_ = "None";
00429   validObjectNames_.resize(0);
00430   validObjectNames_.push_back(defaultObject_name_);
00431 
00432 }
00433 
00434 
00435 } // namespace Teuchos
00436 
00437 
00438 #endif //Teuchos_OBJECT_BUILDER_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines