]> SALOME platform Git repositories - modules/paravis.git/commitdiff
Salome HOME
Re-implementation reader, using Json parser from VTK library.
authorrnv <rnv@opencascade.com>
Wed, 13 Jan 2016 10:34:10 +0000 (13:34 +0300)
committerrnv <rnv@opencascade.com>
Wed, 13 Jan 2016 10:34:10 +0000 (13:34 +0300)
src/Plugins/JSONReader/CMakeLists.txt
src/Plugins/JSONReader/ParaViewPlugin/CMakeLists.txt
src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.cxx
src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.h

index 163fef3102a5fe1a8a0610c65a87ba624a3954dc..1f5aeb09643e47fce0fe6b9ede95e721dc901ed3 100644 (file)
@@ -31,9 +31,10 @@ INCLUDE(${PARAVIEW_USE_FILE})
 OPTION(BUILD_SHARED_LIBS "Build with shared libraries" ${VTK_BUILD_SHARED_LIBS})
 
 # Add subdirectories
-ADD_SUBDIRECTORY(JSONParser)
+# ADD_SUBDIRECTORY(JSONParser)
+#IF(SALOME_BUILD_TESTS)
+#  ENABLE_TESTING()
+#  ADD_SUBDIRECTORY(Test)
+#ENDIF()
+
 ADD_SUBDIRECTORY(ParaViewPlugin)
-IF(SALOME_BUILD_TESTS)
-  ENABLE_TESTING()
-  ADD_SUBDIRECTORY(Test)
-ENDIF()
\ No newline at end of file
index 6fd4e2c4e56ec978239b9a521ddc534c5010ddd9..eac829fae9f09ba0d42a3996e1e12a750f8b7338 100644 (file)
@@ -25,8 +25,6 @@ ADD_PARAVIEW_PLUGIN(JSONReader "1.0"
   SERVER_MANAGER_SOURCES vtkJSONReader.cxx
   REQUIRED_ON_SERVER)
 
-TARGET_LINK_LIBRARIES(JSONReader vtkJSONParser)
-
 INSTALL(TARGETS JSONReader
   DESTINATION lib/paraview
 )
index adec0627896d1bfe1b3a6c2924024cfc6ca596aa..855d7a97894469a11cf5b5abf74307c5ca958ed9 100644 (file)
 // Author: Roman NIKOLAEV
 
 #include "vtkJSONReader.h"
-#include "vtkJSONParser.h"
 
 #include <vtkObjectFactory.h>
 #include <vtkTable.h>
 #include <vtkInformationVector.h>
 #include <vtkInformation.h>
 #include <vtkStreamingDemandDrivenPipeline.h>
+#include <vtkDoubleArray.h>
 #include <vtkVariantArray.h>
 #include <vtkStringArray.h>
 #include <vtkStringToNumeric.h>
+#include <vtkSetGet.h>
+#include <vtksys/RegularExpression.hxx>
 
 #include <stdexcept>
 #include <sstream>
 
+// Key words
+#define MD  "_metadata"
+#define CMT "_comment"
+#define TBN "table_name"
+#define TBD "table_description"
+#define SHT "short_names"
+#define LNG "long_names"
+#define UNT "units"
+#define DT "date"
+
+#define NA "n/a"
+
+// Exception
+//---------------------------------------------------
+vtkJSONException::vtkJSONException(const char *reason) : Reason(reason) {
+
+}
+
+//---------------------------------------------------
+vtkJSONException::~vtkJSONException() throw () {
+}
+
+//---------------------------------------------------
+const char* vtkJSONException::what() const throw() {
+  return Reason.c_str();
+}
+
+
+//---------------------------------------------------
+class Container {
+public:
+  typedef std::vector<std::pair<std::string,std::vector<double>>> DataType;
+  Container(){}
+  void initKeys(std::vector<std::string> &keys, std::string &err) {
+    for(int i = 0; i < keys.size(); i++) {
+      if( !checkVar(keys[i].c_str()) ) {
+       std::ostringstream oss;
+       oss<<"Bad key value '"<<keys[i].c_str()<<"'";
+       err = oss.str();
+       return;
+      }
+      _data.push_back(std::make_pair(keys[i],std::vector<double>()));
+    }
+  }
+
+  void addValue(std::string key, double value, std::string& err) {
+    if( !checkVar(key.c_str()) ) {
+      std::ostringstream oss;
+      oss<<"Bad key value '"<<key.c_str()<<"'";
+      err = oss.str();
+      return;
+    }
+    bool found = false;
+    for(int i = 0; i < _data.size(); i++) {
+      if(_data[i].first == key) {
+       _data[i].second.push_back(value);
+       found = true;
+       break;
+      }
+    }
+    if(!found) {
+      std::ostringstream oss;
+      oss<<"Bad key value '"<<key<"'";
+      err = oss.str();
+    }
+  }
+  
+  DataType& getData() {
+    return _data;
+  }
+private:
+  bool checkVar(const char* var) {
+    vtksys::RegularExpression regEx("^[a-zA-Z_][a-zA-Z0-9_]*$");
+    return regEx.find(var);
+  }
+private:
+  DataType _data;
+};
+
 vtkStandardNewMacro(vtkJSONReader);
 
 //---------------------------------------------------
