From d9959ac81c49a70f7151432fedbb6af852ebfa5b Mon Sep 17 00:00:00 2001 From: rnv Date: Wed, 13 Jan 2016 13:34:10 +0300 Subject: [PATCH] Re-implementation reader, using Json parser from VTK library. --- src/Plugins/JSONReader/CMakeLists.txt | 11 +- .../JSONReader/ParaViewPlugin/CMakeLists.txt | 2 - .../ParaViewPlugin/vtkJSONReader.cxx | 366 ++++++++++++++++-- .../JSONReader/ParaViewPlugin/vtkJSONReader.h | 25 +- 4 files changed, 357 insertions(+), 47 deletions(-) diff --git a/src/Plugins/JSONReader/CMakeLists.txt b/src/Plugins/JSONReader/CMakeLists.txt index 163fef31..1f5aeb09 100644 --- a/src/Plugins/JSONReader/CMakeLists.txt +++ b/src/Plugins/JSONReader/CMakeLists.txt @@ -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 diff --git a/src/Plugins/JSONReader/ParaViewPlugin/CMakeLists.txt b/src/Plugins/JSONReader/ParaViewPlugin/CMakeLists.txt index 6fd4e2c4..eac829fa 100644 --- a/src/Plugins/JSONReader/ParaViewPlugin/CMakeLists.txt +++ b/src/Plugins/JSONReader/ParaViewPlugin/CMakeLists.txt @@ -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 ) diff --git a/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.cxx b/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.cxx index adec0627..855d7a97 100644 --- a/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.cxx +++ b/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.cxx @@ -19,42 +19,114 @@ // Author: Roman NIKOLAEV #include "vtkJSONReader.h" -#include "vtkJSONParser.h" #include #include #include #include #include +#include #include #include #include +#include +#include #include #include +// 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>> DataType; + Container(){} + void initKeys(std::vector &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 '"<())); + } + } + + void addValue(std::string key, double value, std::string& err) { + if( !checkVar(key.c_str()) ) { + std::ostringstream oss; + oss<<"Bad key value '"<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: "<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<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<HasObserver("ErrorEvent") ) + { + this->InvokeEvent("ErrorEvent",const_cast(oss.str().c_str())); + } + else + { + vtkOutputWindowDisplayErrorText(const_cast(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(oss.str().c_str())); + } + else { + vtkOutputWindowDisplayErrorText(const_cast(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 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(< 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(s.c_str())); + } + else { + vtkOutputWindowDisplayWarningText(const_cast(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); + } } diff --git a/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.h b/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.h index 474b7f91..66badcfd 100644 --- a/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.h +++ b/src/Plugins/JSONReader/ParaViewPlugin/vtkJSONReader.h @@ -21,10 +21,21 @@ #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. -- 2.39.2