| 1 | /************************************************************************* |
| 2 | * libjson-rpc-cpp |
| 3 | ************************************************************************* |
| 4 | * @file procedure.cpp |
| 5 | * @date 31.12.2012 |
| 6 | * @author Peter Spiess-Knafl <dev@spiessknafl.at> |
| 7 | * @license See attached LICENSE.txt |
| 8 | ************************************************************************/ |
| 9 | |
| 10 | #include "procedure.h" |
| 11 | #include "errors.h" |
| 12 | #include "exception.h" |
| 13 | #include <cstdarg> |
| 14 | #include <vector> |
| 15 | |
| 16 | using namespace std; |
| 17 | using namespace jsonrpc; |
| 18 | |
| 19 | Procedure::Procedure() : procedureName("" ), procedureType(RPC_METHOD), returntype(JSON_BOOLEAN), paramDeclaration(PARAMS_BY_NAME) {} |
| 20 | |
| 21 | Procedure::Procedure(const string &name, parameterDeclaration_t paramType, jsontype_t returntype, ...) { |
| 22 | va_list parameters; |
| 23 | va_start(parameters, returntype); |
| 24 | const char *paramname = va_arg(parameters, const char *); |
| 25 | jsontype_t type; |
| 26 | while (paramname != NULL) { |
| 27 | type = (jsontype_t)va_arg(parameters, int); |
| 28 | this->AddParameter(paramname, type); |
| 29 | paramname = va_arg(parameters, const char *); |
| 30 | } |
| 31 | va_end(parameters); |
| 32 | this->procedureName = name; |
| 33 | this->returntype = returntype; |
| 34 | this->procedureType = RPC_METHOD; |
| 35 | this->paramDeclaration = paramType; |
| 36 | } |
| 37 | Procedure::Procedure(const string &name, parameterDeclaration_t paramType, ...) { |
| 38 | va_list parameters; |
| 39 | va_start(parameters, paramType); |
| 40 | const char *paramname = va_arg(parameters, const char *); |
| 41 | jsontype_t type; |
| 42 | while (paramname != NULL) { |
| 43 | type = (jsontype_t)va_arg(parameters, int); |
| 44 | this->AddParameter(paramname, type); |
| 45 | paramname = va_arg(parameters, const char *); |
| 46 | } |
| 47 | va_end(parameters); |
| 48 | this->procedureName = name; |
| 49 | this->procedureType = RPC_NOTIFICATION; |
| 50 | this->paramDeclaration = paramType; |
| 51 | this->returntype = JSON_BOOLEAN; |
| 52 | } |
| 53 | |
| 54 | bool Procedure::ValdiateParameters(const Json::Value ¶meters) const { |
| 55 | if (this->parametersName.empty()) { |
| 56 | return true; |
| 57 | } |
| 58 | if (parameters.isArray() && this->paramDeclaration == PARAMS_BY_POSITION) { |
| 59 | return this->ValidatePositionalParameters(parameters); |
| 60 | } else if (parameters.isObject() && this->paramDeclaration == PARAMS_BY_NAME) { |
| 61 | return this->ValidateNamedParameters(parameters); |
| 62 | } else { |
| 63 | return false; |
| 64 | } |
| 65 | } |
| 66 | const parameterNameList_t &Procedure::GetParameters() const { return this->parametersName; } |
| 67 | procedure_t Procedure::GetProcedureType() const { return this->procedureType; } |
| 68 | const std::string &Procedure::GetProcedureName() const { return this->procedureName; } |
| 69 | parameterDeclaration_t Procedure::GetParameterDeclarationType() const { return this->paramDeclaration; } |
| 70 | jsontype_t Procedure::GetReturnType() const { return this->returntype; } |
| 71 | |
| 72 | void Procedure::SetProcedureName(const string &name) { this->procedureName = name; } |
| 73 | void Procedure::SetProcedureType(procedure_t type) { this->procedureType = type; } |
| 74 | void Procedure::SetReturnType(jsontype_t type) { this->returntype = type; } |
| 75 | void Procedure::SetParameterDeclarationType(parameterDeclaration_t type) { this->paramDeclaration = type; } |
| 76 | |
| 77 | void Procedure::AddParameter(const string &name, jsontype_t type) { |
| 78 | this->parametersName[name] = type; |
| 79 | this->parametersPosition.push_back(type); |
| 80 | } |
| 81 | bool Procedure::ValidateNamedParameters(const Json::Value ¶meters) const { |
| 82 | bool ok = parameters.isObject() || parameters.isNull(); |
| 83 | for (map<string, jsontype_t>::const_iterator it = this->parametersName.begin(); ok == true && it != this->parametersName.end(); ++it) { |
| 84 | if (!parameters.isMember(it->first)) { |
| 85 | ok = false; |
| 86 | } else { |
| 87 | ok = this->ValidateSingleParameter(it->second, parameters[it->first]); |
| 88 | } |
| 89 | } |
| 90 | return ok; |
| 91 | } |
| 92 | bool Procedure::ValidatePositionalParameters(const Json::Value ¶meters) const { |
| 93 | bool ok = true; |
| 94 | |
| 95 | if (parameters.size() != this->parametersPosition.size()) { |
| 96 | return false; |
| 97 | } |
| 98 | |
| 99 | for (unsigned int i = 0; ok && i < this->parametersPosition.size(); i++) { |
| 100 | ok = this->ValidateSingleParameter(this->parametersPosition.at(i), parameters[i]); |
| 101 | } |
| 102 | return ok; |
| 103 | } |
| 104 | bool Procedure::ValidateSingleParameter(jsontype_t expectedType, const Json::Value &value) const { |
| 105 | bool ok = true; |
| 106 | switch (expectedType) { |
| 107 | case JSON_STRING: |
| 108 | if (!value.isString()) |
| 109 | ok = false; |
| 110 | break; |
| 111 | case JSON_BOOLEAN: |
| 112 | if (!value.isBool()) |
| 113 | ok = false; |
| 114 | break; |
| 115 | case JSON_INTEGER: |
| 116 | if (!value.isIntegral()) |
| 117 | ok = false; |
| 118 | break; |
| 119 | case JSON_REAL: |
| 120 | if (!value.isDouble()) |
| 121 | ok = false; |
| 122 | break; |
| 123 | case JSON_NUMERIC: |
| 124 | if (!value.isNumeric()) |
| 125 | ok = false; |
| 126 | break; |
| 127 | case JSON_OBJECT: |
| 128 | if (!value.isObject()) |
| 129 | ok = false; |
| 130 | break; |
| 131 | case JSON_ARRAY: |
| 132 | if (!value.isArray()) |
| 133 | ok = false; |
| 134 | break; |
| 135 | } |
| 136 | return ok; |
| 137 | } |
| 138 | |