1 // Copyright (C) 2015-2016 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author: Roman NIKOLAEV
21 #include "vtkJSONReader.h"
23 #include <vtkObjectFactory.h>
25 #include <vtkInformationVector.h>
26 #include <vtkInformation.h>
27 #include <vtkStreamingDemandDrivenPipeline.h>
28 #include <vtkDoubleArray.h>
29 #include <vtkVariantArray.h>
30 #include <vtkStringArray.h>
31 #include <vtkStringToNumeric.h>
32 #include <vtkSetGet.h>
33 #include <vtksys/RegularExpression.hxx>
39 #define MD "_metadata"
40 #define CMT "_comment"
41 #define TBN "table_name"
42 #define TBD "table_description"
43 #define SHT "short_names"
44 #define LNG "long_names"
51 //---------------------------------------------------
52 vtkJSONException::vtkJSONException(const char *reason) : Reason(reason) {
56 //---------------------------------------------------
57 vtkJSONException::~vtkJSONException() throw () {
60 //---------------------------------------------------
61 const char* vtkJSONException::what() const throw() {
62 return Reason.c_str();
66 //---------------------------------------------------
69 typedef std::vector<std::pair<std::string,std::vector<double> > > DataType;
71 void initKeys(std::vector<std::string> &keys, std::string &err) {
72 for(int i = 0; i < keys.size(); i++) {
73 if( !checkVar(keys[i].c_str()) ) {
74 std::ostringstream oss;
75 oss<<"Bad key value '"<<keys[i].c_str()<<"'";
79 _data.push_back(std::make_pair(keys[i],std::vector<double>()));
83 void addValue(std::string key, double value, std::string& err) {
84 if( !checkVar(key.c_str()) ) {
85 std::ostringstream oss;
86 oss<<"Bad key value '"<<key.c_str()<<"'";
91 for(int i = 0; i < _data.size(); i++) {
92 if(_data[i].first == key) {
93 _data[i].second.push_back(value);
99 std::ostringstream oss;
100 oss<<"Bad key value '"<<key<<"'";
105 DataType& getData() {
109 bool checkVar(const char* var) {
110 vtksys::RegularExpression regEx("^[a-zA-Z_][a-zA-Z0-9_]*$");
111 return regEx.find(var);
117 vtkStandardNewMacro(vtkJSONReader);
119 //---------------------------------------------------
120 vtkJSONReader::vtkJSONReader() {
121 this->SetNumberOfInputPorts(0);
122 this->SetNumberOfOutputPorts(1);
123 this->FileName = NULL;
126 //---------------------------------------------------
127 vtkJSONReader::~vtkJSONReader()
129 this->SetFileName(NULL);
132 //---------------------------------------------------
133 void vtkJSONReader::PrintSelf(ostream& os, vtkIndent indent)
135 this->Superclass::PrintSelf(os, indent);
136 os << indent << "FileName: "
137 << (this->FileName ? this->FileName : "(none)") << endl;
140 //---------------------------------------------------
141 int vtkJSONReader::RequestData(vtkInformation*,
142 vtkInformationVector**,
143 vtkInformationVector* outputVector) {
144 vtkTable* const output_table = vtkTable::GetData(outputVector);
146 vtkInformation* const outInfo = outputVector->GetInformationObject(0);
147 if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) &&
148 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) > 0) {
154 parseResult = this->CanParseFile(this->FileName, root);
159 this->Parse(root, output_table);
162 catch(vtkJSONException e) {
163 std::ostringstream oss;
165 if(this->HasObserver("ErrorEvent") )
167 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
171 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
172 vtkObject::BreakOnError();
178 //---------------------------------------------------
179 int vtkJSONReader::CanParseFile(const char *fname, Json::Value &root)
182 vtkErrorMacro(<< "Input file name is not specified !!! ");
187 std::ostringstream oss;
188 bool parsedSuccess = true;
192 if ( !file.is_open() ) {
193 oss<< "Unable to open file: " << this->FileName;
194 parsedSuccess = false;
196 parsedSuccess = reader.parse(file, root, false);
199 if ( !parsedSuccess ) {
200 if(oss.str().empty()) {
201 oss<<"Failed to parse JSON file: " << "\n" << reader.getFormattedErrorMessages();
203 if(this->HasObserver("ErrorEvent") ) {
204 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
207 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
208 vtkObject::BreakOnError();
215 //---------------------------------------------------
216 void vtkJSONReader::Parse(Json::Value& root, vtkTable *table) {
217 bool hasShortNames = false;
218 bool hasUnits = false;
222 Json::Value jSONListOfNames;
223 Json::Value jSONListOfUnits;
224 Json::Value jSONTableName;
225 std::vector<std::string> short_names;
227 if ( root.isMember(MD) ) {
228 Json::Value jSONMetaData = root.get(MD, Json::Value::null);
230 if ( jSONMetaData.isMember(CMT) ) {
231 Json::Value jSONComment = jSONMetaData.get(CMT, Json::Value::null);
232 vtkDebugMacro(<<"Table Comment : " << jSONComment.asString());
234 if ( jSONMetaData.isMember(TBN) ) {
235 jSONTableName = jSONMetaData.get(TBN, Json::Value::null);
236 vtkDebugMacro(<<"Table Name : " << jSONTableName.asString());
239 if ( jSONMetaData.isMember(TBD) ) {
240 Json::Value jSONTableDescription = jSONMetaData.get(TBD, Json::Value::null);
241 vtkDebugMacro(<<"Table Description : " << jSONTableDescription.asString());
244 if ( jSONMetaData.isMember(DT) ) {
245 Json::Value jSONDate = jSONMetaData.get("date", Json::Value::null);
246 vtkDebugMacro(<<"Date : " << jSONDate.asString());
249 if ( jSONMetaData.isMember(SHT) ) {
250 hasShortNames = true;
251 jSONListOfNames = jSONMetaData.get(SHT, Json::Value::null);
252 std::ostringstream oss;
253 oss<< "Short Names : [ ";
254 for (int i = 0; i < jSONListOfNames.size(); i++) {
255 oss << "'" << jSONListOfNames[i].asString() << "'";
256 short_names.push_back(jSONListOfNames[i].asString());
257 if ( i != jSONListOfNames.size() - 1 ) {
262 vtkDebugMacro(<<oss.str().c_str());
265 Json::Value jSONListOfLongName;
266 if ( jSONMetaData.isMember(LNG) ) {
267 jSONListOfLongName = jSONMetaData.get(LNG, Json::Value::null);
268 std::ostringstream oss;
269 oss << "Long Names : [ ";
270 for (int i = 0; i < jSONListOfLongName.size(); ++i) {
271 oss << "'" << jSONListOfLongName[i].asString() << "'";
272 if ( i != jSONListOfLongName.size()-1 ) {
277 vtkDebugMacro(<<oss.str().c_str());
279 if ( jSONMetaData.isMember(UNT) ) {
280 jSONListOfUnits = jSONMetaData.get(UNT, Json::Value::null);
282 std::ostringstream oss;
284 for (int i = 0; i < jSONListOfUnits.size(); ++i) {
285 oss << "'" << jSONListOfUnits[i].asString() << "'";
286 if ( i != jSONListOfUnits.size()-1 ) {
291 vtkDebugMacro(<<oss.str().c_str());
293 root.removeMember(MD);
296 Json::Value::iterator it = root.begin();
297 Json::Value newRoot = Json::Value::null;
300 bool hasArray = false;
301 for( ; it != root.end(); it++) {
303 if((*it).type() == Json::arrayValue) {
308 if(hasArray && nbElems > 1) {
309 throw vtkJSONException("Wrong JSON file: it contains array and others elements");
312 if(newRoot == Json::Value::null) {
316 it = newRoot.begin();
317 bool initContainer = false;
318 for( ; it != newRoot.end(); it++) {
319 if((*it).type() != Json::objectValue) {
320 std::ostringstream oss;
321 oss<<"Wrong JSON file: unexpected element, named '"<<(it.name())<<"'";
322 throw vtkJSONException(oss.str().c_str());
324 Json::Value::Members members = (*it).getMemberNames();
327 short_names = members;
330 container.initKeys(short_names,err);
332 throw vtkJSONException(err.c_str());
334 initContainer = true;
336 for(int i=0; i < members.size(); i++) {
337 Json::Value val = (*it).get(members[i],Json::Value::null);
339 switch (val.type()) {
340 case Json::stringValue: {
341 std::string s("Item with name '");
345 s += "' with string value '";
347 s += "' ! Value set to 0.0";
348 if(this->HasObserver("WarningEvent") ) {
349 this->InvokeEvent("WarningEvent",const_cast<char *>(s.c_str()));
352 vtkOutputWindowDisplayWarningText(const_cast<char *>(s.c_str()));
357 value = val.asDouble();
360 container.addValue(members[i],value,err);
362 throw vtkJSONException(err.c_str());
367 table->GetInformation()->Set(vtkDataObject::FIELD_NAME(), jSONTableName.asString().c_str());
368 Container::DataType data = container.getData();
369 if(hasUnits && data.size() != jSONListOfUnits.size()) {
370 throw vtkJSONException("W");
375 nbRows = data[0].second.size();
377 for(int i = 0; i < data.size(); i++) {
378 vtkDoubleArray* newCol = vtkDoubleArray::New();
379 newCol->SetNumberOfValues(nbRows);
380 std::string name = data[i].first;
382 if(!jSONListOfUnits[i].asString().empty()){
383 name += jSONListOfUnits[i].asString();
388 newCol->SetName(name.c_str());
389 for(int j = 0; j < data[i].second.size(); j++) {
390 newCol->SetValue(j, data[i].second[j]);
392 table->AddColumn(newCol);