-vtkJSONReader::vtkJSONReader()
-{
+vtkJSONReader::vtkJSONReader() {
   this->SetNumberOfInputPorts(0);
   this->SetNumberOfOutputPorts(1);
   this->FileName = NULL;
-  this->Parser = vtkJSONParser::New();
 }
 
 //---------------------------------------------------
 vtkJSONReader::~vtkJSONReader()
 {
   this->SetFileName(NULL);
-  this->Parser->Delete();
-}
-
-//---------------------------------------------------
-int vtkJSONReader::CanReadFile(const char* fname)
-{
-  return 1;
 }
 
 //---------------------------------------------------
@@ -63,34 +135,260 @@ void vtkJSONReader::PrintSelf(ostream& os, vtkIndent indent)
   this->Superclass::PrintSelf(os, indent);
   os << indent << "FileName: " 
       << (this->FileName ? this->FileName : "(none)") << endl;
-  os << indent << "Parser: "<<this->Parser << endl;
 }
 
 //---------------------------------------------------
 int vtkJSONReader::RequestData(vtkInformation*, 
-    vtkInformationVector**,
-    vtkInformationVector* outputVector)
-{
+                              vtkInformationVector**,
+                              vtkInformationVector* outputVector) {
   vtkTable* const output_table = vtkTable::GetData(outputVector);
-
+  
   vtkInformation* const outInfo = outputVector->GetInformationObject(0);
   if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) &&
