00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "Teuchos_ParameterList.hpp"
00032 #include "Teuchos_FancyOStream.hpp"
00033 #include "Teuchos_StrUtils.hpp"
00034
00035 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00036 #include "Teuchos_VerboseObject.hpp"
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00045 namespace {
00046
00047 std::string filterValueToString(const Teuchos::ParameterEntry& entry )
00048 {
00049 return ( entry.isList() ? std::string("...") : toString(entry.getAny()) );
00050 }
00051
00052 struct ListPlusValidList {
00053 Teuchos::ParameterList *list;
00054 Teuchos::ParameterList *validList;
00055 ListPlusValidList(
00056 Teuchos::ParameterList *_list
00057 ,Teuchos::ParameterList *_validList
00058 )
00059 :list(_list),validList(_validList)
00060 {}
00061 };
00062
00063 }
00064
00065 namespace Teuchos {
00066
00067 ParameterList::ParameterList()
00068 :name_("ANONYMOUS"), disableRecursiveValidation_(false)
00069 {}
00070
00071 ParameterList::ParameterList(const std::string &name_in)
00072 :name_(name_in), disableRecursiveValidation_(false)
00073 {}
00074
00075 ParameterList::ParameterList(const ParameterList& source)
00076 {
00077 name_ = source.name_;
00078 params_ = source.params_;
00079 disableRecursiveValidation_ = source.disableRecursiveValidation_;
00080 }
00081
00082 ParameterList& ParameterList::operator=(const ParameterList& source)
00083 {
00084 if (&source == this)
00085 return *this;
00086 name_ = source.name_;
00087 params_ = source.params_;
00088 disableRecursiveValidation_ = source.disableRecursiveValidation_;
00089 return *this;
00090 }
00091
00092 ParameterList& ParameterList::setParameters(const ParameterList& source)
00093 {
00094 for( ConstIterator i = source.begin(); i != source.end(); ++i ) {
00095 const std::string &name_i = this->name(i);
00096 const ParameterEntry &entry_i = this->entry(i);
00097 if(entry_i.isList()) {
00098 this->sublist(name_i,false,entry_i.docString()).setParameters(
00099 getValue<ParameterList>(entry_i) );
00100 }
00101 else {
00102 this->setEntry(name_i,entry_i);
00103 }
00104 }
00105 this->updateSubListNames();
00106 return *this;
00107 }
00108
00109 ParameterList& ParameterList::setParametersNotAlreadySet(
00110 const ParameterList& source
00111 )
00112 {
00113 for( ConstIterator i = source.begin(); i != source.end(); ++i ) {
00114 const std::string &name_i = this->name(i);
00115 const ParameterEntry &entry_i = this->entry(i);
00116 if(entry_i.isList()) {
00117 this->sublist(name_i,false,entry_i.docString()).setParametersNotAlreadySet(
00118 getValue<ParameterList>(entry_i) );
00119 }
00120 else {
00121 const ParameterEntry
00122 *thisEntryPtr = this->getEntryPtr(name_i);
00123
00124
00125 if(!thisEntryPtr)
00126 this->setEntry(name_i,entry_i);
00127 }
00128 }
00129 this->updateSubListNames();
00130 return *this;
00131 }
00132
00133 ParameterList& ParameterList::disableRecursiveValidation()
00134 {
00135 disableRecursiveValidation_ = true;
00136 return *this;
00137 }
00138
00139 ParameterList::~ParameterList()
00140 {}
00141
00142 void ParameterList::unused(std::ostream& os) const
00143 {
00144 for (ConstIterator i = params_.begin(); i != params_.end(); ++i) {
00145 if (!(entry(i).isUsed())) {
00146 os << "WARNING: Parameter \"" << name(i) << "\" " << entry(i)
00147 << " is unused" << std::endl;
00148 }
00149 }
00150 }
00151
00152 std::string ParameterList::currentParametersString() const
00153 {
00154 std::ostringstream oss;
00155 oss << " {\n";
00156 ParameterList::ConstIterator itr;
00157 int i;
00158 for( itr = this->begin(), i = 0; itr != this->end(); ++itr, ++i ) {
00159 const std::string &entryName = this->name(itr);
00160 const ParameterEntry &theEntry = this->entry(itr);
00161 oss
00162 << " \""<<entryName<<"\" : "<<theEntry.getAny().typeName()
00163 <<" = "<<filterValueToString(theEntry) << "\n";
00164 }
00165 oss << " }\n";
00166 return oss.str();
00167 }
00168
00169 bool ParameterList::isSublist(const std::string& name_in) const
00170 {
00171 ConstIterator i = params_.find(name_in);
00172 if (i != params_.end())
00173 return (entry(i).isList());
00174 return false;
00175 }
00176
00177 bool ParameterList::isParameter(const std::string& name_in) const
00178 {
00179 return (params_.find(name_in) != params_.end());
00180 }
00181
00182 bool ParameterList::remove(
00183 std::string const& name_in, bool throwIfNotExists
00184 )
00185 {
00186 Iterator i = params_.find(name_in);
00187 TEST_FOR_EXCEPTION(
00188 throwIfNotExists && i == params_.end(), Exceptions::InvalidParameterName
00189 ,"Teuchos::ParameterList::remove(name,throwIfNotExists):"
00190 "\n\nError, the parameter \"" << name_in << "\" does not exist!"
00191 );
00192 if( i != params_.end() ) {
00193 params_.erase(i);
00194 }
00195 return false;
00196 }
00197
00198 ParameterList& ParameterList::sublist(
00199 const std::string& name_in, bool mustAlreadyExist
00200 ,const std::string& docString
00201 )
00202 {
00203
00204 Iterator i = params_.find(name_in);
00205
00206
00207
00208 if (i != params_.end()) {
00209 #ifdef TEUCHOS_DEBUG
00210 const std::string actualName = this->name(i);
00211 TEST_FOR_EXCEPTION(
00212 name_in != actualName, std::logic_error,
00213 "Error, the sublist named \"" << name_in << "\" was said to be found\n"
00214 "but the actual parameter name is \"" << actualName << "\".\n"
00215 "This suggests some type of memory corruption in the list (try running a\n"
00216 "memory checking tool loke purify or valgrind)."
00217 );
00218 #endif
00219
00220 TEST_FOR_EXCEPTION_PURE_MSG(
00221 !entry(i).isList(), Exceptions::InvalidParameterType
00222 ,"Error, the parameter \"" << name_in << "\" is not a list, it is of type \""
00223 <<entry(i).getAny(false).typeName()<<"\"!" );
00224 return getValue<ParameterList>(entry(i));
00225 }
00226
00227
00228 TEST_FOR_EXCEPTION_PURE_MSG(
00229 mustAlreadyExist, Exceptions::InvalidParameterName
00230 ,"The sublist "<<this->name()<<"->\""<<name_in<<"\" does not exist!"
00231 );
00232 const ParameterList newSubList(this->name()+std::string("->")+name_in);
00233 ParameterEntry &newParamEntry = params_.insert(
00234 Map::value_type(name_in,ParameterEntry(newSubList,false,true,docString))
00235 ).first->second;
00236
00237 #ifdef TEUCHOS_DEBUG
00238 {
00239 ParameterEntry *newNewParamEntry = this->getEntryPtr(name_in);
00240 TEST_FOR_EXCEPTION(
00241 0 == newNewParamEntry, std::logic_error,
00242 "Error, the parameter was not set for sublist \"" << name_in << "\"!"
00243 );
00244 const std::string newDocString = newNewParamEntry->docString();
00245 TEST_FOR_EXCEPTION(
00246 newDocString != docString, std::logic_error,
00247 "Error, the set documentation std::string is not equal to the pass in std::string for\n"
00248 "the sublist \"" << name_in << "\"."
00249 );
00250 }
00251 #endif
00252 return any_cast<ParameterList>(newParamEntry.getAny(false));
00253 }
00254
00255 const ParameterList& ParameterList::sublist(const std::string& name_in) const
00256 {
00257
00258 ConstIterator i = params_.find(name_in);
00259
00260
00261 TEST_FOR_EXCEPTION_PURE_MSG(
00262 i == params_.end(), Exceptions::InvalidParameterName
00263 ,"Error, the sublist "<<this->name()<<"->\""<<name_in<<"\" does not exist!"
00264 );
00265
00266
00267 TEST_FOR_EXCEPTION_PURE_MSG(
00268 !entry(i).isList(), Exceptions::InvalidParameterType
00269 ,"Error, the parameter \""<<name_in<<"\" is not a list! Instead it is of type"
00270 " \""<<entry(i).getAny(false).typeName()<<"\"!"
00271 );
00272 return getValue<ParameterList>(entry(i));
00273 }
00274
00275 std::ostream& ParameterList::print(std::ostream& os, int indent, bool showTypes, bool showFlags) const
00276 {
00277 return this->print(os,PrintOptions().indent(indent).showTypes(showTypes).showFlags(showFlags));
00278 }
00279
00280 std::ostream& ParameterList::print(std::ostream& os, const PrintOptions &printOptions ) const
00281 {
00282 const int indent = printOptions.indent();
00283 const bool showTypes = printOptions.showTypes();
00284 const bool showFlags = printOptions.showFlags();
00285 const bool showDoc = printOptions.showDoc();
00286 const std::string linePrefix(indent,' ');
00287 RCP<FancyOStream>
00288 out = getFancyOStream(rcp(&os,false));
00289 OSTab tab(out,indent);
00290 if (params_.begin() == params_.end()) {
00291 *out <<"[empty list]" << std::endl;
00292 }
00293 else {
00294
00295 for (ConstIterator i = params_.begin(); i != params_.end(); ++i)
00296 {
00297 const std::string &name_i = this->name(i);
00298 const ParameterEntry &entry_i = entry(i);
00299 RCP<const ParameterEntryValidator>
00300 validator = entry_i.validator();
00301 if(entry_i.isList())
00302 continue;
00303 *out << name_i;
00304 const std::string &docString = entry_i.docString();
00305 if(showTypes)
00306 *out << " : " << entry_i.getAny(false).typeName();
00307 *out << " = "; entry_i.leftshift(os,showFlags); *out << std::endl;
00308 if(showDoc) {
00309 if(validator.get()) {
00310 validator->printDoc(docString,OSTab(os).o());
00311 }
00312 else if( docString.length() ) {
00313 StrUtils::printLines(OSTab(out).o(),"# ",docString);
00314 }
00315 }
00316 }
00317
00318 for (ConstIterator i = params_.begin(); i != params_.end(); ++i)
00319 {
00320 const ParameterEntry &entry_i = entry(i);
00321 if(!entry_i.isList())
00322 continue;
00323 const std::string &docString = entry_i.docString();
00324 const std::string &name_i = this->name(i);
00325 *out << name_i << " -> " << std::endl;
00326 if( docString.length() && showDoc ) {
00327 StrUtils::printLines(OSTab(out).o(),"# ",docString);
00328 }
00329 getValue<ParameterList>(entry_i).print(OSTab(out).o(), printOptions.copy().indent(0));
00330 }
00331 }
00332 return os;
00333 }
00334
00335 ParameterList::ConstIterator ParameterList::begin() const
00336 {
00337 return params_.begin();
00338 }
00339
00340 ParameterList::ConstIterator ParameterList::end() const
00341 {
00342 return params_.end();
00343 }
00344
00345 #if defined(TFLOP)
00346
00347 const std::string& ParameterList::name(ConstIterator i) const
00348 {
00349 return ((*i).first);
00350 }
00351
00352 ParameterEntry& ParameterList::entry(Iterator i)
00353 {
00354 return ((*i).second);
00355 }
00356
00357 const ParameterEntry& ParameterList::entry(ConstIterator i) const
00358 {
00359 return ((*i).second);
00360 }
00361
00362 #else // defined(TFLOP)
00363
00364 const std::string& ParameterList::name(ConstIterator i) const
00365 {
00366 return (i->first);
00367 }
00368
00369 ParameterEntry& ParameterList::entry(Iterator i)
00370 {
00371 return (i->second);
00372 }
00373
00374 const ParameterEntry& ParameterList::entry(ConstIterator i) const
00375 {
00376 return (i->second);
00377 }
00378
00379 #endif // defined(TFLOP)
00380
00381
00382 void ParameterList::validateParameters(
00383 ParameterList const& validParamList,
00384 int const depth,
00385 EValidateUsed const validateUsed,
00386 EValidateDefaults const validateDefaults
00387 ) const
00388 {
00389 typedef std::deque<ListPlusValidList> sublist_list_t;
00390 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00391 RCP<FancyOStream> out = VerboseObjectBase::getDefaultOStream();
00392 OSTab tab(out);
00393 *out << "\n*** Entering ParameterList::validateParameters(...) for "
00394 "this->name()=\""<<this->name()<<"\"...\n";
00395 #endif
00396
00397
00398
00399
00400
00401 sublist_list_t sublist_list;
00402 ConstIterator itr;
00403 for( itr = this->begin(); itr != this->end(); ++itr ) {
00404 const std::string &entryName = this->name(itr);
00405 const ParameterEntry &theEntry = this->entry(itr);
00406 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00407 OSTab tab(out);
00408 *out << "\nentryName=\""<<entryName<<"\"\n";
00409 #endif
00410 if(
00411 ( theEntry.isUsed() && validateUsed!=VALIDATE_USED_ENABLED )
00412 ||
00413 ( theEntry.isDefault() && validateDefaults!=VALIDATE_DEFAULTS_ENABLED )
00414 )
00415 {
00416 continue;
00417 }
00418 const ParameterEntry *validEntry = validParamList.getEntryPtr(entryName);
00419 TEST_FOR_EXCEPTION_PURE_MSG(
00420 !validEntry, Exceptions::InvalidParameterName
00421 ,"Error, the parameter {name=\""<<entryName<<"\","
00422 "type=\""<<theEntry.getAny(false).typeName()<<"\""
00423 ",value=\""<<filterValueToString(theEntry)<<"\"}"
00424 "\nin the parameter (sub)list \""<<this->name()<<"\""
00425 "\nwas not found in the list of valid parameters!"
00426 "\n\nThe valid parameters and types are:\n"
00427 <<validParamList.currentParametersString()
00428 );
00429 RCP<const ParameterEntryValidator> validator;
00430 if( (validator=validEntry->validator()).get() ) {
00431 validator->validate( theEntry, entryName, this->name() );
00432 }
00433 else {
00434 const bool validType =
00435 ( validEntry!=NULL
00436 ? theEntry.getAny(false).type() == validEntry->getAny(false).type()
00437 : false
00438 );
00439 TEST_FOR_EXCEPTION_PURE_MSG(
00440 !validType, Exceptions::InvalidParameterType
00441 ,"Error, the parameter {name=\""<<entryName<<"\","
00442 "type=\""<<theEntry.getAny(false).typeName()<<"\""
00443 ",value=\""<<filterValueToString(theEntry)<<"\"}"
00444 "\nin the parameter (sub)list \""<<this->name()<<"\""
00445 "\nexists in the list of valid parameters but has the wrong type."
00446 "\n\nThe correct type is \""
00447 << validEntry->getAny(false).typeName() << "\"."
00448 );
00449 }
00450 if( theEntry.isList() && depth > 0 ) {
00451 sublist_list.push_back(
00452 ListPlusValidList(
00453 &getValue<ParameterList>(theEntry),&getValue<ParameterList>(*validEntry)
00454 )
00455 );
00456 }
00457 }
00458
00459
00460
00461 for(
00462 sublist_list_t::const_iterator sl_itr = sublist_list.begin();
00463 sl_itr != sublist_list.end();
00464 ++sl_itr
00465 )
00466 {
00467 if (!sl_itr->validList->disableRecursiveValidation_) {
00468 sl_itr->list->validateParameters(
00469 *sl_itr->validList
00470 ,depth-1
00471 ,validateUsed
00472 ,validateDefaults
00473 );
00474 }
00475 }
00476 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00477 *out << "\n*** Existing ParameterList::validateParameters(...) for "
00478 "this->name()=\""<<this->name()<<"\"...\n";
00479 #endif
00480 }
00481
00482
00483 void ParameterList::validateParametersAndSetDefaults(
00484 ParameterList const& validParamList,
00485 int const depth
00486 )
00487 {
00488 typedef std::deque<ListPlusValidList> sublist_list_t;
00489 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00490 RCP<FancyOStream> out = VerboseObjectBase::getDefaultOStream();
00491 OSTab tab(out);
00492 *out << "\n*** Entering ParameterList::validateParametersAndSetDefaults(...) "
00493 "for this->name()=\""<<this->name()<<"\"...\n";
00494 #endif
00495
00496
00497
00498
00499
00500 sublist_list_t sublist_list;
00501 {
00502 Iterator itr;
00503 for( itr = this->nonconstBegin(); itr != this->nonconstEnd(); ++itr ) {
00504 const std::string &entryName = this->name(itr);
00505 ParameterEntry &theEntry = this->entry(itr);
00506 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00507 OSTab tab(out);
00508 *out << "\nentryName=\""<<entryName<<"\"\n";
00509 #endif
00510 const ParameterEntry *validEntry = validParamList.getEntryPtr(entryName);
00511 TEST_FOR_EXCEPTION_PURE_MSG(
00512 !validEntry, Exceptions::InvalidParameterName
00513 ,"Error, the parameter {name=\""<<entryName<<"\","
00514 "type=\""<<theEntry.getAny(false).typeName()<<"\""
00515 ",value=\""<<filterValueToString(theEntry)<<"\"}"
00516 "\nin the parameter (sub)list \""<<this->name()<<"\""
00517 "\nwas not found in the list of valid parameters!"
00518 "\n\nThe valid parameters and types are:\n"
00519 <<validParamList.currentParametersString()
00520 );
00521 RCP<const ParameterEntryValidator> validator;
00522 if( (validator=validEntry->validator()).get() ) {
00523 validator->validateAndModify( entryName, this->name(), &theEntry );
00524 theEntry.setValidator(validator);
00525 }
00526 else {
00527 const bool validType =
00528 ( validEntry!=NULL
00529 ? theEntry.getAny(false).type() == validEntry->getAny(false).type()
00530 : false
00531 );
00532 TEST_FOR_EXCEPTION_PURE_MSG(
00533 !validType, Exceptions::InvalidParameterType
00534 ,"Error, the parameter {name=\""<<entryName<<"\","
00535 "type=\""<<theEntry.getAny(false).typeName()<<"\""
00536 ",value=\""<<filterValueToString(theEntry)<<"\"}"
00537 "\nin the parameter (sub)list \""<<this->name()<<"\""
00538 "\nexists in the list of valid parameters but has the wrong type."
00539 "\n\nThe correct type is \""
00540 << validEntry->getAny(false).typeName() << "\"."
00541 );
00542
00543
00544 }
00545 if( theEntry.isList() && depth > 0 ) {
00546 sublist_list.push_back(
00547 ListPlusValidList(
00548 &getValue<ParameterList>(theEntry),
00549 &getValue<ParameterList>(*validEntry)
00550 )
00551 );
00552 }
00553 }
00554 }
00555
00556
00557
00558
00559 {
00560 ConstIterator itr;
00561 for( itr = validParamList.begin(); itr != validParamList.end(); ++itr ) {
00562 const std::string &validEntryName = validParamList.name(itr);
00563 const ParameterEntry &validEntry = validParamList.entry(itr);
00564 const ParameterEntry *theEntry = this->getEntryPtr(validEntryName);
00565 if(!theEntry) {
00566
00567
00568
00569
00570
00571 ParameterEntry newEntry;
00572 newEntry.setAnyValue(
00573 validEntry.getAny(),
00574 true
00575 );
00576 newEntry.setValidator(validEntry.validator());
00577 this->setEntry(validEntryName,newEntry);
00578 }
00579 }
00580 }
00581
00582
00583
00584
00585 for(
00586 sublist_list_t::iterator sl_itr = sublist_list.begin();
00587 sl_itr != sublist_list.end();
00588 ++sl_itr
00589 )
00590 {
00591 if (!sl_itr->validList->disableRecursiveValidation_) {
00592 sl_itr->list->validateParametersAndSetDefaults(*sl_itr->validList,depth-1);
00593 }
00594 }
00595 #ifdef TEUCHOS_PARAMETER_LIST_SHOW_TRACE
00596 *out << "\n*** Existing ParameterList::validateParametersAndSetDefaults(...) "
00597 "for this->name()=\""<<this->name()<<"\"...\n";
00598 #endif
00599 }
00600
00601
00602
00603
00604
00605 ParameterList::Iterator ParameterList::nonconstBegin()
00606 {
00607 return params_.begin();
00608 }
00609
00610
00611 ParameterList::Iterator ParameterList::nonconstEnd()
00612 {
00613 return params_.end();
00614 }
00615
00616
00617 void ParameterList::updateSubListNames(int depth)
00618 {
00619 const std::string this_name = this->name();
00620 Map::iterator itr;
00621 for( itr = params_.begin(); itr != params_.end(); ++itr ) {
00622 const std::string &entryName = this->name(itr);
00623 const ParameterEntry &theEntry = this->entry(itr);
00624 if(theEntry.isList()) {
00625 ParameterList &sublistEntry = getValue<ParameterList>(theEntry);
00626 sublistEntry.setName(this_name+std::string("->")+entryName);
00627 if(depth > 0)
00628 sublistEntry.updateSubListNames(depth-1);
00629 }
00630 }
00631 }
00632
00633
00634 void ParameterList::validateEntryExists(
00635 const std::string & , const std::string &name_in,
00636 const ParameterEntry *entry_in
00637 ) const
00638 {
00639 TEST_FOR_EXCEPTION_PURE_MSG(
00640 entry_in==NULL, Exceptions::InvalidParameterName
00641 ,"Error! The parameter \""<<name_in<<"\" does not exist"\
00642 "\nin the parameter (sub)list \""<<this->name()<<"\"."
00643 "\n\nThe current parameters set in (sub)list \""<<this->name()<<"\" are:\n\n"
00644 << this->currentParametersString()
00645 );
00646 }
00647
00648
00649 }
00650
00651
00652 bool Teuchos::operator==( const ParameterList& list1, const ParameterList& list2 )
00653 {
00654 ParameterList::ConstIterator itr1, itr2;
00655 for(
00656 itr1 = list1.begin(), itr2 = list2.begin();
00657 itr1 != list1.end() && itr2 != list2.end();
00658 ++itr1, ++itr2
00659 )
00660 {
00661 const std::string &entryName1 = list1.name(itr1);
00662 const std::string &entryName2 = list2.name(itr2);
00663 const ParameterEntry &entry1 = list1.entry(itr1);
00664 const ParameterEntry &entry2 = list2.entry(itr2);
00665 if( entryName1 != entryName2 ) {
00666 return false;
00667 }
00668 else if( entry1 != entry2 ) {
00669 return false;
00670 }
00671
00672
00673
00674
00675 }
00676 return true;
00677 }
00678
00679
00680 bool Teuchos::haveSameValues( const ParameterList& list1, const ParameterList& list2 )
00681 {
00682 ParameterList::ConstIterator itr1, itr2;
00683 for(
00684 itr1 = list1.begin(), itr2 = list2.begin();
00685 itr1 != list1.end() && itr2 != list2.end();
00686 ++itr1, ++itr2
00687 )
00688 {
00689 const std::string &entryName1 = list1.name(itr1);
00690 const std::string &entryName2 = list2.name(itr2);
00691 const ParameterEntry &entry1 = list1.entry(itr1);
00692 const ParameterEntry &entry2 = list2.entry(itr2);
00693 if( entryName1 != entryName2 ) {
00694 return false;
00695 }
00696 if( entry1.isList() && entry2.isList() ) {
00697 if (
00698 !haveSameValues(
00699 getValue<ParameterList>(entry1),
00700 getValue<ParameterList>(entry2))
00701 )
00702 {
00703
00704
00705
00706
00707 return false;
00708 }
00709 }
00710 else {
00711 if( entry1.getAny() != entry2.getAny() ) {
00712 return false;
00713 }
00714 }
00715 }
00716 return true;
00717 }