Isis 3 Programmer Reference
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  key = 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
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:100
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
Contains more than one keyword-value pair.
Definition: PvlContainer.h:63
File name manipulation and expansion.
Definition: FileName.h:116
Formats a Pvl name value pair to Isis standards.
Definition: PvlFormat.h:124
QList< PvlKeyword > m_keywords
This is the vector of PvlKeywords the container is holding.
Definition: PvlContainer.h:304
Namespace for the standard library.
QString type() const
Returns the container type.
Definition: PvlContainer.h:93
void validateKeyword(PvlKeyword &pvlKwrd, QString psValueType="", PvlKeyword *pvlKwrdRange=NULL)
Validate Keyword for type and required values.
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
QString m_filename
This contains the filename used to initialize the pvl object.
Definition: PvlContainer.h:297
QString name() const
Returns the container name.
Definition: PvlContainer.h:77
InsertMode
Contains both modes: Append or Replace.
Definition: PvlContainer.h:109
ostream & operator<<(std::ostream &os, PvlContainer &container)
Output the PvlContainer information.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
A single keyword-value pair.
Definition: PvlKeyword.h:98
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
Container for cube-like labels.
Definition: Pvl.h:135
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
QString name() const
Returns the keyword name.
Definition: PvlKeyword.h:114
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
PvlKeyword m_name
This is the name keyword.
Definition: PvlContainer.h:303
QList< PvlKeyword >::const_iterator ConstPvlKeywordIterator
The const keyword iterator.
Definition: PvlContainer.h:174
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
void deleteKeyword(const QString &name)
Remove a specified keyword.
QList< PvlKeyword >::iterator PvlKeywordIterator
The keyword iterator.
Definition: PvlContainer.h:171