blob: 3fad8a706bd254fc6c6877e80e13ebe812e9b5e2 [file] [log] [blame]
#// Copyright (c) 2000-2019 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 module containing the implementation of DsRestAPI'''
import json, re, logging
class DsRestAPI:
'''The implementation of DsRestAPI'''
def __init__(self, getDataHandler, setDataHandler):
self._logger = logging.getLogger(__name__)
self._getDataHandler = getDataHandler
self._setDataHandler = setDataHandler
def _fillFilterFilterParam(self, filter, value, index):
return json.loads(json.dumps(filter).replace('%FilterParent' + str(index) + '%', value))
def _fillFilterParams(self, filter, parents):
parameterizedFilter = json.dumps(filter)
for i in range(len(parents)):
parameterizedFilter = parameterizedFilter.replace('%Parent' + str(i) + '%', parents[i])
return json.loads(parameterizedFilter)
def _filterWalk(self, filter, depth, userCredentials):
if 'dataValue' in filter:
return filter['dataValue']
else:
if 'params' in filter['request']:
for param in filter['request']['params']:
param['paramValue'] = self._filterWalk(param['paramValue'], depth + 1, userCredentials)
else:
filter['request']['params'] = []
response = self._getDataHandler(filter['request'], userCredentials)
if response is None:
return 'false'
elif 'node' in response:
returnValue = response['node']['val']
if 'remapTo' in filter['request']:
returnValue = self._filterWalk(self._fillFilterFilterParam(filter['request']['remapTo'], returnValue, depth), depth + 1, userCredentials)
return returnValue
else:
returnValue = [element['node']['val'] for element in response['list']]
if 'remapTo' in filter['request']:
for i in range(len(returnValue)):
returnValue[i] = self._filterWalk(self._fillFilterFilterParam(filter['request']['remapTo'], returnValue[i], depth), depth + 1, userCredentials)
return json.dumps(returnValue)
def evaluateFilter(self, filter, parents, userCredentials):
try:
return 'true' == self._filterWalk(self._fillFilterParams(filter, parents), 0, userCredentials)
except:
self._logger.exception('Error during filtering')
return False
def _isFilterAllowed(self, filter, parents):
for match in re.finditer(r'%Parent(\d+)%', json.dumps(filter)):
if match is not None:
if int(match.group(1)) >= len(parents):
return False
return True
def _fillGetDataParams(self, parameterizedGetData, originalGetData, parents):
parameterizedGetData['source'] = originalGetData['source']
parameterizedGetData['element'] = originalGetData['element']
if 'ptcname' in originalGetData:
parameterizedGetData['ptcname'] = originalGetData['ptcname']
if 'params' in originalGetData:
parameterizedGetData['params'] = [
{
'paramName': param['paramName'],
'paramValue': param['paramValue']
} for param in originalGetData['params']
]
else:
parameterizedGetData['params'] = []
if 'rangeFilter' in originalGetData:
# this is not modified, so we do not copy it
parameterizedGetData['rangeFilter'] = originalGetData['rangeFilter']
if 'timeline' in originalGetData:
# this is not modified, so we do not copy it
parameterizedGetData['timeline'] = originalGetData['timeline']
if 'filter' in originalGetData:
# Filter will copy it when filling it the parameters, so we don't have to
parameterizedGetData['filter'] = originalGetData['filter']
for i in range(len(parents)):
pattern = '%Parent' + str(i) + '%'
parameterizedGetData['source'] = parameterizedGetData['source'].replace(pattern, parents[i])
parameterizedGetData['element'] = parameterizedGetData['element'].replace(pattern, parents[i])
if 'ptcname' in parameterizedGetData:
parameterizedGetData['ptcname'] = parameterizedGetData['ptcname'].replace(pattern, parents[i])
for param in parameterizedGetData['params']:
param['paramName'] = param['paramName'].replace(pattern, parents[i])
param['paramValue'] = param['paramValue'].replace(pattern, parents[i])
def _fillSetDataParams(self, parameterizedSetData, originalSetData, parents):
self._fillGetDataParams(parameterizedSetData, originalSetData, parents)
if 'content' in originalSetData:
parameterizedSetData['content'] = originalSetData['content']
else:
parameterizedSetData['content'] = ''
if 'tp' in originalSetData:
parameterizedSetData['tp'] = originalSetData['tp']
else:
parameterizedSetData['tp'] = 0
if 'indxsInList' in originalSetData:
parameterizedSetData['indxsInList'] = originalSetData['indxsInList']
else:
parameterizedSetData['indxsInList'] = []
for i in range(len(parents)):
pattern = '%Parent' + str(i) + '%'
parameterizedSetData['content'] = parameterizedSetData['content'].replace(pattern, parents[i])
def _handleChildRequests(self, response, getData, parents, userCredentials):
if 'node' in response:
parents.append(response['node']['val'])
response['node']['childVals'] = []
self._parseRequestList(response['node']['childVals'], getData['children'], parents, userCredentials)
parents.pop()
def _handleGetData(self, responseList, getData, parents, userCredentials):
parameterizedGetData = {}
self._fillGetDataParams(parameterizedGetData, getData, parents)
prefilter = 'filter' in getData and self._isFilterAllowed(getData['filter'], parents)
if prefilter and not self.evaluateFilter(getData['filter'], parents, userCredentials):
responseList.append({'node': {'val': '', 'tp': 0}})
return
response = self._getDataHandler(parameterizedGetData, userCredentials)
if response is not None:
if 'filter' in getData and not prefilter:
if 'node' in response:
parents.append(response['node']['val'])
if self._isFilterAllowed(getData['filter'], parents) and not self.evaluateFilter(getData['filter'], parents, userCredentials):
responseList.append({'node': {'val': '', 'tp': 0}})
parents.pop()
return
else:
parents.pop()
if 'list' in response:
i = 0
while i < len(response['list']):
parents.append(response['list'][i]['node']['val'])
if self._isFilterAllowed(getData['filter'], parents) and not self.evaluateFilter(getData['filter'], parents, userCredentials):
response['list'].pop(i)
else:
i += 1
parents.pop()
if 'rangeFilter' in getData and 'list' in response:
response['list'] = response['list'][max(0, getData['rangeFilter']['offset']) : min(len(response['list']), getData['rangeFilter']['offset'] + getData['rangeFilter']['count'])]
responseList.append(response)
if 'children' in getData and len(getData['children']) > 0:
if 'list' in response:
if 'selection' in getData:
for index in getData['selection']:
if index < len(response['list']):
self._handleChildRequests(response['list'][index], getData, parents, userCredentials)
else:
for element in response['list']:
self._handleChildRequests(element, getData, parents, userCredentials)
else:
self._handleChildRequests(response, getData, parents, userCredentials)
else:
responseList.append({'node': {'val': 'Failed to handle request: ' + parameterizedGetData['source'] + ' ' + parameterizedGetData['element'] + ' ' + str(parameterizedGetData['params']), 'tp': -4}})
def _handleSetData(self, responseList, setData, parents, userCredentials):
parameterizedSetData = {}
self._fillSetDataParams(parameterizedSetData, setData, parents)
response = self._setDataHandler(parameterizedSetData, userCredentials)
if response is not None:
responseList.append(response)
else:
responseList.append({'node': {'val': 'Failed to handle request: ' + parameterizedSetData['source'] + ' ' + parameterizedSetData['element'] + ' ' + str(parameterizedSetData['params']), 'tp': -4}})
def _parseRequestList(self, responseList, requestList, parents, userCredentials):
for request in requestList:
if 'getData' in request:
self._handleGetData(responseList, request['getData'], parents, userCredentials)
elif 'setData' in request:
self._handleSetData(responseList, request['setData'], parents, userCredentials)
def parseRequest(self, request, userCredentials):
parents = []
response = {'contentList': []}
try:
self._parseRequestList(response['contentList'], request['requests'], parents, userCredentials)
except Exception as e:
self._logger.exception('Error handling DsRestAPI request')
response = {'contentList': [{'node': {'val': 'Failed to handle request: ' + str(e), 'tp': 4}}]}
return response