USGS

Isis 3.0 Object Programmers' Reference

Home

PvlObject.cpp
Go to the documentation of this file.
1 
22 #include "PvlObject.h"
23 
24 #include "FileName.h"
25 #include "Pvl.h"
26 #include "IException.h"
27 #include "IString.h"
28 #include "Message.h"
29 #include "PvlFormat.h"
30 
31 #include <QList>
32 
33 #include <iostream>
34 #include <sstream>
35 
36 using namespace std;
37 namespace Isis {
38 
40  PvlObject::PvlObject() : Isis::PvlContainer("Object") {
41  }
42 
43 
49  PvlObject::PvlObject(const QString &name) :
50  Isis::PvlContainer("Object", name) {
51  }
52 
53 
56  PvlContainer::PvlContainer(other) {
57  m_objects = other.m_objects;
58  m_groups = other.m_groups;
59  }
60 
61 
72  Isis::PvlGroup &PvlObject::findGroup(const QString &name,
74  vector<PvlObject *> searchList;
75  searchList.push_back(this);
76 
77  while(searchList.size() > 0) {
78  PvlGroupIterator it =
79  searchList[0]->findGroup(name,
80  searchList[0]->beginGroup(),
81  searchList[0]->endGroup());
82  if(it != searchList[0]->endGroup()) return *it;
83  if(opts == Traverse) {
84  for(int i = 0; i < searchList[0]->objects(); i++) {
85  searchList.push_back(&searchList[0]->object(i));
86  }
87  }
88  searchList.erase(searchList.begin());
89  }
90 
91  QString msg = "Unable to find PVL group [" + name + "]";
92  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
94  }
95 
96 
107  const Isis::PvlGroup &PvlObject::findGroup(const QString &name,
108  PvlObject::FindOptions opts) const {
109  vector<const PvlObject *> searchList;
110  searchList.push_back(this);
111 
112  while(searchList.size() > 0) {
113  ConstPvlGroupIterator it =
114  searchList[0]->findGroup(name,
115  searchList[0]->beginGroup(),
116  searchList[0]->endGroup());
117  if(it != searchList[0]->endGroup()) return *it;
118  if(opts == Traverse) {
119  for(int i = 0; i < searchList[0]->objects(); i++) {
120  searchList.push_back(&searchList[0]->object(i));
121  }
122  }
123  searchList.erase(searchList.begin());
124  }
125 
126  QString msg = "Unable to find PVL group [" + name + "]";
127  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
129  }
130 
131 
148  PvlKeyword &PvlObject::findKeyword(const QString &kname,
149  FindOptions opts) {
150 
151  // Call the parent's version if they don't want to dig deeper
152  if(opts == None) return findKeyword(kname);
153 
154  // Search this PvlObject, and all PvlObjects and PvlContainers within
155  // it for the first occurrence of the requested keyword.
156  vector<PvlObject *> searchList;
157  searchList.push_back(this);
158 
159  while(searchList.size() > 0) {
160  PvlKeywordIterator it =
161  searchList[0]->findKeyword(kname, searchList[0]->begin(),
162  searchList[0]->end());
163  if(it != searchList[0]->end()) {
164  return *it;
165  }
166 
167  // See if the keyword is inside a Group of this Object
168  for(int g = 0; g < searchList[0]->groups(); g++) {
169  PvlKeywordIterator it =
170  searchList[0]->group(g).findKeyword(kname,
171  searchList[0]->group(g).begin(),
172  searchList[0]->group(g).end());
173  if(it != searchList[0]->group(g).end()) {
174  return *it;
175  }
176  }
177 
178  // It's not in this Object or any groups in this Object, so
179  // add all Objects inside this Object to the search list
180  for(int i = 0; i < searchList[0]->objects(); i++) {
181  searchList.push_back(&searchList[0]->object(i));
182  }
183 
184  // This Object has been searched to remove it from the list
185  searchList.erase(searchList.begin());
186  }
187 
188  // No where else to look for the Keyword so throw an error
189  QString msg = "Unable to find PVL keyword [" + kname + "]";
190  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
192  }
193 
194 
207  bool PvlObject::hasKeyword(const QString &kname,
208  FindOptions opts) const {
209 
210  // Call the parent's version if they don't want to dig deeper
211  if(opts == None) return hasKeyword(kname);
212 
213  // Search this PvlObject, and all PvlObjects and PvlContainers within
214  // it for the first occurrence of the requested keyword.
215  vector<const PvlObject *> searchList;
216  searchList.push_back(this);
217 
218  while(searchList.size() > 0) {
220  searchList[0]->findKeyword(kname, searchList[0]->begin(),
221  searchList[0]->end());
222  if(it != searchList[0]->end()) {
223  return true;
224  }
225 
226  // See if the keyword is inside a Group of this Object
227  for(int g = 0; g < searchList[0]->groups(); g++) {
229  searchList[0]->group(g).findKeyword(kname,
230  searchList[0]->group(g).begin(),
231  searchList[0]->group(g).end());
232 
233  if(it != searchList[0]->group(g).end()) {
234  return true;
235  }
236  }
237 
238  // It's not in this Object or any groups in this Object, so
239  // add all Objects inside this Object to the search list
240  for(int i = 0; i < searchList[0]->objects(); i++) {
241  searchList.push_back(&searchList[0]->object(i));
242  }
243 
244  // This Object has been searched to remove it from the list
245  searchList.erase(searchList.begin());
246  }
247  return false;
248  }
249 
250 
261  PvlObject &PvlObject::findObject(const QString &name,
262  PvlObject::FindOptions opts) {
263  vector<PvlObject *> searchList;
264  searchList.push_back(this);
265 
266  while(searchList.size() > 0) {
267  PvlObjectIterator it =
268  searchList[0]->findObject(name,
269  searchList[0]->beginObject(),
270  searchList[0]->endObject());
271  if(it != searchList[0]->endObject()) return *it;
272  if(opts == Traverse) {
273  for(int i = 0; i < searchList[0]->objects(); i++) {
274  searchList.push_back(&searchList[0]->object(i));
275  }
276  }
277  searchList.erase(searchList.begin());
278  }
279 
280  QString msg = "Unable to find PVL object [" + name + "]";
281  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
283  }
284 
285 
296  const PvlObject &PvlObject::findObject(const QString &name,
297  FindOptions opts) const {
298  vector<const PvlObject *> searchList;
299  searchList.push_back(this);
300 
301  while(searchList.size() > 0) {
302  ConstPvlObjectIterator it =
303  searchList[0]->findObject(name,
304  searchList[0]->beginObject(),
305  searchList[0]->endObject());
306 
307  if(it != searchList[0]->endObject()) {
308  return *it;
309  }
310 
311  if(opts == Traverse) {
312  for(int i = 0; i < searchList[0]->objects(); i++) {
313  searchList.push_back(&searchList[0]->object(i));
314  }
315  }
316 
317  searchList.erase(searchList.begin());
318  }
319 
320  QString msg = "Unable to find PVL object [" + name + "]";
321 
322  if(m_filename.size() > 0) {
323  msg += " in file [" + m_filename + "]";
324  }
325 
327  }
328 
329 
337  void PvlObject::deleteObject(const QString &name) {
339  if(key == endObject()) {
340  QString msg = "Unable to find PVL object [" + name + "] in " + type() +
341  " [" + this->name() + "]";
342  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
344  }
345 
346  m_objects.erase(key);
347  }
348 
349 
357  void PvlObject::deleteObject(const int index) {
358  if(index >= (int)m_objects.size() || index < 0) {
359  QString msg = "The specified index is out of bounds in PVL " + type() +
360  " [" + name() + "]";
361  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
363  }
364 
366  for(int i = 0; i < index; i++) key++;
367 
368  m_objects.erase(key);
369  }
370 
371 
379  void PvlObject::deleteGroup(const QString &name) {
380  PvlGroupIterator key = findGroup(name, beginGroup(), endGroup());
381  if(key == endGroup()) {
382  QString msg = "Unable to find PVL group [" + name + "] in " + type() +
383  " [" + this->name() + "]";
384  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
386  }
387 
388  m_groups.erase(key);
389  }
390 
391 
399  void PvlObject::deleteGroup(const int index) {
400  if(index >= (int)m_groups.size() || index < 0) {
401  QString msg = "The specified index is out of bounds in PVL " + type() +
402  " [" + name() + "]";
403  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
405  }
406 
408  for(int i = 0; i < index; i++) key++;
409 
410  m_groups.erase(key);
411  }
412 
413 
423  Isis::PvlGroup &PvlObject::group(const int index) {
424  if(index < 0 || index >= (int)m_groups.size()) {
425  QString msg = Message::ArraySubscriptNotInRange(index);
427  }
428 
429  return m_groups[index];
430  }
431 
432 
442  const Isis::PvlGroup &PvlObject::group(const int index) const {
443  if(index < 0 || index >= (int)m_groups.size()) {
444  QString msg = Message::ArraySubscriptNotInRange(index);
446  }
447 
448  return m_groups[index];
449  }
450 
460  PvlObject &PvlObject::object(const int index) {
461  if(index < 0 || index >= (int)m_objects.size()) {
462  QString msg = Message::ArraySubscriptNotInRange(index);
464  }
465 
466  return m_objects[index];
467  }
468 
478  const PvlObject &PvlObject::object(const int index) const {
479  if(index < 0 || index >= (int)m_objects.size()) {
480  QString msg = Message::ArraySubscriptNotInRange(index);
482  }
483 
484  return m_objects[index];
485  }
486 
487 
494  ostream &operator<<(std::ostream &os, PvlObject &object) {
495 
496  // Set up a Formatter
497  bool removeFormatter = false;
498  if(object.format() == NULL) {
499  object.setFormat(new PvlFormat());
500  removeFormatter = true;
501  }
502 
503  Isis::PvlObject outTemplate("DEFAULT");
504  if(object.hasFormatTemplate())
505  outTemplate = *(Isis::PvlObject *)object.formatTemplate();
506 
507  // Look for and process all include files and remove duplicates
508  Isis::PvlObject newTemp(outTemplate.name());
509 
510  // Make sure the new template has all the original's comments
511  for(int i = 0; i < outTemplate.comments(); i++) {
512  newTemp.addComment(outTemplate.comment(i));
513  }
514 
515  // Include files take precedence to all other objects and groups
516  for(int i = 0; i < outTemplate.keywords(); i++) {
517  if(outTemplate[i].isNamed("Isis:PvlTemplate:File")) {
518  QString filename = outTemplate[i];
519  Isis::FileName file(filename);
520  if(!file.fileExists()) {
521  QString message = "Could not open the following PVL template file: ";
522  message += filename;
523  throw IException(IException::Io, message, _FILEINFO_);
524  }
525 
526  Isis::Pvl include(file.expanded());
527 
528  for(int j = 0; j < include.keywords(); j++) {
529  if(!newTemp.hasKeyword(include[j].name()))
530  newTemp.addKeyword(include[j]);
531  }
532 
533  for(int j = 0; j < include.objects(); j++) {
534  if(!newTemp.hasObject(include.object(j).name()))
535  newTemp.addObject(include.object(j));
536  }
537 
538  for(int j = 0; j < include.groups(); j++) {
539  if(!newTemp.hasGroup(include.group(j).name()))
540  newTemp.addGroup(include.group(j));
541  }
542  }
543  // If it is not an include file keyword add it in place
544  else if(!newTemp.hasKeyword(outTemplate[i].name()))
545  newTemp.addKeyword(outTemplate[i]);
546  }
547 
548  // Copy over the objects
549  for(int i = 0; i < outTemplate.objects(); i++) {
550  if(!newTemp.hasObject(outTemplate.object(i).name()))
551  newTemp.addObject(outTemplate.object(i));
552  }
553 
554  // Copy over the groups
555  for(int i = 0; i < outTemplate.groups(); i++) {
556  if(!newTemp.hasGroup(outTemplate.group(i).name()))
557  newTemp.addGroup(outTemplate.group(i));
558  }
559 
560  outTemplate = newTemp;
561 
562  // Write out comments for this Object that were in the template
563  if(outTemplate.comments() > 0) {
564  for(int k = 0; k < outTemplate.comments(); k++) {
565  for(int l = 0; l < object.indent(); l++) os << " ";
566  os << outTemplate.comment(k) << object.format()->formatEOL();
567  }
568  //os << object.format()->FormatEOL();
569  }
570 
571  // Output the object comments and name
572  os << object.nameKeyword() << object.format()->formatEOL();
573  object.setIndent(object.indent() + 2);
574 
575  // Output the keywords in this Object
576  if(object.keywords() > 0) {
577  os << (Isis::PvlContainer &) object << object.format()->formatEOL();
578  }
579 
580  // This number keeps track of the number of objects have been written
581  int numObjects = 0;
582 
583  // Output the Objects within this Object using the format template
584  for(int i = 0; i < outTemplate.objects(); i++) {
585  for(int j = 0; j < object.objects(); j++) {
586  if(outTemplate.object(i).name() != object.object(j).name()) continue;
587  if(j == 0 && object.keywords() > 0)
588  os << object.format()->formatEOL();
589 
590  object.object(j).setIndent(object.indent());
591  object.object(j).setFormatTemplate(outTemplate.object(i));
592  object.object(j).setFormat(object.format());
593  os << object.object(j) << object.format()->formatEOL();
594  object.object(j).setFormat(NULL);
595  object.object(j).setIndent(0);
596 
597  if(++numObjects < object.objects())
598  os << object.format()->formatEOL();
599  }
600  }
601 
602  // Output the Objects within this Object that were not included in the
603  // format template pvl
604  for(int i = 0; i < object.objects(); i++) {
605  if(outTemplate.hasObject(object.object(i).name())) continue;
606  if(i == 0 && object.keywords() > 0)
607  os << object.format()->formatEOL();
608 
609  object.object(i).setIndent(object.indent());
610  object.object(i).setFormat(object.format());
611  os << object.object(i) << object.format()->formatEOL();
612  object.object(i).setFormat(NULL);
613  object.object(i).setIndent(0);
614 
615  if(++numObjects < object.objects())
616  os << object.format()->formatEOL();
617 
618  }
619 
620  // This number keeps track of the number of groups that have been written
621  int numgroups = 0;
622 
623  // Output the groups within this Object using the format template
624  for(int i = 0; i < outTemplate.groups(); i++) {
625  for(int j = 0; j < object.groups(); j++) {
626  if(outTemplate.group(i).name() != object.group(j).name()) continue;
627  if((numgroups == 0) &&
628  (object.objects() > 0 || object.keywords() > 0))
629  os << object.format()->formatEOL();
630 
631  object.group(j).setIndent(object.indent());
632  object.group(j).setFormatTemplate(outTemplate.group(i));
633  object.group(j).setFormat(object.format());
634  os << object.group(j) << object.format()->formatEOL();
635  object.group(j).setFormat(NULL);
636  object.group(j).setIndent(0);
637  if(++numgroups < object.groups()) os << object.format()->formatEOL();
638  }
639  }
640 
641  // Output the groups that were not in the format template
642  for(int i = 0; i < object.groups(); i++) {
643  if(outTemplate.hasGroup(object.group(i).name())) continue;
644  if((numgroups == 0) &&
645  (object.objects() > 0 || object.keywords() > 0))
646  os << object.format()->formatEOL();
647 
648  object.group(i).setIndent(object.indent());
649  object.group(i).setFormat(object.format());
650  os << object.group(i) << object.format()->formatEOL();
651  object.group(i).setFormat(NULL);
652  object.group(i).setIndent(0);
653 
654  if(++numgroups < object.groups())
655  os << object.format()->formatEOL();
656  }
657 
658  // Output the end of the object
659  object.setIndent(object.indent() - 2);
660  for(int i = 0; i < object.indent(); i++) os << " ";
661  os << object.format()->formatEnd("End_Object", object.nameKeyword());
662 
663  if(removeFormatter) {
664  delete object.format();
665  object.setFormat(NULL);
666  }
667 
668  return os;
669  }
670 
671 
676  std::istream &operator>>(std::istream &is, PvlObject &result) {
677  PvlKeyword termination("EndObject");
678 
679  PvlKeyword errorKeywords[] = {
680  PvlKeyword("EndGroup")
681  };
682 
683  PvlKeyword readKeyword;
684 
685  istream::pos_type beforeKeywordPos = is.tellg();
686  is >> readKeyword;
687 
688  if(readKeyword != PvlKeyword("Object")) {
689  if(is.eof() && !is.bad()) {
690  is.clear();
691  }
692 
693  is.seekg(beforeKeywordPos, ios::beg);
694 
695  QString msg = "Expected PVL keyword named [Object], found keyword named [";
696  msg += readKeyword.name();
697  msg += "]";
699  }
700 
701  if(readKeyword.size() == 1) {
702  result.setName(readKeyword[0]);
703  }
704  else {
705  is.seekg(beforeKeywordPos, ios::beg);
706 
707  QString msg = "Expected a single value for PVL object name, found [(";
708 
709  for(int i = 0; i < readKeyword.size(); i++) {
710  if(i != 0) msg += ", ";
711 
712  msg += readKeyword[i];
713  }
714 
715  msg += ")]";
717  }
718 
719  for(int comment = 0; comment < readKeyword.comments(); comment++) {
720  result.addComment(readKeyword.comment(comment));
721  }
722 
723  readKeyword = PvlKeyword();
724  beforeKeywordPos = is.tellg();
725 
726  is >> readKeyword;
727  while(readKeyword != termination) {
728  for(unsigned int errorKey = 0;
729  errorKey < sizeof(errorKeywords) / sizeof(PvlKeyword);
730  errorKey++) {
731  if(readKeyword == errorKeywords[errorKey]) {
732  if(is.eof() && !is.bad()) {
733  is.clear();
734  }
735 
736  is.seekg(beforeKeywordPos, ios::beg);
737 
738  QString msg = "Unexpected [";
739  msg += readKeyword.name();
740  msg += "] in PVL Object [";
741  msg += result.name();
742  msg += "]";
744  }
745  }
746 
747  if(readKeyword == PvlKeyword("Group")) {
748  is.seekg(beforeKeywordPos);
749  PvlGroup newGroup;
750  is >> newGroup;
751  result.addGroup(newGroup);
752  }
753  else if(readKeyword == PvlKeyword("Object")) {
754  is.seekg(beforeKeywordPos);
755  PvlObject newObject;
756  is >> newObject;
757  result.addObject(newObject);
758  }
759  else {
760  result.addKeyword(readKeyword);
761  }
762 
763  readKeyword = PvlKeyword();
764  beforeKeywordPos = is.tellg();
765 
766  if(is.good()) {
767  is >> readKeyword;
768  }
769  else {
770  // eof found
771  break;
772  }
773  }
774 
775  if(readKeyword != termination) {
776  if(is.eof() && !is.bad()) {
777  is.clear();
778  }
779 
780  is.seekg(beforeKeywordPos, ios::beg);
781 
782  QString msg = "PVL Object [" + result.name();
783  msg += "] EndObject not found before end of file";
785  }
786 
787  return is;
788  }
789 
790 
792  const PvlObject &PvlObject::operator=(const PvlObject &other) {
793  this->PvlContainer::operator=(other);
794 
795  m_objects = other.m_objects;
796  m_groups = other.m_groups;
797 
798  return *this;
799  }
800 
813  {
814  // Validate the current object
815  int iObjSize = objects();
816 
817  for(int i=0; i<iObjSize; i++) {
818  PvlObject & pvlTmplObj = object(i);
819 
820  QString sObjName = pvlTmplObj.name();
821  bool bObjFound = false;
822 
823  // Pvl contains the Object Name
824  if(pPvlObj.hasObject(sObjName)) {
825  PvlObject & pvlObj = pPvlObj.findObject(sObjName);
826  pvlTmplObj.validateObject(pvlObj);
827  if(pvlObj.objects()==0 && pvlObj.groups()==0 && pvlObj.keywords()==0) {
828  pPvlObj.deleteObject(pvlObj.name());
829  }
830  bObjFound = true;
831  }
832  else {
833  QString sOption = sObjName + "__Required";
834  bObjFound = true; // optional is the default
835  if(pvlTmplObj.hasKeyword(sOption)) {
836  PvlKeyword pvlKeyOption = pvlTmplObj.findKeyword(sOption);
837  if(pvlKeyOption[0] == "true") { // Required is true
838  bObjFound = false;
839  }
840  }
841  }
842  if (bObjFound == false) {
843  QString sErrMsg = "Object \"" + sObjName + "\" Not Found in the Template File\n";
844  throw IException(IException::User, sErrMsg, _FILEINFO_);
845  }
846  }
847 
848  // Validate the groups in the current object
849  int iTmplGrpSize = groups();
850  for(int i=0; i<iTmplGrpSize; i++) {
851  PvlGroup & pvlTmplGrp = group(i);
852  bool bGrpFound = false;
853  QString sGrpName = pvlTmplGrp.name();
854 
855  // Pvl contains the Object Name
856  if(pPvlObj.hasGroup(sGrpName)) {
857  PvlGroup & pvlGrp = pPvlObj.findGroup(sGrpName);
858  pvlTmplGrp.validateGroup(pvlGrp);
859  if(pvlGrp.keywords()==0) {
860  pPvlObj.deleteGroup(pvlGrp.name());
861  }
862  bGrpFound = true;
863  }
864  else {
865  bGrpFound = true;
866  QString sOption = sGrpName + "__Required";
867  if(pvlTmplGrp.hasKeyword(sOption)) {
868  PvlKeyword pvlKeyOption = pvlTmplGrp.findKeyword(sOption);
869  if(pvlKeyOption[0] == "true") { // Required is true
870  bGrpFound = false;
871  }
872  }
873  }
874  if (bGrpFound == false) {
875  QString sErrMsg = "Group \"" + sGrpName + "\" Not Found in the Template File\n";
876  throw IException(IException::User, sErrMsg, _FILEINFO_);
877  }
878  }
879 
880  // Validate the Keywords in the current Object
881  validateAllKeywords((PvlContainer &)pPvlObj);
882  }
883 
884 } // end namespace isis