Isis 3 Programmer Reference
PvlToXmlTranslationManager.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "LabelTranslationManager.h"
8
9#include <QDebug>
10#include <QDomDocument>
11#include <QDomElement>
12#include <QString>
13
14#include "IException.h"
15#include "IString.h"
16#include "Message.h"
17#include "Pvl.h"
18#include "PvlContainer.h"
19#include "PvlGroup.h"
20#include "PvlKeyword.h"
21#include "PvlObject.h"
22#include "PvlToXmlTranslationManager.h"
23
24using namespace std;
25namespace Isis {
26
39
40
50 const QString &transFile)
51 : LabelTranslationManager(transFile) {
52 m_inputLabel = inputLabel;
53 }
54
55
59
60
67 m_inputLabel = inputLabel;
68 }
69
70
79 vector< pair<QString, int> > PvlToXmlTranslationManager::validKeywords() const {
80
81 vector< pair<QString, int> > validKeywords = PvlTranslationTable::validKeywords();
82 validKeywords.push_back(pair<QString, int>("OutputAttributes", -1));
83 validKeywords.push_back(pair<QString, int>("OutputSiblings", -1));
84
85 return validKeywords;
86 }
87
88
104 QString PvlToXmlTranslationManager::Translate(QString transGroupName,
105 int inputIndex) {
106 const PvlContainer *con;
107 int inst = 0;
108 PvlKeyword grp;
109
110 while((grp = InputGroup(transGroupName, inst++)).name() != "") {
111 if((con = GetContainer(grp)) != NULL) {
112 if(con->hasKeyword(InputKeywordName(transGroupName))) {
114 transGroupName, (*con)[InputKeywordName(transGroupName)][inputIndex]);
115 }
116 }
117 }
118 return PvlTranslationTable::Translate(transGroupName);
119 }
120
121
134 QDomElement &parentElement) {
135
136 int inst = 0;
137 QString transGroupName = transGroup.name();
138 PvlKeyword grp = InputGroup(transGroupName, inst);
139
140 while (grp.name() != "") {
141
142 const PvlContainer *con = GetContainer(grp);
143 if (con != NULL) {
144 if (con->hasKeyword(InputKeywordName(transGroupName))) {
145
146 QStringList outputName = parseSpecification(OutputName(transGroupName));
147 // Get the InputKey from the input label.
148 PvlKeyword inputKeyword = (*con)[InputKeywordName(transGroupName)];
149 // Translate input keyword value and set the qdomelement
150 // NOTE: We are assuming this is a single valued keyword since
151 // xml does not allow multiple values
152 QString untranslatedValue = inputKeyword[0];
153 QString translatedValue = PvlTranslationTable::Translate(transGroupName,
154 untranslatedValue);
155 QString units = inputKeyword.unit();
156 if (outputName.size() == 2 && outputName[0] == "att") {
157 parentElement.setAttribute(outputName[1], translatedValue);
158 if (transGroup.hasKeyword("OutputAttributes")) {
159 addAttributes(transGroup.findKeyword("OutputAttributes"), parentElement);
160 }
161 }
162 else {
163 QDomElement newElement = parentElement.ownerDocument().createElement(outputName[0]);
164 setElementValue(newElement, translatedValue, units);
165 parentElement.appendChild(newElement);
166 if (transGroup.hasKeyword("OutputAttributes")) {
167 addAttributes(transGroup.findKeyword("OutputAttributes"), newElement);
168 }
169 }
170
171 if (transGroup.hasKeyword("OutputSiblings")) {
172 addSiblings(transGroup.findKeyword("OutputSiblings"), parentElement);
173 }
174 return;
175
176 }
177 }
178 grp = InputGroup(transGroupName, ++inst);
179 }
180
181 // Look for default
182 QString translatedValue = PvlTranslationTable::Translate(transGroupName, "");
183 QDomElement newElement = parentElement.ownerDocument().createElement(OutputName(transGroupName));
184 setElementValue(newElement, translatedValue);
185 parentElement.appendChild(newElement);
186 if (transGroup.hasKeyword("OutputAttributes")) {
187 addAttributes(transGroup.findKeyword("OutputAttributes"), newElement);
188 }
189 if (transGroup.hasKeyword("OutputSiblings")) {
190 addSiblings(transGroup.findKeyword("OutputSiblings"), parentElement);
191 }
192
193 }
194
195
208 QDomDocument &outputLabel) {
209 m_inputLabel = inputLabel;
210 Auto(outputLabel);
211 }
212
213
221 void PvlToXmlTranslationManager::Auto(QDomDocument &outputLabel) {
222 Pvl pvl;
223 // Attempt to translate every group in the translation table
224 for(int i = 0; i < TranslationTable().groups(); i++) {
226 if(IsAuto(g.name())) {
227 try {
228 QDomElement element = outputLabel.documentElement();
229 QDomElement *parentElement = createParentElements(g.name(), element);
230 // deal with siblings and attributes
231 doTranslation(g, *parentElement);
232 }
233 catch(IException &e) {
234 if(!IsOptional(g.name())) {
235 throw;//???
236 }
237 }
238 }
239 }
240 }
241
242
254 const PvlKeyword &PvlToXmlTranslationManager::InputKeyword(const QString transGroupName) const {
255
256 int instanceNumber = 0;
257 PvlKeyword inputGroupKeyword = InputGroup(transGroupName, instanceNumber);
258 bool anInputGroupFound = false;
259
260 while(inputGroupKeyword.name() != "") {
261 const PvlContainer *containingGroup = GetContainer(inputGroupKeyword);
262 if(containingGroup != NULL) {
263 anInputGroupFound = true;
264
265 if(containingGroup->hasKeyword(InputKeywordName(transGroupName))) {
266 return containingGroup->findKeyword(InputKeywordName(transGroupName));
267 }
268 }
269
270 instanceNumber ++;
271 inputGroupKeyword = InputGroup(transGroupName, instanceNumber);
272 }
273
274 if(anInputGroupFound) {
275 QString msg = "Unable to find input keyword [" + InputKeywordName(transGroupName) +
276 "] for output name [" + transGroupName + "] in file [" +
277 TranslationTable().fileName() + "]";
278 throw IException(IException::Programmer, msg, _FILEINFO_);
279 }
280 else {
281 QString container = "";
282
283 for(int i = 0; i < InputGroup(transGroupName).size(); i++) {
284 if(i > 0) container += ",";
285
286 container += InputGroup(transGroupName)[i];
287 }
288
289 QString msg = "Unable to find input group [" + container + "] for output name [" +
290 transGroupName + "] in file [" + TranslationTable().fileName() + "]";
291 throw IException(IException::Programmer, msg, _FILEINFO_);
292 }
293 }
294
295
304 bool PvlToXmlTranslationManager::InputHasKeyword(const QString transGroupName) {
305
306 // Set the current position in the input label pvl
307 // by finding the input group corresponding to the output group
308 const PvlContainer *con;
309 int inst = 0;
310
311 PvlKeyword grp;
312 while((grp = InputGroup(transGroupName, inst++)).name() != "") {
313 if((con = GetContainer(grp)) != NULL) {
314 if(con->hasKeyword(InputKeywordName(transGroupName))) return true;
315 }
316 }
317
318 return false;
319 }
320
321
331
332
333 // Return the root container if "ROOT" is the ONLY thing in the list
334 if(inputGroup.size() == 1 &&
335 PvlKeyword::stringEqual(inputGroup[0], "ROOT")) {
336 return &m_inputLabel;
337 }
338
339 const PvlObject *currentObject = &m_inputLabel;
340
341 // Search for object containing our solution
342 int objectIndex;
343 for(objectIndex = 0;
344 objectIndex < inputGroup.size() - 1;
345 objectIndex ++) {
346 if(currentObject->hasObject(inputGroup[objectIndex])) {
347 currentObject = &currentObject->findObject(inputGroup[objectIndex]);
348 }
349 else {
350 return NULL;
351 }
352 }
353
354 // Our solution can be an object or a group
355 if(currentObject->hasObject(inputGroup[objectIndex])) {
356 return &currentObject->findObject(inputGroup[objectIndex]);
357 }
358 else if(currentObject->hasGroup(inputGroup[objectIndex])) {
359 return &currentObject->findGroup(inputGroup[objectIndex]);
360 }
361 else {
362 return NULL;
363 }
364 }
365
366
378 QDomElement *PvlToXmlTranslationManager::createParentElements(const QString translationGroupName,
379 QDomElement &xmlRootElement) {
380
381 // Get the OutputPosition array using the name of the translation group
382 PvlKeyword containers = OutputPosition(translationGroupName);
383
384 QDomElement *currentElement = &xmlRootElement;
385
386 int i = 0;
387 // Check if the root node (e.g. Product_Observational) exits in the OutputPosition values
388 // If so, skip over that OutputPosition value so we don't add it as a child of itself
389 if (containers.size() > 0 && currentElement->tagName() == containers[0]) {
390 i = 1;
391 }
392
393 // Look at all the containers and add any missing ones or ones explicitly requested with new@
394 while (i < containers.size()) {
395
396 // Parse current value in the OuputPosition
397 // (i.e. parse into string tokens using "@" and ":" as delimiters)
398 QStringList specifications = parseSpecification(containers[i]);
399
400 bool addNewElement = false;
401 // After parsing, if the first token is "new", then add a new child element
402 if (specifications.size() == 2 && specifications[0] == "new") {
403 addNewElement = true;
404 }
405
406 // Check if the specification says we need a new element
407 if (addNewElement) {
408
409 QDomElement childElement = xmlRootElement.ownerDocument().createElement(specifications[1]);
410 *currentElement = currentElement->appendChild(childElement).toElement();
411 }
412
413 // If the current element does not have a direct child with the name at containers[i]
414 else if (currentElement->namedItem(containers[i]).isNull()) {
415 QDomElement childElement = xmlRootElement.ownerDocument().createElement(specifications[0]);
416 *currentElement = currentElement->appendChild(childElement).toElement();
417 }
418
419 // Otherwise, if we are not requesting a container with @new, grab the child container
420 else {
421 *currentElement = currentElement->firstChildElement(containers[i]);
422 }
423 i++;
424 }
425 return currentElement;
426 }
427
428
439 QDomElement &parent) {
440
441 for (int i = 0; i < outputSiblings.size(); i++) {
442 QStringList parsedSibling;
443 parsedSibling.reserve(5);
444 parsedSibling = parseSpecification(outputSiblings[i]);
445 if (parsedSibling.size() != 2) {
446 // If the sibling does not have a tag name AND a tag value
447 QString msg = "Malformed OutputSibling [" + outputSiblings[i] + "]. OutputSiblings must" +
448 " be in the form of tag|value";
449 throw IException(IException::Programmer, msg, _FILEINFO_);
450 }
451
452 if (parent.namedItem(parsedSibling[0]).isNull()) {
453 // parsedSibling[0] is the tag name, parsedSibling[1] is the tag value
454 QDomElement childElement = parent.ownerDocument().createElement(parsedSibling[0]);
455 setElementValue(childElement, parsedSibling[1]);
456 parent.appendChild(childElement).toElement();;
457 }
458 }
459 }
460
461
472 QDomElement &element) {
473 QStringList parsedAttribute;
474
475 for (int i = 0; i < outputAttributes.size(); i++) {
476 parsedAttribute = parseSpecification(outputAttributes[i]);
477
478 if (parsedAttribute.size() != 2) {
479 QString msg = "Malformed output attribute [" + outputAttributes[i] +
480 "]. OutputAttributes must be in the form of att@attribute_name|value";
481 throw IException(IException::Programmer,msg ,_FILEINFO_);
482 }
483 element.setAttribute(parsedAttribute[0], parsedAttribute[1]);
484 }
485 }
486
487
499 QString name,
500 QString value,
501 QString units) {
502 QDomElement newElement = parent.ownerDocument().createElement(name);
503 setElementValue(newElement, value, units);
504 // append element to parent node???
505 parent.appendChild(newElement).toElement();;
506 }
507
508
517 QString value,
518 QString units) {
519 QDomText valueText = element.ownerDocument().createTextNode(value);
520 // append value to element???
521 element.appendChild(valueText);
522
523 if (units != "") {
524 element.setAttribute("unit", units);
525 }
526 }
527
528
537 QString value,
538 QString units) {
539 element.firstChild().setNodeValue(value);
540 if (units != "") {
541 element.setAttribute("unit", units);
542 }
543 }
544} // end namespace isis
545
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Allows applications to translate simple text files.
virtual QStringList parseSpecification(QString specification) const
Parses and validates a dependency specification.
Contains more than one keyword-value pair.
QString fileName() const
Returns the filename used to initialise the Pvl object.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
static bool stringEqual(const QString &string1, const QString &string2)
Checks to see if two QStrings are equal.
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
PvlGroup & group(const int index)
Return the group at the specified index.
int groups() const
Returns the number of groups contained.
Definition PvlObject.h:75
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:276
void SetLabel(Pvl &inputLabel)
Internalizes a Pvl formatted label for translation.
PvlToXmlTranslationManager(const QString &transFile)
Constructs and initializes a TranslationManager object from given the Pvl translation file.
void doTranslation(PvlGroup transGroup, QDomElement &parent)
Translate the requested output name to output values using the input name and values or default value...
virtual ~PvlToXmlTranslationManager()
Destroys the TranslationManager object.
QDomElement * createParentElements(const QString translationGroupName, QDomElement &xml)
Read the OutputPosition for the translation group name passed and create any parent elements specifie...
static void resetElementValue(QDomElement &element, QString value, QString units="")
Reset the QDomElement's value, and units, if units != "".
static void setElementValue(QDomElement &element, QString value, QString units="")
Set the QDomElement's value, and units, if units != "".
virtual bool InputHasKeyword(const QString translationGroupName)
Indicates if the input keyword corresponding to the output name exists in the label.
virtual QString Translate(QString translationGroupName, int inputIndex=0)
Returns a translated value.
void addSiblings(PvlKeyword outputSiblings, QDomElement &parent)
Take in outputSiblings PvlKeyword and turn each sibling into its corresponding QDomElement.
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
void addAttributes(PvlKeyword something, QDomElement &parent)
Take in the outputAttributes PvlKeyword and add each attribute to the appropriate element given as an...
virtual const PvlKeyword & InputKeyword(const QString translationGroupName) const
Uses the translation file group name to find the input label's PvlKeyword that corresponds to the Inp...
virtual const PvlContainer * GetContainer(const PvlKeyword &inputGroup) const
Return a container from the input label with the path given by the "InputPosition" keyword of the tra...
void Auto(QDomDocument &outputLabel)
Automatically translate all the output names found in the translation table.
static void addElement(QDomElement &parent, QString name, QString value, QString units="")
Add a QDomElement to the given parent with the indicated value and units.
Pvl m_inputLabel
A Pvl object for the input label file.
bool IsOptional(const QString translationGroupName)
Determines whether the translation group is optional.
PvlKeyword OutputPosition(const QString translationGroupName)
Retrieves the OutputPosition PvlKeyword for the translation group with the given name.
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
QString Translate(const QString translationGroupName, const QString inputKeyValue="") const
Translates a single output value from the given translation group name and input value.
QString OutputName(const QString translationGroupName)
Retrieves a string containing the value of the OutputName keyword for the translation group with the ...
virtual QString InputKeywordName(const QString translationGroupName) const
Returns the input keyword name from the translation table corresponding to the output name argument.
virtual PvlKeyword InputGroup(const QString translationGroupName, const int inst=0) const
Returns the input group name from the translation table corresponding to the output name argument.
bool IsAuto(const QString translationGroupName)
Determines whether the given group should be automatically translated.
Pvl & TranslationTable()
Protected accessor for pvl translation table passed into class.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.