Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_ParameterList.hpp
Go to the documentation of this file.
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 
00043 #ifndef TEUCHOS_PARAMETER_LIST_H
00044 #define TEUCHOS_PARAMETER_LIST_H
00045 
00050 #include "Teuchos_ParameterListExceptions.hpp"
00051 #include "Teuchos_ParameterEntry.hpp"
00052 #include "Teuchos_Assert.hpp"
00053 #include "Teuchos_RCP.hpp"
00054 #include "Teuchos_Array.hpp"
00055 #include "Teuchos_map.hpp"
00056 
00061 namespace Teuchos {
00062 
00066 enum EValidateUsed {
00067   VALIDATE_USED_ENABLED   /*< \brief Validate that parameters in <tt>*this</tt> list
00068                               set using the default value are present in
00069                               the validation list */
00070   ,VALIDATE_USED_DISABLED /*< \brief Do not validate that parameters in <tt>*this</tt> list
00071                               set using the default value are present in
00072                               the validation list */
00073 };
00074 
00078 enum EValidateDefaults {
00079   VALIDATE_DEFAULTS_ENABLED   /*< \brief Validate that parameters in <tt>*this</tt> list
00080                                   set using the default value are present in
00081                                    the validation list */
00082   ,VALIDATE_DEFAULTS_DISABLED /*< \brief Do not validate that parameters in <tt>*this</tt> list
00083                                   set using the default value are present in
00084                                   the validation list */
00085 };
00086 
00100 class TEUCHOS_LIB_DLL_EXPORT ParameterList {
00101 
00103   typedef Teuchos::map<std::string, ParameterEntry> Map;
00104 
00106   typedef Map::iterator Iterator;
00107   
00108 public:
00109 
00111 
00112 
00114   typedef Map::const_iterator ConstIterator;
00115 
00117   class PrintOptions {
00118   public:
00119     PrintOptions() : indent_(0), showTypes_(false), showFlags_(false), showDoc_(false) {}
00120     PrintOptions& indent(int _indent)        { indent_ = _indent; return *this; }
00121     PrintOptions& showTypes(bool _showTypes) { showTypes_ = _showTypes; return *this; }
00122     PrintOptions& showFlags(bool _showFlags) { showFlags_ = _showFlags; return *this; }
00123     PrintOptions& showDoc(bool _showDoc)     { showDoc_ = _showDoc; return *this; }
00124     PrintOptions& incrIndent(int indents)    { indent_ += indents; return *this; }
00125     int indent() const { return indent_; }
00126     bool showTypes() const { return showTypes_; }
00127     bool showFlags() const { return showFlags_; }
00128     bool showDoc() const { return showDoc_; }
00129     PrintOptions copy() const { return PrintOptions(*this); }
00130   private:
00131     int    indent_;
00132     bool   showTypes_;
00133     bool   showFlags_;
00134     bool   showDoc_;
00135   };
00136 
00138   
00140 
00141 
00143   ParameterList();
00144 
00146   ParameterList(const std::string &name);
00147   
00149   ParameterList(const ParameterList& source);
00150   
00152   virtual ~ParameterList();
00153 
00155   
00157 
00158 
00161   ParameterList& setName( const std::string &name );
00162   
00166   ParameterList& operator=(const ParameterList& source);
00167   
00175   ParameterList& setParameters(const ParameterList& source);
00176   
00186   ParameterList& setParametersNotAlreadySet(const ParameterList& source);
00187 
00195   ParameterList& disableRecursiveValidation();
00196   
00205   template<typename T>
00206   ParameterList& set(
00207     std::string const& name, T const& value, std::string const& docString = ""
00208     ,RCP<const ParameterEntryValidator> const& validator = null
00209     );
00210 
00214   ParameterList& set(
00215     std::string const& name, char value[], std::string const& docString = ""
00216     ,RCP<const ParameterEntryValidator> const& validator = null
00217     );
00218 
00222   ParameterList& set(
00223     std::string const& name, const char value[], std::string const& docString = ""
00224     ,RCP<const ParameterEntryValidator> const& validator = null
00225     );
00226 
00229   ParameterList& set(
00230     std::string const& name, ParameterList const& value, std::string const& docString = ""
00231     );
00232 
00237   ParameterList& setEntry(const std::string& name, const ParameterEntry& entry);
00238 
00240   
00242 
00243   
00254   template<typename T>
00255   T& get(const std::string& name, T def_value);
00256 
00260   std::string& get(const std::string& name, char def_value[]);
00261   
00265   std::string& get(const std::string& name, const char def_value[]);
00266   
00274   template<typename T>
00275   T& get(const std::string& name);
00276   
00284   template<typename T>
00285   const T& get(const std::string& name) const;  
00286   
00292   template<typename T>
00293   inline
00294   T* getPtr(const std::string& name);
00295   
00301   template<typename T>
00302   inline
00303   const T* getPtr(const std::string& name) const;  
00304   
00310   ParameterEntry& getEntry(const std::string& name);  
00311   
00317   inline
00318   const ParameterEntry& getEntry(const std::string& name) const;  
00319   
00322   inline
00323   ParameterEntry* getEntryPtr(const std::string& name);  
00324   
00327   inline
00328   const ParameterEntry* getEntryPtr(const std::string& name) const;  
00329 
00332   inline RCP<ParameterEntry> getEntryRCP(const std::string& name);  
00333   
00336   inline RCP<const ParameterEntry> getEntryRCP(const std::string& name) const;
00337 
00339 
00341 
00342  
00356   bool remove(
00357     std::string const& name, bool throwIfNotExists = true
00358     );
00359 
00361   
00363 
00364 
00370   ParameterList& sublist(
00371     const std::string& name, bool mustAlreadyExist = false
00372     ,const std::string& docString = ""
00373     );
00374   
00379   const ParameterList& sublist(const std::string& name) const;
00380 
00382   
00384 
00385 
00387   const std::string& name() const;
00388 
00394   bool isParameter(const std::string& name) const;
00395   
00401   bool isSublist(const std::string& name) const;
00402   
00409   template<typename T>
00410   bool isType(const std::string& name) const;
00411 
00412 #ifndef DOXYGEN_SHOULD_SKIP_THIS  
00413 
00423   template<typename T>
00424   bool isType(const std::string& name, T* ptr) const;
00425 #endif
00426 
00428   
00430 
00431 
00437   void print() const;
00438 
00441   std::ostream& print(std::ostream& os, const PrintOptions &printOptions) const;
00442 
00445   std::ostream& print(std::ostream& os, int indent = 0, bool showTypes = false, bool showFlags = true ) const;
00446   
00448   void unused(std::ostream& os) const;
00449 
00451   std::string currentParametersString() const;
00452 
00454 
00456 
00457 
00459   ConstIterator begin() const ;
00460 
00462   ConstIterator end() const ;
00463 
00465   const ParameterEntry& entry(ConstIterator i) const;
00466   
00468   const std::string& name(ConstIterator i) const;
00469 
00471 
00473 
00474 
00519   void validateParameters(
00520     ParameterList const& validParamList,
00521     int const depth = 1000,
00522     EValidateUsed const validateUsed = VALIDATE_USED_ENABLED,
00523     EValidateDefaults const validateDefaults = VALIDATE_DEFAULTS_ENABLED
00524     ) const;
00525 
00563   void validateParametersAndSetDefaults(
00564     ParameterList const& validParamList,
00565     int const depth = 1000
00566     );
00567 
00569   
00570 private: // Functions
00571  
00573   Iterator nonconstBegin();
00575   Iterator nonconstEnd();
00577   ParameterEntry& entry(Iterator i);
00579   void validateEntryExists( const std::string &funcName, const std::string &name, const ParameterEntry *entry ) const;
00581   template<typename T>
00582   void validateEntryType( const std::string &funcName, const std::string &name, const ParameterEntry &entry ) const;
00584   void updateSubListNames(int depth = 0);
00585   
00586 private: // Data members
00587 
00589   std::string name_;
00590 
00592 //use pragmas to disable some false-positive warnings for windows sharedlibs export
00593 #ifdef _MSC_VER
00594 #pragma warning(push)
00595 #pragma warning(disable:4251)
00596 #endif
00597   Map params_;
00598 #ifdef _MSC_VER
00599 #pragma warning(pop)
00600 #endif
00601 
00603   bool disableRecursiveValidation_;
00604 
00605 };
00606 
00607 
00612 inline
00613 RCP<ParameterList> parameterList()
00614 {
00615   return rcp(new ParameterList);
00616 }
00617 
00618 
00623 inline
00624 RCP<ParameterList> parameterList(const std::string &name)
00625 {
00626   return rcp(new ParameterList(name));
00627 }
00628   
00629 
00634 inline
00635 RCP<ParameterList> parameterList(const ParameterList& source)
00636 {
00637   return rcp(new ParameterList(source));
00638 }
00639 
00640 
00645 inline
00646 RCP<ParameterList> createParameterList()
00647 {
00648   return rcp(new ParameterList);
00649 }
00650 
00651 
00656 inline
00657 RCP<ParameterList> createParameterList(const std::string &name)
00658 {
00659   return rcp(new ParameterList(name));
00660 }
00661 
00662 
00667 template<>
00668 class TEUCHOS_LIB_DLL_EXPORT TypeNameTraits<ParameterList> {
00669 public:
00670   static std::string name() { return "ParameterList"; }
00671   static std::string concreteName( const ParameterList& /*t2*/ )
00672     { return name(); }
00673 };
00674 
00679 TEUCHOS_LIB_DLL_EXPORT bool operator==( const ParameterList& list1, const ParameterList& list2 );
00680 
00685 inline
00686 bool operator!=( const ParameterList& list1, const ParameterList& list2 )
00687 {
00688   return !( list1 == list2 );
00689 }
00690 
00699 TEUCHOS_LIB_DLL_EXPORT bool haveSameValues( const ParameterList& list1, const ParameterList& list2 );
00700 
00701 
00702 // /////////////////////////////////////////////////////
00703 // Inline and Template Function Definitions
00704 
00705 
00706 inline
00707 ParameterList& ParameterList::setName( const std::string &name_in )
00708 {
00709   name_ = name_in;
00710   return *this;
00711 }
00712 
00713 // Set functions
00714 
00715 template<typename T>
00716 inline
00717 ParameterList& ParameterList::set(
00718   std::string const& name_in, T const& value_in, std::string const& docString_in,
00719   RCP<const ParameterEntryValidator> const& validator_in
00720   )
00721 {
00722   ParameterEntry &foundEntry = params_[name_in]; // Will add the entry if not exists
00723   foundEntry.setValue(value_in,false,docString_in,validator_in);
00724   // Validate the value *after* you set it.  It is important to use
00725   // entry.validator() instead of validator since validator might be null!
00726   if(foundEntry.validator().get())
00727     foundEntry.validator()->validate(foundEntry,name_in,this->name());
00728   return *this;
00729 }
00730 
00731 inline
00732 ParameterList& ParameterList::set(
00733   std::string const& name_in, char value[], std::string const& docString
00734   ,RCP<const ParameterEntryValidator> const& validator
00735   ) 
00736 { return set( name_in, std::string(value), docString, validator ); }
00737 
00738 inline
00739 ParameterList& ParameterList::set(
00740   const std::string& name_in, const char value[], const std::string &docString
00741   ,RCP<const ParameterEntryValidator> const& validator
00742   ) 
00743 { return set( name_in, std::string(value), docString, validator ); }
00744 
00745 inline
00746 ParameterList& ParameterList::set(
00747   std::string const& name_in, ParameterList const& value, std::string const& /*docString*/
00748   )
00749 {
00750   sublist(name_in) = value;
00751   return *this;
00752 }
00753 
00754 inline
00755 ParameterList& ParameterList::setEntry(std::string const& name_in, ParameterEntry const& entry_in)
00756 {
00757   params_[name_in] = entry_in;
00758   return *this;
00759 }
00760 
00761 // Get functions
00762 
00763 template<typename T>
00764 T& ParameterList::get(const std::string& name_in, T def_value)
00765 {
00766   ConstIterator i = params_.find(name_in);
00767     
00768   // The parameter was not found, add it to the list
00769   if (i == params_.end()) {
00770     params_[name_in].setValue(def_value, true);
00771     i = params_.find(name_in);
00772   } else {
00773     // The parameter was found, make sure it is the same type as T.
00774     this->template validateEntryType<T>("get", name_in, entry(i));
00775   }
00776 
00777   // Return the value of the parameter
00778   return getValue<T>(entry(i));
00779 }
00780 
00781 inline
00782 std::string& ParameterList::get(const std::string& name_in, char def_value[])
00783 { return get(name_in, std::string(def_value)); }
00784 
00785 inline
00786 std::string& ParameterList::get(const std::string& name_in, const char def_value[])
00787 { return get(name_in, std::string(def_value)); }
00788 
00789 template<typename T>
00790 T& ParameterList::get(const std::string& name_in) 
00791 {
00792   ParameterEntry *foundEntry = this->getEntryPtr(name_in);
00793   validateEntryExists("get",name_in,foundEntry);
00794   this->template validateEntryType<T>("get",name_in,*foundEntry);
00795   return getValue<T>(*foundEntry);
00796 }
00797   
00798 template<typename T>
00799 const T& ParameterList::get(const std::string& name_in) const
00800 {
00801   const ParameterEntry *foundEntry = this->getEntryPtr(name_in);
00802   validateEntryExists("get",name_in,foundEntry);
00803   this->template validateEntryType<T>("get",name_in,*foundEntry);
00804   return getValue<T>(*foundEntry);
00805 }
00806 
00807 template<typename T>
00808 inline
00809 T* ParameterList::getPtr(const std::string& name_in) 
00810 {
00811   ConstIterator i = params_.find(name_in);
00812   if ( i == params_.end() || entry(i).getAny().type() != typeid(T) )
00813     return NULL;
00814   return &getValue<T>(entry(i));
00815 }
00816   
00817 template<typename T>
00818 inline
00819 const T* ParameterList::getPtr(const std::string& name_in) const
00820 {
00821   ConstIterator i = params_.find(name_in);
00822   if ( i == params_.end() || entry(i).getAny().type() != typeid(T) )
00823     return NULL;
00824   return &getValue<T>(entry(i));
00825 }
00826 
00827 inline
00828 ParameterEntry& ParameterList::getEntry(const std::string& name_in)
00829 {
00830   ParameterEntry *foundEntry = this->getEntryPtr(name_in);
00831   validateEntryExists("get",name_in,foundEntry);
00832   return *foundEntry;
00833 }
00834   
00835 inline
00836 const ParameterEntry& ParameterList::getEntry(const std::string& name_in) const
00837 {
00838   const ParameterEntry *foundEntry = this->getEntryPtr(name_in);
00839   validateEntryExists("get",name_in,foundEntry);
00840   return *foundEntry;
00841 }
00842 
00843 inline
00844 ParameterEntry*
00845 ParameterList::getEntryPtr(const std::string& name_in)
00846 {
00847   Map::iterator i = params_.find(name_in);
00848   if ( i == params_.end() )
00849     return NULL;
00850   return &entry(i);
00851 }
00852 
00853 inline
00854 const ParameterEntry*
00855 ParameterList::getEntryPtr(const std::string& name_in) const
00856 {
00857   ConstIterator i = params_.find(name_in);
00858   if ( i == params_.end() )
00859     return NULL;
00860   return &entry(i);
00861 }
00862 
00863 inline RCP<ParameterEntry>
00864 ParameterList::getEntryRCP(const std::string& name_in)
00865 {
00866   Iterator i = params_.find(name_in);
00867   if ( i == params_.end() )
00868     return null;
00869   return rcpFromRef(entry(i));
00870 }
00871 
00872 inline RCP<const ParameterEntry>
00873 ParameterList::getEntryRCP(const std::string& name_in) const
00874 {
00875   ConstIterator i = params_.find(name_in);
00876   if ( i == params_.end() )
00877     return null;
00878   return rcpFromRef(entry(i));
00879 }
00880 
00881 // Attribute Functions
00882 
00883 inline
00884 const std::string& ParameterList::name() const
00885 {
00886   return name_;
00887 }
00888   
00889 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00890 template<typename T>
00891 bool ParameterList::isType(const std::string& name_in, T* /*ptr*/) const
00892 {
00893   ConstIterator i = params_.find(name_in);
00894   // If parameter doesn't exist, return false.
00895   if (i == params_.end()) 
00896     return false;
00897   return entry(i).getAny().type() == typeid(T);
00898 }
00899 #endif
00900   
00901 template<typename T>
00902 bool ParameterList::isType(const std::string& name_in) const
00903 {
00904   ConstIterator i = params_.find(name_in);
00905   // If parameter doesn't exist, return false.
00906   if (i == params_.end()) 
00907     return false;
00908   return entry(i).getAny().type() == typeid(T);
00909 }
00910 
00911 
00912 // private
00913 
00914 
00915 template<typename T>
00916 inline
00917 void ParameterList::validateEntryType(
00918   const std::string &/*funcName*/, const std::string &name_in,
00919   const ParameterEntry &entry_in
00920   ) const
00921 {
00922   TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(
00923     entry_in.getAny().type() != typeid(T), Exceptions::InvalidParameterType
00924     ,"Error!  An attempt was made to access parameter \""<<name_in<<"\""
00925     " of type \""<<entry_in.getAny().typeName()<<"\""
00926     "\nin the parameter (sub)list \""<<this->name()<<"\""
00927     "\nusing the incorrect type \""<<TypeNameTraits<T>::name()<<"\"!"
00928     );
00929 }
00930 
00931 // //////////////////////////////////////
00932 // Helper functions
00933   
00940 template<typename T>
00941 T& getParameter( ParameterList& l, const std::string& name )
00942 {
00943   return l.template get<T>(name);
00944 }
00945   
00951 template<typename T>
00952 inline
00953 T& get( ParameterList& l, const std::string& name )
00954 {
00955   return getParameter<T>(l,name);
00956 }
00957   
00964 template<typename T>
00965 const T& getParameter( const ParameterList& l, const std::string& name )
00966 {
00967   return l.template get<T>(name);
00968 }
00969   
00977 template<typename T>
00978 inline
00979 T* getParameterPtr( ParameterList& l, const std::string& name )
00980 {
00981   return l.template getPtr<T>(name);
00982 }
00983   
00991 template<typename T>
00992 inline
00993 const T* getParameterPtr( const ParameterList& l, const std::string& name )
00994 {
00995   return l.template getPtr<T>(name);
00996 }
00997   
01004 template<typename T>
01005 inline
01006 bool isParameterType( ParameterList& l, const std::string& name )
01007 {
01008   return l.isType( name, (T*)NULL );
01009 }
01010   
01017 template<typename T>
01018 inline
01019 bool isParameterType( const ParameterList& l, const std::string& name )
01020 {
01021   return l.isType( name, (T*)NULL );
01022 }
01023   
01035 template<typename T>
01036 void setStringParameterFromArray(
01037   const std::string          &paramName
01038   ,const Array<T>       &array
01039   ,ParameterList        *paramList
01040   )
01041 {
01042   TEUCHOS_TEST_FOR_EXCEPT(!paramList);
01043   paramList->set(paramName,toString(array));
01044 }
01045   
01110 template<typename T>
01111 Array<T> getArrayFromStringParameter(
01112   const ParameterList   &paramList
01113   ,const std::string         &paramName
01114   ,const int            arrayDim        = -1
01115   ,const bool           mustExist       = true
01116   )
01117 {
01118   std::string arrayStr;
01119   if(mustExist) {
01120     arrayStr = getParameter<std::string>(paramList,paramName);
01121   }
01122   else {
01123     const std::string
01124       *arrayStrPtr = getParameterPtr<std::string>(paramList,paramName);
01125     if(arrayStrPtr) {
01126       arrayStr = *arrayStrPtr;
01127     }
01128     else {
01129       return Array<T>(); // Return an empty array
01130     }
01131   }
01132   Array<T> a;
01133   try {
01134     a = fromStringToArray<T>(arrayStr);
01135   }
01136   catch( const InvalidArrayStringRepresentation&) {
01137     TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(
01138       true, Exceptions::InvalidParameterValue
01139       ,"Error!  The parameter \""<<paramName<<"\"\n"
01140       "in the sublist \""<<paramList.name()<<"\"\n"
01141       "exists, but the std::string value:\n"
01142       "----------\n"
01143       <<arrayStr<<
01144       "\n----------\n"
01145       "is not a valid array represntation!"
01146       );
01147   }
01148   TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(
01149     ( ( a.size()>0 && arrayDim>=0 ) && static_cast<int>(a.size())!=arrayDim )
01150     ,Exceptions::InvalidParameterValue
01151     ,"Error!  The parameter \""<<paramName<<"\"\n"
01152     "in the sublist \""<<paramList.name()<<"\"\n"
01153     "exists and is a valid array, but the dimension of\n"
01154     "the read in array a.size() = " << a.size() << "\n"
01155     "was not equal to the expected size arrayDim = " << arrayDim << "!"
01156     );
01157   return a;
01158 }
01159 
01163 inline
01164 RCP<ParameterList> sublist(
01165   const RCP<ParameterList> &paramList, const std::string& name,
01166   bool mustAlreadyExist = false, const std::string& docString = ""
01167   )
01168 {
01169   return rcpWithEmbeddedObjPostDestroy(
01170     &paramList->sublist(name, mustAlreadyExist, docString), paramList, false );
01171 }
01172 
01176 inline
01177 RCP<const ParameterList> sublist(
01178   const RCP<const ParameterList> &paramList, const std::string& name
01179   )
01180 {
01181   return rcpWithEmbeddedObjPostDestroy(
01182     &paramList->sublist(name), paramList, false );
01183 }
01184   
01188 inline std::ostream& operator<<(std::ostream& os, const ParameterList& l)
01189 {
01190   return l.print(os);
01191 }
01192   
01193 } // end of Teuchos namespace
01194 
01195 #endif
01196 
01197 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines