Isis 3 Programmer Reference
XmlToPvlTranslationManager.cpp
Go to the documentation of this file.
1 
23 
24 #include <ostream>
25 
26 #include <QDebug>
27 #include <QFile>
28 #include <QString>
29 
30 #include "IException.h"
31 #include "IString.h"
32 #include "Message.h"
33 #include "Pvl.h"
34 #include "PvlContainer.h"
35 #include "PvlGroup.h"
36 #include "PvlKeyword.h"
37 #include "PvlObject.h"
39 
40 
41 using namespace std;
42 namespace Isis {
43 
54  XmlToPvlTranslationManager::XmlToPvlTranslationManager(const QString &transFile)
56  AddTable(transFile);
57  }
58 
59 
72  AddTable(transStrm);
73  }
74 
75 
86  const QString &transFile)
88  AddTable(transFile);
89  parseFile(inputLabel);
90  }
91 
92 
103  std::istream &transStrm)
105  AddTable(transStrm);
106  parseFile(inputLabel);
107  }
108 
109 
114  }
115 
116 
123  parseFile(inputLabel);
124  }
125 
126 
133  vector< pair<QString, int> > XmlToPvlTranslationManager::validKeywords() const {
134 
135  vector< pair<QString, int> > validKeywords = PvlTranslationTable::validKeywords();
136  validKeywords.push_back(pair<QString, int>("InputKeyAttribute", -1));
137  validKeywords.push_back(pair<QString, int>("InputKeyDependencies", -1));
138  validKeywords.push_back(pair<QString, int>("Debug", 0));
139 
140  return validKeywords;
141  }
142 
143 
178  QString XmlToPvlTranslationManager::Translate(QString translationGroupName,
179  int index) {
180  try {
181  if (index != 0) {
182  QString msg = "Cannot translate value at index [" + toString(index) +
183  "]. Xml files can only store a single value in each element.";
185  }
186 
187  const Pvl &transTable = TranslationTable();
188  PvlGroup transGroup;
189  try {
190  transGroup = transTable.findGroup(translationGroupName);
191  }
192  catch (IException &e){
193  QString msg = "Unable to retrieve translation group from translation table.";
194  throw IException(e, IException::Unknown, msg, _FILEINFO_);
195  }
196 
197  // get input position values
198  PvlKeyword inputPosition;
199  try {
200  inputPosition = transGroup["InputPosition"];
201  }
202  catch (IException &e){
203  QString msg = "Unable to retrieve [InputPosition] keyword from "
204  "translation group.";
205  throw IException(e, IException::Unknown, msg, _FILEINFO_);
206  }
207  QString inputParentName = inputPosition[inputPosition.size() - 1];
208 
209  // get input key (tag or att)
210  QString inputKey;
211  try {
212  inputKey = transGroup["InputKey"][0];
213  }
214  catch (IException &e){
215  QString msg = "Unable to retrieve [InputKey] keyword from "
216  "translation group.";
217  throw IException(e, IException::Unknown, msg, _FILEINFO_);
218  }
219  QString attributeName;
220  if (transGroup.hasKeyword("InputKeyAttribute")) {
221  attributeName = transGroup["InputKeyAttribute"][0];
222  }
223 
224  // get dependencies
225  PvlKeyword keyDependencies;
226  if (transGroup.hasKeyword("InputKeyDependencies")) {
227  keyDependencies = transGroup["InputKeyDependencies"];
228  }
229 
230  // Check for debug
231  bool isDebug = transGroup.hasKeyword("Debug");
232 
233  // Notify what we are translating and what the translating group is.
234  if (isDebug) {
235  cout << endl << " ==================== " << endl;
236  cout << endl << "Translating output keyword: " << translationGroupName << endl;
237  cout << endl << "Translation group:" << endl;
238  cout << transGroup << endl << endl;
239  }
240 
241  // read input value
242  QDomElement inputParentElement = m_xmlLabel.documentElement();
243  QString indent = "";
244  if (isDebug) {
245  cout << endl << "Finding input element:" << endl << endl;
246  cout << inputParentElement.tagName() << endl;
247  }
248  // traverse the input position path
249  Pvl::ConstPvlKeywordIterator it = transGroup.findKeyword("InputPosition",
250  transGroup.begin(),
251  transGroup.end());
252 
253  QDomElement oldInputParentElement = inputParentElement;
254  QString childName;
255  while(it != transGroup.end()) {
256  const PvlKeyword &inputPosition = *it;
257  inputParentElement = oldInputParentElement;
258 
259  for (int i = 0; i < inputPosition.size(); i++) {
260  childName = inputPosition[i];
261  inputParentElement = inputParentElement.firstChildElement(childName);
262  if(inputParentElement.isNull()) {
263  break;
264  }
265  if (isDebug) {
266  indent += " ";
267  cout << indent << inputParentElement.tagName() << endl;
268  }
269  }
270  if (!inputParentElement.isNull()) {
271  break;
272  }
273  it = transGroup.findKeyword("InputPosition", it + 1, transGroup.end());
274  }
275 
276  if (inputParentElement.isNull()) {
277  if (hasInputDefault(translationGroupName)) {
278  if (isDebug) {
279  cout << endl << "Could not traverse input position, " <<
280  "using default value: " <<
281  InputDefault(translationGroupName) << endl;
282  }
283  return PvlTranslationTable::Translate( translationGroupName );
284  }
285  else {
286  QString msg = "Failed traversing input position. [" +
287  inputPosition.name() + "] element does not have a child element named [" +
288  childName + "].";
290  }
291  }
292  // now get input value at given input position path
293  QDomElement inputKeyElement = inputParentElement.firstChildElement(inputKey);
294  if (isDebug) {
295  indent += " ";
296  cout << indent << inputKeyElement.tagName() << endl;
297  }
298 
299  // Check dependencies
300  while ( !inputParentElement.isNull() &&
301  !checkDependencies(inputKeyElement, keyDependencies, isDebug) ) {
302  if (isDebug) {
303  cout << endl << "Dependencies failed, checking next candidate." << endl;
304  }
305  // Check if a sibling satisfies the dependencies
306  inputKeyElement = inputKeyElement.nextSiblingElement(inputKey);
307  // If there are no siblings to check, try cousins.
308  while ( inputKeyElement.isNull() ) {
309  inputParentElement = inputParentElement.nextSiblingElement(inputParentName);
310  // If there are no more siblings of the parent we've run out of things to check.
311  if ( inputParentElement.isNull() ) {
312  break;
313  }
314  inputKeyElement = inputParentElement.firstChildElement(inputKey);
315  }
316  }
317  // If the parent element is NULL at this point then we traversed every
318  // potential input element and none of them satisfied the dependencies.
319  if ( inputParentElement.isNull() ) {
320  if ( hasInputDefault(translationGroupName) ) {
321  if (isDebug) {
322  cout << endl << "No input value found, using default value: " <<
323  InputDefault(translationGroupName) << endl;
324  }
325  return PvlTranslationTable::Translate( translationGroupName );
326  }
327  else {
328  QString msg = "Could not find an input or default value that fits the given input "
329  "keyword dependencies.";
331  }
332  }
333 
334  // translate value to output value
335  QString inputValue = inputKeyElement.text();
336  // for attributes, overwrite inputValue
337  if (attributeName.size() > 0) {
338  if ( inputKeyElement.hasAttribute(attributeName) ) {
339  inputValue = inputKeyElement.attribute(attributeName);
340  }
341  else if (hasInputDefault(translationGroupName) ) {
342  if (isDebug) {
343  cout << endl << "No input value found, using default value: " <<
344  InputDefault(translationGroupName) << endl;
345  }
346  return PvlTranslationTable::Translate( translationGroupName );
347  }
348  else {
349  QString msg = "Input element [" + inputKeyElement.tagName() +
350  "] does not have an attribute named [" +
351  attributeName + "].";
353  }
354  }
355  if (isDebug) {
356  cout << endl << "Translating input value: " << inputValue << endl;
357  }
358  return PvlTranslationTable::Translate( translationGroupName, inputValue.trimmed() );
359  }
360  catch (IException &e){
361  QString msg = "Failed to translate output value for [" + translationGroupName + "].";
362  throw IException(e, IException::Unknown, msg, _FILEINFO_);
363  }
364  }
365 
366 
388  PvlKeyword dependencies,
389  bool isDebug) const{
390 
391  if (isDebug) {
392  cout << endl << "Testing dependencies:" << endl;
393  }
394  for (int i = 0; i < dependencies.size(); i++) {
395  QStringList specification = parseSpecification(dependencies[i]);
396 
397  if (specification.size() != 3) { // the specification is not a dependancy
398  return true;
399  }
400  if (isDebug) {
401  cout << endl << "Testing dependency number " << toString(i+1) << endl;
402  cout << " Specification: " << dependencies[i] << endl;
403  cout << endl;
404  cout << " Dependency type: " << specification[0] << endl;
405  cout << " Dependency name: " << specification[1] << endl;
406  cout << " Dependency value: " << specification[2] << endl;
407  }
408  if (specification[0] == "att") {
409  if ( element.hasAttributes() ) {
410  QDomNamedNodeMap atts = element.attributes();
411  QString attributeValue = atts.namedItem(specification[1]).nodeValue();
412  if (isDebug) {
413  cout << endl;
414  cout << " Attribute name: " << atts.namedItem(specification[1]).nodeName();
415  cout << " Attribute value: " << attributeValue << endl;
416  }
417  if ( attributeValue != specification[2] ) {
418  // attribute value does not match specification or
419  // element does not have the named attribute
420  return false;
421  }
422  }
423  else {
424  // element does not have any attributes
425  return false;
426  }
427  }
428 
429  else if (specification[0] == "tag") {
430  QDomElement candidateSibling = element.parentNode().firstChildElement(specification[1]);
431  QString siblingValue = candidateSibling.text();
432  if (isDebug) {
433  cout << endl;
434  cout << " Tag name: " << candidateSibling.tagName() << endl;
435  cout << " Tag value: " << siblingValue << endl;
436  }
437  if (siblingValue != specification[2] ) {
438  // sibling tag value does not match specification or
439  // named sibling tag does not exist
440  return false;
441  }
442  }
443 
444  else {
445  QString msg = "Parsing error, dependency type [" + specification[0] +
446  "] is not [att] or [tag].";
448  }
449  }
450 
451  // No dependencies failed!
452  return true;
453  }
454 
455 
465  Pvl &outputLabel) {
466  parseFile(inputLabel);
467  Auto(outputLabel);
468  }
469 
470 
480  QFile xmlFile(xmlFileName.expanded());
481  if ( !xmlFile.open(QIODevice::ReadOnly) ) {
482  QString msg = "Could not open label file [" + xmlFileName.expanded() +
483  "].";
485  }
486 
487  QString errmsg;
488  int errline, errcol;
489  if ( !m_xmlLabel.setContent(&xmlFile, false, &errmsg, &errline, &errcol) ) {
490  xmlFile.close();
491  QString msg = "XML read/parse error in file [" + xmlFileName.expanded()
492  + "] at line [" + toString(errline) + "], column [" + toString(errcol)
493  + "], message: " + errmsg;
495  }
496 
497  xmlFile.close();
498  return;
499  }
500 } // end namespace isis
PvlKeywordIterator end()
Return the ending iterator.
Definition: PvlContainer.h:208
QDomDocument m_xmlLabel
The contents of the xml label.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
bool hasInputDefault(const QString translationGroupName)
Determines whether the given group has a default input value.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
File name manipulation and expansion.
Definition: FileName.h:116
virtual QStringList parseSpecification(QString specification) const
Parses and validates a dependency specification.
void SetLabel(FileName &inputLabel)
Reads an Xml label file and internalizes it for translation.
PvlKeywordIterator begin()
Return the beginning iterator.
Definition: PvlContainer.h:192
Namespace for the standard library.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
virtual QString Translate(QString translationGroupName, int findex=0)
Returns a translated value.
QString Translate(const QString translationGroupName, const QString inputKeyValue="") const
Translates a single output value from the given translation group name and input value.
void AddTable(std::istream &transStm)
Adds the contents of a translation table to the searchable groups/keys Also performs a verification...
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:141
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
Pvl & TranslationTable()
Protected accessor for pvl translation table passed into class.
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
A single keyword-value pair.
Definition: PvlKeyword.h:98
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
XmlToPvlTranslationManager(const QString &transFile)
Constructs and initializes an XmlToPvlTranslationManager object from the given Pvl translation file...
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
virtual std::vector< std::pair< QString, int > > validKeywords() const
Returns a vector of valid keyword names and their sizes.
Container for cube-like labels.
Definition: Pvl.h:135
void parseFile(const FileName &xmlFileName)
Opens, parses, and internalizes an Xml label file.
void Auto(FileName &inputLabel, Pvl &outputLabel)
Automatically translate all the output names flagged with the Auto keyword in the translation table a...
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
bool checkDependencies(QDomElement element, PvlKeyword dependencies, bool isDebug) const
Checks if a element in the xml label satisfies a list of dependencies.
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
virtual ~XmlToPvlTranslationManager()
Destroys the XmlToPvlTranslationManager object.
Allows applications to translate simple text files.
QString InputDefault(const QString translationGroupName) const
Returns the input default value from the translation table corresponding to the output name argument...
QList< PvlKeyword >::const_iterator ConstPvlKeywordIterator
The const keyword iterator.
Definition: PvlContainer.h:174