Auto-generated patch by python-black
[integration/test.git] / csit / libraries / IoTDM / client_libs / onem2m_primitive.py
1 """
2  Definition of IoT data concepts specific to OneM2M
3 """
4
5 #
6 # Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
7 #
8 # This program and the accompanying materials are made available under the
9 # terms of the Eclipse Public License v1.0 which accompanies this distribution,
10 # and is available at http://www.eclipse.org/legal/epl-v10.html
11 #
12
13 from iot_data_concepts import IoTData
14 from iot_data_concepts import IoTDataBuilder
15 from iot_data_concepts import IoTDataEncoder
16 from iot_data_concepts import IoTDataDecoder
17 from iot_data_concepts import IoTDataEncodeError
18 from iot_data_concepts import IoTDataDecodeError
19
20
21 class OneM2MPrimitiveDefinitions:
22     """OneM2M constants and definitions"""
23
24     # Operations
25     operation_create = 1
26     operation_retrieve = 2
27     operation_update = 3
28     operation_delete = 4
29     operation_notify = 5
30
31     operation_valid_values = [
32         operation_create,
33         operation_retrieve,
34         operation_update,
35         operation_delete,
36         operation_notify,
37     ]
38
39     # Long naming schema definitions
40     long_primitive_content = "primitiveContent"
41
42     # Short naming schema definitions
43     short_operation = "op"
44     short_to = "to"
45     short_from = "fr"
46     short_request_identifier = "rqi"
47     short_resource_type = "ty"
48     short_primitive_content = "pc"
49     short_role_ids = "rids"
50     short_originating_timestamp = "ot"
51     short_request_expiration_timestamp = "rset"
52     short_operation_execution_time = "oet"
53     short_response_type = "rt"
54     short_result_persistence = "rp"
55     short_result_content = "rcn"
56     short_event_category = "ec"
57     short_delivery_aggregation = "da"
58     short_group_request_identifier = "gid"
59     short_filter_criteria = "fc"
60     short_discovery_result_type = "drt"
61     short_response_status_code = "rsc"
62     short_tokens = "ts"
63     short_token_ids = "tids"
64     short_token_request_indicator = "tqi"
65     short_local_token_ids = "ltids"
66     short_assigned_token_identifiers = "ati"
67     short_token_request_information = "tqf"
68     short_content_status = "cnst"
69     short_content_offset = "cnot"
70
71     # OneM2M result codes
72     result_code_accepted = 1000
73
74     result_code_ok = 2000
75     result_code_created = 2001
76     result_code_deleted = 2002
77     result_code_updated = 2004
78
79     result_code_bad_request = 4000
80     result_code_not_found = 4004
81     result_code_operation_not_allowed = 4005
82     result_code_request_timeout = 4008
83     result_code_subscription_creator_has_no_privilege = 4101
84     result_code_contents_unacceptable = 4102
85     result_code_originator_has_no_privilege = 4103
86     result_code_group_request_identifier_exists = 4104
87     result_code_conflict = 4105
88     result_code_originator_has_not_registered = 4106
89     result_code_security_association_required = 4107
90     result_code_invalid_child_resource_type = 4108
91     result_code_no_members = 4109
92     result_code_group_member_type_inconsistent = 4110
93     result_code_esprim_unsupported_option = 4111
94     result_code_esprim_unknown_key_id = 4112
95     result_code_esprim_unknown_orig_rand_id = 4113
96     result_code_esprim_unknown_recv_rand_id = 4114
97     result_code_esprim_bad_mac = 4115
98
99     result_code_internal_server_error = 5000
100     result_code_not_implemened = 5001
101     result_code_target_not_reachable = 5103
102     result_code_receiver_has_no_privilege = 5105
103     result_code_already_exists = 5106
104     result_code_target_not_subscribable = 5203
105     result_code_subscription_verification_initiation_failed = 5204
106     result_code_subscription_host_has_no_privilege = 5205
107     result_code_non_blocking_request_not_supported = 5206
108     result_code_not_acceptable = 5207
109     result_code_discovery_denied_by_ipe = 5208
110     result_code_group_members_not_responded = 5209
111     result_code_esprim_decryption_error = 5210
112     result_code_esprim_encryption_error = 5211
113     result_code_sparql_update_error = 5212
114
115     result_code_external_object_not_reachable = 6003
116     result_code_external_object_not_found = 6005
117     result_code_max_number_of_member_exceeded = 6010
118     result_code_member_type_inconsistent = 6011
119     result_code_mgmt_session_cannot_be_established = 6020
120     result_code_mgmt_session_establishment_timeout = 6021
121     result_code_invalid_cmd_type = 6022
122     result_code_invalid_arguments = 6023
123     result_code_insufficient_argument = 6024
124     result_code_mgmt_conversion_error = 6025
125     result_code_mgmt_cancellation_failed = 6026
126     result_code_already_complete = 6028
127     result_code_mgmt_command_not_cancellable = 6029
128
129     supported_result_codes = [
130         result_code_accepted,
131         result_code_ok,
132         result_code_created,
133         result_code_deleted,
134         result_code_updated,
135         result_code_bad_request,
136         result_code_not_found,
137         result_code_operation_not_allowed,
138         result_code_request_timeout,
139         result_code_subscription_creator_has_no_privilege,
140         result_code_contents_unacceptable,
141         result_code_originator_has_no_privilege,
142         result_code_group_request_identifier_exists,
143         result_code_conflict,
144         result_code_originator_has_not_registered,
145         result_code_security_association_required,
146         result_code_invalid_child_resource_type,
147         result_code_no_members,
148         result_code_group_member_type_inconsistent,
149         result_code_esprim_unsupported_option,
150         result_code_esprim_unknown_key_id,
151         result_code_esprim_unknown_orig_rand_id,
152         result_code_esprim_unknown_recv_rand_id,
153         result_code_esprim_bad_mac,
154         result_code_internal_server_error,
155         result_code_not_implemened,
156         result_code_target_not_reachable,
157         result_code_receiver_has_no_privilege,
158         result_code_already_exists,
159         result_code_target_not_subscribable,
160         result_code_subscription_verification_initiation_failed,
161         result_code_subscription_host_has_no_privilege,
162         result_code_non_blocking_request_not_supported,
163         result_code_not_acceptable,
164         result_code_discovery_denied_by_ipe,
165         result_code_group_members_not_responded,
166         result_code_esprim_decryption_error,
167         result_code_esprim_encryption_error,
168         result_code_sparql_update_error,
169         result_code_external_object_not_reachable,
170         result_code_external_object_not_found,
171         result_code_max_number_of_member_exceeded,
172         result_code_member_type_inconsistent,
173         result_code_mgmt_session_cannot_be_established,
174         result_code_mgmt_session_establishment_timeout,
175         result_code_invalid_cmd_type,
176         result_code_invalid_arguments,
177         result_code_insufficient_argument,
178         result_code_mgmt_conversion_error,
179         result_code_mgmt_cancellation_failed,
180         result_code_already_complete,
181         result_code_mgmt_command_not_cancellable,
182     ]
183
184     positive_result_codes = [
185         result_code_ok,
186         result_code_deleted,
187         result_code_updated,
188         result_code_created,
189         result_code_accepted,
190     ]
191
192     # Expected positive result codes per operation
193     expected_result_codes = {
194         operation_create: result_code_created,
195         operation_retrieve: result_code_ok,
196         operation_update: result_code_updated,
197         operation_delete: result_code_deleted,
198         operation_notify: result_code_ok,
199     }
200
201     # Error message content item
202     error_message_item = "error"
203
204     # Resource types
205     resource_type_access_control_policy = 1
206     resource_type_application_entity = 2
207     resource_type_container = 3
208     resource_type_content_instance = 4
209     resource_type_cse_base = 5
210     resource_type_delivery = 6
211     resource_type_event_config = 7
212     resource_type_exec_instance = 8
213     resource_type_group = 9
214     resource_type_location_policy = 10
215     resource_type_m2m_service_subscription_profile = 11
216     resource_type_mgmt_cmd = 12
217     resource_type_mgmt_obj = 13
218     resource_type_node = 14
219     resource_type_polling_channel = 15
220     resource_type_remote_cse = 16
221     resource_type_request = 17
222     resource_type_schedule = 18
223     resource_type_service_subscribed_app_rule = 19
224     resource_type_service_subscribed_node = 20
225     resource_type_stats_collect = 21
226     resource_type_stats_config = 22
227     resource_type_subscription = 23
228     resource_type_semantic_descriptor = 24
229     resource_type_notification_target_mgmt_policy_ref = 25
230     resource_type_notification_target_policy = 26
231     resource_type_policy_deletion_rules = 27
232     resource_type_flex_container = 28
233     resource_type_time_series = 29
234     resource_type_time_series_instance = 30
235     resource_type_role = 31
236     resource_type_token = 32
237     resource_type_traffic_pattern = 33
238     resource_type_dynamic_authorization_consultation = 34
239
240     # Notification event types
241     net_update_of_resource = 1  # default
242     net_delete_of_resource = 2
243     net_create_of_direct_child_resource = 3
244     net_delete_of_direct_child_resource = 4
245     net_retrieve_of_container_resource_with_no_child_resource = 5
246
247     # Notification content types
248     nct_all_attributes = 1
249     nct_modified_attributes = 2
250     nct_resource_id = 3
251
252
253 # Instantiates definitions (used by robot framework test suites)
254 OneM2M = OneM2MPrimitiveDefinitions()
255
256
257 class OneM2MEncodeDecodeData(object):
258     """Utility class which allows to define encoding/decoding dictionaries"""
259
260     def __init__(self, data_type):
261         if not data_type:
262             raise Exception("No data type string specified")
263
264         self.data_type = data_type  # name of data type
265         self._encode = {}  # dictionary stores OneM2M: protocol mapping
266         self._decode = {}  # dictionary stores protocol: OneM2M mapping
267         self._encode_ci = {}  # stores case insensitive OneM2M: protocol mapping
268         self._decode_ci = {}  # stores case insensitive protocol: OneM2M mapping
269
270     def add(self, onem2m, protocol_specific):
271         """Adds new encoding/decoding pair"""
272         if onem2m in self._encode:
273             raise Exception(
274                 "Data type: {}, Encoding key {} already exists".format(
275                     self.data_type, onem2m
276                 )
277             )
278         self._encode[onem2m] = protocol_specific
279         decoded_ci = onem2m if not isinstance(onem2m, basestring) else onem2m.lower()
280         self._encode_ci[decoded_ci] = protocol_specific
281
282         if protocol_specific in self._decode:
283             raise Exception(
284                 "Data type: {}, Decoding key {} already exists".format(
285                     self.data_type, protocol_specific
286                 )
287             )
288         self._decode[protocol_specific] = onem2m
289         encoded_ci = (
290             protocol_specific
291             if not isinstance(protocol_specific, basestring)
292             else protocol_specific.lower()
293         )
294         self._decode_ci[encoded_ci] = onem2m
295         return self
296
297     def encode(self, key):
298         """Returns key encoded to protocol specific form"""
299         if key not in self._encode:
300             raise IoTDataEncodeError(
301                 "Data type: {}, Encoding key {} not found".format(self.data_type, key)
302             )
303         return self._encode[key]
304
305     def encode_default(self, key, default):
306         """Returns encoded key or default value if the key doesn't exist"""
307         if key not in self._encode:
308             return default
309         return self._encode[key]
310
311     def encode_ci(self, key):
312         """Performs case insensitive encoding and returns encoded key"""
313         k = key if not isinstance(key, basestring) else key.lower()
314         if k not in self._encode_ci:
315             raise IoTDataEncodeError(
316                 "Data type: {}, Case Insensitive Encoding key {} not found".format(
317                     self.data_type, key
318                 )
319             )
320         return self._encode_ci[k]
321
322     def encode_default_ci(self, key, default):
323         """
324         Performs case insensitive encoding and returns encoded key or default
325         value if the key doesn't exit
326         """
327         k = key if not isinstance(key, basestring) else key.lower()
328         if k not in self._encode_ci:
329             return default
330         return self._encode_ci[k]
331
332     def decode(self, key):
333         """Decodes protocol specific key and returns decoded OneM2M string"""
334         if key not in self._decode:
335             raise IoTDataDecodeError(
336                 "Data type: {}, Decoding key {} not found".format(self.data_type, key)
337             )
338         return self._decode[key]
339
340     def decode_default(self, key, default):
341         """
342         Decodes protocol specific key and returns decoded OneM2M string
343         or default value if the key doesn't exist
344         """
345         if key not in self._decode:
346             return default
347         return self._decode[key]
348
349     def decode_ci(self, key):
350         """Performs case insensitive decoding and returns decoded OneM2M string"""
351         k = key if not isinstance(key, basestring) else key.lower()
352         if k not in self._decode_ci:
353             raise IoTDataDecodeError(
354                 "Data type: {}, Case Insensitive Decoding key {} not found".format(
355                     self.data_type, key
356                 )
357             )
358         return self._decode_ci[k]
359
360     def decode_default_ci(self, key, default):
361         """
362         Performs case insensitive decoding and returns decoded OneM2M string
363         or default value if the key doesn't exist
364         """
365         k = key if not isinstance(key, basestring) else key.lower()
366         if k not in self._decode_ci:
367             return default
368         return self._decode_ci[k]
369
370
371 class OneM2MPrimitive(IoTData):
372     """
373     Abstract class, specialization of IoTData which describes
374     OneM2M primitive. Primitive data object is divided into three parts:
375         1. Primitive parameters - consists of items called param
376         2. Primitive content - consists of items called attr
377         3. Protocol specific parameters - consists of items called proto_param
378     """
379
380     def get_parameters(self):
381         """Returns all primitive parameters as dict"""
382         raise NotImplementedError()
383
384     def get_param(self, param):
385         """Returns value of specific parameter"""
386         raise NotImplementedError()
387
388     def get_content(self):
389         """Returns primitive content as dict"""
390         raise NotImplementedError()
391
392     def get_attr(self, attr):
393         """Returns value of specific attribute of primitive content"""
394         raise NotImplementedError()
395
396     def get_protocol_specific_parameters(self):
397         """Returns protocol specific primitive parameters as dict"""
398         raise NotImplementedError()
399
400     def get_proto_param(self, proto_param):
401         """Returns value of specific protocol parameter"""
402         raise NotImplementedError()
403
404     def get_primitive_str(self):
405         """Returns string representation of primitive including parameters and content"""
406         raise NotImplementedError()
407
408     def get_communication_protocol(self):
409         """Returns communication protocol used when sending / receiving this primitive"""
410         raise NotImplementedError()
411
412     def check_request(self):
413         """Verifies this instance as request"""
414         raise NotImplementedError("Request validation not implemented")
415
416     def check_response(self, rqi=None, rsc=None, request_operation=None):
417         """
418         Verifies this instance as response and checks parameter values
419         if provided
420         """
421         raise NotImplementedError("Response validation not implemented")
422
423     def check_response_negative(self, rqi=None, rsc=None, error_message=None):
424         """
425         Verifies this instance as negative response primitive and checks
426         parameters if provided
427         """
428         raise NotImplementedError("Negative response validation not implemented")
429
430     def check_exchange(self, response_primitive, rsc=None):
431         """
432         Verifies this instance as request primitive, verifies provided response
433         primitive and checks request and response primitive parameters if the
434         request and response primitive represents valid data exchange
435         """
436         raise NotImplementedError("Exchange validation not implemented")
437
438     def check_exchange_negative(self, response_primitive, rsc, error_message=None):
439         """
440         Verifies this instance as request primitive, verifies provided negative
441         response primitive and checks request and response primitive parameters
442         if the request and response primitive represents valid data exchange
443         """
444         raise NotImplementedError("Negative exchange validation not implemented")
445
446
447 class OneM2MPrimitiveBuilderException(Exception):
448     """OneM2M primitive build error"""
449
450     pass
451
452
453 class OneM2MPrimitiveBuilder(IoTDataBuilder, OneM2MPrimitive):
454     """Abstract class describes OneM2M primitive object builder"""
455
456     def set_parameters(self, parameters):
457         raise NotImplementedError()
458
459     def set_param(self, param_name, param_value):
460         raise NotImplementedError()
461
462     def set_content(self, attributes):
463         raise NotImplementedError()
464
465     def set_att(self, attr_name, attr_value):
466         raise NotImplementedError()
467
468     def set_communication_protocol(self, proto_name):
469         raise NotImplementedError()
470
471     def set_protocol_specific_parameters(self, proto_params):
472         raise NotImplementedError()
473
474     def set_proto_param(self, param_name, param_value):
475         raise NotImplementedError()
476
477     def clone(self):
478         raise NotImplementedError()
479
480     def build(self):
481         raise NotImplementedError()
482
483
484 class OneM2MPrimitiveEncoder(IoTDataEncoder):
485     """IoT Data Encoder specialization for OneM2M primitives"""
486
487     def encode(self, onem2m_primitive):
488         raise NotImplementedError()
489
490
491 class OneM2MPrimitiveDecoder(IoTDataDecoder):
492     """IoT Data Decoder specialization for OneM2M primitives"""
493
494     def decode(self, protocol_message):
495         raise NotImplementedError()