X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fjson%2Fjson_handler.cc;fp=src%2Fjson%2Fjson_handler.cc;h=0000000000000000000000000000000000000000;hb=4e545a8b013e60f2ff59254cb3fe435012d8fe5a;hp=a14b341ae4a1ac6019d432f1c3ed05e4dfb64f14;hpb=82ba4b9999ca8e09461315a919b36a66641a6c7d;p=ric-app%2Fadmin.git diff --git a/src/json/json_handler.cc b/src/json/json_handler.cc deleted file mode 100644 index a14b341..0000000 --- a/src/json/json_handler.cc +++ /dev/null @@ -1,686 +0,0 @@ -/* -================================================================================== - - Copyright (c) 2018-2019 AT&T Intellectual Property. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -================================================================================== -*/ -/* - Author : Ashwin Sridharan - - -*/ - -#include -#include - -TrieNode::TrieNode(int val): val_type(-1){ - _id.tag = DataContainer::Types::integer; - _id.value.i = val; -} - -TrieNode::TrieNode( std::string val) : val_type(-1){ - _id.tag = DataContainer::Types::str; - _id.value.s.assign(val); -} - -void TrieNode::set_value(const char * val){ - _val.tag = DataContainer::Types::str; - _val.value.s.assign(val); -} - - -void TrieNode::set_value(bool val){ - _val.tag = DataContainer::Types::boolean; - _val.value.b = val; - -} - -void TrieNode::set_value(int val){ - _val.tag = DataContainer::Types::integer; - _val.value.i = val; - //std::cout <<"Assigned integer " << val << std::endl; - - -} - -void TrieNode::set_value(unsigned int val){ - _val.tag = DataContainer::Types::uinteger; - _val.value.ui = val; - -} - -void TrieNode::set_value( long int val){ - _val.tag = DataContainer::Types::big_integer; - _val.value.l = val; -} - -void TrieNode::set_value(unsigned long int val){ - _val.tag = DataContainer::Types::ubig_integer; - _val.value.ul = val; -} - -void TrieNode::set_value(double val){ - _val.tag = DataContainer::Types::real; - _val.value.f = val; - -} - - -void TrieNode::set_value(std::string val){ - _val.tag = DataContainer::Types::str; - _val.value.s.assign(val); -} - -void TrieNode::set_value(const char * c, size_t len){ - _val.tag = DataContainer::Types::str; - _val.value.s.assign(c, len); -} - -void TrieNode::add_child(TrieNode * node){ - _children.push_back(node); -}; - - - -void TrieNode::print_id(void){ - switch(_id.tag){ - - case DataContainer::Types::integer : - std::cout <<"Type = " << _id.tag << " Value = " << _id.value.i << std::endl; - break; - case DataContainer::Types::str : - std::cout <<"Type = " << _id.tag << " Value = " << _id.value.s << std::endl; - break; - default: - std::cerr<< "Error ! ID not set or unknown type " << _id.tag; - } -}; - -void TrieNode::print_value(void){ - switch(_val.tag){ - - case DataContainer::Types::boolean : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.b << std::endl; - break; - case DataContainer::Types::integer : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.i << std::endl; - break; - case DataContainer::Types::uinteger : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.ui << std::endl; - break; - case DataContainer::Types::big_integer : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.l << std::endl; - break; - case DataContainer::Types::ubig_integer : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.ul << std::endl; - break; - case DataContainer::Types::real : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.f << std::endl; - break; - case DataContainer::Types::str : - std::cout <<"Type = " << _val.tag << " Value = " << _val.value.s << std::endl; - break; - default: - std::cerr<< "Error ! Value not set or unknown type " << _val.tag; - } -}; - - -jsonHandler::jsonHandler(void):_is_root(false), _is_schema(false), _is_buffer(false){ - -}; - - - - -void jsonHandler::load_file(std::string input_file, std::string & contents ){ - - std::FILE *fp ; - try{ - fp = std::fopen(input_file.c_str(), "rb"); - } - catch(std::exception &e){ - std::string error_string = "Error opening input schema file " + input_file; - throw std::runtime_error(error_string); - } - - if (fp){ - std::fseek(fp, 0, SEEK_END); - contents.resize(std::ftell(fp)); - std::rewind(fp); - std::fread(&contents[0], 1, contents.size(), fp); - std::fclose(fp); - } - - else{ - std::string error_string = "Error opening input file " + input_file; - throw std::runtime_error(error_string); - } - -} - - - -void jsonHandler::load_schema(std::string input_file){ - - load_file(input_file, _contents); - Document _doc; - if (_doc.Parse(_contents.c_str()).HasParseError()){ - std::string error_string = input_file + " is invalid JSON" ; - throw std::runtime_error(error_string); - } - - _ref_schema_doc= std::make_unique(_doc); - _is_schema = true; - - -} - -void jsonHandler::load_schema(std::string input_file, TrieNode * root){ - - load_file(input_file, _contents); - std::string response; - Document _doc; - if (_doc.Parse(_contents.c_str()).HasParseError()){ - std::string error_string = input_file + " is invalid JSON" ; - throw std::runtime_error(error_string); - } - - // Get message schema - bool res; - Value _schema_root; - Value &_root = _doc; - res = find_member(_root, response, root, _schema_root); - if (res == false){ - throw std::runtime_error(response); - } - - _ref_schema_doc= std::make_unique(_schema_root); - _is_schema = true; - -} - -void jsonHandler::load_buffer(std::string input_file){ - - load_file(input_file, _buffer); - Document _doc; - if (_doc.Parse(_buffer.c_str()).HasParseError()){ - std::string error_string = input_file + " is invalid JSON" ; - throw std::runtime_error(error_string); - } - _is_buffer = true; - -} - -void jsonHandler::load_buffer(std::string input_file, TrieNode * root){ - - load_file(input_file, _buffer); - Document _doc; - std::string response; - - if (_doc.Parse(_buffer.c_str()).HasParseError()){ - std::string error_string = input_file + " is invalid JSON" ; - throw std::runtime_error(error_string); - } - - bool res; - Value _buffer_root; - res = find_member(_doc, response, root, _buffer_root); - if(res == false){ - throw std::runtime_error(response); - } - - StringBuffer out_buffer; - Writer writer(out_buffer); - _buffer_root.Accept(writer); - _buffer.assign(out_buffer.GetString(), out_buffer.GetLength()); - _is_buffer = true; -} - - -std::string jsonHandler::get_buffer(void){ - std::string response; - if (_is_buffer){ - response.assign(_buffer); - } - else{ - response = ""; - } - - return response; -} - - - - - - -bool jsonHandler::find_member(const std::string schema, std::string & response, TrieNode * root, Value & TargetVal){ - - Document doc; - std::string contents(schema); - - if(doc.Parse(contents.c_str()).HasParseError()){ - response.assign("Error Parsing JSON File"); - return false; - } - - return find_member(doc, response, root, TargetVal); - return true; -}; - - -bool jsonHandler::find_member(Value & doc_root, std::string & response, TrieNode * root, Value & TargetVal){ - - if (!root){ - response.assign("Null Trie root node"); - return false; - } - //std::cout <<"LOoking for schema root" << std::endl; - - Value & json_node = doc_root; - TrieNode * trie_node = root; - Value::MemberIterator itr; - - while(1){ - - DataContainer const * d = trie_node->get_id(); - if (! d){ - response.assign("Error could not find any id for trie node "); - return false; - } - - if (d->tag == DataContainer::Types::integer && json_node.IsArray()){ - if (json_node.Size() < d->value.i){ - response.assign("Error json array size "); - response += std::to_string(json_node.Size()) + " is smaller than trie node index " + std::to_string( d->value.i); - return false; - } - - if (trie_node->is_child()){ - response.assign("Error child trie points to an array ? "); - return false; - } - - trie_node = trie_node->get_children()[0]; - json_node = json_node[d->value.i]; - } - else if (d->tag == DataContainer::Types::str && json_node.IsObject()){ - - itr = json_node.FindMember(d->value.s.c_str()); - if (itr == json_node.MemberEnd()){ - response.assign("Error ! Could not find key = "); - response += d->value.s; - return false; - } - if (trie_node->is_child()){ - // reached end of trie - if (itr->value.IsObject()){ - TargetVal = itr->value.GetObject(); - //std::cout <<"Reached root = " << itr->name.GetString() << std::endl; - } - else if (itr->value.IsArray()){ - TargetVal = itr->value.GetArray(); - } - else{ - response.assign("Error ! JSON node selected must be object or array in current version"); - std::cerr << response << std::endl; - return false; - } - break; - } - else{ - trie_node = trie_node->get_children()[0]; - trie_node->print_id(); - - if (itr->value.IsObject()){ - json_node = itr->value.GetObject(); - } - else if (itr->value.IsArray()){ - json_node = itr->value.GetArray(); - } - else{ - std::string error_string= " Path must be an object or array"; - response.assign(error_string); - return false; - } - } - } - else{ - std::string error_string = "Mismatch when setting root : Trie node is of type = " + std::to_string (d->tag) + " and json node is of type = " + std::to_string(json_node.GetType()); - response.assign(error_string); - return false; - } - - } - - return true; - -} - -bool jsonHandler::is_valid(const char *message, int message_length, std::string & response){ - - Document doc; - if (! _is_schema){ - return false; - } - - SchemaValidator validator(*(_ref_schema_doc.get())); - - // ensure message has terminator by translating to string ? - std::string message_s(message, message_length); - - - // validate json - if (doc.Parse(message_s.c_str()).HasParseError()){ - - // return error message - std::string failed_message = "\"message\": \"Invalid JSON\""; - response.assign( failed_message ); - return false; - } - - - // Validate against our JSON input schema - if (!doc.Accept(validator)){ - - StringBuffer sb; - validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); - std::string failed_message = std::string("\"message\": \"Schema Violation:") + std::string(sb.GetString()); - failed_message += std::string(" Invalid keyword :") + std::string(validator.GetInvalidSchemaKeyword()) + " \""; - response.assign(failed_message); - return false; - - } - response.assign("SUCCESS"); - return true; - - -} - - - -// should be thread safe since it can be expected to be called from multiple threads -// only static external variable referenced is the schema (which should be read-only and hence ok ?) - -// Returns 0 if success -// -1 if invalid json -// -2 if invalid schema (assuming schema provided) -// -3 unknown key -// -4 no buffer available - -int jsonHandler::get_values(const char *message, int message_length, std::string & response, TrieNode * root, std::vector & response_list){ - - Document doc; - - // ensure message has terminator by translating to string ? - std::string message_s(message, message_length); - - // validate json - if (doc.Parse(message_s.c_str()).HasParseError()){ - - // return error message - response.assign("Invalid JSON"); - return -1; - } - - // Validate against our JSON input schema - if ( _is_schema){ - SchemaValidator validator(*(_ref_schema_doc.get())); - - if (!doc.Accept(validator)){ - - StringBuffer sb; - validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); - response = std::string("Schema Violation ") + std::string(sb.GetString()) ; - response += std::string(" Invalid keyword = ") + std::string(validator.GetInvalidSchemaKeyword()) + " \""; - return -2; - } - - } - - Value & doc_root = doc; - bool res = traverse_doc(doc_root, root, true, response, response_list); - if (!res){ - return -3; - } - - response.assign("SUCCESS"); - return 0; -} - - -int jsonHandler::get_values( std::string & response, TrieNode * root, std::vector & response_list){ - int res; - if (_is_buffer){ - Document _doc; - _doc.Parse(_buffer.c_str()); - Value & _buffer_root = _doc; - - res = traverse_doc(_buffer_root, root, true, response, response_list); - return res; - } - else{ - response = "Error ! No buffer loaded in json object for get"; - return -4; - } -} - - -// If in get mode, return all values we can get -// If in set mode, return false if we cannot set a value -bool jsonHandler::traverse_doc(Value & json_node, TrieNode * trie_node, bool get, std::string & response, std::vector & response_list ){ - - if (!trie_node){ - response.assign(" Null Trie node "); - return false; - } - - bool res; - - DataContainer const * d = trie_node->get_id(); - if (! d){ - response.assign(" Error could not find any id for trie node"); - return false; - } - - Value::MemberIterator itr; - - - if (d->tag == DataContainer::Types::integer && json_node.IsArray()){ - if (json_node.Size() < d->value.i){ - response = "Error json array size " + std::to_string( json_node.Size()) + " is smaller than trie node index " + std::to_string( d->value.i); - return false; - } - - if (trie_node->is_child()){ - response.assign("Error child trie points to an array ? "); - return false; - } - - for (auto & e: trie_node->get_children()){ - res = traverse_doc(json_node[d->value.i], e, get, response, response_list); - if (!res && ! get){ - // if not in get mode and we hit a not found - // don't go any further, else move to next ... - return res; - } - } - } - - else if (d->tag == DataContainer::Types::str && json_node.IsObject()){ - itr = json_node.FindMember(d->value.s.c_str()); - - if (itr == json_node.MemberEnd()){ - response = "Error ! Could not find key " + d->value.s; - return false; - } - - if (trie_node->is_child()){ - // end of the line : do we get or set values ? - bool is_set = false; - if (get){ - if (itr->value.IsBool()){ - trie_node->set_value(itr->value.GetBool()); - is_set = true; - } - else if (itr->value.IsInt()){ - trie_node->set_value(itr->value.GetInt()); - is_set = true; - } - else if(itr->value.IsUint()){ - trie_node->set_value(static_cast(itr->value.GetUint())); - is_set = true; - } - else if(itr->value.IsUint64()){ - trie_node->set_value(static_cast(itr->value.GetUint64())); - is_set = true; - } - else if (itr->value.IsInt64()){ - trie_node->set_value(static_cast(itr->value.GetInt64())); - is_set = true; - } - else if ( itr->value.IsDouble()){ - trie_node->set_value(itr->value.GetDouble()); - is_set = true; - } - else if ( itr->value.IsString()){ - trie_node->set_value(itr->value.GetString(), itr->value.GetStringLength()); - is_set = true; - } - else{ - response = " json node corresponding to child node key must of type bool, int or string. Is of type = " + std::to_string(itr->value.GetType()); - return false; - } - - if (is_set){ - response_list.push_back(trie_node); - } - - //std::cout <<"Set value of child node with key = " << d->value.s.c_str() << " Type = " << trie_node->get_type() << std::endl; - - } - else{ - DataContainer const * d_val = trie_node->get_value(); - if (d_val->tag == DataContainer::Types::boolean){ - itr->value.SetBool(d_val->value.b); - } - else if (d_val->tag == DataContainer::Types::integer){ - itr->value.SetInt(d_val->value.i); - - } - else if (d_val->tag == DataContainer::Types::uinteger){ - itr->value.SetUint(d_val->value.ui); - - } - else if (d_val->tag == DataContainer::Types::big_integer){ - itr->value.SetInt64(d_val->value.l); - } - else if (d_val->tag == DataContainer::Types::ubig_integer){ - itr->value.SetUint64(d_val->value.ul); - } - else if (d_val->tag == DataContainer::Types::real){ - itr->value.SetDouble(d_val->value.f); - } - else if (d_val->tag == DataContainer::Types::str){ - itr->value.SetString(d_val->value.s.c_str(), d_val->value.s.length()); - } - else{ - response = " unknown type for child node value = " + std::to_string(d_val->tag) + " cannot set json node key = " + d->value.s; - return false; - } - } - return true; - } - else{ - for (auto & e: trie_node->get_children()){ - res = traverse_doc(itr->value, e, get, response, response_list); - if(res == false && ! get){ - return false; - } - } - } - } - - else{ - response = "Mismatch : Trie node is of type = " + std::to_string(d->tag) + " while json node is of type = " + std::to_string( json_node.GetType()); - return false; - } - - return true; - - -} - - -int jsonHandler::set_values(const char * buffer, int len, std::string & response, std::vector root_nodes){ - - Document doc; - std::string message_s(buffer, len); - - // validate json - if (doc.Parse(message_s.c_str()).HasParseError()){ - // return error message - response.assign("Invalid JSON"); - return -1; - } - - - Value & doc_root = doc; - // fake list to maintain signature for re-using traverse_doc - // since we don't return trie nodes when setting ... - std::vector fake_list; - for(auto const & e: root_nodes){ - bool res = traverse_doc(doc_root, e, false, response, fake_list); - if (!res){ - return -3; - } - } - - StringBuffer out_buffer; - Writer writer(out_buffer); - doc_root.Accept(writer); - response.assign(out_buffer.GetString(), out_buffer.GetLength()); - return 0; - } - - -// wrapper if instead of providing buffer, we simply use stored json object and use it -int jsonHandler::set_values(std::string & response, std::vector root_nodes){ - if (_is_buffer){ - std::vector fake_list; - Document _doc; - _doc.Parse(_buffer.c_str()); - Value & _buffer_root = _doc; - - for(auto const & e: root_nodes){ - bool res = traverse_doc(_buffer_root, e, false, response, fake_list); - if (!res){ - return -3; - } - } - - StringBuffer out_buffer; - Writer writer(out_buffer); - _buffer_root.Accept(writer); - response.assign(out_buffer.GetString(), out_buffer.GetLength()); - return 0; - } - else{ - response = "Error ! " + std::string( __FILE__) + "," + std::to_string(__LINE__) + " : No buffer loaded in json object to set"; - return -1; - } - -}