Isis 3 Programmer Reference
XmlToPvlTranslationManager.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "LabelTranslationManager.h"
8 
9 #include <ostream>
10 
11 #include <QDebug>
12 #include <QFile>
13 #include <QString>
14 
15 #include "IException.h"
16 #include "IString.h"
17 #include "Message.h"
18 #include "Pvl.h"
19 #include "PvlContainer.h"
20 #include "PvlGroup.h"
21 #include "PvlKeyword.h"
22 #include "PvlObject.h"
23 #include "XmlToPvlTranslationManager.h"
24 
25 
26 using namespace std;
27 namespace Isis {
28 
39  XmlToPvlTranslationManager::XmlToPvlTranslationManager(const QString &transFile)
41  AddTable(transFile);
42  }
43 
44 
57  AddTable(transStrm);
58  }
59 
60 
71  const QString &transFile)
73  AddTable(transFile);
74  parseFile(inputLabel);
75  }
76 
77 
88  std::istream &transStrm)
90  AddTable(transStrm);
91  parseFile(inputLabel);
92  }
93 
94 
99  }
100 
101 
108  parseFile(inputLabel);
109  }
110 
111 
118  vector< pair<QString, int> > XmlToPvlTranslationManager::validKeywords() const {
119 
120  vector< pair<QString, int> > validKeywords = PvlTranslationTable::validKeywords();
121  validKeywords.push_back(pair<QString, int>("InputKeyAttribute", -1));
122  validKeywords.push_back(pair<QString, int>("InputKeyDependencies", -1));
123  validKeywords.push_back(pair<QString, int>("Debug", 0));
124 
125  return validKeywords;
126  }
127 
128 
163  QString XmlToPvlTranslationManager::Translate(QString translationGroupName,
164  int index) {
165  try {
166  if (index != 0) {
167  QString msg = "Cannot translate value at index [" + toString(index) +
168  "]. Xml files can only store a single value in each element.";
169  throw IException(IException::Unknown, msg, _FILEINFO_);
170  }
171 
172  const Pvl &transTable = TranslationTable();
173  PvlGroup transGroup;
174  try {
175  transGroup = transTable.findGroup(translationGroupName);
176  }
177  catch (IException &e){
178  QString msg = "Unable to retrieve translation group from translation table.";
179  throw IException(e, IException::Unknown, msg, _FILEINFO_);
180  }
181 
182  // get input position values
183  PvlKeyword inputPosition;
184  try {
185  inputPosition = transGroup["InputPosition"];
186  }
187  catch (IException &e){
188  QString msg = "Unable to retrieve [InputPosition] keyword from "
189  "translation group.";
190  throw IException(e, IException::Unknown, msg, _FILEINFO_);
191  }
192  QString inputParentName = inputPosition[inputPosition.size() - 1];
193 
194  // get input key (tag or att)
195  QString inputKey;
196  try {
197  inputKey = transGroup["InputKey"][0];
198  }
199  catch (IException &e){
200  QString msg = "Unable to retrieve [InputKey] keyword from "
201  "translation group.";
202  throw IException(e, IException::Unknown, msg, _FILEINFO_);
203  }
204  QString attributeName;
205  if (transGroup.hasKeyword("InputKeyAttribute")) {
206  attributeName = transGroup["InputKeyAttribute"][0];
207  }
208 
209  // get dependencies
210  PvlKeyword keyDependencies;
211  if (transGroup.hasKeyword("InputKeyDependencies")) {
212  keyDependencies = transGroup["InputKeyDependencies"];
213  }
214 
215  // Check for debug
216  bool isDebug = transGroup.hasKeyword("Debug");
217 
218  // Notify what we are translating and what the translating group is.
219  if (isDebug) {
220  cout << endl << " ==================== " << endl;
221  cout << endl << "Translating output keyword: " << translationGroupName << endl;
222  cout << endl << "Translation group:" << endl;
223  cout << transGroup << endl << endl;
224  }
225 
226  // read input value
227  QDomElement inputParentElement = m_xmlLabel.documentElement();
228  QString indent = "";
229  if (isDebug) {
230  cout << endl << "Finding input element:" << endl << endl;
231  cout << inputParentElement.tagName() << endl;
232  }
233  // traverse the input position path
234  Pvl::ConstPvlKeywordIterator it = transGroup.findKeyword("InputPosition",
235  transGroup.begin(),
236  transGroup.end());
237 
238  QDomElement oldInputParentElement = inputParentElement;
239  QString childName;
240  while(it != transGroup.end()) {
241  const PvlKeyword &inputPosition = *it;
242  inputParentElement = oldInputParentElement;
243 
244  for (int i = 0; i < inputPosition.size(); i++) {
245  childName = inputPosition[i];
246  inputParentElement = inputParentElement.firstChildElement(childName);
247  if(inputParentElement.isNull()) {
248  break;
249  }
250  if (isDebug) {
251  indent += " ";
252  cout << indent << inputParentElement.tagName() << endl;
253  }
254  }
255  if (!inputParentElement.isNull()) {
256  break;
257  }
258  it = transGroup.findKeyword("InputPosition", it + 1, transGroup.end());
259  }
260 
261  if (inputParentElement.isNull()) {
262  if (hasInputDefault(translationGroupName)) {
263  if (isDebug) {
264  cout << endl << "Could not traverse input position, " <<
265  "using default value: " <<
266  InputDefault(translationGroupName) << endl;
267  }
268  return PvlTranslationTable::Translate( translationGroupName );
269  }
270  else {
271  QString msg = "Failed traversing input position. [" +
272  inputPosition.name() + "] element does not have a child element named [" +
273  childName + "].";
274  throw IException(IException::Unknown, msg, _FILEINFO_);
275  }
276  }
277  // now get input value at given input position path
278  QDomElement inputKeyElement = inputParentElement.firstChildElement(inputKey);
279  if (isDebug) {
280  indent += " ";
281  cout << indent << inputKeyElement.tagName() << endl;
282  }
283 
284  // Check dependencies
285  while ( !inputParentElement.isNull() &&
286  !checkDependencies(inputKeyElement, keyDependencies, isDebug) ) {
287  if (isDebug) {
288  cout << endl << "Dependencies failed, checking next candidate." << endl;
289  }
290  // Check if a sibling satisfies the dependencies
291  inputKeyElement = inputKeyElement.nextSiblingElement(inputKey);
292  // If there are no siblings to check, try cousins.
293  while ( inputKeyElement.isNull() ) {
294  inputParentElement = inputParentElement.nextSiblingElement(inputParentName);
295  // If there are no more siblings of the parent we've run out of things to check.
296  if ( inputParentElement.isNull() ) {
297  break;
298  }
299  inputKeyElement = inputParentElement.firstChildElement(inputKey);
300  }
301  }
302  // If the parent element is NULL at this point then we traversed every
303  // potential input element and none of them satisfied the dependencies.
304  if ( inputParentElement.isNull() ) {
305  if ( hasInputDefault(translationGroupName) ) {
306  if (isDebug) {
307  cout << endl << "No input value found, using default value: " <<
308  InputDefault(translationGroupName) << endl;
309  }
310  return PvlTranslationTable::Translate( translationGroupName );
311  }
312  else {
313  QString msg = "Could not find an input or default value that fits the given input "
314  "keyword dependencies.";
315  throw IException(IException::Unknown, msg, _FILEINFO_);
316  }
317  }
318 
319  // translate value to output value
320  QString inputValue = inputKeyElement.text();
321  // for attributes, overwrite inputValue
322  if (attributeName.size() > 0) {
323  if ( inputKeyElement.hasAttribute(attributeName) ) {
324  inputValue = inputKeyElement.attribute(attributeName);
325  }
326  else if (hasInputDefault(translationGroupName) ) {
327  if (isDebug) {
328  cout << endl << "No input value found, using default value: " <<
329  InputDefault(translationGroupName) << endl;
330  }
331  return PvlTranslationTable::Translate( translationGroupName );
332  }
333  else {
334  QString msg = "Input element [" + inputKeyElement.tagName() +
335  "] does not have an attribute named [" +
336  attributeName + "].";
337  throw IException(IException::Unknown, msg, _FILEINFO_);
338  }
339  }
340  if (isDebug) {
341  cout << endl << "Translating input value: " << inputValue << endl;
342  }
343  return PvlTranslationTable::Translate( translationGroupName, inputValue.trimmed() );
344  }
345  catch (IException &e){
346  QString msg = "Failed to translate output value for [" + translationGroupName + "].";
347  throw IException(e, IException::Unknown, msg, _FILEINFO_);
348  }
349  }
350 
351 
373  PvlKeyword dependencies,
374  bool isDebug) const{
375 
376  if (isDebug) {
377  cout << endl << "Testing dependencies:" << endl;
378  }
379  for (int i = 0; i < dependencies.size(); i++) {
380  QStringList specification = parseSpecification(dependencies[i]);
381 
382  if (specification.size() != 3) { // the specification is not a dependancy
383  return true;
384  }
385  if (isDebug) {
386  cout << endl << "Testing dependency number " << toString(i+1) << endl;
387  cout << " Specification: " << dependencies[i] << endl;
388  cout << endl;
389  cout << " Dependency type: " << specification[0] << endl;
390  cout << " Dependency name: " << specification[1] << endl;
391  cout << " Dependency value: " << specification[2] << endl;
392  }
393  if (specification[0] == "att") {
394  if ( element.hasAttributes() ) {
395  QDomNamedNodeMap atts = element.attributes();
396  QString attributeValue = atts.namedItem(specification[1]).nodeValue();
397  if (isDebug) {
398  cout << endl;
399  cout << " Attribute name: " << atts.namedItem(specification[1]).nodeName();
400  cout << " Attribute value: " << attributeValue << endl;
401  }
402  if ( attributeValue != specification[2] ) {
403  // attribute value does not match specification or
404  // element does not have the named attribute
405  return false;
406  }
407  }
408  else {
409  // element does not have any attributes
410  return false;
411  }
412  }
413 
414  else if (specification[0] == "tag") {
415  QDomElement candidateSibling = element.parentNode().firstChildElement(specification[1]);
416  QString siblingValue = candidateSibling.text();
417  if (isDebug) {
418  cout << endl;
419  cout << " Tag name: " << candidateSibling.tagName() << endl;
420  cout << " Tag value: " << siblingValue << endl;
421  }
422  if (siblingValue != specification[2] ) {
423  // sibling tag value does not match specification or
424  // named sibling tag does not exist
425  return false;
426  }
427  }
428 
429  else {
430  QString msg = "Parsing error, dependency type [" + specification[0] +
431  "] is not [att] or [tag].";
432  throw IException(IException::Unknown, msg, _FILEINFO_);
433  }
434  }
435 
436  // No dependencies failed!
437  return true;
438  }
439 
440 
450  Pvl &outputLabel) {
451  parseFile(inputLabel);
452  Auto(outputLabel);
453  }
454 
455 
465  QFile xmlFile(xmlFileName.expanded());
466  if ( !xmlFile.open(QIODevice::ReadOnly) ) {
467  QString msg = "Could not open label file [" + xmlFileName.expanded() +
468  "].";
469  throw IException(IException::Unknown, msg, _FILEINFO_);
470  }
471 
472  QString errmsg;
473  int errline, errcol;
474  if ( !m_xmlLabel.setContent(&xmlFile, false, &errmsg, &errline, &errcol) ) {
475  xmlFile.close();
476  QString msg = "XML read/parse error in file [" + xmlFileName.expanded()
477  + "] at line [" + toString(errline) + "], column [" + toString(errcol)
478  + "], message: " + errmsg;
479  throw IException(IException::Unknown, msg, _FILEINFO_);
480  }
481 
482  xmlFile.close();
483  return;
484  }
485 } // end namespace isis
Isis::LabelTranslationManager::parseSpecification
virtual QStringList parseSpecification(QString specification) const
Parses and validates a dependency specification.
Definition: LabelTranslationManager.cpp:172
Isis::PvlKeyword::name
QString name() const
Returns the keyword name.
Definition: PvlKeyword.h:98
Isis::PvlObject::findGroup
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:129
Isis::PvlTranslationTable::validKeywords
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
Definition: PvlTranslationTable.cpp:179
Isis::XmlToPvlTranslationManager::Auto
virtual void Auto(Pvl &outputLabel)
Automatically translate all the output names tagged as Auto in the translation table If a output name...
Definition: LabelTranslationManager.cpp:70
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::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::IException::Unknown
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:118
Isis::PvlTranslationTable::AddTable
void AddTable(std::istream &transStm)
Adds the contents of a translation table to the searchable groups/keys Also performs a verification,...
Definition: PvlTranslationTable.cpp:102
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::PvlTranslationTable::hasInputDefault
bool hasInputDefault(const QString translationGroupName)
Determines whether the given group has a default input value.
Definition: PvlTranslationTable.cpp:407
Isis::XmlToPvlTranslationManager::SetLabel
void SetLabel(FileName &inputLabel)
Reads an Xml label file and internalizes it for translation.
Definition: XmlToPvlTranslationManager.cpp:107
QStringList
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::XmlToPvlTranslationManager::Translate
virtual QString Translate(QString translationGroupName, int findex=0)
Returns a translated value.
Definition: XmlToPvlTranslationManager.cpp:163
Isis::XmlToPvlTranslationManager::checkDependencies
bool checkDependencies(QDomElement element, PvlKeyword dependencies, bool isDebug) const
Checks if a element in the xml label satisfies a list of dependencies.
Definition: XmlToPvlTranslationManager.cpp:372
Isis::XmlToPvlTranslationManager::XmlToPvlTranslationManager
XmlToPvlTranslationManager(const QString &transFile)
Constructs and initializes an XmlToPvlTranslationManager object from the given Pvl translation file.
Definition: XmlToPvlTranslationManager.cpp:39
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::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::XmlToPvlTranslationManager::~XmlToPvlTranslationManager
virtual ~XmlToPvlTranslationManager()
Destroys the XmlToPvlTranslationManager object.
Definition: XmlToPvlTranslationManager.cpp:98
Isis::XmlToPvlTranslationManager::parseFile
void parseFile(const FileName &xmlFileName)
Opens, parses, and internalizes an Xml label file.
Definition: XmlToPvlTranslationManager.cpp:464
Isis::LabelTranslationManager
Allows applications to translate simple text files.
Definition: LabelTranslationManager.h:43
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::PvlTranslationTable::Translate
QString Translate(const QString translationGroupName, const QString inputKeyValue="") const
Translates a single output value from the given translation group name and input value.
Definition: PvlTranslationTable.cpp:216
Isis::XmlToPvlTranslationManager::validKeywords
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
Definition: XmlToPvlTranslationManager.cpp:118
std
Namespace for the standard library.
Isis::PvlKeyword::size
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:125
Isis::XmlToPvlTranslationManager::m_xmlLabel
QDomDocument m_xmlLabel
The contents of the xml label.
Definition: XmlToPvlTranslationManager.h:145
Isis::PvlTranslationTable::InputDefault
QString InputDefault(const QString translationGroupName) const
Returns the input default value from the translation table corresponding to the output name argument.
Definition: PvlTranslationTable.cpp:382
Isis::PvlContainer::findKeyword
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Definition: PvlContainer.cpp:62
Isis::PvlContainer::end
PvlKeywordIterator end()
Return the ending iterator.
Definition: PvlContainer.h:194
Isis::PvlContainer::begin
PvlKeywordIterator begin()
Return the beginning iterator.
Definition: PvlContainer.h:178
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::PvlTranslationTable::TranslationTable
Pvl & TranslationTable()
Protected accessor for pvl translation table passed into class.
Definition: PvlTranslationTable.cpp:62