-  outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0)
-  {
-   return 1;
-  }
-
- // If the filename is not defined
- if (!this->FileName && !this->Parser)
-   {
-     return 1;
-   }
-
- this->Parser->SetFileName(this->FileName);
- try{
-   return this->Parser->Parse(output_table);
- } catch(vtkJSONException e) {
-   std::cout<<e.what()<<std::endl;
-   return 1;
- }
+     outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) {
+    return 0;
+  }
+  
+  Json::Value root;
+  int parseResult = 0;
+  parseResult = this->CanParseFile(this->FileName, root);
+  if(!parseResult)
+    return 0;
+
+  try {
+    return this->Parse(root, output_table);
+    return 1;
+  } 
+  catch(vtkJSONException e)  {
+    std::ostringstream oss;
+    oss<<e.what();
+    if(this->HasObserver("ErrorEvent") )
+      {
+       this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
+      }
+    else
+      {
+       vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str())); 
+       vtkObject::BreakOnError();
+      }
+    return 0;
+  }
+}
+
+//---------------------------------------------------
+int vtkJSONReader::CanParseFile(const char *fname, Json::Value &root)
+{
+  if ( !fname) {
+    vtkErrorMacro(<< "Input file name is not specified !!! ");
+    return 0;
+  }
+
+  ifstream file;
+  std::ostringstream oss;
+  bool parsedSuccess = true;
+  Json::Reader reader;
+
+  file.open(fname);
+  if ( !file.is_open() ) {
+      oss<< "Unable to open file: " << this->FileName;
+      parsedSuccess = false;
+  } else {
+    parsedSuccess = reader.parse(file, root, false);
+    file.close();    
+  }
+  if ( !parsedSuccess ) {
+    if(oss.str().empty()) {
+      oss<<"Failed to parse JSON file: " << "\n" << reader.getFormattedErrorMessages();
+    }
+    if(this->HasObserver("ErrorEvent") ) {
+      this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
+    }
+    else {
+      vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str())); 
+      vtkObject::BreakOnError();
+    }
+    return 0;
+  }
+  return 1;
+}
+
+//---------------------------------------------------
+int vtkJSONReader::Parse(Json::Value& root, vtkTable *table) {
+  bool hasShortNames = false;
+  bool hasUnits = false;
+  Container container;
+
+
+  Json::Value jSONListOfNames;
+  Json::Value jSONListOfUnits;
+  Json::Value jSONTableName;
+  std::vector<std::string> short_names;
+
+  if ( root.isMember(MD) ) {
+    Json::Value jSONMetaData = root.get(MD, Json::Value::null);
+
+    if ( jSONMetaData.isMember(CMT) ) {
+      Json::Value jSONComment = jSONMetaData.get(CMT, Json::Value::null);
+      vtkDebugMacro(<<"Table Comment  : " << jSONComment.asString());
+    }
+    if ( jSONMetaData.isMember(TBN) ) {
+      jSONTableName = jSONMetaData.get(TBN, Json::Value::null);      
+      vtkDebugMacro(<<"Table Name  : " << jSONTableName.asString());
+    }
+
+    if ( jSONMetaData.isMember(TBD) ) {
+      Json::Value jSONTableDescription = jSONMetaData.get(TBD, Json::Value::null);
+      vtkDebugMacro(<<"Table Description  : "  << jSONTableDescription.asString());
+    }
+
+    if ( jSONMetaData.isMember(DT) ) {
+      Json::Value jSONDate = jSONMetaData.get("date", Json::Value::null);
+      vtkDebugMacro(<<"Date  : " << jSONDate.asString());
+    }
+
+    if ( jSONMetaData.isMember(SHT) ) {
+      hasShortNames = true;
+      jSONListOfNames = jSONMetaData.get(SHT, Json::Value::null);
+      std::ostringstream oss;
+      oss<< "Short Names : [ ";
+      for (int i = 0; i < jSONListOfNames.size(); i++) {
+        oss << "'" << jSONListOfNames[i].asString() << "'";
+       short_names.push_back(jSONListOfNames[i].asString());
+        if ( i != jSONListOfNames.size() - 1 ) {
+          oss << ", ";
+        }
+      }
+      oss << " ]";
+      vtkDebugMacro(<<oss.str().c_str());
+    }
+
+    Json::Value jSONListOfLongName;
+    if ( jSONMetaData.isMember(LNG) ) {
+      jSONListOfLongName = jSONMetaData.get(LNG, Json::Value::null);
+      std::ostringstream oss;
+      oss << "Long Names : [ ";
+      for (int i = 0; i < jSONListOfLongName.size(); ++i) {
+        oss << "'" << jSONListOfLongName[i].asString() << "'";
+        if ( i != jSONListOfLongName.size()-1 ) {
+          oss << ", ";
+        }
+      }
+      oss<<" ]";
+      vtkDebugMacro(<<oss.str().c_str());
+    }
+    if ( jSONMetaData.isMember(UNT) ) {
+      jSONListOfUnits = jSONMetaData.get(UNT, Json::Value::null);
+      hasUnits = true;
+      std::ostringstream oss;
+      oss << "Units : [ ";
+      for (int i = 0; i < jSONListOfUnits.size(); ++i) {
+        oss << "'" << jSONListOfUnits[i].asString() << "'";
+        if ( i != jSONListOfUnits.size()-1 ) {
+          oss << ", ";
+        }
+      }
+      oss << " ]";
+      vtkDebugMacro(<<oss.str().c_str());
+    }
+    root.removeMember(MD);
+  }
+
+  Json::Value::iterator it = root.begin();
+  Json::Value newRoot = Json::Value::null;
+  
+  int nbElems=0;
+  bool hasArray = false;
+  for( ; it != root.end(); it++) {
+    nbElems++;
+    if((*it).type() == Json::arrayValue) {
+      newRoot = (*it);
+      hasArray = true;
+    }
+  }
+  if(hasArray && nbElems > 1) {
+    throw vtkJSONException("Wrong JSON file: it contains array and others elements");
+  }
+
+  if(newRoot == Json::Value::null) {
+    newRoot = root;
+  }
+    
+  it = newRoot.begin();
+  bool initContainer = false;
+  for( ; it != newRoot.end(); it++) {
+    if((*it).type() != Json::objectValue) {
+      std::ostringstream oss;
+      oss<<"Wrong JSON file: unexpected element, named '"<<(it.name())<<"'";
+      throw vtkJSONException(oss.str().c_str());
+    }
+    Json::Value::Members members = (*it).getMemberNames();    
+    if(!initContainer) {
+      if(!hasShortNames) {
+       short_names = members;
+      }
+      std::string err;
+      container.initKeys(short_names,err);
+      if(!err.empty()){
+       throw vtkJSONException(err.c_str());
+      }
+      initContainer = true;
+    }
+    for(int i=0; i < members.size(); i++) { 
+      Json::Value val = (*it).get(members[i],Json::Value::null);
+      double value = 0.0;
+      switch (val.type()) {    
+          case Json::stringValue: {
+            std::string s("Item with name '");
+            s += it.name();
+            s += "' has key '";
+            s += members[i];
+            s += "' with string value '";
+            s += val.asString();
+            s += "' ! Value set to 0.0";
+           if(this->HasObserver("WarningEvent") ) {
+             this->InvokeEvent("WarningEvent",const_cast<char *>(s.c_str()));
+           }
+           else {
+             vtkOutputWindowDisplayWarningText(const_cast<char *>(s.c_str())); 
+           }
+            break;
+         }
+          default:
+            value = val.asDouble();
+      }
+      std::string err;
+      container.addValue(members[i],value,err);
+      if(!err.empty()){
+       throw vtkJSONException(err.c_str());
+      }
+    }
+  }
+  
+  table->GetInformation()->Set(vtkDataObject::FIELD_NAME(), jSONTableName.asString().c_str());
+  Container::DataType data = container.getData();
+  if(hasUnits && data.size() != jSONListOfUnits.size()) {
+    throw vtkJSONException("W");
+  }
+  
+  int nbRows = 0;
+  if(data.size() > 0)
+    nbRows = data[0].second.size();
+
+  for(int i = 0; i < data.size(); i++) {
+    vtkDoubleArray* newCol = vtkDoubleArray::New();
+    newCol->SetNumberOfValues(nbRows);
+    std::string name = data[i].first;
+    name += "[";
+    if(!jSONListOfUnits[i].asString().empty()){
+      name += jSONListOfUnits[i].asString();
+    } else {
+      name += NA;
+    }
+    name += "]";
+    newCol->SetName(name.c_str());
+    for(int j = 0; j < data[i].second.size(); j++) {
+      newCol->SetValue(j, data[i].second[j]);
+    }
+    table->AddColumn(newCol);
+  }
 }
