Added ability to specify different obligatory arguments list for different

functions to the PHP and JavaScript MibewAPI library
This commit is contained in:
Dmitriy Simushev 2012-08-21 14:55:09 +00:00
parent 79c4da8b2c
commit 2f18eb65b1
3 changed files with 222 additions and 58 deletions

View File

@ -6,14 +6,16 @@
License: http://mibew.org/license.php License: http://mibew.org/license.php
*/ */
function MibewAPI(a){this.protocolVersion="1.0";if("object"!=typeof a||!(a instanceof MibewAPIInteraction))throw Error("Wrong interaction type");this.interaction=a} function MibewAPI(a){this.protocolVersion="1.0";if("object"!=typeof a||!(a instanceof MibewAPIInteraction))throw Error("Wrong interaction type");this.interaction=a}
MibewAPI.prototype.checkFunction=function(a,b){if("undefined"==typeof a["function"]||""==a["function"])throw Error("Cannot call for function with no name");if(b)for(var c=0;c<this.interaction.reservedFunctionNames.length;c++)if(a["function"]==this.interaction.reservedFunctionNames[c])throw Error("'"+a["function"]+"' is reserved function name");if("object"!=typeof a.arguments)throw Error("There are no arguments in '"+a["function"]+"' function");var d=0,e;a:for(e in a.arguments)for(c=0;c<this.interaction.obligatoryArguments.length;c++)if(e== MibewAPI.prototype.checkFunction=function(a,b){if("undefined"==typeof a["function"]||""==a["function"])throw Error("Cannot call for function with no name");if(b)for(var c=0;c<this.interaction.reservedFunctionNames.length;c++)if(a["function"]==this.interaction.reservedFunctionNames[c])throw Error("'"+a["function"]+"' is reserved function name");if("object"!=typeof a.arguments)throw Error("There are no arguments in '"+a["function"]+"' function");var d=0,f=this.interaction.getObligatoryArguments(a["function"]),
this.interaction.obligatoryArguments[c]){d++;continue a}if(d!=this.interaction.obligatoryArguments.length)throw Error("Not all obligatory arguments are set in '"+a["function"]+"' function");}; e;a:for(e in a.arguments)for(c=0;c<f.length;c++)if(e==f[c]){d++;continue a}if(d!=f.length)throw Error("Not all obligatory arguments are set in '"+a["function"]+"' function");};
MibewAPI.prototype.checkRequest=function(a){if("string"!=typeof a.token){if("undefined"==typeof a.token)throw Error("Empty token");throw Error("Wrong token type");}if(""==a.token)throw Error("Empty token");if("object"!=typeof a.functions||!(a.functions instanceof Array)||0==a.functions.length)throw Error("Empty functions set");for(var b=0;b<a.functions.length;b++)this.checkFunction(a.functions[b])}; MibewAPI.prototype.checkRequest=function(a){if("string"!=typeof a.token){if("undefined"==typeof a.token)throw Error("Empty token");throw Error("Wrong token type");}if(""==a.token)throw Error("Empty token");if("object"!=typeof a.functions||!(a.functions instanceof Array)||0==a.functions.length)throw Error("Empty functions set");for(var b=0;b<a.functions.length;b++)this.checkFunction(a.functions[b])};
MibewAPI.prototype.checkPackage=function(a){if("undefined"==typeof a.signature)throw Error("Missed package signature");if("undefined"==typeof a.proto)throw Error("Missed protocol version");if(a.proto!=this.protocolVersion)throw Error("Wrong protocol version");if("undefined"==typeof a.async)throw Error("'async' flag is missed");if("boolean"!=typeof a.async)throw Error("Wrong 'async' flag value");if("object"!=typeof a.requests||!(a.requests instanceof Array)||0==a.requests.length)throw Error("Empty requests set"); MibewAPI.prototype.checkPackage=function(a){if("undefined"==typeof a.signature)throw Error("Missed package signature");if("undefined"==typeof a.proto)throw Error("Missed protocol version");if(a.proto!=this.protocolVersion)throw Error("Wrong protocol version");if("undefined"==typeof a.async)throw Error("'async' flag is missed");if("boolean"!=typeof a.async)throw Error("Wrong 'async' flag value");if("object"!=typeof a.requests||!(a.requests instanceof Array)||0==a.requests.length)throw Error("Empty requests set");
for(var b=0;b<a.requests.length;b++)this.checkRequest(a.requests[b])};MibewAPI.prototype.getResultFunction=function(a,b){"undefined"==typeof b&&(b=null);var c=null,d;for(d in a)if(a.hasOwnProperty(d)&&"result"==a[d]["function"]){if(null!==c)throw Error("Function 'result' already exists in functions list");c=a[d]}if(!0===b&&null===c)throw Error("There is no 'result' function in functions list");if(!1===b&&null!==c)throw Error("There is 'result' function in functions list");return c}; for(var b=0;b<a.requests.length;b++)this.checkRequest(a.requests[b])};MibewAPI.prototype.getResultFunction=function(a,b){"undefined"==typeof b&&(b=null);var c=null,d;for(d in a)if(a.hasOwnProperty(d)&&"result"==a[d]["function"]){if(null!==c)throw Error("Function 'result' already exists in functions list");c=a[d]}if(!0===b&&null===c)throw Error("There is no 'result' function in functions list");if(!1===b&&null!==c)throw Error("There is 'result' function in functions list");return c};
MibewAPI.prototype.buildResult=function(a,b){var c=this.interaction.getDefaultObligatoryArguments(),d;for(d in c)c.hasOwnProperty(d)&&(a[d]=c[d]);return{token:b,functions:[{"function":"result",arguments:a}]}};MibewAPI.prototype.encodePackage=function(a){var b={signature:""};b.proto=this.protocolVersion;b.async=!0;b.requests=a;return encodeURIComponent(JSON.stringify(b)).replace(/\%20/gi,"+")}; MibewAPI.prototype.buildResult=function(a,b){var c=this.interaction.getDefaultObligatoryArguments("result"),d;for(d in c)c.hasOwnProperty(d)&&(a[d]=c[d]);return{token:b,functions:[{"function":"result",arguments:a}]}};MibewAPI.prototype.encodePackage=function(a){var b={signature:""};b.proto=this.protocolVersion;b.async=!0;b.requests=a;return encodeURIComponent(JSON.stringify(b)).replace(/\%20/gi,"+")};
MibewAPI.prototype.decodePackage=function(a){a=JSON.parse(decodeURIComponent(a.replace(/\+/gi," ")));this.checkPackage(a);return a};function MibewAPIInteraction(){this.reservedFunctionNames=[];this.obligatoryArguments=[];this.getDefaultObligatoryArguments=function(){return{}}}function MibewAPIWindowToCoreInteraction(){this.reservedFunctionNames=["result"];this.obligatoryArguments=["return","references"];this.getDefaultObligatoryArguments=function(){return{"return":{},references:{}}}} MibewAPI.prototype.decodePackage=function(a){a=JSON.parse(decodeURIComponent(a.replace(/\+/gi," ")));this.checkPackage(a);return a};function MibewAPIInteraction(){this.obligatoryArguments={};this.reservedFunctionNames=[]}
MibewAPIWindowToCoreInteraction.prototype=new MibewAPIInteraction;function MibewAPIExecutionContext(){this.returnValues={};this.functionsResults=[]} MibewAPIInteraction.prototype.getObligatoryArguments=function(a){var b=[];if("object"==typeof this.obligatoryArguments["*"]&&this.obligatoryArguments["*"]instanceof Array)for(var c in this.obligatoryArguments["*"])this.obligatoryArguments["*"].hasOwnProperty(c)&&b.push(c);if("object"==typeof this.obligatoryArguments[a]&&this.obligatoryArguments[a]instanceof Array)for(c in this.obligatoryArguments[a])this.obligatoryArguments[a].hasOwnProperty(c)&&b.push(c);return b};
MibewAPIExecutionContext.prototype.getArgumentsList=function(a){var b=a.arguments,c=a.arguments.references,d,e,f;for(f in c)if(c.hasOwnProperty(f)){e=c[f];if("undefined"==typeof this.functionsResults[e-1])throw Error("Wrong reference in '"+a["function"]+"' function. Function #"+e+" does not call yet.");if("undefined"==typeof b[f]||""==b[f])throw Error("Wrong reference in '"+a["function"]+"' function. Empty '"+f+"' argument.");d=b[f];if("undefined"==typeof this.functionsResults[e-1][d])throw Error("Wrong reference in '"+ MibewAPIInteraction.prototype.getDefaultObligatoryArguments=function(a){var b=[];if("object"==typeof this.obligatoryArguments["*"]&&this.obligatoryArguments["*"]instanceof Array)for(var c in this.obligatoryArguments["*"])this.obligatoryArguments["*"].hasOwnProperty(c)&&(b[c]=this.obligatoryArguments["*"][c]);if("object"==typeof this.obligatoryArguments[a]&&this.obligatoryArguments[a]instanceof Array)for(c in this.obligatoryArguments[a])this.obligatoryArguments[a].hasOwnProperty(c)&&(b[c]=this.obligatoryArguments[a][c]);
a["function"]+"' function. There is no '"+d+"' argument in #"+e+" function results");b[f]=this.functionsResults[e-1][d]}return b};MibewAPIExecutionContext.prototype.getResults=function(){return this.returnValues}; return b};function MibewAPIWindowToCoreInteraction(){this.obligatoryArguments={"*":{"return":{},references:{}}};this.reservedFunctionNames=["result"]}MibewAPIWindowToCoreInteraction.prototype=new MibewAPIInteraction;function MibewAPIExecutionContext(){this.returnValues={};this.functionsResults=[]}
MibewAPIExecutionContext.prototype.getArgumentsList=function(a){var b=a.arguments,c=a.arguments.references,d,f,e;for(e in c)if(c.hasOwnProperty(e)){f=c[e];if("undefined"==typeof this.functionsResults[f-1])throw Error("Wrong reference in '"+a["function"]+"' function. Function #"+f+" does not call yet.");if("undefined"==typeof b[e]||""==b[e])throw Error("Wrong reference in '"+a["function"]+"' function. Empty '"+e+"' argument.");d=b[e];if("undefined"==typeof this.functionsResults[f-1][d])throw Error("Wrong reference in '"+
a["function"]+"' function. There is no '"+d+"' argument in #"+f+" function results");b[e]=this.functionsResults[f-1][d]}return b};MibewAPIExecutionContext.prototype.getResults=function(){return this.returnValues};
MibewAPIExecutionContext.prototype.storeFunctionResults=function(a,b){var c,d;for(d in a.arguments["return"])if(a.arguments["return"].hasOwnProperty(d)){c=a.arguments["return"][d];if("undefined"==typeof b[d])throw Error("Variable with name '"+d+"' is undefined in the results of the '"+a["function"]+"' function");this.returnValues[c]=b[d]}this.functionsResults.push(b)}; MibewAPIExecutionContext.prototype.storeFunctionResults=function(a,b){var c,d;for(d in a.arguments["return"])if(a.arguments["return"].hasOwnProperty(d)){c=a.arguments["return"][d];if("undefined"==typeof b[d])throw Error("Variable with name '"+d+"' is undefined in the results of the '"+a["function"]+"' function");this.returnValues[c]=b[d]}this.functionsResults.push(b)};

