blob: 6511a7e9bca71036255d0c2484cb96e3cab76716 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2017 Ericsson Telecom AB //
// //
// All rights reserved. This program and the accompanying materials //
// are made available under the terms of the Eclipse Public License v2.0 //
// which accompanies this distribution, and is available at //
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html //
///////////////////////////////////////////////////////////////////////////////
/**
The function we mock.
*/
function CDsRestAPIComm(p_extension, p_model) {
"use strict";
////////////////////////// MOCK OF DS CALLS //////////////////////////
var model;
if (p_model != undefined) {
model = p_model;
} else {
model = new Model(new DataGenerator());
}
var schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"filter": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"dataValue": {
"type": "string"
}
}
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"request": {
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string"
},
"ptcname": {
"type": "string"
},
"element": {
"type": "string"
},
"params": {
"$ref": "#/definitions/filterParams"
}
}
}
}
}
]
},
"filterParams": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"paramName": {
"type": "string"
},
"paramValue": {
"$ref": "#/definitions/filter"
}
}
}
},
"params": {
"type": "array",
"items": {
"title": "params",
"description": "params",
"type" : "object",
"additionalProperties": false,
"properties": {
"paramName": {
"type": "string"
},
"paramValue": {
"type": "string"
}
},
"required": [
"paramName",
"paramValue"
]
}
},
"getDataRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
"getData": {
"title": "getDataFieldsDef",
"description": "getDataFieldsDef",
"type": "object",
"additionalProperties": false,
"properties": {
"source": {
"type": "string"
},
"ptcname": {
"type": "string"
},
"element": {
"type": "string"
},
"params": {
"$ref": "#/definitions/params"
},
"cookie": {
"type": "string"
},
"children": {
"type": "array",
"items": {
"$ref": "#/definitions/getDataRequest"
}
},
"filter": {
"$ref": "#/definitions/filter"
},
"rangeFilter": {
"type": "object",
"properties": {
"offset": {
"type": "integer",
"minimum": 0
},
"count": {
"type": "integer",
"minimum": 0
}
},
"additionalProperties": false
},
"selection": {
"type": "array",
"items": {
"type": "integer"
}
},
"selectionValues": {
"type": "array",
"items": {
"type": "string"
}
},
"writableInfo": {
"type": "boolean"
},
"timeline": {
"type": "object",
"additionalProperties": false,
"properties": {
"period": {
"type": "number",
"minimum": 0
},
"maxpoints": {
"type": "integer",
"minimum": 0
},
"since": {
"type": "integer",
"minimum": 0
}
}
}
},
"required": [
"source",
"element"
]
}
}
},
"setDataRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
"setData": {
"type": "object",
"properties": {
"source": {
"type": "string"
},
"ptcname": {
"type": "string"
},
"element": {
"type": "string"
},
"content": {
"type": "string"
},
"tp": {
"type": "integer"
},
"indxsInList": {
"type": "array",
"items": {
"type": "integer"
}
},
"params": {
"$ref": "#/definitions/params"
}
},
"required": [
"source",
"element",
"content",
"tp"
]
}
}
}
},
"type": "object",
"additionalProperties": true,
"properties": {
"requests": {
"type": "array",
"items": {
"anyOf": [
{
"$ref": "#/definitions/getDataRequest"
},
{
"$ref": "#/definitions/setDataRequest"
}
]
}
}
}
};
var ajv = new Ajv({
allErrors : true,
format : "full",
verbose : true,
inlineRefs : false
});
var validate = ajv.compile(schema);
this.ajaxCall = function (request, callback) {
var v_requestObj = request;
var isRequestValid = validate(v_requestObj);
var answer;
if (isRequestValid) {
answer = parseRequest(v_requestObj).contentList;
} else {
console.log("AJV validate says, the request is invalid per DsRestAPI DSServer JSON API!");
console.log("AJV says, these are the errors:", validate.errors);
console.log("The invalid request:", JSON.stringify(request, null, 4));
answer = [
{
"node" : {
"val" : "Error processing request, Reason: While JSON-decoding type '@EPTF_CLL_DsRestAPI_DSServer_Definitions.EPTF_DsRestAPI_RqWrapper': Invalid field name 'XY'",
"tp" : 4
}
}
];
}
callback(answer);
};
/**
This method obtains or sets the data from the outside source.
@param data: a getData or a setData object
@param parents: the parents of the current node
@returns the content belonging to the current node obtained from an outside source
*/
function getContent(data, parents) {
var content;
if (data.content) {
content = model.setContent(data);
} else {
content = model.getContent(data, parents);
}
// we create a copy of the answer since we may have to modify it
content = mcopy(content);
return content;
}
/**
This method creates the tree using a recursive DFS algorithm. For more details, see the comments below.
@param data: either a getData or a setData object
@param contentList: the list that will contain the children of the parent
@param parents: the parent list of the current node of the tree
*/
function expand(data, contentList, parents) {
// data can be undefined if the request is wrong, in this case, we return the already constructed list
// TODO the real server returns an empty content list as the complete answer even if a single child request is invalid somewhere
if (data == undefined) {
return;
}
// we obtain the content that belongs to this node
// this is an object that either contains a single "node" object or a "list" of node objects
var content = getContent(data, parents);
// we add the content to the output
contentList.push(content);
// a tricky part that keeps the code shorter
// we create an empty list
// if the content we got is a list of nodes, then this list will be the same
// else we got a single node that we now add to the empty list
// the point is, we can iterate over this list and do not have to check multiple conditions and there will be no code duplication
var list = [];
if (content.list == undefined) {
list.push(content);
} else {
list = content.list;
}
if (data.children != undefined && data.children.length > 0) {
var ListLength = list.length;
for (var i = 0; i < ListLength; ++i) {
// NOTE: originally the second part of the condition was "i in data.selection", which does not work with arrays...
if (data.selection == undefined || data.selection.indexOf(i) != -1) {
// here we create an empty list of children for the current node
var node = list[i].node;
node.childVals = [];
// we add the node to the parent list, which we use as a simple stack
parents.push(node);
var childrenLength = data.children.length;
for (var j = 0; j < childrenLength; ++j) {
// we expand the children of the currently examined node recursively
expand(getGetData(data.children[j]), node.childVals, parents);
}
// we remove the current node from the parents list, since we have now finished examined all its children
parents.pop();
}
}
}
}
/**
This method parses the request and returns the answer.
The result is obtained by a simple DFS algorithm.
@param request: The request
@returns the answer to the request that is accepted by the GUI
*/
function parseRequest(request) {
var answer = {
contentList : []
};
var requestsLength = request.requests.length;
for (var i = 0; i < requestsLength; ++i) {
var data = getGetData(request.requests[i]);
// if there is no getData or setData, return
if (data == undefined) {
return answer;
}
// ---------- setData and tp checking ----------
var isSetData = !!(request.requests[i].setData);
var isTpMatch = false;
var TpMatchErrorMsg = ">> TODO This error message is not set properly in DsRestAPIComm_Mock! It should be set according to the datatype conversion failure. <<";
if (isSetData) {
// Check if tp matches the content's implicit type
switch (data.tp) {
case 1:
isTpMatch = /^(\-|\+)?([0-9]+)$/.test(data.content);
if (!isTpMatch)
TpMatchErrorMsg = "Cannot convert content: " + data.content + " to tp: " + data.tp + ", Reason: The argument of function str2int(), which is \"" + data.content + "\", does not represent a valid int value. Invalid character `" + data.content[0] + "' was found at index 0.";
break; // int
case 2:
isTpMatch = /^(\-|\+)?([0-9]+(\.[0-9]+)?)$/.test(data.content);
if (!isTpMatch)
TpMatchErrorMsg = "Cannot convert content: " + data.content + " to tp: " + data.tp + ", Reason: The argument of function str2float(), which is \"" + data.content + "\", does not represent a valid float value. Invalid character `" + data.content[0] + "' was found at index 0.";
break; // float
case 3:
isTpMatch = /^(true|false)$/.test(data.content);
break; // boolean
case 4:
isTpMatch = true;
break; // charstring
case 5: // octetstring
case 6:
isTpMatch = /^([0-9a-fA-F]{2})*$/.test(data.content);
break; // hexstring
case 7:
isTpMatch = /^[0-1]*$/.test(data.content);
break; // bitstring
case 8: // integer[]
case 9: // float[]
case 10:
isTpMatch = /^\[.*\]$/.test(data.content);
break; // charstring[] -- we only check if it is a list, not the inner type.
case 11:
isTpMatch = /^\[led:\w+\]/.test(data.content);
break; // LED
default:
TpMatchErrorMsg = "Invalid tp: " + data.tp;
// error - invalid tp#
}
}
// the help needs to be returned in a special way
if (data.element === "help" && data.params != undefined && data.params.length === 1) {
if (!isTpMatch && isSetData) {
// request tp does not match request content's datatype
answer.contentList.push({
"node" : {
"val" : a2hex(TpMatchErrorMsg),
"tp" : 4
}
});
} else if (isSetData) {
// Nothing is writable in the help section.
answer.contentList.push({
"node" : {
"val" : a2hex("Value cannot be changed"),
"tp" : 4
}
});
// ---------- end of setData and tp checking ----------
} else {
var helpstr = JSON.stringify(DSHelp, null, 4);
var hex = a2hex(helpstr);
answer.contentList.push({
"node" : {
"val" : hex,
"tp" : 10
}
});
}
} else {
var parents = [];
expand(data, answer.contentList, parents);
}
}
return answer;
}
/**
@param obj An object
@returns getData or setData from the object if one of them exists, or null if they do not
*/
function getGetData(obj) {
if (obj.getData != undefined) {
return obj.getData;
} else if (obj.setData != undefined) {
return obj.setData;
} else if (obj.listOfGetData != undefined) {
return obj.listOfGetData;
} else {
mlog("Request has neither getData, nor setData element...");
return undefined;
}
}
this.getSchema = function () {
return mcopy(schema);
};
}