Isis 3 Programmer Reference
PvlContainer.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <algorithm>
8 
9 #include <QList>
10 
11 #include "PvlContainer.h"
12 #include "Pvl.h"
13 #include "FileName.h"
14 #include "IException.h"
15 #include "Message.h"
16 #include "PvlFormat.h"
17 
18 using namespace std;
19 
20 namespace Isis {
21 
26  PvlContainer::PvlContainer(const QString &type) {
27  init();
28  m_name.setName(type);
29  }
30 
31 
37  PvlContainer::PvlContainer(const QString &type, const QString &name) {
38  init();
39  m_name.setName(type);
40  setName(name);
41  }
42 
43 
44  PvlContainer::PvlContainer(const PvlContainer &other) {
45  *this = other;
46  }
47 
48 
49 
51  void PvlContainer::init() {
52  m_filename = "";
53  m_formatTemplate = NULL;
54  }
55 
62  Isis::PvlKeyword &PvlContainer::findKeyword(const QString &name) {
63  PvlKeywordIterator key = findKeyword(name, begin(), end());
64  if(key == end()) {
65  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
66  type() + " = " + this->name() + "]";
67  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
68  throw IException(IException::Unknown, msg, _FILEINFO_);
69  }
70 
71  return *key;
72  }
73 
80  const Isis::PvlKeyword &PvlContainer::findKeyword(const QString &name) const {
81  ConstPvlKeywordIterator key = findKeyword(name, begin(), end());
82  if(key == end()) {
83  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
84  type() + " = " + this->name() + "]";
85  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
86  throw IException(IException::Unknown, msg, _FILEINFO_);
87  }
88 
89  return *key;
90  }
91 
97  void PvlContainer::deleteKeyword(const QString &name) {
98  PvlKeywordIterator key = findKeyword(name, begin(), end());
99  if(key == end()) {
100  QString msg = "PVL Keyword [" + name + "] does not exist in [" +
101  type() + " = " + this->name() + "]";
102  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
103  throw IException(IException::Unknown, msg, _FILEINFO_);
104  }
105 
106  m_keywords.erase(key);
107  }
108 
109 
115  void PvlContainer::deleteKeyword(const int index) {
116  if(index >= (int)m_keywords.size() || index < 0) {
117  QString msg = "The specified index is out of bounds in PVL [" +
118  type() + " = " + name() + "]";
119  if(m_filename.size() > 0) msg += " in file [" + m_filename + "]";
120  throw IException(IException::Unknown, msg, _FILEINFO_);
121  }
122 
123  PvlKeywordIterator key = begin();
124  for(int i = 0; i < index; i++) key++;
125 
126  m_keywords.erase(key);
127  }
128 
129 
136  bool PvlContainer::cleanDuplicateKeywords() {
137  bool keywordDeleted = false;
138 
139  for(int index = 0; index < m_keywords.size(); index ++) {
140  PvlKeyword &current = m_keywords[index];
141 
142  for(PvlKeywordIterator key = begin() + index + 1; key < end(); key ++) {
143  if(current == *key) {
144  key = m_keywords.erase(key);
145  keywordDeleted = true;
146  }
147  }
148  }
149 
150  return keywordDeleted;
151  }
152 
153 
159  bool PvlContainer::hasKeyword(const QString &name) const {
160  ConstPvlKeywordIterator key = findKeyword(name, begin(), end());
161  if(key == end()) return false;
162  return true;
163  }
164 
165 
172  PvlKeyword &PvlContainer::operator[](const int index) {
173  if(index < 0 || index >= (int)m_keywords.size()) {
174  QString msg = Message::ArraySubscriptNotInRange(index);
175  throw IException(IException::Programmer, msg, _FILEINFO_);
176  }
177  return *(m_keywords.begin() + index);
178  };
179 
180 
187  const Isis::PvlKeyword &PvlContainer::operator[](const int index) const {
188  if(index < 0 || index >= (int)m_keywords.size()) {
189  QString msg = Message::ArraySubscriptNotInRange(index);
190  throw IException(IException::Programmer, msg, _FILEINFO_);
191  }
192  return *(m_keywords.begin() + index);
193  }
194 
202  void PvlContainer::addKeyword(const Isis::PvlKeyword &key,
203  const InsertMode mode) {
204  if(mode == Append) {
205  m_keywords.push_back(key);
206  }
207  else if(hasKeyword(key.name())) {
208  Isis::PvlKeyword &outkey = findKeyword(key.name());
209  outkey = key;
210  }
211  else {
212  m_keywords.push_back(key);
213  }
214  }
215 
233  PvlContainer::PvlKeywordIterator PvlContainer::addKeyword(const Isis::PvlKeyword &key,
234  PvlKeywordIterator pos) {
235  return (m_keywords.insert(pos, key));
236  }
237 
244  ostream &operator<<(std::ostream &os, PvlContainer &container) {
245 
246  // Set up a Formatter (This should not be necessary for a container because
247  // Object or Group should have done this already, but just in case.
248  bool removeFormatter = false;
249  if(container.format() == NULL) {
250  container.setFormat(new PvlFormat());
251  removeFormatter = true;
252  }
253 
254  Isis::PvlContainer outTemplate("DEFAULT_TEMPLATE");
255  if(container.hasFormatTemplate()) outTemplate = *(container.formatTemplate());
256 
257  // Look for and process all include files inside the template
258  Isis::PvlContainer newTemp(outTemplate.type());
259 
260  // Include files take precedence over all other objects and groups
261  for(int i = 0; i < outTemplate.keywords(); i++) {
262  if(outTemplate[i].isNamed("Isis:PvlTemplate:File")) {
263  QString filename = outTemplate[i];
264  Isis::FileName file(filename);
265  if(!file.fileExists()) {
266  QString message = "Could not open the template file [" + filename + "]";
267  throw IException(IException::Io, message, _FILEINFO_);
268  }
269  Isis::Pvl include(file.expanded());
270 
271  for(int j = 0; j < include.keywords(); j++) {
272  if(!newTemp.hasKeyword(include[j].name()))
273  newTemp.addKeyword(include[j]);
274  }
275  }
276  // If it is not an include file keyword add it in place
277  else if(!newTemp.hasKeyword(outTemplate[i].name())) {
278  newTemp.addKeyword(outTemplate[i]);
279  }
280  }
281 
282  outTemplate = newTemp;
283 
284  // Figure out the longest keyword
285  int width = 0;
286  for(int i = 0; i < container.keywords(); i++) {
287  if(container[i].name().length() > width) width = container[i].name().length();
288  }
289 
290  // This number keeps track of the number of keywords written
291  int numKeywords = 0;
292 
293  // Write out the container using the output format template
294  for(int i = 0; i < outTemplate.keywords(); i++) {
295  for(int j = 0; j < container.keywords(); j++) {
296  if(outTemplate[i].name() != container[j].name()) continue;
297  container[j].setIndent(container.indent());
298  container[j].setWidth(width);
299  container[j].setFormat(container.format());
300  // Add a blank line before keyword comments
301  if(outTemplate[i].comments() + container[j].comments() > 0) os << container.format()->formatEOL();
302  if(outTemplate[i].comments() > 0) {
303  for(int k = 0; k < outTemplate[i].comments(); k++) {
304  for(int l = 0; l < outTemplate[i].indent() + container[j].indent(); l++) os << " ";
305  os << outTemplate[i].comment(k) << container.format()->formatEOL();
306  }
307  }
308  os << container[j];
309  container[j].setFormat(NULL);
310  container[j].setIndent(0);
311  container[j].setWidth(0);
312  if(++numKeywords < container.keywords()) {
313 // if (j+1 < container.Keywords() && container[j+1].comments() > 0) os << container.format()->formatEOL();
314  os << container.format()->formatEOL();
315  }
316  }
317  }
318 
319  // Output the keywords in the container that were not specified in the template
320  for(int i = 0; i < container.keywords(); i++) {
321  if(outTemplate.hasKeyword(container[i].name())) continue;
322  container[i].setIndent(container.indent());
323  container[i].setWidth(width);
324  container[i].setFormat(container.format());
325  os << container[i];
326  container[i].setFormat(NULL);
327  container[i].setIndent(0);
328  container[i].setWidth(0);
329  if(++numKeywords < container.keywords()) {
330  if(i + 1 < container.keywords() && container[i+1].comments() > 0) os << container.format()->formatEOL();
331  os << container.format()->formatEOL();
332  }
333  }
334 
335  if(removeFormatter) {
336  delete container.format();
337  container.setFormat(NULL);
338  }
339 
340  return os;
341  }
342 
343 
351  PvlContainer::PvlKeywordIterator PvlContainer::findKeyword(const QString &name,
354  PvlKeyword temp(name);
355  return find(beg, end, temp);
356  };
357 
358 
366  PvlContainer::ConstPvlKeywordIterator PvlContainer::findKeyword(const QString &name,
369  PvlKeyword temp(name);
370  return find(beg, end, temp);
371  };
372 
373 
375  const PvlContainer &PvlContainer::operator=(const PvlContainer &other) {
376  m_filename = other.m_filename;
377  m_name = other.m_name;
378  m_keywords = other.m_keywords;
379  m_formatTemplate = other.m_formatTemplate;
380 
381  return *this;
382  }
383 
394  void PvlContainer::validateAllKeywords(PvlContainer & pPvlCont)
395  {
396  // Validate the Keywords in the current Object
397  int iTmplKeySize = keywords();
398  for(int i=0; i<iTmplKeySize; i++) {
399  PvlKeyword & pvlTmplKwrd = (*this)[i];
400  QString sKeyName = pvlTmplKwrd.name();
401  bool bKwrdFound = false;
402 
403  // These are reserved keywords for properties like "Range", "Value", "Type",
404  // "Required" or "Repeated"
405  if(sKeyName.contains("__Required") || sKeyName.contains("__Repeated") ||
406  sKeyName.contains("__Range") || sKeyName.contains("__Value") ||
407  sKeyName.contains("__Type")) {
408  continue;
409  }
410 
411  if(pPvlCont.hasKeyword(sKeyName)) {
412  PvlKeyword & pvlKwrd = pPvlCont.findKeyword(sKeyName);
413  QString sTmplKwrdRange = sKeyName + "__Range";
414  QString sTmplKwrdValue = sKeyName + "__Value";
415  QString sTmplKwrdType = sKeyName + "__Type";
416  QString sType="";
417  PvlKeyword pvlTmplKwrdRange, pvlTmplKwrdValue;
418 
419  // Check if Type is specified (positive or negative for numbers)
420  if(hasKeyword(sTmplKwrdType)) {
421  sType = findKeyword(sTmplKwrdType)[0];
422  }
423  // Check for Range
424  if(hasKeyword(sTmplKwrdRange)) {
425  pvlTmplKwrdRange = findKeyword(sTmplKwrdRange);
426  pvlTmplKwrd.validateKeyword(pvlKwrd, sType, &pvlTmplKwrdRange);
427  }
428  // Check for Value
429  else if(hasKeyword(sTmplKwrdValue)) {
430  pvlTmplKwrdValue = findKeyword(sTmplKwrdValue);
431  pvlTmplKwrd.validateKeyword(pvlKwrd, sType, &pvlTmplKwrdValue);
432  }
433  else {
434  pvlTmplKwrd.validateKeyword(pvlKwrd, sType);
435  }
436  pPvlCont.deleteKeyword(pvlKwrd.name());
437  bKwrdFound = true;
438  }
439  else {
440  bKwrdFound = true;
441  QString sOption = sKeyName + "__Required";
442  if(hasKeyword(sOption)) {
443  PvlKeyword pvlKeyOption = findKeyword(sOption);
444  if(pvlKeyOption[0] == "true") { // Required is true
445  bKwrdFound = false;
446  }
447  }
448  }
449  if (bKwrdFound == false) {
450  QString sErrMsg = "Keyword \"" + sKeyName + "\" Not Found in the Template File\n";
451  throw IException(IException::User, sErrMsg, _FILEINFO_);
452  }
453 
454  // Check for "Repeated" Option
455  validateRepeatOption(pvlTmplKwrd, pPvlCont);
456  }
457  }
458 
470  void PvlContainer::validateRepeatOption(PvlKeyword & pPvlTmplKwrd, PvlContainer & pPvlCont)
471  {
472  QString sTmplKeyName = pPvlTmplKwrd.name();
473 
474  // Check for the Type
475  QString sType = sTmplKeyName + "__Type";
476  QString sValueType ="";
477  if(hasKeyword(sType)) {
478  sValueType = findKeyword(sType)[0];
479  }
480  QString sRepeatOption = sTmplKeyName + "__Repeated";
481  bool bRepeat =false;
482  if(hasKeyword(sRepeatOption)) {
483  PvlKeyword pvlKeyOption = findKeyword(sRepeatOption);
484  if(pvlKeyOption[0] == "true") { // Required is true
485  bRepeat = true;
486  }
487  }
488  if(bRepeat) {
489  int iKeySize = pPvlCont.keywords();
490  for(int j=(iKeySize-1); j>=0; j--) {
491  PvlKeyword & pvlKwrd = pPvlCont[j];
492  QString sKeyName = pvlKwrd.name();
493  if(sTmplKeyName == sKeyName) {
494  pPvlTmplKwrd.validateKeyword(pvlKwrd, sValueType);
495  pPvlCont.deleteKeyword(pvlKwrd.name());
496  }
497  }
498  }
499  }
500 
501 } // end namespace isis
Isis::PvlContainer::m_name
PvlKeyword m_name
This is the name keyword.
Definition: PvlContainer.h:289
Isis::PvlKeyword::name
QString name() const
Returns the keyword name.
Definition: PvlKeyword.h:98
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::PvlContainer::ConstPvlKeywordIterator
QList< PvlKeyword >::const_iterator ConstPvlKeywordIterator
The const keyword iterator.
Definition: PvlContainer.h:160
Isis::PvlContainer::m_filename
QString m_filename
This contains the filename used to initialize the pvl object.
Definition: PvlContainer.h:283
Isis::PvlFormat
Formats a Pvl name value pair to Isis standards.
Definition: PvlFormat.h:108
Isis::PvlKeyword::validateKeyword
void validateKeyword(PvlKeyword &pvlKwrd, QString psValueType="", PvlKeyword *pvlKwrdRange=NULL)
Validate Keyword for type and required values.
Definition: PvlKeyword.cpp:1873
Isis::PvlContainer::addKeyword
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
Definition: PvlContainer.cpp:202
Isis::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::FileName::fileExists
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:449
Isis::PvlContainer::hasKeyword
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Definition: PvlContainer.cpp:159
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::PvlContainer::m_keywords
QList< PvlKeyword > m_keywords
This is the vector of PvlKeywords the container is holding.
Definition: PvlContainer.h:290
Isis::FileName::expanded
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:196
Isis::PvlContainer::InsertMode
InsertMode
Contains both modes: Append or Replace.
Definition: PvlContainer.h:95
Isis::PvlContainer::name
QString name() const
Returns the container name.
Definition: PvlContainer.h:63
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::PvlContainer::deleteKeyword
void deleteKeyword(const QString &name)
Remove a specified keyword.
Definition: PvlContainer.cpp:97
std
Namespace for the standard library.
Isis::PvlContainer::PvlKeywordIterator
QList< PvlKeyword >::iterator PvlKeywordIterator
The keyword iterator.
Definition: PvlContainer.h:157
Isis::PvlContainer::keywords
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Definition: PvlContainer.h:86
Isis::PvlContainer::findKeyword
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Definition: PvlContainer.cpp:62
Isis::PvlContainer
Contains more than one keyword-value pair.
Definition: PvlContainer.h:49
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::PvlContainer::type
QString type() const
Returns the container type.
Definition: PvlContainer.h:79