USGS

Isis 3.0 Object Programmers' Reference

Home

PvlContainer.cpp
Go to the documentation of this file.
1 
23 #include <algorithm>
24 
25 #include <QList>
26 
27 #include "PvlContainer.h"
28 #include "Pvl.h"
29 #include "FileName.h"
30 #include "IException.h"
31 #include "Message.h"
32 #include "PvlFormat.h"
33 
34 using namespace std;
35 
36 namespace Isis {
37 
42  PvlContainer::PvlContainer(const QString &type) {
43  init();
44  m_name.setName(type);
45  }
46 
47 
53  PvlContainer::PvlContainer(const QString &type, const QString &name) {
54  init();
55  m_name.setName(type);
56  setName(name);
57  }
58 
59 
60  PvlContainer::PvlContainer(const PvlContainer &other) {
61  *this = other;
62  }
63 
64 
65 
67  void PvlContainer::init() {
68  m_filename = "";
69  m_formatTemplate = NULL;
70  }
71 
78  Isis::PvlKeyword &PvlContainer::findKeyword(const QString &name) {
79  PvlKeywordIterator key = findKeyword(name, begin(), end());
80  if(key == end()) {
81  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
82  type() + " = " + this->name() + "]";
83  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
84  throw IException(IException::Unknown, msg, _FILEINFO_);
85  }
86 
87  return *key;
88  }
89 
96  const Isis::PvlKeyword &PvlContainer::findKeyword(const QString &name) const {
97  ConstPvlKeywordIterator key = findKeyword(name, begin(), end());
98  if(key == end()) {
99  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
100  type() + " = " + this->name() + "]";
101  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
102  throw IException(IException::Unknown, msg, _FILEINFO_);
103  }
104 
105  return *key;
106  }
107 
113  void PvlContainer::deleteKeyword(const QString &name) {
114  PvlKeywordIterator key = findKeyword(name, begin(), end());
115  if(key == end()) {
116  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
117  type() + " = " + this->name() + "]";
118  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
119  throw IException(IException::Unknown, msg, _FILEINFO_);
120  }
121 
122  m_keywords.erase(key);
123  }
124 
125 
131  void PvlContainer::deleteKeyword(const int index) {
132  if(index >= (int)m_keywords.size() || index < 0) {
133  QString msg = "The specified index is out of bounds in PVL [" +
134  type() + " = " + name() + "]";
135  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
136  throw IException(IException::Unknown, msg, _FILEINFO_);
137  }
138 
139  PvlKeywordIterator key = begin();
140  for(int i = 0; i < index; i++) key++;
141 
142  m_keywords.erase(key);
143  }
144 
145 
152  bool PvlContainer::cleanDuplicateKeywords() {
153  bool keywordDeleted = false;
154 
155  for(int index = 0; index < m_keywords.size(); index ++) {
156  PvlKeyword &current = m_keywords[index];
157 
158  for(PvlKeywordIterator key = begin() + index + 1; key < end(); key ++) {
159  if(current == *key) {
160  m_keywords.erase(key);
161  keywordDeleted = true;
162  }
163  }
164  }
165 
166  return keywordDeleted;
167  }
168 
169 
175  bool PvlContainer::hasKeyword(const QString &name) const {
176  ConstPvlKeywordIterator key = findKeyword(name, begin(), end());
177  if(key == end()) return false;
178  return true;
179  }
180 
181 
188  PvlKeyword &PvlContainer::operator[](const int index) {
189  if(index < 0 || index >= (int)m_keywords.size()) {
190  QString msg = Message::ArraySubscriptNotInRange(index);
191  throw IException(IException::Programmer, msg, _FILEINFO_);
192  }
193  return *(m_keywords.begin() + index);
194  };
195 
196 
203  const Isis::PvlKeyword &PvlContainer::operator[](const int index) const {
204  if(index < 0 || index >= (int)m_keywords.size()) {
205  QString msg = Message::ArraySubscriptNotInRange(index);
206  throw IException(IException::Programmer, msg, _FILEINFO_);
207  }
208  return *(m_keywords.begin() + index);
209  }
210 
218  void PvlContainer::addKeyword(const Isis::PvlKeyword &key,
219  const InsertMode mode) {
220  if(mode == Append) {
221  m_keywords.push_back(key);
222  }
223  else if(hasKeyword(key.name())) {
224  Isis::PvlKeyword &outkey = findKeyword(key.name());
225  outkey = key;
226  }
227  else {
228  m_keywords.push_back(key);
229  }
230  }
231 
249  PvlContainer::PvlKeywordIterator PvlContainer::addKeyword(const Isis::PvlKeyword &key,
250  PvlKeywordIterator pos) {
251  return (m_keywords.insert(pos, key));
252  }
253 
260  ostream &operator<<(std::ostream &os, PvlContainer &container) {
261 
262  // Set up a Formatter (This should not be necessary for a container because
263  // Object or Group should have done this already, but just in case.
264  bool removeFormatter = false;
265  if(container.format() == NULL) {
266  container.setFormat(new PvlFormat());
267  removeFormatter = true;
268  }
269 
270  Isis::PvlContainer outTemplate("DEFAULT_TEMPLATE");
271  if(container.hasFormatTemplate()) outTemplate = *(container.formatTemplate());
272 
273  // Look for and process all include files inside the template
274  Isis::PvlContainer newTemp(outTemplate.type());
275 
276  // Include files take precedence over all other objects and groups
277  for(int i = 0; i < outTemplate.keywords(); i++) {
278  if(outTemplate[i].isNamed("Isis:PvlTemplate:File")) {
279  QString filename = outTemplate[i];
280  Isis::FileName file(filename);
281  if(!file.fileExists()) {
282  QString message = "Could not open the template file [" + filename + "]";
283  throw IException(IException::Io, message, _FILEINFO_);
284  }
285  Isis::Pvl include(file.expanded());
286 
287  for(int j = 0; j < include.keywords(); j++) {
288  if(!newTemp.hasKeyword(include[j].name()))
289  newTemp.addKeyword(include[j]);
290  }
291  }
292  // If it is not an include file keyword add it in place
293  else if(!newTemp.hasKeyword(outTemplate[i].name())) {
294  newTemp.addKeyword(outTemplate[i]);
295  }
296  }
297 
298  outTemplate = newTemp;
299 
300  // Figure out the longest keyword
301  int width = 0;
302  for(int i = 0; i < container.keywords(); i++) {
303  if(container[i].name().length() > width) width = container[i].name().length();
304  }
305 
306  // This number keeps track of the number of keywords written
307  int numKeywords = 0;
308 
309  // Write out the container using the output format template
310  for(int i = 0; i < outTemplate.keywords(); i++) {
311  for(int j = 0; j < container.keywords(); j++) {
312  if(outTemplate[i].name() != container[j].name()) continue;
313  container[j].setIndent(container.indent());
314  container[j].setWidth(width);
315  container[j].setFormat(container.format());
316  // Add a blank line before keyword comments
317  if(outTemplate[i].comments() + container[j].comments() > 0) os << container.format()->formatEOL();
318  if(outTemplate[i].comments() > 0) {
319  for(int k = 0; k < outTemplate[i].comments(); k++) {
320  for(int l = 0; l < outTemplate[i].indent() + container[j].indent(); l++) os << " ";
321  os << outTemplate[i].comment(k) << container.format()->formatEOL();
322  }
323  }
324  os << container[j];
325  container[j].setFormat(NULL);
326  container[j].setIndent(0);
327  container[j].setWidth(0);
328  if(++numKeywords < container.keywords()) {
329 // if (j+1 < container.Keywords() && container[j+1].comments() > 0) os << container.format()->formatEOL();
330  os << container.format()->formatEOL();
331  }
332  }
333  }
334 
335  // Output the keywords in the container that were not specified in the template
336  for(int i = 0; i < container.keywords(); i++) {
337  if(outTemplate.hasKeyword(container[i].name())) continue;
338  container[i].setIndent(container.indent());
339  container[i].setWidth(width);
340  container[i].setFormat(container.format());
341  os << container[i];
342  container[i].setFormat(NULL);
343  container[i].setIndent(0);
344  container[i].setWidth(0);
345  if(++numKeywords < container.keywords()) {
346  if(i + 1 < container.keywords() && container[i+1].comments() > 0) os << container.format()->formatEOL();
347  os << container.format()->formatEOL();
348  }
349  }
350 
351  if(removeFormatter) {
352  delete container.format();
353  container.setFormat(NULL);
354  }
355 
356  return os;
357  }
358 
359 
367  PvlContainer::PvlKeywordIterator PvlContainer::findKeyword(const QString &name,
370  PvlKeyword temp(name);
371  return find(beg, end, temp);
372  };
373 
374 
382  PvlContainer::ConstPvlKeywordIterator PvlContainer::findKeyword(const QString &name,
385  PvlKeyword temp(name);
386  return find(beg, end, temp);
387  };
388 
389 
391  const PvlContainer &PvlContainer::operator=(const PvlContainer &other) {
392  m_filename = other.m_filename;
393  m_name = other.m_name;
394  m_keywords = other.m_keywords;
395  m_formatTemplate = other.m_formatTemplate;
396 
397  return *this;
398  }
399 
410  void PvlContainer::validateAllKeywords(PvlContainer & pPvlCont)
411  {
412  // Validate the Keywords in the current Object
413  int iTmplKeySize = keywords();
414  for(int i=0; i<iTmplKeySize; i++) {
415  PvlKeyword & pvlTmplKwrd = (*this)[i];
416  QString sKeyName = pvlTmplKwrd.name();
417  bool bKwrdFound = false;
418 
419  // These are reserved keywords for properties like "Range", "Value", "Type",
420  // "Required" or "Repeated"
421  if(sKeyName.contains("__Required") || sKeyName.contains("__Repeated") ||
422  sKeyName.contains("__Range") || sKeyName.contains("__Value") ||
423  sKeyName.contains("__Type")) {
424  continue;
425  }
426 
427  if(pPvlCont.hasKeyword(sKeyName)) {
428  PvlKeyword & pvlKwrd = pPvlCont.findKeyword(sKeyName);
429  QString sTmplKwrdRange = sKeyName + "__Range";
430  QString sTmplKwrdValue = sKeyName + "__Value";
431  QString sTmplKwrdType = sKeyName + "__Type";
432  QString sType="";
433  PvlKeyword pvlTmplKwrdRange, pvlTmplKwrdValue;
434 
435  // Check if Type is specified (positive or negative for numbers)
436  if(hasKeyword(sTmplKwrdType)) {
437  sType = findKeyword(sTmplKwrdType)[0];
438  }
439  // Check for Range
440  if(hasKeyword(sTmplKwrdRange)) {
441  pvlTmplKwrdRange = findKeyword(sTmplKwrdRange);
442  pvlTmplKwrd.validateKeyword(pvlKwrd, sType, &pvlTmplKwrdRange);
443  }
444  // Check for Value
445  else if(hasKeyword(sTmplKwrdValue)) {
446  pvlTmplKwrdValue = findKeyword(sTmplKwrdValue);
447  pvlTmplKwrd.validateKeyword(pvlKwrd, sType, &pvlTmplKwrdValue);
448  }
449  else {
450  pvlTmplKwrd.validateKeyword(pvlKwrd, sType);
451  }
452  pPvlCont.deleteKeyword(pvlKwrd.name());
453  bKwrdFound = true;
454  }
455  else {
456  bKwrdFound = true;
457  QString sOption = sKeyName + "__Required";
458  if(hasKeyword(sOption)) {
459  PvlKeyword pvlKeyOption = findKeyword(sOption);
460  if(pvlKeyOption[0] == "true") { // Required is true
461  bKwrdFound = false;
462  }
463  }
464  }
465  if (bKwrdFound == false) {
466  QString sErrMsg = "Keyword \"" + sKeyName + "\" Not Found in the Template File\n";
467  throw IException(IException::User, sErrMsg, _FILEINFO_);
468  }
469 
470  // Check for "Repeated" Option
471  validateRepeatOption(pvlTmplKwrd, pPvlCont);
472  }
473  }
474 
486  void PvlContainer::validateRepeatOption(PvlKeyword & pPvlTmplKwrd, PvlContainer & pPvlCont)
487  {
488  QString sTmplKeyName = pPvlTmplKwrd.name();
489 
490  // Check for the Type
491  QString sType = sTmplKeyName + "__Type";
492  QString sValueType ="";
493  if(hasKeyword(sType)) {
494  sValueType = findKeyword(sType)[0];
495  }
496  QString sRepeatOption = sTmplKeyName + "__Repeated";
497  bool bRepeat =false;
498  if(hasKeyword(sRepeatOption)) {
499  PvlKeyword pvlKeyOption = findKeyword(sRepeatOption);
500  if(pvlKeyOption[0] == "true") { // Required is true
501  bRepeat = true;
502  }
503  }
504  if(bRepeat) {
505  int iKeySize = pPvlCont.keywords();
506  for(int j=(iKeySize-1); j>=0; j--) {
507  PvlKeyword & pvlKwrd = pPvlCont[j];
508  QString sKeyName = pvlKwrd.name();
509  if(sTmplKeyName == sKeyName) {
510  pPvlTmplKwrd.validateKeyword(pvlKwrd, sValueType);
511  pPvlCont.deleteKeyword(pvlKwrd.name());
512  }
513  }
514  }
515  }
516 
517 } // end namespace isis