|
Isis 3.0 Object Programmers' Reference |
Home |
00001 00023 #include <algorithm> 00024 00025 #include <QList> 00026 00027 #include "PvlContainer.h" 00028 #include "Pvl.h" 00029 #include "FileName.h" 00030 #include "IException.h" 00031 #include "Message.h" 00032 #include "PvlFormat.h" 00033 00034 using namespace std; 00035 00036 namespace Isis { 00037 00042 PvlContainer::PvlContainer(const QString &type) { 00043 Init(); 00044 p_name.SetName(type); 00045 } 00046 00047 00053 PvlContainer::PvlContainer(const QString &type, const QString &name) { 00054 Init(); 00055 p_name.SetName(type); 00056 SetName(name); 00057 } 00058 00059 00060 PvlContainer::PvlContainer(const PvlContainer &other) { 00061 *this = other; 00062 } 00063 00064 00065 00067 void PvlContainer::Init() { 00068 p_filename = ""; 00069 p_formatTemplate = NULL; 00070 } 00071 00078 Isis::PvlKeyword &PvlContainer::FindKeyword(const QString &name) { 00079 PvlKeywordIterator key = FindKeyword(name, Begin(), End()); 00080 if(key == End()) { 00081 QString msg = "PVL Keyword [" + name + "] does not exist in [" + 00082 Type() + " = " + Name() + "]"; 00083 if(p_filename.size() > 0) msg += " in file [" + p_filename + "]"; 00084 throw IException(IException::Unknown, msg, _FILEINFO_); 00085 } 00086 00087 return *key; 00088 } 00089 00096 const Isis::PvlKeyword &PvlContainer::FindKeyword(const QString &name) const { 00097 ConstPvlKeywordIterator key = FindKeyword(name, Begin(), End()); 00098 if(key == End()) { 00099 QString msg = "PVL Keyword [" + name + "] does not exist in [" + 00100 Type() + " = " + Name() + "]"; 00101 if(p_filename.size() > 0) msg += " in file [" + p_filename + "]"; 00102 throw IException(IException::Unknown, msg, _FILEINFO_); 00103 } 00104 00105 return *key; 00106 } 00107 00113 void PvlContainer::DeleteKeyword(const QString &name) { 00114 PvlKeywordIterator key = FindKeyword(name, Begin(), End()); 00115 if(key == End()) { 00116 QString msg = "PVL Keyword [" + name + "] does not exist in [" + 00117 Type() + " = " + Name() + "]"; 00118 if(p_filename.size() > 0) msg += " in file [" + p_filename + "]"; 00119 throw IException(IException::Unknown, msg, _FILEINFO_); 00120 } 00121 00122 p_keywords.erase(key); 00123 } 00124 00125 00131 void PvlContainer::DeleteKeyword(const int index) { 00132 if(index >= (int)p_keywords.size() || index < 0) { 00133 QString msg = "The specified index is out of bounds in PVL [" + 00134 Type() + " = " + Name() + "]"; 00135 if(p_filename.size() > 0) msg += " in file [" + p_filename + "]"; 00136 throw IException(IException::Unknown, msg, _FILEINFO_); 00137 } 00138 00139 PvlKeywordIterator key = Begin(); 00140 for(int i = 0; i < index; i++) key++; 00141 00142 p_keywords.erase(key); 00143 } 00144 00145 00152 bool PvlContainer::CleanDuplicateKeywords() { 00153 bool keywordDeleted = false; 00154 00155 for(int index = 0; index < p_keywords.size(); index ++) { 00156 PvlKeyword ¤t = p_keywords[index]; 00157 00158 for(PvlKeywordIterator key = Begin() + index + 1; key < End(); key ++) { 00159 if(current == *key) { 00160 p_keywords.erase(key); 00161 keywordDeleted = true; 00162 } 00163 } 00164 } 00165 00166 return keywordDeleted; 00167 } 00168 00169 00175 bool PvlContainer::HasKeyword(const QString &name) const { 00176 ConstPvlKeywordIterator key = FindKeyword(name, Begin(), End()); 00177 if(key == End()) return false; 00178 return true; 00179 } 00180 00181 00188 PvlKeyword &PvlContainer::operator[](const int index) { 00189 if(index < 0 || index >= (int)p_keywords.size()) { 00190 QString msg = Message::ArraySubscriptNotInRange(index); 00191 throw IException(IException::Programmer, msg, _FILEINFO_); 00192 } 00193 return *(p_keywords.begin() + index); 00194 }; 00195 00196 00203 const Isis::PvlKeyword &PvlContainer::operator[](const int index) const { 00204 if(index < 0 || index >= (int)p_keywords.size()) { 00205 QString msg = Message::ArraySubscriptNotInRange(index); 00206 throw IException(IException::Programmer, msg, _FILEINFO_); 00207 } 00208 return *(p_keywords.begin() + index); 00209 } 00210 00218 void PvlContainer::AddKeyword(const Isis::PvlKeyword &key, 00219 const InsertMode mode) { 00220 if(mode == Append) { 00221 p_keywords.push_back(key); 00222 } 00223 else if(HasKeyword(key.Name())) { 00224 Isis::PvlKeyword &outkey = FindKeyword(key.Name()); 00225 outkey = key; 00226 } 00227 else { 00228 p_keywords.push_back(key); 00229 } 00230 } 00231 00249 PvlContainer::PvlKeywordIterator PvlContainer::AddKeyword(const Isis::PvlKeyword &key, 00250 PvlKeywordIterator pos) { 00251 return (p_keywords.insert(pos, key)); 00252 } 00253 00260 ostream &operator<<(std::ostream &os, PvlContainer &container) { 00261 00262 // Set up a Formatter (This should not be necessary for a container because 00263 // Object or Group should have done this already, but just in case. 00264 bool removeFormatter = false; 00265 if(container.GetFormat() == NULL) { 00266 container.SetFormat(new PvlFormat()); 00267 removeFormatter = true; 00268 } 00269 00270 Isis::PvlContainer outTemplate("DEFAULT_TEMPLATE"); 00271 if(container.HasFormatTemplate()) outTemplate = *(container.FormatTemplate()); 00272 00273 // Look for and process all include files inside the template 00274 Isis::PvlContainer newTemp(outTemplate.Type()); 00275 00276 // Include files take precedence over all other objects and groups 00277 for(int i = 0; i < outTemplate.Keywords(); i++) { 00278 if(outTemplate[i].IsNamed("Isis:PvlTemplate:File")) { 00279 QString filename = outTemplate[i]; 00280 Isis::FileName file(filename); 00281 if(!file.fileExists()) { 00282 QString message = "Could not open the template file [" + filename + "]"; 00283 throw IException(IException::Io, message, _FILEINFO_); 00284 } 00285 Isis::Pvl include(file.expanded()); 00286 00287 for(int j = 0; j < include.Keywords(); j++) { 00288 if(!newTemp.HasKeyword(include[j].Name())) 00289 newTemp.AddKeyword(include[j]); 00290 } 00291 } 00292 // If it is not an include file keyword add it in place 00293 else if(!newTemp.HasKeyword(outTemplate[i].Name())) { 00294 newTemp.AddKeyword(outTemplate[i]); 00295 } 00296 } 00297 00298 outTemplate = newTemp; 00299 00300 // Figure out the longest keyword 00301 int width = 0; 00302 for(int i = 0; i < container.Keywords(); i++) { 00303 if(container[i].Name().length() > width) width = container[i].Name().length(); 00304 } 00305 00306 // This number keeps track of the number of keywords written 00307 int numKeywords = 0; 00308 00309 // Write out the container using the output format template 00310 for(int i = 0; i < outTemplate.Keywords(); i++) { 00311 for(int j = 0; j < container.Keywords(); j++) { 00312 if(outTemplate[i].Name() != container[j].Name()) continue; 00313 container[j].SetIndent(container.Indent()); 00314 container[j].SetWidth(width); 00315 container[j].SetFormat(container.GetFormat()); 00316 // Add a blank line before keyword comments 00317 if(outTemplate[i].Comments() + container[j].Comments() > 0) os << container.GetFormat()->FormatEOL(); 00318 if(outTemplate[i].Comments() > 0) { 00319 for(int k = 0; k < outTemplate[i].Comments(); k++) { 00320 for(int l = 0; l < outTemplate[i].Indent() + container[j].Indent(); l++) os << " "; 00321 os << outTemplate[i].Comment(k) << container.GetFormat()->FormatEOL(); 00322 } 00323 } 00324 os << container[j]; 00325 container[j].SetFormat(NULL); 00326 container[j].SetIndent(0); 00327 container[j].SetWidth(0); 00328 if(++numKeywords < container.Keywords()) { 00329 // if (j+1 < container.Keywords() && container[j+1].Comments() > 0) os << container.GetFormat()->FormatEOL(); 00330 os << container.GetFormat()->FormatEOL(); 00331 } 00332 } 00333 } 00334 00335 // Output the keywords in the container that were not specified in the template 00336 for(int i = 0; i < container.Keywords(); i++) { 00337 if(outTemplate.HasKeyword(container[i].Name())) continue; 00338 container[i].SetIndent(container.Indent()); 00339 container[i].SetWidth(width); 00340 container[i].SetFormat(container.GetFormat()); 00341 os << container[i]; 00342 container[i].SetFormat(NULL); 00343 container[i].SetIndent(0); 00344 container[i].SetWidth(0); 00345 if(++numKeywords < container.Keywords()) { 00346 if(i + 1 < container.Keywords() && container[i+1].Comments() > 0) os << container.GetFormat()->FormatEOL(); 00347 os << container.GetFormat()->FormatEOL(); 00348 } 00349 } 00350 00351 if(removeFormatter) { 00352 delete container.GetFormat(); 00353 container.SetFormat(NULL); 00354 } 00355 00356 return os; 00357 } 00358 00359 00367 PvlContainer::PvlKeywordIterator PvlContainer::FindKeyword(const QString &name, 00368 PvlContainer::PvlKeywordIterator beg, 00369 PvlContainer::PvlKeywordIterator end) { 00370 PvlKeyword temp(name); 00371 return find(beg, end, temp); 00372 }; 00373 00374 00382 PvlContainer::ConstPvlKeywordIterator PvlContainer::FindKeyword(const QString &name, 00383 PvlContainer::ConstPvlKeywordIterator beg, 00384 PvlContainer::ConstPvlKeywordIterator end) const { 00385 PvlKeyword temp(name); 00386 return find(beg, end, temp); 00387 }; 00388 00389 00391 const PvlContainer &PvlContainer::operator=(const PvlContainer &other) { 00392 p_filename = other.p_filename; 00393 p_name = other.p_name; 00394 p_keywords = other.p_keywords; 00395 p_formatTemplate = other.p_formatTemplate; 00396 00397 return *this; 00398 } 00399 00410 void PvlContainer::ValidateAllKeywords(PvlContainer & pPvlCont) 00411 { 00412 // Validate the Keywords in the current Object 00413 int iTmplKeySize = Keywords(); 00414 for(int i=0; i<iTmplKeySize; i++) { 00415 PvlKeyword & pvlTmplKwrd = (*this)[i]; 00416 QString sKeyName = pvlTmplKwrd.Name(); 00417 bool bKwrdFound = false; 00418 00419 // These are reserved keywords for properties like "Range", "Value", "Type", 00420 // "Required" or "Repeated" 00421 if(sKeyName.contains("__Required") || sKeyName.contains("__Repeated") || 00422 sKeyName.contains("__Range") || sKeyName.contains("__Value") || 00423 sKeyName.contains("__Type")) { 00424 continue; 00425 } 00426 00427 if(pPvlCont.HasKeyword(sKeyName)) { 00428 PvlKeyword & pvlKwrd = pPvlCont.FindKeyword(sKeyName); 00429 QString sTmplKwrdRange = sKeyName + "__Range"; 00430 QString sTmplKwrdValue = sKeyName + "__Value"; 00431 QString sTmplKwrdType = sKeyName + "__Type"; 00432 QString sType=""; 00433 PvlKeyword pvlTmplKwrdRange, pvlTmplKwrdValue; 00434 00435 // Check if Type is specified (positive or negative for numbers) 00436 if(HasKeyword(sTmplKwrdType)) { 00437 sType = FindKeyword(sTmplKwrdType)[0]; 00438 } 00439 // Check for Range 00440 if(HasKeyword(sTmplKwrdRange)) { 00441 pvlTmplKwrdRange = FindKeyword(sTmplKwrdRange); 00442 pvlTmplKwrd.ValidateKeyword(pvlKwrd, sType, &pvlTmplKwrdRange); 00443 } 00444 // Check for Value 00445 else if(HasKeyword(sTmplKwrdValue)) { 00446 pvlTmplKwrdValue = FindKeyword(sTmplKwrdValue); 00447 pvlTmplKwrd.ValidateKeyword(pvlKwrd, sType, &pvlTmplKwrdValue); 00448 } 00449 else { 00450 pvlTmplKwrd.ValidateKeyword(pvlKwrd, sType); 00451 } 00452 pPvlCont.DeleteKeyword(pvlKwrd.Name()); 00453 bKwrdFound = true; 00454 } 00455 else { 00456 bKwrdFound = true; 00457 QString sOption = sKeyName + "__Required"; 00458 if(HasKeyword(sOption)) { 00459 PvlKeyword pvlKeyOption = FindKeyword(sOption); 00460 if(pvlKeyOption[0] == "true") { // Required is true 00461 bKwrdFound = false; 00462 } 00463 } 00464 } 00465 if (bKwrdFound == false) { 00466 QString sErrMsg = "Keyword \"" + sKeyName + "\" Not Found in the Template File\n"; 00467 throw IException(IException::User, sErrMsg, _FILEINFO_); 00468 } 00469 00470 // Check for "Repeated" Option 00471 ValidateRepeatOption(pvlTmplKwrd, pPvlCont); 00472 } 00473 } 00474 00486 void PvlContainer::ValidateRepeatOption(PvlKeyword & pPvlTmplKwrd, PvlContainer & pPvlCont) 00487 { 00488 QString sTmplKeyName = pPvlTmplKwrd.Name(); 00489 00490 // Check for the Type 00491 QString sType = sTmplKeyName + "__Type"; 00492 QString sValueType =""; 00493 if(HasKeyword(sType)) { 00494 sValueType = FindKeyword(sType)[0]; 00495 } 00496 QString sRepeatOption = sTmplKeyName + "__Repeated"; 00497 bool bRepeat =false; 00498 if(HasKeyword(sRepeatOption)) { 00499 PvlKeyword pvlKeyOption = FindKeyword(sRepeatOption); 00500 if(pvlKeyOption[0] == "true") { // Required is true 00501 bRepeat = true; 00502 } 00503 } 00504 if(bRepeat) { 00505 int iKeySize = pPvlCont.Keywords(); 00506 for(int j=(iKeySize-1); j>=0; j--) { 00507 PvlKeyword & pvlKwrd = pPvlCont[j]; 00508 QString sKeyName = pvlKwrd.Name(); 00509 if(sTmplKeyName == sKeyName) { 00510 pPvlTmplKwrd.ValidateKeyword(pvlKwrd, sValueType); 00511 pPvlCont.DeleteKeyword(pvlKwrd.Name()); 00512 } 00513 } 00514 } 00515 } 00516 00517 } // end namespace isis