Update error handling; update selector; change delete response code to 200
[pti/o2.git] / o2common / views / view.py
1 # Copyright (C) 2021-2022 Wind River Systems, Inc.
2 #
3 #  Licensed under the Apache License, Version 2.0 (the "License");
4 #  you may not use this file except in compliance with the License.
5 #  You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 #  Unless required by applicable law or agreed to in writing, software
10 #  distributed under the License is distributed on an "AS IS" BASIS,
11 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #  See the License for the specific language governing permissions and
13 #  limitations under the License.
14
15 from sqlalchemy.sql.elements import ColumnElement
16 from sqlalchemy import or_
17
18 from o2common.views.route_exception import BadRequestException
19
20 from o2common.helper import o2logging
21 logger = o2logging.get_logger(__name__)
22
23
24 def gen_filter(obj: ColumnElement, filter_str: str):
25     if filter_str == '':
26         return []
27     filter_without_space = filter_str.replace(" ", "")
28     items = filter_without_space.split(';')
29
30     filter_list = list()
31     for i in items:
32         if '(' in i:
33             i = i.replace("(", "")
34         if ')' in i:
35             i = i.replace(")", "")
36         filter_expr = i.split(',')
37         if len(filter_expr) < 3:
38             continue
39         filter_op = filter_expr[0]
40         filter_key = filter_expr[1]
41         filter_vals = filter_expr[2:]
42         filter_list.extend(toFilterArgs(
43             filter_op, obj, filter_key, filter_vals))
44     logger.info('Filter list length: %d' % len(filter_list))
45     return filter_list
46
47
48 def toFilterArgs(operation: str, obj: ColumnElement, key: str, values: list):
49     if not hasattr(obj, key):
50         logger.warning('Filter attrName %s not in Object %s.' %
51                        (key, str(obj)))
52         raise BadRequestException(
53             'Filter attrName {} not in the Object'.format(key))
54
55     if operation in ['eq', 'neq', 'gt', 'lt', 'gte', 'lte']:
56         if len(values) != 1:
57             raise KeyError('Filter operation one is only support one value.')
58     elif operation in ['in', 'nin', 'cont', 'ncont']:
59         if len(values) == 0:
60             raise KeyError('Filter operation value is needed.')
61     else:
62         raise KeyError('Filter operation value not support.')
63
64     ll = list()
65     if operation == 'eq':
66         val = values[0]
67         if val.lower() == 'null':
68             val = None
69         ll.append(getattr(obj, key) == val)
70     elif operation == 'neq':
71         val = values[0]
72         if val.lower() == 'null':
73             val = None
74         ll.append(getattr(obj, key) != val)
75     elif operation == 'gt':
76         val = values[0]
77         ll.append(getattr(obj, key) > val)
78     elif operation == 'lt':
79         val = values[0]
80         ll.append(getattr(obj, key) < val)
81     elif operation == 'gte':
82         val = values[0]
83         ll.append(getattr(obj, key) >= val)
84     elif operation == 'lte':
85         val = values[0]
86         ll.append(getattr(obj, key) <= val)
87     elif operation == 'in':
88         ll.append(getattr(obj, key).in_(values))
89     elif operation == 'nin':
90         ll.append(~getattr(obj, key).in_(values))
91     elif operation == 'cont':
92         val_list = list()
93         for val in values:
94             val_list.append(getattr(obj, key).contains(val))
95         ll.append(or_(*val_list))
96     elif operation == 'ncont':
97         val_list = list()
98         for val in values:
99             val_list.append(getattr(obj, key).contains(val))
100         ll.append(~or_(*val_list))
101     return ll