Teuchos_ParameterList.cpp

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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 //#define TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00030 
00031 #include "Teuchos_ParameterList.hpp"
00032 
00033 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00034 #include "Teuchos_VerboseObject.hpp"
00035 #endif
00036 
00037 /* NOTE: ASCI Red (TFLOP) does not support the i-> function for iterators 
00038  * in the STL.  Therefore when compiling for the TFLOP we must redefine the 
00039  * iterator from i-> to (*i). This slows things down on other platforms 
00040  * so we switch between the two when necessary.
00041  */
00042 
00043 namespace {
00044 
00045 std::string filterValueToString(const Teuchos::ParameterEntry& entry )
00046 {
00047   return ( entry.isList() ? std::string("...") : toString(entry.getAny()) );
00048 }
00049 
00050 struct ListPlusValidList {
00051   Teuchos::ParameterList   *list;
00052   Teuchos::ParameterList   *validList;
00053   ListPlusValidList(
00054     Teuchos::ParameterList   *_list
00055     ,Teuchos::ParameterList  *_validList
00056     )
00057     :list(_list),validList(_validList)
00058     {}
00059 };
00060 
00061 } // namespace 
00062 
00063 namespace Teuchos {
00064 
00065 ParameterList::ParameterList()
00066   :name_("ANONYMOUS")
00067 {}
00068 
00069 ParameterList::ParameterList(const std::string &name)
00070   :name_(name)
00071 {}
00072 
00073 ParameterList::ParameterList(const ParameterList& source) 
00074 {
00075   name_ = source.name_;
00076   params_ = source.params_;
00077 }
00078 
00079 ParameterList& ParameterList::operator=(const ParameterList& source) 
00080 {
00081   if (&source == this)
00082     return *this;
00083   name_ = source.name_;
00084   params_ = source.params_;
00085   return *this;
00086 }
00087 
00088 ParameterList& ParameterList::setParameters(const ParameterList& source) 
00089 {
00090   for( ConstIterator i = source.begin(); i != source.end(); ++i ) {
00091     const std::string     &name_i  = this->name(i);
00092     const ParameterEntry  &entry_i = this->entry(i);
00093     if(entry_i.isList()) {
00094       this->sublist(name_i).setParameters(getValue<ParameterList>(entry_i));
00095     }
00096     else {
00097       this->setEntry(name_i,entry_i);
00098     }
00099   }
00100   this->updateSubListNames();
00101   return *this;
00102 }
00103 
00104 ParameterList::~ParameterList() 
00105 {}
00106 
00107 void ParameterList::unused(ostream& os) const
00108 {
00109   for (ConstIterator i = params_.begin(); i != params_.end(); ++i) {
00110     if (!(entry(i).isUsed())) {
00111       os << "WARNING: Parameter \"" << name(i) << "\" " << entry(i)
00112          << " is unused" << endl;
00113     }
00114   }
00115 }
00116 
00117 std::string ParameterList::currentParametersString() const
00118 {
00119   std::ostringstream oss;
00120   oss << "{";
00121   ParameterList::ConstIterator itr;
00122   int i;
00123   for( itr = this->begin(), i = 0; itr != this->end(); ++itr, ++i ) {
00124     const std::string     &entryName   = this->name(itr);
00125     const ParameterEntry  &entry       = this->entry(itr);
00126     if(i) oss << ",";
00127     oss
00128       << "\""<<entryName<<"\":"<<entry.getAny().typeName()
00129       <<"="<<filterValueToString(entry);
00130   }
00131   oss << "}";
00132   return oss.str();
00133 }
00134 
00135 bool ParameterList::isSublist(const string& name) const
00136 {
00137   ConstIterator i = params_.find(name);
00138 
00139   if (i != params_.end())
00140     return (entry(i).isList());
00141 
00142   return false;
00143 }
00144 
00145 bool ParameterList::isParameter(const string& name) const
00146 {
00147   return (params_.find(name) != params_.end());
00148 }
00149 
00150 ParameterList& ParameterList::sublist(const string& name, bool mustAlreadyExist)
00151 {
00152   // Find name in list, if it exists.
00153   Iterator i = params_.find(name);
00154 
00155   // If it does exist and is a list, return the list value.
00156   // Otherwise, throw an error.
00157   if (i != params_.end()) {
00158     TEST_FOR_EXCEPTION(
00159       !entry(i).isList(), std::runtime_error,
00160       " Parameter " << name << " is not a list, it is of type \""
00161       <<entry(i).getAny(false).typeName()<<"\"!" );
00162     return getValue<ParameterList>(entry(i));
00163   }
00164 
00165   // The list does not exist so create a new empty list and return its reference
00166   TEST_FOR_EXCEPTION(
00167     mustAlreadyExist, Exceptions::InvalidParameter
00168     ,"The sublist "<<this->name()<<"->\""<<name<<"\" does not exist!"
00169     );
00170   const ParameterList newSubList(this->name()+std::string("->")+name);
00171   return any_cast<ParameterList>(
00172     params_.insert(
00173       Map::value_type(name,ParameterEntry(newSubList,false,true))
00174       ).first->second.getAny(false)
00175     );
00176   // Note that above I am very careful to construct the parameter list entry
00177   // directly in the insertion call to avoid the creation of a tempory list
00178   // object.  This looks ugly but it should be fast.
00179 }
00180 
00181 const ParameterList& ParameterList::sublist(const string& name) const
00182 {
00183   // Find name in list, if it exists.
00184   ConstIterator i = params_.find(name);
00185 
00186   // If it does not exist, throw an error
00187   TEST_FOR_EXCEPTION(
00188     i == params_.end(), Exceptions::InvalidParameter
00189     ,"The sublist "<<this->name()<<"->\""<<name<<"\" does not exist!"
00190     );
00191 
00192   // If it does exist and is a list, return the list value.
00193   TEST_FOR_EXCEPTION( !entry(i).isList(), std::runtime_error,
00194                       " Parameter " << name << " is not a list!" );
00195   return getValue<ParameterList>(entry(i));
00196 }
00197   
00198 ostream& ParameterList::print(ostream& os, int indent, bool showTypes, bool showFlags) const
00199 {
00200   if (params_.begin() == params_.end()) {
00201     for (int j = 0; j < indent; j ++)
00202       os << ' ';
00203     os << "[empty list]" << endl;
00204   }
00205   else { 
00206     // Print parameters first
00207     for (ConstIterator i = params_.begin(); i != params_.end(); ++i) 
00208     {
00209       const ParameterEntry &entry_i = entry(i);
00210       if(entry_i.isList())
00211         continue;
00212       for (int j = 0; j < indent; j ++)
00213         os << ' ';
00214       os << name(i);
00215       if(showTypes)
00216         os << " : " << entry_i.getAny(false).typeName();
00217       os << " = "; entry_i.leftshift(os,showFlags); os << endl;
00218     }
00219     // Print sublists second
00220     for (ConstIterator i = params_.begin(); i != params_.end(); ++i) 
00221     {
00222       const ParameterEntry &entry_i = entry(i);
00223       if(!entry_i.isList())
00224         continue;
00225       for (int j = 0; j < indent; j ++)
00226         os << ' ';
00227       os << name(i) << " -> " << endl;
00228       getValue<ParameterList>(entry_i).print(os, indent + 2,showTypes,showFlags);
00229     }
00230   }
00231   return os;
00232 }
00233 
00234 ParameterList::ConstIterator ParameterList::begin() const
00235 {
00236   return params_.begin();
00237 }
00238 
00239 ParameterList::ConstIterator ParameterList::end() const
00240 {
00241   return params_.end();
00242 }
00243 
00244 
00245 
00246 #if defined(TFLOP)
00247 
00248 const string& ParameterList::name(ConstIterator i) const
00249 {
00250   return ((*i).first);
00251 }
00252 
00253 ParameterEntry& ParameterList::entry(Iterator i)
00254 {
00255   return ((*i).second);
00256 }
00257 
00258 const ParameterEntry& ParameterList::entry(ConstIterator i) const
00259 {
00260   return ((*i).second);
00261 }
00262 
00263 #else
00264 
00265 const string& ParameterList::name(ConstIterator i) const
00266 {
00267   return (i->first);
00268 }
00269 
00270 ParameterEntry& ParameterList::entry(Iterator i)
00271 {
00272   return (i->second);
00273 }
00274 
00275 const ParameterEntry& ParameterList::entry(ConstIterator i) const
00276 {
00277   return (i->second);
00278 }
00279 
00280 #endif
00281 
00282 void ParameterList::validateParameters(
00283   const ParameterList              &validParamList
00284   ,const int                       depth
00285   ,const EValidateUsed             validateUsed
00286   ,const EValidateDefaults         validateDefaults
00287   ) const
00288 {
00289   typedef std::deque<ListPlusValidList> sublist_list_t;
00290 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00291   RefCountPtr<FancyOStream> out = VerboseObjectBase::getDefaultOStream();
00292   OSTab tab(out);
00293   *out << "\n*** Entering ParameterList::validateParameters(...) for this->name()=\""<<this->name()<<"\"...\n";
00294 #endif
00295   //
00296   // First loop through and validate the parameters at this level.
00297   //
00298   // Here we generate a list of sublists that we will search next
00299   //
00300   sublist_list_t sublist_list;
00301   ConstIterator itr;
00302   for( itr = this->begin(); itr != this->end(); ++itr ) {
00303     const std::string    &entryName   = this->name(itr);
00304     const ParameterEntry &entry       = this->entry(itr);
00305     if(
00306       ( entry.isUsed() && validateUsed!=VALIDATE_USED_ENABLED )
00307       ||
00308       ( entry.isDefault() && validateDefaults!=VALIDATE_DEFAULTS_ENABLED )
00309       )
00310     {
00311       continue;
00312     }
00313     const ParameterEntry *validEntry = validParamList.getEntryPtr(entryName);
00314 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00315     OSTab tab(out);
00316     *out << "\nentryName=\""<<entryName<<"\"\n";
00317 #endif
00318     const bool validType = ( validEntry!=NULL ? entry.getAny(false).type() == validEntry->getAny(false).type() : false );
00319     TEST_FOR_EXCEPTION(
00320       !( validEntry!=NULL && validType )
00321       ,Exceptions::InvalidParameter
00322       ,"Error, the parameter {name=\""<<entryName<<"\",type=\""<<entry.getAny(false).typeName()<<"\""
00323       ",value=\""<<filterValueToString(entry)<<"\"} in the parameter (sub)list \""<<this->name()<<"\" "
00324       << ( validEntry==NULL
00325            ? "was not found in the list of valid parameters"
00326            : std::string("exists in the list of valid parameters but has the wrong type.  The correct type is \"")
00327            +validEntry->getAny(false).typeName()+std::string("\"")
00328         )
00329       << ". The valid parameters and types are "<<validParamList.currentParametersString()
00330       );
00331     if( entry.isList() && depth > 0 ) {
00332       sublist_list.push_back(
00333         ListPlusValidList(
00334           &getValue<ParameterList>(entry),&getValue<ParameterList>(*validEntry)
00335           )
00336         );
00337     }
00338   }
00339   //
00340   // Now loop through the sublists and validate their parameters
00341   //
00342   for( sublist_list_t::const_iterator sl_itr = sublist_list.begin(); sl_itr != sublist_list.end(); ++sl_itr ) {
00343     sl_itr->list->validateParameters(
00344       *sl_itr->validList
00345       ,depth-1
00346       ,validateUsed
00347       ,validateDefaults
00348       );
00349   }
00350 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00351   *out << "\n*** Existing ParameterList::validateParameters(...) for this->name()=\""<<this->name()<<"\"...\n";
00352 #endif
00353 }
00354 
00355 // private
00356 
00357 void ParameterList::updateSubListNames(int depth)
00358 {
00359   const std::string this_name = this->name();
00360   Map::iterator itr;
00361   for( itr = params_.begin(); itr != params_.end(); ++itr ) {
00362     const std::string    &entryName   = this->name(itr);
00363     const ParameterEntry &entry       = this->entry(itr);
00364     if(entry.isList()) {
00365       ParameterList &sublist = getValue<ParameterList>(entry);
00366       sublist.setName(this_name+std::string("->")+entryName);
00367       if(depth > 0)
00368         sublist.updateSubListNames(depth-1);
00369     }
00370   }
00371 }
00372 
00373 } // namespace Teuchos
00374 
00375 bool Teuchos::operator==( const ParameterList& list1, const ParameterList& list2 )
00376 {
00377   bool isSame = true;
00378   ParameterList::ConstIterator itr1, itr2;
00379   for(
00380     itr1 = list1.begin(), itr2 = list2.begin();
00381     itr1 != list1.end() && itr2 != list2.end();
00382     ++itr1, ++itr2
00383     )
00384   {
00385     const std::string    &entryName1   = list1.name(itr1);
00386     const std::string    &entryName2   = list2.name(itr2);
00387     const ParameterEntry &entry1       = list1.entry(itr1);
00388     const ParameterEntry &entry2       = list2.entry(itr2);
00389     if( entryName1 != entryName2 )
00390       isSame = false;
00391     else if( entry1 != entry2 )
00392       isSame = false;
00393     // Note that the above statement automatically recursively compare the
00394     // sublists since ParameterList objects are stored in the 'any' variable
00395     // held by the ParameterEntry object and this same comparison operator will
00396     // be used.
00397   }
00398   return isSame;
00399 }

Generated on Thu Sep 18 12:30:30 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1