USGS

Isis 3.0 Object Programmers' Reference

Home

PvlContainer.cpp

Go to the documentation of this file.
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 &current = 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