openc2lib.types.basetypes
OpenC2 structures
Definition of the base types (structures) in the OpenC2 DataModels (Sec. 3.1.1) Each OpenC2 object must derive from these classes, which affects serialization operations
1""" OpenC2 structures 2 3 Definition of the base types (structures) in the OpenC2 DataModels (Sec. 3.1.1) 4 Each OpenC2 object must derive from these classes, which 5 affects serialization operations 6 7""" 8 9import aenum 10import inspect 11import logging 12 13logger = logging.getLogger('openc2lib') 14""" openc2lib logger """ 15 16 17class Openc2Type(): 18 """ OpenC2 Language Element 19 20 This class is currently unused and is only provided to have a common ancestor for all 21 OpenC2 basic types. It may be used in the future to implement common methods or arguments. 22 """ 23 pass 24 25 26#@register_basetype 27class Record(Openc2Type): 28 """ OpenC2 Record 29 30 Implements OpenC2 Record: 31 >An ordered map from a list of keys with positions to values with 32 positionally-defined semantics. Each key has a position and name, 33 and is mapped to a type. 34 35 It expect keys to be public class attributes. All internal attributes 36 must be kept private by prefixing it with an '_'. 37 38 """ 39 def todict(self, e): 40 """ Converts to dictionary 41 42 It is used to convert this object to an intermediary representation during 43 serialization. It takes an `Encoder` argument that is used to recursively 44 serialize inner data and structures (the `Encoder` provides standard methods 45 for converting base types to dictionaries).. 46 47 :param e: The `Encoder` that is being used. 48 :return: A dictionary compliants to the Language Specification's serialization 49 rules. 50 """ 51 objdic = vars(self) 52 53 dic = {} 54 for k,v in objdic.items(): 55 # Fix keywords corresponding to variable names that clash with Python keywords 56 if isinstance(k, str) and k.endswith('_'): 57 k = k.rstrip('_') 58 # Remove empty and private elements; do not include non-string keys 59 if not v is None and not k.startswith('_') and isinstance(k, str): 60 dic[k] = v 61 62 return e.todict(dic) 63 64 @classmethod 65 def fromdict(clstype, dic, e): 66 """ Builds instance from dictionary 67 68 It is used during deserialization to create an openc2lib instance from the text message. 69 It takes an `Encoder` instance that is used to recursively build instances of the inner 70 objects (the `Encoder` provides standard methods to create instances of base objects like 71 strings, integers, boolean). 72 73 :param dic: The intermediary dictionary representation from which the object is built. 74 :param e: The `Encoder that is being used. 75 :return: An instance of this class initialized from the dictionary values. 76 """ 77 objdic = {} 78 # Retrieve class type for each field in the dictionary 79 fielddesc = None 80 for tpl in inspect.getmembers(clstype): 81 if tpl[0] == '__annotations__': 82 fielddesc = tpl[1] 83 84 for k,v in dic.items(): 85 if k not in fielddesc: 86 raise Exception("Unknown field '" + k + "' from message") 87 objdic[k] = e.fromdict(fielddesc[k], v) 88 89 90 # A record should always have more than one field, so the following statement 91 # should not raise exceptions 92 return clstype(**objdic) 93 94 95 96class Choice(Openc2Type): 97 """ OpenC2 Choice 98 Implements the OpenC2 Choice: 99 >One field selected from a set of named fields. The API value has a name and a type. 100 101 It expect all allowed values to be provided in a `Register` class, which must be defined 102 as class attribute `register` in all derived classes (see `Target` and `Actuator` as examples). 103 """ 104 register = None 105 """ List of registered name/class options available """ 106 107 def __init__(self, obj): 108 """ Initialize the `Choice` object 109 110 Objects used as `Choice` must be registered in advance in the `register` dictionary. 111 112 :arg obj: An object among those defined in the `register`. 113 """ 114 self.choice: str = self.register.getName(obj.__class__) 115 """ Selected name for the `Choice` """ 116 self.obj = obj 117 """ Class corresponding to the `choice` """ 118 119 def getObj(self): 120 """ Returns the objet instance embedded in the `register`.""" 121 return self.obj 122 123 def getName(self): 124 """Returns the name of the choice 125 126 Returns the name of object, which is the selector carried by the `Choice` element. 127 This does not include the object itself. 128 """ 129 return self.choice 130 131 @classmethod 132 def getClass(cls, choice): 133 """ Get the class corresponding to the current `choice` 134 135 It may be implemented by any derived class, if a different logic than the `Register` class 136 is followed to store the name/class bindings. 137 :param choice: The name of the alternative that is being looked for. 138 :return: The class corresponding to the provided `choice`. 139 """ 140 return cls.register.get(choice) 141 142 def __str__(self): 143 return self.choice 144 145 def __repr__(self): 146 return str(self.obj) 147 148 def todict(self, e): 149 """ Converts to dictionary 150 151 It is used to convert this object to an intermediary representation during 152 serialization. It takes an `Encoder` argument that is used to recursively 153 serialize inner data and structures (the `Encoder` provides standard methods 154 for converting base types to dictionaries).. 155 156 :param e: The `Encoder` that is being used. 157 :return: A dictionary compliants to the Language Specification's serialization 158 rules. 159 """ 160 # In case of Choice, the specific choice may be the implementation of an additional type, 161 # which affects its representation. So, first of all, get the representation of the inner 162 # data type 163 dic = {} 164 dic[self.choice] = e.todict(self.obj) 165 return dic 166 167 @classmethod 168 def fromdict(cls, dic, e): 169 """ Builds instance from dictionary 170 171 It is used during deserialization to create an openc2lib instance from the text message. 172 It takes an `Encoder` instance that is used to recursively build instances of the inner 173 objects (the `Encoder` provides standard methods to create instances of base objects like 174 strings, integers, boolean). 175 176 :param dic: The intermediary dictionary representation from which the object is built. 177 :param e: The `Encoder that is being used. 178 :return: An instance of this class initialized from the dictionary values. 179 """ 180 if not len(dic) == 1: 181 raise ValueError("Unexpected dict: ", dic) 182 183 for k, v in dic.items(): 184 # Expected to run one time only! 185 objtype = cls.getClass(k) 186 return cls(e.fromdict(objtype, v)) 187 188class Enumerated(Openc2Type, aenum.Enum): 189 """ OpenC2 Enumerated 190 191 Implements OpenC2 Enumerated: 192 >A set of named integral constants. The API value is a name. 193 194 The constants may be anything, including strings, integers, classes. 195 """ 196 197 # Convert enumerations to str 198 def todict(self, e): 199 """ Converts to dictionary 200 201 It is used to convert this object to an intermediary representation during 202 serialization. It takes an `Encoder` argument that is used to recursively 203 serialize inner data and structures (the `Encoder` provides standard methods 204 for converting base types to dictionaries).. 205 206 :param e: The `Encoder` that is being used. 207 :return: A dictionary compliants to the Language Specification's serialization 208 rules. 209 """ 210 return self.name 211 212 @classmethod 213 def fromdict(cls, dic, e): 214 """ Builds instance from dictionary 215 216 It is used during deserialization to create an openc2lib instance from the text message. 217 It takes an `Encoder` instance that is used to recursively build instances of the inner 218 objects (the `Encoder` provides standard methods to create instances of base objects like 219 strings, integers, boolean). 220 221 :param dic: The intermediary dictionary representation from which the object is built. 222 :param e: The `Encoder that is being used. 223 :return: An instance of this class initialized from the dictionary values. 224 """ 225 try: 226 return cls[str(dic)] 227 except: 228 raise TypeError("Unexpected enum value: ", dic) 229 230# This class should check the names are integers. 231# The enum syntax only allows to define <str = int> pairs, 232# so to use this class it is necessary to define mnemonic label 233# TODO: Test this code 234class EnumeratedID(Enumerated): 235 """ OpenC2 EnumeratedID 236 237 Implements OpenC2 EnumeratedID: 238 >A set of unnamed integral constants. The API value is an id. 239 240 The current implementation does not check the values to be integer. 241 However, coversion to/from integer is explicitly done during the 242 intermediary dictionary serialization, hence throwing an Exception if 243 the IDs are not integers. 244 """ 245 246 def todict(self, e): 247 """ Converts to dictionary 248 249 It is used to convert this object to an intermediary representation during 250 serialization. It takes an `Encoder` argument that is used to recursively 251 serialize inner data and structures (the `Encoder` provides standard methods 252 for converting base types to dictionaries).. 253 254 :param e: The `Encoder` that is being used. 255 :return: A dictionary compliants to the Language Specification's serialization 256 rules. 257 """ 258 return int(self.value) 259 260 @classmethod 261 def fromdict(cls, dic, e): 262 """ Builds instance from dictionary 263 264 It is used during deserialization to create an openc2lib instance from the text message. 265 It takes an `Encoder` instance that is used to recursively build instances of the inner 266 objects (the `Encoder` provides standard methods to create instances of base objects like 267 strings, integers, boolean). 268 269 :param dic: The intermediary dictionary representation from which the object is built. 270 :param e: The `Encoder that is being used. 271 :return: An instance of this class initialized from the dictionary values. 272 """ 273 try: 274 return cls(int(dic)) 275 except: 276 raise TypeError("Unexpected enum value: ", dic) 277 278class Array(Openc2Type, list): 279 """ OpenC2 Array 280 281 Implements OpenC2 Array: 282 >An ordered list of unnamed fields with positionally-defined semantics. 283 Each field has a position, label, and type. 284 285 However, position does not matter in this implementation. 286 287 Derived classes must provide a `fieldtypes` dictionary that associate each field name 288 to its class. This is strictly required in order to instantiate the object at 289 deserialization time. However, no check is performed when new items are inserted. 290 """ 291 fieldtypes = None 292 """ Field types 293 294 A `dictionary` which keys are field names and which values are the corresponding classes. 295 Must be provided by any derived class. 296 """ 297 298 def todict(self, e): 299 """ Converts to dictionary 300 301 It is used to convert this object to an intermediary representation during 302 serialization. It takes an `Encoder` argument that is used to recursively 303 serialize inner data and structures (the `Encoder` provides standard methods 304 for converting base types to dictionaries).. 305 306 :param e: The `Encoder` that is being used. 307 :return: A dictionary compliants to the Language Specification's serialization 308 rules. 309 """ 310 lis = [] 311 for i in self: 312 lis.append = e.todict(i) 313 return lis 314 315 def fromdict(cls, dic, e): 316 """ !!! WARNING !!! 317 Currently not implemented because there are no examples of usage of this 318 type (only Array/net, which is not clear) 319 """ 320 raise Exception("Function not implemented") 321 322class ArrayOf: 323 """ OpenC2 ArrayOf 324 325 Implements OpenC2 ArrayOf(*vtype*): 326 >An ordered list of fields with the same semantics. 327 Each field has a position and type *vtype*. 328 329 It extends the `Array` type. However, to make its usage simpler and compliant 330 to the description given in the 331 Language Specification, the implementation is quite different. 332 Note that in many cases `ArrayOf` is only used to create arrays without the need 333 to derive an additional data type. 334 """ 335 336 def __new__(self, fldtype): 337 """ `ArrayOf` builder 338 339 Creates a unnamed derived class from `Array`, which `fieldtypes` is set to `fldtype`. 340 :param fldtype: The type of the fields stored in the array (indicated as *vtype* in 341 the Language Specification. 342 :return: A new unnamed class definition. 343 """ 344 class ArrayOf(Array): 345 """ OpenC2 unnamed `ArrayOf` 346 347 This class inherits from `Array` and sets its `fieldtypes` to a given type. 348 349 One might like to check the type of the elements before inserting them. 350 However, this is not the Python-way. Python use the duck typing approach: 351 https://en.wikipedia.org/wiki/Duck_typing 352 We ask for the type of objects just to keep this information according to 353 the OpenC2 data model. 354 355 Note: no `todict()` method is provided, since `Array.todict()` is fine here. 356 """ 357 fieldtype = fldtype 358 """ The type of values stored in this container """ 359 360 @classmethod 361 def fromdict(cls, lis, e): 362 """ Builds instance from dictionary 363 364 It is used during deserialization to create an openc2lib instance from the text message. 365 It takes an `Encoder` instance that is used to recursively build instances of the inner 366 objects (the `Encoder` provides standard methods to create instances of base objects like 367 strings, integers, boolean). 368 369 :param lis: The intermediary dictionary representation from which the object is built. 370 :param e: The `Encoder that is being used. 371 :return: An instance of this class initialized from the dictionary values. 372 """ 373 objlis = cls() 374 logger.debug('Building %s from %s in ArrayOf', cls, lis) 375 logger.debug('-> instantiating: %s', cls.fieldtype) 376 for k in lis: 377 objlis.append(e.fromdict(cls.fieldtype, k)) 378 379 return objlis 380 381 # This is the code if I would like to do type checking 382 # when inserting data 383# def append(self, item): 384# if isinstance(item, self.fieldtype): 385# super().append(item) 386# else: 387# raise ValueError(self.fieldtype,' allowed only') 388# 389# def insert(self, index, item): 390# if isinstance(item, self.fieldtype): 391# super().insert(index, item) 392# else: 393# raise ValueError(self.fieldtype,' allowed only') 394# 395# def __add__(self, item): 396# if isinstance(item, self.fieldtype): 397# super().__add__(item) 398# else: 399# raise ValueError(self.fieldtype,' allowed only') 400# 401# def __iadd__(self, item): 402# if isinstance(item, self.fieldtype): 403# super().__iadd__(item) 404# else: 405# raise ValueError(self.fieldtype,' allowed only') 406 407 return ArrayOf 408 409 410class Map(Openc2Type, dict): 411 """ OpenC2 Map 412 413 Implements OpenC2 Map: 414 >An unordered map from a set of specified keys to values with semantics 415 bound to each key. Each field has an id, name and type. 416 417 However, the id is not considered in this implementation. 418 419 The implementation follows a similar logic than `Array`. Each derived class 420 is expected to provide a `fieldtypes` class attribute that associate field names 421 with their class definition. 422 423 Additionally, according to the Language Specification, `Map`s may be extended by 424 Profiles. Such extensions must use the `extend` and `regext` class attributes to 425 bind to the base element they extend and the `Profile` in which they are defined. 426 """ 427 fieldtypes: dict = None 428 """ Field types 429 430 A `dictionary` which keys are field names and which values are the corresponding classes. 431 Must be provided by any derived class. 432 """ 433 extend = None 434 """ Base class 435 436 Data types defined in the Language Specification shall not set this field. Data types defined in 437 Profiles that extends a Data Type defined in the Language Specification, must set this field to 438 the corresponding class of the base Data Type. 439 440 Note: Extensions defined in the openc2lib context are recommended to use the same name of the base 441 Data Type, and to distinguish them through appropriate usage of the namespacing mechanism. 442 """ 443 regext = {} 444 """ Registered extensions 445 446 Classes that implement a Data Type defined in the Language Specification will use this field to 447 register extensions defined by external Profiles. Classes that define extensions within Profiles 448 shall register themselves according to the specific documentation of the base type class, but 449 shall not modify this field. 450 """ 451 452 def todict(self, e): 453 """ Converts to dictionary 454 455 It is used to convert this object to an intermediary representation during 456 serialization. It takes an `Encoder` argument that is used to recursively 457 serialize inner data and structures (the `Encoder` provides standard methods 458 for converting base types to dictionaries).. 459 460 :param e: The `Encoder` that is being used. 461 :return: A dictionary compliants to the Language Specification's serialization 462 rules. 463 """ 464 newdic=dict() 465 466 # This is necessary because self.extend.fieldtypes does 467 # not exist for non-extended classes 468 if self.extend is None: 469 return e.todict(dict(self)) 470 471 for k,v in self.items(): 472 if k not in self.fieldtypes: 473 raise ValueError('Unknown field: ', k) 474 if k in self.extend.fieldtypes: 475 newdic[k] = v 476 else: 477 if self.nsid not in newdic: 478 newdic[self.nsid]={} 479 newdic[self.nsid][k]=v 480 481 return e.todict(newdic) 482 483 @classmethod 484 def fromdict(cls, dic, e): 485 """ Builds instance from dictionary 486 487 It is used during deserialization to create an openc2lib instance from the text message. 488 It takes an `Encoder` instance that is used to recursively build instances of the inner 489 objects (the `Encoder` provides standard methods to create instances of base objects like 490 strings, integers, boolean). 491 492 :param dic: The intermediary dictionary representation from which the object is built. 493 :param e: The `Encoder that is being used. 494 :return: An instance of this class initialized from the dictionary values. 495 """ 496 objdic = {} 497 extension = None 498 logger.debug('Building %s from %s in Map', cls, dic) 499 for k,v in dic.items(): 500 if k in cls.fieldtypes: 501 objdic[k] = e.fromdict(cls.fieldtypes[k], v) 502 elif k in cls.regext: 503 logger.debug(' Using profile %s to decode: %s', k, v) 504 extension = cls.regext[k] 505 for l,w in v.items(): 506 objdic[l] = e.fromdict(extension.fieldtypes[l], w) 507 else: 508 raise TypeError("Unexpected field: ", k) 509 510 if extension is not None: 511 cls = extension 512 513 return cls(objdic) 514 515class MapOf: 516 """ OpenC2 MapOf 517 518 Implements OpenC2 MapOf(*ktype, vtype*): 519 >An unordered set of keys to values with the same semantics. 520 Each key has key type *ktype* and is mapped to value type *vtype*. 521 522 It extends `Map` with the same approach already used for `ArrayOf`. 523 `MapOf` for specific types are created as anonymous classes by passing 524 `ktype` and `vtype` as arguments. 525 526 Note: `MapOf` implementation currently does not support extensins!. 527 """ 528 529 def __new__(self,ktype, vtype): 530 """ `MapOf` builder 531 532 Creates a unnamed derived class from `Map`, which `fieldtypes` is set to a single value 533 `ktype: vtype`. 534 :param ktype: The key type of the items stored in the map. 535 :param vtype: The value type of the items stored in the map. 536 :return: A new unnamed class definition. 537 """ 538 class MapOf(Map): 539 """ OpenC2 unnamed `MapOf` 540 541 This class inherits from `Map` and sets its `fieldtypes` to a given type. 542 543 Note: no `todict()` method is provided, since `Map.todict()` is fine here. 544 """ 545 fieldtypes = {ktype: vtype} 546 """ The type of values stored in this container """ 547 548 @classmethod 549 def fromdict(cls, dic, e): 550 """ Builds instance from dictionary 551 552 It is used during deserialization to create an openc2lib instance from the text message. 553 It takes an `Encoder` instance that is used to recursively build instances of the inner 554 objects (the `Encoder` provides standard methods to create instances of base objects like 555 strings, integers, boolean). 556 557 :param dic: The intermediary dictionary representation from which the object is built. 558 :param e: The `Encoder that is being used. 559 :return: An instance of this class initialized from the dictionary values. 560 """ 561 objdic = {} 562 logger.debug('Building %s from %s in MapOf', cls, dic) 563 for k,v in dic.items(): 564 kclass = list(cls.fieldtypes)[0] 565 objk = e.fromdict(kclass, k) 566 objdic[objk] = e.fromdict(cls.fieldtypes[kclass], v) 567 return objdic 568 569 return MapOf
openc2lib logger
18class Openc2Type(): 19 """ OpenC2 Language Element 20 21 This class is currently unused and is only provided to have a common ancestor for all 22 OpenC2 basic types. It may be used in the future to implement common methods or arguments. 23 """ 24 pass
OpenC2 Language Element
This class is currently unused and is only provided to have a common ancestor for all OpenC2 basic types. It may be used in the future to implement common methods or arguments.
28class Record(Openc2Type): 29 """ OpenC2 Record 30 31 Implements OpenC2 Record: 32 >An ordered map from a list of keys with positions to values with 33 positionally-defined semantics. Each key has a position and name, 34 and is mapped to a type. 35 36 It expect keys to be public class attributes. All internal attributes 37 must be kept private by prefixing it with an '_'. 38 39 """ 40 def todict(self, e): 41 """ Converts to dictionary 42 43 It is used to convert this object to an intermediary representation during 44 serialization. It takes an `Encoder` argument that is used to recursively 45 serialize inner data and structures (the `Encoder` provides standard methods 46 for converting base types to dictionaries).. 47 48 :param e: The `Encoder` that is being used. 49 :return: A dictionary compliants to the Language Specification's serialization 50 rules. 51 """ 52 objdic = vars(self) 53 54 dic = {} 55 for k,v in objdic.items(): 56 # Fix keywords corresponding to variable names that clash with Python keywords 57 if isinstance(k, str) and k.endswith('_'): 58 k = k.rstrip('_') 59 # Remove empty and private elements; do not include non-string keys 60 if not v is None and not k.startswith('_') and isinstance(k, str): 61 dic[k] = v 62 63 return e.todict(dic) 64 65 @classmethod 66 def fromdict(clstype, dic, e): 67 """ Builds instance from dictionary 68 69 It is used during deserialization to create an openc2lib instance from the text message. 70 It takes an `Encoder` instance that is used to recursively build instances of the inner 71 objects (the `Encoder` provides standard methods to create instances of base objects like 72 strings, integers, boolean). 73 74 :param dic: The intermediary dictionary representation from which the object is built. 75 :param e: The `Encoder that is being used. 76 :return: An instance of this class initialized from the dictionary values. 77 """ 78 objdic = {} 79 # Retrieve class type for each field in the dictionary 80 fielddesc = None 81 for tpl in inspect.getmembers(clstype): 82 if tpl[0] == '__annotations__': 83 fielddesc = tpl[1] 84 85 for k,v in dic.items(): 86 if k not in fielddesc: 87 raise Exception("Unknown field '" + k + "' from message") 88 objdic[k] = e.fromdict(fielddesc[k], v) 89 90 91 # A record should always have more than one field, so the following statement 92 # should not raise exceptions 93 return clstype(**objdic)
OpenC2 Record
Implements OpenC2 Record:
An ordered map from a list of keys with positions to values with positionally-defined semantics. Each key has a position and name, and is mapped to a type.
It expect keys to be public class attributes. All internal attributes must be kept private by prefixing it with an '_'.
40 def todict(self, e): 41 """ Converts to dictionary 42 43 It is used to convert this object to an intermediary representation during 44 serialization. It takes an `Encoder` argument that is used to recursively 45 serialize inner data and structures (the `Encoder` provides standard methods 46 for converting base types to dictionaries).. 47 48 :param e: The `Encoder` that is being used. 49 :return: A dictionary compliants to the Language Specification's serialization 50 rules. 51 """ 52 objdic = vars(self) 53 54 dic = {} 55 for k,v in objdic.items(): 56 # Fix keywords corresponding to variable names that clash with Python keywords 57 if isinstance(k, str) and k.endswith('_'): 58 k = k.rstrip('_') 59 # Remove empty and private elements; do not include non-string keys 60 if not v is None and not k.startswith('_') and isinstance(k, str): 61 dic[k] = v 62 63 return e.todict(dic)
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
65 @classmethod 66 def fromdict(clstype, dic, e): 67 """ Builds instance from dictionary 68 69 It is used during deserialization to create an openc2lib instance from the text message. 70 It takes an `Encoder` instance that is used to recursively build instances of the inner 71 objects (the `Encoder` provides standard methods to create instances of base objects like 72 strings, integers, boolean). 73 74 :param dic: The intermediary dictionary representation from which the object is built. 75 :param e: The `Encoder that is being used. 76 :return: An instance of this class initialized from the dictionary values. 77 """ 78 objdic = {} 79 # Retrieve class type for each field in the dictionary 80 fielddesc = None 81 for tpl in inspect.getmembers(clstype): 82 if tpl[0] == '__annotations__': 83 fielddesc = tpl[1] 84 85 for k,v in dic.items(): 86 if k not in fielddesc: 87 raise Exception("Unknown field '" + k + "' from message") 88 objdic[k] = e.fromdict(fielddesc[k], v) 89 90 91 # A record should always have more than one field, so the following statement 92 # should not raise exceptions 93 return clstype(**objdic)
Builds instance from dictionary
It is used during deserialization to create an openc2lib instance from the text message.
It takes an Encoder instance that is used to recursively build instances of the inner
objects (the Encoder provides standard methods to create instances of base objects like
strings, integers, boolean).
Parameters
- dic: The intermediary dictionary representation from which the object is built.
- e: The `Encoder that is being used.
Returns
An instance of this class initialized from the dictionary values.
97class Choice(Openc2Type): 98 """ OpenC2 Choice 99 Implements the OpenC2 Choice: 100 >One field selected from a set of named fields. The API value has a name and a type. 101 102 It expect all allowed values to be provided in a `Register` class, which must be defined 103 as class attribute `register` in all derived classes (see `Target` and `Actuator` as examples). 104 """ 105 register = None 106 """ List of registered name/class options available """ 107 108 def __init__(self, obj): 109 """ Initialize the `Choice` object 110 111 Objects used as `Choice` must be registered in advance in the `register` dictionary. 112 113 :arg obj: An object among those defined in the `register`. 114 """ 115 self.choice: str = self.register.getName(obj.__class__) 116 """ Selected name for the `Choice` """ 117 self.obj = obj 118 """ Class corresponding to the `choice` """ 119 120 def getObj(self): 121 """ Returns the objet instance embedded in the `register`.""" 122 return self.obj 123 124 def getName(self): 125 """Returns the name of the choice 126 127 Returns the name of object, which is the selector carried by the `Choice` element. 128 This does not include the object itself. 129 """ 130 return self.choice 131 132 @classmethod 133 def getClass(cls, choice): 134 """ Get the class corresponding to the current `choice` 135 136 It may be implemented by any derived class, if a different logic than the `Register` class 137 is followed to store the name/class bindings. 138 :param choice: The name of the alternative that is being looked for. 139 :return: The class corresponding to the provided `choice`. 140 """ 141 return cls.register.get(choice) 142 143 def __str__(self): 144 return self.choice 145 146 def __repr__(self): 147 return str(self.obj) 148 149 def todict(self, e): 150 """ Converts to dictionary 151 152 It is used to convert this object to an intermediary representation during 153 serialization. It takes an `Encoder` argument that is used to recursively 154 serialize inner data and structures (the `Encoder` provides standard methods 155 for converting base types to dictionaries).. 156 157 :param e: The `Encoder` that is being used. 158 :return: A dictionary compliants to the Language Specification's serialization 159 rules. 160 """ 161 # In case of Choice, the specific choice may be the implementation of an additional type, 162 # which affects its representation. So, first of all, get the representation of the inner 163 # data type 164 dic = {} 165 dic[self.choice] = e.todict(self.obj) 166 return dic 167 168 @classmethod 169 def fromdict(cls, dic, e): 170 """ Builds instance from dictionary 171 172 It is used during deserialization to create an openc2lib instance from the text message. 173 It takes an `Encoder` instance that is used to recursively build instances of the inner 174 objects (the `Encoder` provides standard methods to create instances of base objects like 175 strings, integers, boolean). 176 177 :param dic: The intermediary dictionary representation from which the object is built. 178 :param e: The `Encoder that is being used. 179 :return: An instance of this class initialized from the dictionary values. 180 """ 181 if not len(dic) == 1: 182 raise ValueError("Unexpected dict: ", dic) 183 184 for k, v in dic.items(): 185 # Expected to run one time only! 186 objtype = cls.getClass(k) 187 return cls(e.fromdict(objtype, v))
OpenC2 Choice Implements the OpenC2 Choice:
One field selected from a set of named fields. The API value has a name and a type.
It expect all allowed values to be provided in a Register class, which must be defined
as class attribute register in all derived classes (see Target and Actuator as examples).
108 def __init__(self, obj): 109 """ Initialize the `Choice` object 110 111 Objects used as `Choice` must be registered in advance in the `register` dictionary. 112 113 :arg obj: An object among those defined in the `register`. 114 """ 115 self.choice: str = self.register.getName(obj.__class__) 116 """ Selected name for the `Choice` """ 117 self.obj = obj 118 """ Class corresponding to the `choice` """
120 def getObj(self): 121 """ Returns the objet instance embedded in the `register`.""" 122 return self.obj
Returns the objet instance embedded in the register.
124 def getName(self): 125 """Returns the name of the choice 126 127 Returns the name of object, which is the selector carried by the `Choice` element. 128 This does not include the object itself. 129 """ 130 return self.choice
Returns the name of the choice
Returns the name of object, which is the selector carried by the Choice element.
This does not include the object itself.
132 @classmethod 133 def getClass(cls, choice): 134 """ Get the class corresponding to the current `choice` 135 136 It may be implemented by any derived class, if a different logic than the `Register` class 137 is followed to store the name/class bindings. 138 :param choice: The name of the alternative that is being looked for. 139 :return: The class corresponding to the provided `choice`. 140 """ 141 return cls.register.get(choice)
Get the class corresponding to the current choice
It may be implemented by any derived class, if a different logic than the Register class
is followed to store the name/class bindings.
Parameters
- choice: The name of the alternative that is being looked for.
Returns
The class corresponding to the provided
choice.
149 def todict(self, e): 150 """ Converts to dictionary 151 152 It is used to convert this object to an intermediary representation during 153 serialization. It takes an `Encoder` argument that is used to recursively 154 serialize inner data and structures (the `Encoder` provides standard methods 155 for converting base types to dictionaries).. 156 157 :param e: The `Encoder` that is being used. 158 :return: A dictionary compliants to the Language Specification's serialization 159 rules. 160 """ 161 # In case of Choice, the specific choice may be the implementation of an additional type, 162 # which affects its representation. So, first of all, get the representation of the inner 163 # data type 164 dic = {} 165 dic[self.choice] = e.todict(self.obj) 166 return dic
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
168 @classmethod 169 def fromdict(cls, dic, e): 170 """ Builds instance from dictionary 171 172 It is used during deserialization to create an openc2lib instance from the text message. 173 It takes an `Encoder` instance that is used to recursively build instances of the inner 174 objects (the `Encoder` provides standard methods to create instances of base objects like 175 strings, integers, boolean). 176 177 :param dic: The intermediary dictionary representation from which the object is built. 178 :param e: The `Encoder that is being used. 179 :return: An instance of this class initialized from the dictionary values. 180 """ 181 if not len(dic) == 1: 182 raise ValueError("Unexpected dict: ", dic) 183 184 for k, v in dic.items(): 185 # Expected to run one time only! 186 objtype = cls.getClass(k) 187 return cls(e.fromdict(objtype, v))
Builds instance from dictionary
It is used during deserialization to create an openc2lib instance from the text message.
It takes an Encoder instance that is used to recursively build instances of the inner
objects (the Encoder provides standard methods to create instances of base objects like
strings, integers, boolean).
Parameters
- dic: The intermediary dictionary representation from which the object is built.
- e: The `Encoder that is being used.
Returns
An instance of this class initialized from the dictionary values.
189class Enumerated(Openc2Type, aenum.Enum): 190 """ OpenC2 Enumerated 191 192 Implements OpenC2 Enumerated: 193 >A set of named integral constants. The API value is a name. 194 195 The constants may be anything, including strings, integers, classes. 196 """ 197 198 # Convert enumerations to str 199 def todict(self, e): 200 """ Converts to dictionary 201 202 It is used to convert this object to an intermediary representation during 203 serialization. It takes an `Encoder` argument that is used to recursively 204 serialize inner data and structures (the `Encoder` provides standard methods 205 for converting base types to dictionaries).. 206 207 :param e: The `Encoder` that is being used. 208 :return: A dictionary compliants to the Language Specification's serialization 209 rules. 210 """ 211 return self.name 212 213 @classmethod 214 def fromdict(cls, dic, e): 215 """ Builds instance from dictionary 216 217 It is used during deserialization to create an openc2lib instance from the text message. 218 It takes an `Encoder` instance that is used to recursively build instances of the inner 219 objects (the `Encoder` provides standard methods to create instances of base objects like 220 strings, integers, boolean). 221 222 :param dic: The intermediary dictionary representation from which the object is built. 223 :param e: The `Encoder that is being used. 224 :return: An instance of this class initialized from the dictionary values. 225 """ 226 try: 227 return cls[str(dic)] 228 except: 229 raise TypeError("Unexpected enum value: ", dic)
OpenC2 Enumerated
Implements OpenC2 Enumerated:
A set of named integral constants. The API value is a name.
The constants may be anything, including strings, integers, classes.
199 def todict(self, e): 200 """ Converts to dictionary 201 202 It is used to convert this object to an intermediary representation during 203 serialization. It takes an `Encoder` argument that is used to recursively 204 serialize inner data and structures (the `Encoder` provides standard methods 205 for converting base types to dictionaries).. 206 207 :param e: The `Encoder` that is being used. 208 :return: A dictionary compliants to the Language Specification's serialization 209 rules. 210 """ 211 return self.name
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
213 @classmethod 214 def fromdict(cls, dic, e): 215 """ Builds instance from dictionary 216 217 It is used during deserialization to create an openc2lib instance from the text message. 218 It takes an `Encoder` instance that is used to recursively build instances of the inner 219 objects (the `Encoder` provides standard methods to create instances of base objects like 220 strings, integers, boolean). 221 222 :param dic: The intermediary dictionary representation from which the object is built. 223 :param e: The `Encoder that is being used. 224 :return: An instance of this class initialized from the dictionary values. 225 """ 226 try: 227 return cls[str(dic)] 228 except: 229 raise TypeError("Unexpected enum value: ", dic)
Builds instance from dictionary
It is used during deserialization to create an openc2lib instance from the text message.
It takes an Encoder instance that is used to recursively build instances of the inner
objects (the Encoder provides standard methods to create instances of base objects like
strings, integers, boolean).
Parameters
- dic: The intermediary dictionary representation from which the object is built.
- e: The `Encoder that is being used.
Returns
An instance of this class initialized from the dictionary values.
Inherited Members
- aenum._enum.Enum
- name
- value
- values
235class EnumeratedID(Enumerated): 236 """ OpenC2 EnumeratedID 237 238 Implements OpenC2 EnumeratedID: 239 >A set of unnamed integral constants. The API value is an id. 240 241 The current implementation does not check the values to be integer. 242 However, coversion to/from integer is explicitly done during the 243 intermediary dictionary serialization, hence throwing an Exception if 244 the IDs are not integers. 245 """ 246 247 def todict(self, e): 248 """ Converts to dictionary 249 250 It is used to convert this object to an intermediary representation during 251 serialization. It takes an `Encoder` argument that is used to recursively 252 serialize inner data and structures (the `Encoder` provides standard methods 253 for converting base types to dictionaries).. 254 255 :param e: The `Encoder` that is being used. 256 :return: A dictionary compliants to the Language Specification's serialization 257 rules. 258 """ 259 return int(self.value) 260 261 @classmethod 262 def fromdict(cls, dic, e): 263 """ Builds instance from dictionary 264 265 It is used during deserialization to create an openc2lib instance from the text message. 266 It takes an `Encoder` instance that is used to recursively build instances of the inner 267 objects (the `Encoder` provides standard methods to create instances of base objects like 268 strings, integers, boolean). 269 270 :param dic: The intermediary dictionary representation from which the object is built. 271 :param e: The `Encoder that is being used. 272 :return: An instance of this class initialized from the dictionary values. 273 """ 274 try: 275 return cls(int(dic)) 276 except: 277 raise TypeError("Unexpected enum value: ", dic)
OpenC2 EnumeratedID
Implements OpenC2 EnumeratedID:
A set of unnamed integral constants. The API value is an id.
The current implementation does not check the values to be integer. However, coversion to/from integer is explicitly done during the intermediary dictionary serialization, hence throwing an Exception if the IDs are not integers.
247 def todict(self, e): 248 """ Converts to dictionary 249 250 It is used to convert this object to an intermediary representation during 251 serialization. It takes an `Encoder` argument that is used to recursively 252 serialize inner data and structures (the `Encoder` provides standard methods 253 for converting base types to dictionaries).. 254 255 :param e: The `Encoder` that is being used. 256 :return: A dictionary compliants to the Language Specification's serialization 257 rules. 258 """ 259 return int(self.value)
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
261 @classmethod 262 def fromdict(cls, dic, e): 263 """ Builds instance from dictionary 264 265 It is used during deserialization to create an openc2lib instance from the text message. 266 It takes an `Encoder` instance that is used to recursively build instances of the inner 267 objects (the `Encoder` provides standard methods to create instances of base objects like 268 strings, integers, boolean). 269 270 :param dic: The intermediary dictionary representation from which the object is built. 271 :param e: The `Encoder that is being used. 272 :return: An instance of this class initialized from the dictionary values. 273 """ 274 try: 275 return cls(int(dic)) 276 except: 277 raise TypeError("Unexpected enum value: ", dic)
Builds instance from dictionary
It is used during deserialization to create an openc2lib instance from the text message.
It takes an Encoder instance that is used to recursively build instances of the inner
objects (the Encoder provides standard methods to create instances of base objects like
strings, integers, boolean).
Parameters
- dic: The intermediary dictionary representation from which the object is built.
- e: The `Encoder that is being used.
Returns
An instance of this class initialized from the dictionary values.
Inherited Members
- aenum._enum.Enum
- name
- value
- values
279class Array(Openc2Type, list): 280 """ OpenC2 Array 281 282 Implements OpenC2 Array: 283 >An ordered list of unnamed fields with positionally-defined semantics. 284 Each field has a position, label, and type. 285 286 However, position does not matter in this implementation. 287 288 Derived classes must provide a `fieldtypes` dictionary that associate each field name 289 to its class. This is strictly required in order to instantiate the object at 290 deserialization time. However, no check is performed when new items are inserted. 291 """ 292 fieldtypes = None 293 """ Field types 294 295 A `dictionary` which keys are field names and which values are the corresponding classes. 296 Must be provided by any derived class. 297 """ 298 299 def todict(self, e): 300 """ Converts to dictionary 301 302 It is used to convert this object to an intermediary representation during 303 serialization. It takes an `Encoder` argument that is used to recursively 304 serialize inner data and structures (the `Encoder` provides standard methods 305 for converting base types to dictionaries).. 306 307 :param e: The `Encoder` that is being used. 308 :return: A dictionary compliants to the Language Specification's serialization 309 rules. 310 """ 311 lis = [] 312 for i in self: 313 lis.append = e.todict(i) 314 return lis 315 316 def fromdict(cls, dic, e): 317 """ !!! WARNING !!! 318 Currently not implemented because there are no examples of usage of this 319 type (only Array/net, which is not clear) 320 """ 321 raise Exception("Function not implemented")
OpenC2 Array
Implements OpenC2 Array:
An ordered list of unnamed fields with positionally-defined semantics. Each field has a position, label, and type.
However, position does not matter in this implementation.
Derived classes must provide a fieldtypes dictionary that associate each field name
to its class. This is strictly required in order to instantiate the object at
deserialization time. However, no check is performed when new items are inserted.
Field types
A dictionary which keys are field names and which values are the corresponding classes.
Must be provided by any derived class.
299 def todict(self, e): 300 """ Converts to dictionary 301 302 It is used to convert this object to an intermediary representation during 303 serialization. It takes an `Encoder` argument that is used to recursively 304 serialize inner data and structures (the `Encoder` provides standard methods 305 for converting base types to dictionaries).. 306 307 :param e: The `Encoder` that is being used. 308 :return: A dictionary compliants to the Language Specification's serialization 309 rules. 310 """ 311 lis = [] 312 for i in self: 313 lis.append = e.todict(i) 314 return lis
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
316 def fromdict(cls, dic, e): 317 """ !!! WARNING !!! 318 Currently not implemented because there are no examples of usage of this 319 type (only Array/net, which is not clear) 320 """ 321 raise Exception("Function not implemented")
!!! WARNING !!! Currently not implemented because there are no examples of usage of this type (only Array/net, which is not clear)
Inherited Members
- builtins.list
- list
- clear
- copy
- append
- insert
- extend
- pop
- remove
- index
- count
- reverse
- sort
323class ArrayOf: 324 """ OpenC2 ArrayOf 325 326 Implements OpenC2 ArrayOf(*vtype*): 327 >An ordered list of fields with the same semantics. 328 Each field has a position and type *vtype*. 329 330 It extends the `Array` type. However, to make its usage simpler and compliant 331 to the description given in the 332 Language Specification, the implementation is quite different. 333 Note that in many cases `ArrayOf` is only used to create arrays without the need 334 to derive an additional data type. 335 """ 336 337 def __new__(self, fldtype): 338 """ `ArrayOf` builder 339 340 Creates a unnamed derived class from `Array`, which `fieldtypes` is set to `fldtype`. 341 :param fldtype: The type of the fields stored in the array (indicated as *vtype* in 342 the Language Specification. 343 :return: A new unnamed class definition. 344 """ 345 class ArrayOf(Array): 346 """ OpenC2 unnamed `ArrayOf` 347 348 This class inherits from `Array` and sets its `fieldtypes` to a given type. 349 350 One might like to check the type of the elements before inserting them. 351 However, this is not the Python-way. Python use the duck typing approach: 352 https://en.wikipedia.org/wiki/Duck_typing 353 We ask for the type of objects just to keep this information according to 354 the OpenC2 data model. 355 356 Note: no `todict()` method is provided, since `Array.todict()` is fine here. 357 """ 358 fieldtype = fldtype 359 """ The type of values stored in this container """ 360 361 @classmethod 362 def fromdict(cls, lis, e): 363 """ Builds instance from dictionary 364 365 It is used during deserialization to create an openc2lib instance from the text message. 366 It takes an `Encoder` instance that is used to recursively build instances of the inner 367 objects (the `Encoder` provides standard methods to create instances of base objects like 368 strings, integers, boolean). 369 370 :param lis: The intermediary dictionary representation from which the object is built. 371 :param e: The `Encoder that is being used. 372 :return: An instance of this class initialized from the dictionary values. 373 """ 374 objlis = cls() 375 logger.debug('Building %s from %s in ArrayOf', cls, lis) 376 logger.debug('-> instantiating: %s', cls.fieldtype) 377 for k in lis: 378 objlis.append(e.fromdict(cls.fieldtype, k)) 379 380 return objlis 381 382 # This is the code if I would like to do type checking 383 # when inserting data 384# def append(self, item): 385# if isinstance(item, self.fieldtype): 386# super().append(item) 387# else: 388# raise ValueError(self.fieldtype,' allowed only') 389# 390# def insert(self, index, item): 391# if isinstance(item, self.fieldtype): 392# super().insert(index, item) 393# else: 394# raise ValueError(self.fieldtype,' allowed only') 395# 396# def __add__(self, item): 397# if isinstance(item, self.fieldtype): 398# super().__add__(item) 399# else: 400# raise ValueError(self.fieldtype,' allowed only') 401# 402# def __iadd__(self, item): 403# if isinstance(item, self.fieldtype): 404# super().__iadd__(item) 405# else: 406# raise ValueError(self.fieldtype,' allowed only') 407 408 return ArrayOf
OpenC2 ArrayOf
Implements OpenC2 ArrayOf(vtype):
An ordered list of fields with the same semantics. Each field has a position and type vtype.
It extends the Array type. However, to make its usage simpler and compliant
to the description given in the
Language Specification, the implementation is quite different.
Note that in many cases ArrayOf is only used to create arrays without the need
to derive an additional data type.
337 def __new__(self, fldtype): 338 """ `ArrayOf` builder 339 340 Creates a unnamed derived class from `Array`, which `fieldtypes` is set to `fldtype`. 341 :param fldtype: The type of the fields stored in the array (indicated as *vtype* in 342 the Language Specification. 343 :return: A new unnamed class definition. 344 """ 345 class ArrayOf(Array): 346 """ OpenC2 unnamed `ArrayOf` 347 348 This class inherits from `Array` and sets its `fieldtypes` to a given type. 349 350 One might like to check the type of the elements before inserting them. 351 However, this is not the Python-way. Python use the duck typing approach: 352 https://en.wikipedia.org/wiki/Duck_typing 353 We ask for the type of objects just to keep this information according to 354 the OpenC2 data model. 355 356 Note: no `todict()` method is provided, since `Array.todict()` is fine here. 357 """ 358 fieldtype = fldtype 359 """ The type of values stored in this container """ 360 361 @classmethod 362 def fromdict(cls, lis, e): 363 """ Builds instance from dictionary 364 365 It is used during deserialization to create an openc2lib instance from the text message. 366 It takes an `Encoder` instance that is used to recursively build instances of the inner 367 objects (the `Encoder` provides standard methods to create instances of base objects like 368 strings, integers, boolean). 369 370 :param lis: The intermediary dictionary representation from which the object is built. 371 :param e: The `Encoder that is being used. 372 :return: An instance of this class initialized from the dictionary values. 373 """ 374 objlis = cls() 375 logger.debug('Building %s from %s in ArrayOf', cls, lis) 376 logger.debug('-> instantiating: %s', cls.fieldtype) 377 for k in lis: 378 objlis.append(e.fromdict(cls.fieldtype, k)) 379 380 return objlis 381 382 # This is the code if I would like to do type checking 383 # when inserting data 384# def append(self, item): 385# if isinstance(item, self.fieldtype): 386# super().append(item) 387# else: 388# raise ValueError(self.fieldtype,' allowed only') 389# 390# def insert(self, index, item): 391# if isinstance(item, self.fieldtype): 392# super().insert(index, item) 393# else: 394# raise ValueError(self.fieldtype,' allowed only') 395# 396# def __add__(self, item): 397# if isinstance(item, self.fieldtype): 398# super().__add__(item) 399# else: 400# raise ValueError(self.fieldtype,' allowed only') 401# 402# def __iadd__(self, item): 403# if isinstance(item, self.fieldtype): 404# super().__iadd__(item) 405# else: 406# raise ValueError(self.fieldtype,' allowed only') 407 408 return ArrayOf
411class Map(Openc2Type, dict): 412 """ OpenC2 Map 413 414 Implements OpenC2 Map: 415 >An unordered map from a set of specified keys to values with semantics 416 bound to each key. Each field has an id, name and type. 417 418 However, the id is not considered in this implementation. 419 420 The implementation follows a similar logic than `Array`. Each derived class 421 is expected to provide a `fieldtypes` class attribute that associate field names 422 with their class definition. 423 424 Additionally, according to the Language Specification, `Map`s may be extended by 425 Profiles. Such extensions must use the `extend` and `regext` class attributes to 426 bind to the base element they extend and the `Profile` in which they are defined. 427 """ 428 fieldtypes: dict = None 429 """ Field types 430 431 A `dictionary` which keys are field names and which values are the corresponding classes. 432 Must be provided by any derived class. 433 """ 434 extend = None 435 """ Base class 436 437 Data types defined in the Language Specification shall not set this field. Data types defined in 438 Profiles that extends a Data Type defined in the Language Specification, must set this field to 439 the corresponding class of the base Data Type. 440 441 Note: Extensions defined in the openc2lib context are recommended to use the same name of the base 442 Data Type, and to distinguish them through appropriate usage of the namespacing mechanism. 443 """ 444 regext = {} 445 """ Registered extensions 446 447 Classes that implement a Data Type defined in the Language Specification will use this field to 448 register extensions defined by external Profiles. Classes that define extensions within Profiles 449 shall register themselves according to the specific documentation of the base type class, but 450 shall not modify this field. 451 """ 452 453 def todict(self, e): 454 """ Converts to dictionary 455 456 It is used to convert this object to an intermediary representation during 457 serialization. It takes an `Encoder` argument that is used to recursively 458 serialize inner data and structures (the `Encoder` provides standard methods 459 for converting base types to dictionaries).. 460 461 :param e: The `Encoder` that is being used. 462 :return: A dictionary compliants to the Language Specification's serialization 463 rules. 464 """ 465 newdic=dict() 466 467 # This is necessary because self.extend.fieldtypes does 468 # not exist for non-extended classes 469 if self.extend is None: 470 return e.todict(dict(self)) 471 472 for k,v in self.items(): 473 if k not in self.fieldtypes: 474 raise ValueError('Unknown field: ', k) 475 if k in self.extend.fieldtypes: 476 newdic[k] = v 477 else: 478 if self.nsid not in newdic: 479 newdic[self.nsid]={} 480 newdic[self.nsid][k]=v 481 482 return e.todict(newdic) 483 484 @classmethod 485 def fromdict(cls, dic, e): 486 """ Builds instance from dictionary 487 488 It is used during deserialization to create an openc2lib instance from the text message. 489 It takes an `Encoder` instance that is used to recursively build instances of the inner 490 objects (the `Encoder` provides standard methods to create instances of base objects like 491 strings, integers, boolean). 492 493 :param dic: The intermediary dictionary representation from which the object is built. 494 :param e: The `Encoder that is being used. 495 :return: An instance of this class initialized from the dictionary values. 496 """ 497 objdic = {} 498 extension = None 499 logger.debug('Building %s from %s in Map', cls, dic) 500 for k,v in dic.items(): 501 if k in cls.fieldtypes: 502 objdic[k] = e.fromdict(cls.fieldtypes[k], v) 503 elif k in cls.regext: 504 logger.debug(' Using profile %s to decode: %s', k, v) 505 extension = cls.regext[k] 506 for l,w in v.items(): 507 objdic[l] = e.fromdict(extension.fieldtypes[l], w) 508 else: 509 raise TypeError("Unexpected field: ", k) 510 511 if extension is not None: 512 cls = extension 513 514 return cls(objdic)
OpenC2 Map
Implements OpenC2 Map:
An unordered map from a set of specified keys to values with semantics bound to each key. Each field has an id, name and type.
However, the id is not considered in this implementation.
The implementation follows a similar logic than Array. Each derived class
is expected to provide a fieldtypes class attribute that associate field names
with their class definition.
Additionally, according to the Language Specification, Maps may be extended by
Profiles. Such extensions must use the extend and regext class attributes to
bind to the base element they extend and the Profile in which they are defined.
Field types
A dictionary which keys are field names and which values are the corresponding classes.
Must be provided by any derived class.
Base class
Data types defined in the Language Specification shall not set this field. Data types defined in Profiles that extends a Data Type defined in the Language Specification, must set this field to the corresponding class of the base Data Type.
Note: Extensions defined in the openc2lib context are recommended to use the same name of the base Data Type, and to distinguish them through appropriate usage of the namespacing mechanism.
Registered extensions
Classes that implement a Data Type defined in the Language Specification will use this field to register extensions defined by external Profiles. Classes that define extensions within Profiles shall register themselves according to the specific documentation of the base type class, but shall not modify this field.
453 def todict(self, e): 454 """ Converts to dictionary 455 456 It is used to convert this object to an intermediary representation during 457 serialization. It takes an `Encoder` argument that is used to recursively 458 serialize inner data and structures (the `Encoder` provides standard methods 459 for converting base types to dictionaries).. 460 461 :param e: The `Encoder` that is being used. 462 :return: A dictionary compliants to the Language Specification's serialization 463 rules. 464 """ 465 newdic=dict() 466 467 # This is necessary because self.extend.fieldtypes does 468 # not exist for non-extended classes 469 if self.extend is None: 470 return e.todict(dict(self)) 471 472 for k,v in self.items(): 473 if k not in self.fieldtypes: 474 raise ValueError('Unknown field: ', k) 475 if k in self.extend.fieldtypes: 476 newdic[k] = v 477 else: 478 if self.nsid not in newdic: 479 newdic[self.nsid]={} 480 newdic[self.nsid][k]=v 481 482 return e.todict(newdic)
Converts to dictionary
It is used to convert this object to an intermediary representation during
serialization. It takes an Encoder argument that is used to recursively
serialize inner data and structures (the Encoder provides standard methods
for converting base types to dictionaries)..
Parameters
- e: The
Encoderthat is being used.
Returns
A dictionary compliants to the Language Specification's serialization rules.
484 @classmethod 485 def fromdict(cls, dic, e): 486 """ Builds instance from dictionary 487 488 It is used during deserialization to create an openc2lib instance from the text message. 489 It takes an `Encoder` instance that is used to recursively build instances of the inner 490 objects (the `Encoder` provides standard methods to create instances of base objects like 491 strings, integers, boolean). 492 493 :param dic: The intermediary dictionary representation from which the object is built. 494 :param e: The `Encoder that is being used. 495 :return: An instance of this class initialized from the dictionary values. 496 """ 497 objdic = {} 498 extension = None 499 logger.debug('Building %s from %s in Map', cls, dic) 500 for k,v in dic.items(): 501 if k in cls.fieldtypes: 502 objdic[k] = e.fromdict(cls.fieldtypes[k], v) 503 elif k in cls.regext: 504 logger.debug(' Using profile %s to decode: %s', k, v) 505 extension = cls.regext[k] 506 for l,w in v.items(): 507 objdic[l] = e.fromdict(extension.fieldtypes[l], w) 508 else: 509 raise TypeError("Unexpected field: ", k) 510 511 if extension is not None: 512 cls = extension 513 514 return cls(objdic)
Builds instance from dictionary
It is used during deserialization to create an openc2lib instance from the text message.
It takes an Encoder instance that is used to recursively build instances of the inner
objects (the Encoder provides standard methods to create instances of base objects like
strings, integers, boolean).
Parameters
- dic: The intermediary dictionary representation from which the object is built.
- e: The `Encoder that is being used.
Returns
An instance of this class initialized from the dictionary values.
Inherited Members
- builtins.dict
- get
- setdefault
- pop
- popitem
- keys
- items
- values
- update
- fromkeys
- clear
- copy
516class MapOf: 517 """ OpenC2 MapOf 518 519 Implements OpenC2 MapOf(*ktype, vtype*): 520 >An unordered set of keys to values with the same semantics. 521 Each key has key type *ktype* and is mapped to value type *vtype*. 522 523 It extends `Map` with the same approach already used for `ArrayOf`. 524 `MapOf` for specific types are created as anonymous classes by passing 525 `ktype` and `vtype` as arguments. 526 527 Note: `MapOf` implementation currently does not support extensins!. 528 """ 529 530 def __new__(self,ktype, vtype): 531 """ `MapOf` builder 532 533 Creates a unnamed derived class from `Map`, which `fieldtypes` is set to a single value 534 `ktype: vtype`. 535 :param ktype: The key type of the items stored in the map. 536 :param vtype: The value type of the items stored in the map. 537 :return: A new unnamed class definition. 538 """ 539 class MapOf(Map): 540 """ OpenC2 unnamed `MapOf` 541 542 This class inherits from `Map` and sets its `fieldtypes` to a given type. 543 544 Note: no `todict()` method is provided, since `Map.todict()` is fine here. 545 """ 546 fieldtypes = {ktype: vtype} 547 """ The type of values stored in this container """ 548 549 @classmethod 550 def fromdict(cls, dic, e): 551 """ Builds instance from dictionary 552 553 It is used during deserialization to create an openc2lib instance from the text message. 554 It takes an `Encoder` instance that is used to recursively build instances of the inner 555 objects (the `Encoder` provides standard methods to create instances of base objects like 556 strings, integers, boolean). 557 558 :param dic: The intermediary dictionary representation from which the object is built. 559 :param e: The `Encoder that is being used. 560 :return: An instance of this class initialized from the dictionary values. 561 """ 562 objdic = {} 563 logger.debug('Building %s from %s in MapOf', cls, dic) 564 for k,v in dic.items(): 565 kclass = list(cls.fieldtypes)[0] 566 objk = e.fromdict(kclass, k) 567 objdic[objk] = e.fromdict(cls.fieldtypes[kclass], v) 568 return objdic 569 570 return MapOf
OpenC2 MapOf
Implements OpenC2 MapOf(ktype, vtype):
An unordered set of keys to values with the same semantics. Each key has key type ktype and is mapped to value type vtype.
It extends Map with the same approach already used for ArrayOf.
MapOf for specific types are created as anonymous classes by passing
ktype and vtype as arguments.
Note: MapOf implementation currently does not support extensins!.
530 def __new__(self,ktype, vtype): 531 """ `MapOf` builder 532 533 Creates a unnamed derived class from `Map`, which `fieldtypes` is set to a single value 534 `ktype: vtype`. 535 :param ktype: The key type of the items stored in the map. 536 :param vtype: The value type of the items stored in the map. 537 :return: A new unnamed class definition. 538 """ 539 class MapOf(Map): 540 """ OpenC2 unnamed `MapOf` 541 542 This class inherits from `Map` and sets its `fieldtypes` to a given type. 543 544 Note: no `todict()` method is provided, since `Map.todict()` is fine here. 545 """ 546 fieldtypes = {ktype: vtype} 547 """ The type of values stored in this container """ 548 549 @classmethod 550 def fromdict(cls, dic, e): 551 """ Builds instance from dictionary 552 553 It is used during deserialization to create an openc2lib instance from the text message. 554 It takes an `Encoder` instance that is used to recursively build instances of the inner 555 objects (the `Encoder` provides standard methods to create instances of base objects like 556 strings, integers, boolean). 557 558 :param dic: The intermediary dictionary representation from which the object is built. 559 :param e: The `Encoder that is being used. 560 :return: An instance of this class initialized from the dictionary values. 561 """ 562 objdic = {} 563 logger.debug('Building %s from %s in MapOf', cls, dic) 564 for k,v in dic.items(): 565 kclass = list(cls.fieldtypes)[0] 566 objk = e.fromdict(kclass, k) 567 objdic[objk] = e.fromdict(cls.fieldtypes[kclass], v) 568 return objdic 569 570 return MapOf