View File

@ -12,7 +12,6 @@
* @constructor * @constructor
* @param {MibewAPIInteraction} interaction An object that represents * @param {MibewAPIInteraction} interaction An object that represents
* interaction type * interaction type
* @todo Think about error code
*/ */
function MibewAPI(interaction) { function MibewAPI(interaction) {
@ -73,17 +72,19 @@ MibewAPI.prototype.checkFunction = function(functionObject, filterReservedFuncti
); );
} }
var obligatoryArgumentsCount = 0; var obligatoryArgumentsCount = 0;
var obligatoryArgumentsList = this.interaction.getObligatoryArguments(
functionObject['function']
);
argumentsLoop: argumentsLoop:
for (var argName in functionObject.arguments){ for (var argName in functionObject.arguments){
for (var i = 0; i < this.interaction.obligatoryArguments.length; i++) { for (var i = 0; i < obligatoryArgumentsList.length; i++) {
if (argName == this.interaction.obligatoryArguments[i]) { if (argName == obligatoryArgumentsList[i]) {
obligatoryArgumentsCount++; obligatoryArgumentsCount++;
continue argumentsLoop; continue argumentsLoop;
} }
} }
} }
if (obligatoryArgumentsCount != if (obligatoryArgumentsCount != obligatoryArgumentsList.length) {
this.interaction.obligatoryArguments.length) {
throw new Error( throw new Error(
"Not all obligatory arguments are set in '" + "Not all obligatory arguments are set in '" +
functionObject["function"] + "' function" functionObject["function"] + "' function"
@ -222,7 +223,7 @@ MibewAPI.prototype.getResultFunction = function(functionsList, existance){
*/ */
MibewAPI.prototype.buildResult = function(resultArguments, token) { MibewAPI.prototype.buildResult = function(resultArguments, token) {
var mergedArguments = resultArguments; var mergedArguments = resultArguments;
var defaultArguments = this.interaction.getDefaultObligatoryArguments(); var defaultArguments = this.interaction.getDefaultObligatoryArguments('result');
for (var argName in defaultArguments) { for (var argName in defaultArguments) {
if (! defaultArguments.hasOwnProperty(argName)) { if (! defaultArguments.hasOwnProperty(argName)) {
continue; continue;
@ -282,23 +283,103 @@ MibewAPI.prototype.decodePackage = function(encodedPackage){
*/ */
function MibewAPIInteraction(){ function MibewAPIInteraction(){
/** /**
* Abligatory arguments in called functions * Defines obligatory arguments and default values for them
*
* Keys of the array are function names ('*' for all functions). Values are
* arrays of obligatory arguments with key for name of an argument and value
* for default value.
*
* For example:
* <code>
* this.obligatoryArguments = {
* '*': {
* 'return': {},
* 'references': {}
* },
* 'result': {
* 'errorCode': 0
* }
* }
* </code>
* @type Object
* @private
*/
this.obligatoryArguments = {};
/**
* Reserved function's names
*
* Defines reserved(system) function's names described in the Mibew API.
* @type Array
*/ */
this.reservedFunctionNames = []; this.reservedFunctionNames = [];
}
/** /**
* Reserved function names * Returns obligatory arguments for the functionName function
*/
this.obligatoryArguments = [];
/**
* Returns default values of obligatory arguments
* *
* @param {String} functionName Function name
* @returns {Array} An array of obligatory arguments
*/
MibewAPIInteraction.prototype.getObligatoryArguments = function(functionName) {
var obligatoryArguments = [];
// Add obligatory for all functions arguments
if (typeof this.obligatoryArguments['*'] == 'object' &&
this.obligatoryArguments['*'] instanceof Array) {
for (var arg in this.obligatoryArguments['*']) {
if (! this.obligatoryArguments['*'].hasOwnProperty(arg)) {
continue;
}
obligatoryArguments.push(arg);
}
}
// Add obligatory arguments for given function
if (typeof this.obligatoryArguments[functionName] == 'object' &&
this.obligatoryArguments[functionName] instanceof Array) {
for (var arg in this.obligatoryArguments[functionName]) {
if (! this.obligatoryArguments[functionName].hasOwnProperty(arg)) {
continue;
}
obligatoryArguments.push(arg);
}
}
return obligatoryArguments;
}
/**
* Returns default values of obligatory arguments for the functionName function
*
* @param {String} functionName Function name
* @returns {Object} An object fields names are obligatory arguments and * @returns {Object} An object fields names are obligatory arguments and
* values are default values of them * values are default values of them
*/ */
this.getDefaultObligatoryArguments = function(){ MibewAPIInteraction.prototype.getDefaultObligatoryArguments = function(functionName) {
return {} var obligatoryArguments = [];
// Add obligatory for all functions arguments
if (typeof this.obligatoryArguments['*'] == 'object' &&
this.obligatoryArguments['*'] instanceof Array) {
for (var arg in this.obligatoryArguments['*']) {
if (! this.obligatoryArguments['*'].hasOwnProperty(arg)) {
continue;
}
obligatoryArguments[arg] = this.obligatoryArguments['*'][arg];
} }
} }
// Add obligatory arguments for given function
if (typeof this.obligatoryArguments[functionName] == 'object' &&
this.obligatoryArguments[functionName] instanceof Array) {
for (var arg in this.obligatoryArguments[functionName]) {
if (! this.obligatoryArguments[functionName].hasOwnProperty(arg)) {
continue;
}
obligatoryArguments[arg] = this.obligatoryArguments[functionName][arg];
}
}
return obligatoryArguments;
}
/**
* End of MibewAPIInteraction class
*/
/** /**
* Represents Window to core interaction type * Represents Window to core interaction type
@ -307,21 +388,16 @@ function MibewAPIInteraction(){
* @todo Think about real values! * @todo Think about real values!
*/ */
function MibewAPIWindowToCoreInteraction() { function MibewAPIWindowToCoreInteraction() {
this.obligatoryArguments = {
'*': {
'return': {},
'references': {}
}
};
this.reservedFunctionNames = [ this.reservedFunctionNames = [
'result' 'result'
]; ];
this.obligatoryArguments = [
'return',
'references'
];
this.getDefaultObligatoryArguments = function(){
return {
"return" : {},
"references" : {}
}
}
} }
MibewAPIWindowToCoreInteraction.prototype = new MibewAPIInteraction(); MibewAPIWindowToCoreInteraction.prototype = new MibewAPIInteraction();

View File

@ -201,7 +201,7 @@ Class MibewAPI {
); );
} }
$unset_arguments = array_diff( $unset_arguments = array_diff(
$this->interaction->obligatoryArguments, $this->interaction->getObligatoryArguments($function['function']),
array_keys($function['arguments']) array_keys($function['arguments'])
); );
if (! empty($unset_arguments)) { if (! empty($unset_arguments)) {
@ -273,7 +273,7 @@ Class MibewAPI {
* @return array Result package * @return array Result package
*/ */
public function buildResult($token, $result_arguments) { public function buildResult($token, $result_arguments) {
$arguments = $result_arguments + $this->interaction->getDefaultObligatoryArguments(); $arguments = $result_arguments + $this->interaction->getDefaultObligatoryArguments('result');
$package = array( $package = array(
'token' => $token, 'token' => $token,
'functions' => array( 'functions' => array(
@ -438,44 +438,130 @@ Class MibewAPIExecutionContext {
*/ */
abstract class MibewAPIInteraction { abstract class MibewAPIInteraction {
/** /**
* Abligatory arguments in called functions * Defines obligatory arguments and default values for them
* @var array *
* @var array Keys of the array are function names ('*' for all functions). Values are arrays of obligatory
* arguments with key for name of an argument and value for default value.
*
* For example:
* <code>
* protected $obligatoryArguments = array(
* '*' => array( // Obligatory arguments for all functions are
* 'return' => array(), // 'return' with array() by default and
* 'references' => array() // 'references' with array() by default
* ),
* 'result' => array( // There is an additional argument for the result function
* 'errorCode' => 0 // This is 'error_code' with 0 by default
* )
* );
* </code>
*/ */
public $obligatoryArguments; protected $obligatoryArguments = array();
/**
* Reserved function names
* @var array
*/
public $reservedFunctionNames;
/** /**
* Returns default values of obligatory arguments * Reserved function's names
* *
* Defines reserved(system) function's names described in the Mibew API.
* @var array
*/
public $reservedFunctionNames = array();
/**
* Returns obligatory arguments for the $function_name function
*
* @param string $function_name Function name
* @return array An array of obligatory arguments
*/
public function getObligatoryArguments($function_name) {
$obligatory_arguments = array();
// Add obligatory for all functions arguments
if (! empty($this->obligatoryArguments['*'])) {
$obligatory_arguments = array_merge(
$obligatory_arguments,
array_keys($this->obligatoryArguments['*'])
);
}
// Add obligatory arguments for given function
if (! empty($this->obligatoryArguments[$function_name])) {
$obligatory_arguments = array_merge(
$obligatory_arguments,
array_keys($this->obligatoryArguments[$function_name])
);
}
return array_unique($obligatory_arguments);
}
/**
* Returns default values of obligatory arguments for the $function_name function
*
* @param string $function_name Function name
* @return array Associative array with keys are obligatory arguments and values are default * @return array Associative array with keys are obligatory arguments and values are default
* values of them * values of them
*/ */
abstract public function getDefaultObligatoryArguments(); public function getDefaultObligatoryArguments($function_name) {
$obligatory_arguments = array();
// Add obligatory for all functions arguments
if (! empty($this->obligatoryArguments['*'])) {
$obligatory_arguments = array_merge($obligatory_arguments, $this->obligatoryArguments['*']);
}
// Add obligatory arguments for given function
if (! empty($this->obligatoryArguments[$function_name])) {
$obligatory_arguments = array_merge($obligatory_arguments, $this->obligatoryArguments[$function_name]);
}
return $obligatory_arguments;
}
} }
/** /**
* Implements Base Mibew Interaction * Implements Base Mibew Interaction
*/ */
class MibewAPIBaseInteraction extends MibewAPIInteraction { class MibewAPIBaseInteraction extends MibewAPIInteraction {
public $obligatoryArguments = array( /**
'references', * Defines obligatory arguments and default values for them
'return' * @var array
* @see MibewAPIInteraction::$obligatoryArgumnents
*/
protected $obligatoryArguments = array(
'*' => array(
'references' => array(),
'return' => array()
)
); );
/**
* Reserved function's names
* @var array
* @see MibewAPIInteraction::$reservedFunctionNames
*/
public $reservedFunctionNames = array( public $reservedFunctionNames = array(
'result' 'result'
); );
}
public function getDefaultObligatoryArguments() { /**
return array( * Implements Mibew Core - Mibew Chat Window interaction
*/
class MibewAPIWindowInteraction extends MibewAPIInteraction {
/**
* Defines obligatory arguments and default values for them
* @var array
* @see MibewAPIInteraction::$obligatoryArgumnents
*/
protected $obligatoryArguments = array(
'*' => array(
'references' => array(), 'references' => array(),
'return' => array() 'return' => array()
)
);
/**
* Reserved function's names
* @var array
* @see MibewAPIInteraction::$reservedFunctionNames
*/
public $reservedFunctionNames = array(
'result'
); );
}
} }
/** /**