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
18using namespace std;
19
20namespace Isis {
21
26 PvlContainer::PvlContainer(const QString &type) {
27 init();
29 }
30
31
37 PvlContainer::PvlContainer(const QString &type, const QString &name) {
38 init();
41 }
42
43
45 *this = other;
46 }
47
48
49
52 m_filename = "";
53 m_formatTemplate = NULL;
54 }
55
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 {
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) {
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
124 for(int i = 0; i < index; i++) key++;
125
126 m_keywords.erase(key);
127 }
128
129
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 {
161 if(key == end()) return false;
162 return true;
164
165
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
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
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
354 PvlKeyword temp(name);
355 return find(beg, end, temp);
356 };
357
358
372
373
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
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
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
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Contains more than one keyword-value pair.
PvlContainer(const QString &type)
Constructs a PvlContainer object with a type.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
bool cleanDuplicateKeywords()
Removes keywords from the container that have BOTH the same name and value.
const PvlContainer & operator=(const PvlContainer &other)
This is an assignment operator.
QList< PvlKeyword >::iterator PvlKeywordIterator
The keyword iterator.
void init()
Sets the filename to blank.
QString m_filename
This contains the filename used to initialize the pvl object.
void validateRepeatOption(PvlKeyword &pPvlTmplKwrd, PvlContainer &pPvlCont)
Validate the Repeat Option for a Keyword.
PvlKeywordIterator begin()
Return the beginning iterator.
QList< PvlKeyword >::const_iterator ConstPvlKeywordIterator
The const keyword iterator.
PvlKeyword m_name
This is the name keyword.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
PvlKeywordIterator end()
Return the ending iterator.
void setName(const QString &name)
Set the name of the container.
InsertMode
Contains both modes: Append or Replace.
PvlKeyword & operator[](const QString &name)
When you use the [] operator with a (string) name, it will call the findKeyword() method.
QString name() const
Returns the container name.
QString type() const
Returns the container type.
void validateAllKeywords(PvlContainer &pPvlCont)
Validate All the Keywords in a Container comparing with the Template.
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
void deleteKeyword(const QString &name)
Remove a specified keyword.
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
QList< PvlKeyword > m_keywords
This is the vector of PvlKeywords the container is holding.
Formats a Pvl name value pair to Isis standards.
Definition PvlFormat.h:108
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
void setName(QString name)
Sets the keyword name.
QString name() const
Returns the keyword name.
Definition PvlKeyword.h:103
char * m_name
The keyword's name... This is a c-string for memory efficiency.
Definition PvlKeyword.h:266
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QDebug operator<<(QDebug debug, const Hillshade &hillshade)
Print this class out to a QDebug object.
Namespace for the standard library.