Commit 5b94d700 authored by Kelvin's avatar Kelvin Committed by acpaquette
Browse files

gdal json pvl parsing

parent d8fb22f8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -447,6 +447,9 @@ namespace Isis {
   * @return Boolean
   */
  bool FileName::fileExists() const {
    if (toString().contains((QString)"https://")) { 
      return true; 
    }
    return QFileInfo(expanded()).exists();
  }

+76 −1
Original line number Diff line number Diff line
@@ -11,6 +11,12 @@ find files of those names at the top level of this repository. **/
#include <locale>
#include <fstream>
#include <sstream>
#include <cctype>

#include <filesystem>
#include <random>
#include <gdal_priv.h>
#include <nlohmann/json.hpp>

#include "FileName.h"
#include "IException.h"
@@ -18,6 +24,9 @@ find files of those names at the top level of this repository. **/
#include "PvlTokenizer.h"
#include "PvlFormat.h"

namespace fs = std::filesystem;
using json = nlohmann::json;

using namespace std;
namespace Isis {
  //! Constructs an empty Pvl object.
@@ -32,9 +41,75 @@ namespace Isis {
   * @param file The file containing the pvl formatted information
   */
  Pvl::Pvl(const QString &file) : Isis::PvlObject("Root") {

    function<PvlObject(PvlObject&, json)> read_object = [&](PvlObject &pvlobj, json jdata) -> PvlObject { 
      for(auto &[key, value] : jdata.items()) { 
        string name = key; 
        if(value.contains("_type")) { 
          string type = value.at("_type"); 
          value.erase("_type"); 
          if (value.contains("_container_name")) { 
            name = value["_container_name"];
            value.erase("_container_name");
          }

          if(type == "object") { 
            PvlObject nestedObj(QString::fromStdString(name));
            pvlobj.addObject(read_object(nestedObj, value)); 
          }
          if(type == "group") { 
            // parse keys 
            PvlGroup group(QString::fromStdString(name)); 
            for(auto &[pvlkeyword, pvlvalue] : value.items())  { 
              PvlKeyword keyword;
              keyword.setName(QString::fromStdString(pvlkeyword));
              if (pvlvalue.is_array())
                  keyword.addJsonArrayValue(pvlvalue);
              else 
                keyword.setJsonValue(pvlvalue);
              group.addKeyword(keyword);
            }
            pvlobj.addGroup(group);
          } // end of group
        } // end of _type search

        // not a group or object, must be a keyword
        else if (key != "_type" && key != "_filename") { 
          PvlKeyword keyword;
          keyword.setName(QString::fromStdString(key));
          if (value.is_array()) 
            keyword.setJsonArrayValue(value);
          else 
            keyword.setJsonValue(value);

          pvlobj.addKeyword(keyword);
        }
      }
      return pvlobj;
    };


    init();
    // try to read as a geodataset 
    try{ 
      GDALAllRegister();
      const GDALAccess eAccess = GA_ReadOnly;
      GDALDataset *dataset = GDALDataset::FromHandle(GDALOpen( file.toStdString().c_str(), eAccess ));

      char** metadata = dataset->GetMetadata("json:ISIS3");
      json jsonlabel = json::parse(metadata[0]);
      if (jsonlabel.contains("_name")) { 
        QString name = QString::fromStdString(jsonlabel["name"].get<string>());
        this->setName(name);
      }

      read_object(*this, jsonlabel);

    } catch (exception &e) { 
      cout << "failed : " << e.what() << endl;
      read(file);
    }
  }


  //! Copy constructor
+74 −16
Original line number Diff line number Diff line
@@ -172,10 +172,9 @@ namespace Isis {
   *
   * @see addJsonValue()
   */
  void PvlKeyword::setJsonValue(json jsonobj, QString unit)
  {
  void PvlKeyword::setJsonValue(json jsonobj) {
    clear();
    addJsonValue(jsonobj, unit);
    addJsonValue(jsonobj);
  }

  /**
@@ -301,31 +300,90 @@ namespace Isis {
   *
   * @throws Isis::iException::Unknown - jsonobj cannot be an array of values
   */
  void PvlKeyword::addJsonValue(json jsonobj, QString unit) {
  void PvlKeyword::addJsonValue(json jsonobj) {
    QString value;
    if (jsonobj.is_array()) {
    QString unit = "";
    json jvalue = jsonobj; 
    if (jsonobj.contains("unit")) {
       unit = QString::fromStdString(jsonobj["unit"].get<string>());
       jvalue = jsonobj["value"];
    }

    if (jvalue.is_array()) {
      QString msg = "Unable to convert " + name() + " with nested json array value into PvlKeyword";
      throw IException(IException::Unknown, msg, _FILEINFO_);
    }
    else if (jsonobj.is_number())
    {
      value = QString::number(jsonobj.get<double>(), 'g', 16);
    else if (jvalue.is_number()) {
      value = QString::number(jvalue.get<double>(), 'g', 16);
    }
    else if (jsonobj.is_boolean())
    {
      value = QString(jsonobj.get<bool>() ? "true" : "false");
    else if (jvalue.is_boolean()) {
      value = QString(jvalue.get<bool>() ? "true" : "false");
    }
    else if (jsonobj.is_null())
    {
    else if (jvalue.is_null()) {
      value = QString("Null");
    }
    else
    {
      value = QString::fromStdString(jsonobj);
    else {
      value = QString::fromStdString(jvalue);
    }
    addValue(value, unit);
  }

  /**
   * Adds multiple items from a json array.
   *
   * If no current value exists, this method sets the given json value.
   * Otherwise, it retains any current values and adds the json value
   * given to the array of values for this PvlKeyword object using addValue.
   * Defaults to unit = "" (empty QString).
   *
   * @param jsonobj New jsonobj to be parsed and assigned.
   * @param unit Units of measurement corresponding to the value.
   *
   * @see setJsonValue()
   * @see addValue()
   *
   * @throws Isis::iException::Unknown - jsonobj must be a json array
   */
  void PvlKeyword::addJsonArrayValue(json jsonobj) { 
    if(!jsonobj.is_array()) { 
      QString msg = "Unable to convert to a json array:\n" + QString::fromStdString(jsonobj.dump());
      throw IException(IException::Unknown, msg, _FILEINFO_); 
    } 

    for(auto ar = jsonobj.begin(); ar!=jsonobj.end(); ar++) {
      try {
        addJsonValue(*ar);
      }
      catch (IException &e) {
        QString msg = "While attempting to parse " + name() + " the following occured";
        throw IException(e, IException::Unknown, msg, _FILEINFO_);
      }
    }
  }


  /**
   * sets multiple items from a json array.
   *
   * If no current value exists, this method sets the given json value.
   * Otherwise, it retains any current values and adds the json value
   * given to the array of values for this PvlKeyword object using addValue.
   * Defaults to unit = "" (empty QString).
   *
   * @param jsonobj New jsonobj to be parsed and assigned.
   * @param unit Units of measurement corresponding to the value.
   *
   * @see setJsonValue()
   * @see addValue()
   *
   * @throws Isis::iException::Unknown - jsonobj must be a json array
   */
  void PvlKeyword::setJsonArrayValue(json jsonobj) { 
    clear(); 
    addJsonArrayValue(jsonobj);
  }


  /**
   * Adds a value.
   *
+5 −2
Original line number Diff line number Diff line
@@ -117,7 +117,9 @@ namespace Isis {
      };

      void setValue(QString value, QString unit = "");
      void setJsonValue(nlohmann::json jsonobj, QString unit = "");
      void setJsonValue(nlohmann::json jsonobj);
      void setJsonArrayValue(nlohmann::json jsonobj);


      void setUnits(QString units);
      void setUnits(QString value, QString units);
@@ -125,7 +127,8 @@ namespace Isis {
      PvlKeyword &operator=(QString value);

      void addValue(QString value, QString unit = "");
      void addJsonValue(nlohmann::json jsonobj, QString unit = "");
      void addJsonValue(nlohmann::json jsonobj);
      void addJsonArrayValue(nlohmann::json jsonobj);

      PvlKeyword &operator+=(QString value);