index 474b7f919bd9183929c6066a76f3d072002b5312..66badcfdaaa7b4b8fa755d42e27eaf7d12bd5af0 100644 (file)
 #ifndef __vtkJSONReader_h_
 #define __vtkJSONReader_h_
 
+#include "vtk_jsoncpp.h" // For json parser
 #include "vtkTableAlgorithm.h"
 
+
+//---------------------------------------------------
+class VTK_EXPORT vtkJSONException : public std::exception {
+ public:
+    vtkJSONException(const char *reason);
+    ~vtkJSONException() throw ();
+    const char* what() const throw();
+ protected:
+  std::string Reason;
+};
+
 class vtkStringArray;
-class vtkJSONParser;
 
 class VTK_EXPORT vtkJSONReader: public vtkTableAlgorithm
 {
@@ -38,16 +49,20 @@ public:
   vtkGetStringMacro(FileName);
   vtkSetStringMacro(FileName);
 
-  // Description:
-  // Determine whether the given file can be read
-  virtual int CanReadFile(const char* fname);
 
   // Description:
   // Request Data
   virtual int RequestData(vtkInformation*, 
                          vtkInformationVector**,
                          vtkInformationVector*);
+  // Decription:
+  // Parse the Json Value corresponding to the root data from the file
+  virtual int Parse(Json::Value& root, vtkTable *theTable);
 
+  // Decription:
+  // Verify if file exists and can be read by the parser
+  // If exists, parse into Jsoncpp data structure
+  int CanParseFile(const char *fname, Json::Value &root);
 
 protected:
   vtkJSONReader();
@@ -55,8 +70,6 @@ protected:
   // name of the file to read from
   char*            FileName;
 
-  vtkJSONParser*   Parser;
-
 private:
   vtkJSONReader(const vtkJSONReader&); // Not implemented.
   void operator=(const vtkJSONReader&); // Not implemented.