from .LibraryParser import LibraryParser from ..Guid import Guid class YAMLLibraryParser (LibraryParser): def __init__(self, manager): LibraryParser.__init__(self, manager) self.yamlIds = dict() # these two are special reserved tagNames # self.yamlIds["entityDefinitions"] = None # self.yamlIds["instance"] = { } self.manager = manager self._instances_awaiting_sugar = [] def apply_sugar(self): print("applying syntactic sugar to remaining instances...") for inst in self._instances_awaiting_sugar: self.load_instance(inst) def load_sugar_from_file(self, filename): print("loading sugar from " + filename) import yaml with open(filename, 'r') as file: content = yaml.safe_load_all(file) for doc in content: for elem in doc: if "entityDefinitions" in elem or "instance" in elem: continue self.load_instance(elem) pass def load_entity_definitions_from_file(self, filename): print("loading entity defs from " + filename) import yaml with open(filename, 'r') as file: content = yaml.safe_load_all(file) for doc in content: for elem in doc: if "entityDefinitions" in elem: entities = elem["entityDefinitions"] for entity in entities: for key in entity: self.manager.register_entity_reference(key, entity[key]) def load_instance_with_template(self, elem, template): parentInstanceId = None if "instance" in template: parentInstanceId = self.manager.expand_entity_references(template["instance"]) else: for key in self.yamlIds: if key in template: parentInstanceId = self.manager.expand_entity_references(template[key]) break if "instance" in elem: instanceId = Guid(self.manager.expand_entity_references(elem["instance"])) creatorKey = 'instance' else: for key in self.yamlIds: if key in elem: instanceId = Guid(self.manager.expand_entity_references(elem[key])) creatorKey = key break if "attributes" in template: attrs = template["attributes"] if isinstance(attrs, list): for attr in attrs: if "customTagName" in attr: customTagName = attr["customTagName"] if customTagName in elem: attrinst = Guid(self.manager.expand_entity_references(attr["instance"])) attrval = elem[customTagName] self.manager.set_attribute_value(instanceId, attrinst, attrval) if "relationships" in template: rels = template["relationships"] for rel in rels: if "customTagName" in rel: customTagName = rel["customTagName"] if customTagName in elem: relinst = Guid(self.manager.expand_entity_references(rel["instance"])) relval = Guid(self.manager.expand_entity_references(elem[customTagName])) self.manager.assign_relationship(instanceId, relinst, relval) def load_instance(self, elem, elemParent = None): # 'class' and 'relationship' are both at the 'same level' # so we can't define 'relationship' without first defining 'class' # we could try to keep looping as long as we're still getting "unknown tag name" # (instanceID is None), but we could get stuck that way... # for now, let's just forward define important classes (e.g. IDC_Relationship) customTagName = None if "customTagName" in elem: customTagName = elem["customTagName"] self.yamlIds[customTagName] = elem print("registering customTagName '" + customTagName + "'") template = None templateKey = None if not "instance" in elem: for key in self.yamlIds: #print(elem) if key != "instance" and key in elem: template = self.yamlIds[key] templateKey = key #print("got template " + key) break classId = None classIndex = None if template is None and elemParent is not None: template = elemParent if template is not None: if "instance" in template: classId = Guid(self.manager.expand_entity_references(template["instance"])) else: for key in self.yamlIds: if key in template: classId = Guid(self.manager.expand_entity_references(template[key])) break if "index" in template: classIndex = template["index"] instanceId = None creatorKey = None if "instance" in elem: instanceId = Guid(self.manager.expand_entity_references(elem["instance"])) creatorKey = 'instance' else: for key in self.yamlIds: if key in elem: instanceId = Guid(self.manager.expand_entity_references(elem[key])) creatorKey = key break index = None if "index" in elem: index = elem["index"] # else: # print("index not found for element") # print(elem) if classId is None and instanceId is not None: classId = instanceId # HACK HACK if instanceId is not None: self.manager.add_instance(classId, instanceId, classIndex, index) if creatorKey == 'class': print("creating class " + instanceId.get_value()) if "instances" in elem: classInsts = elem["instances"] for inst in classInsts: self.load_instance(inst, elem) self.manager.create_class(instanceId, index) else: print("creating instance " + instanceId.get_value() + " (of class " + classId.get_value() + ")") self.manager.create_instance_of(classId, instanceId, classIndex, index) if templateKey is not None: if template is not None: #print("using template (" + templateKey + ")") #print(template) self.load_instance_with_template(elem, template) else: #print("ignoring '" + templateKey + "'") pass def load_instances_from_file(self, filename): print("loading instances from " + filename) import yaml with open(filename, 'r') as file: content = yaml.safe_load_all(file) for doc in content: for elem in doc: if "instance" in elem: self.load_instance(elem) else: self._instances_awaiting_sugar.append(elem)