def parse_ontology_content_property(self, ontology_content, new_property_proxy_order, model_proxy): new_property_proxy_name = ontology_content["name"] new_property_proxy_id = ontology_content.get("id") new_property_proxy_field_type = QPropertyTypes.get(ontology_content["property_type"]) assert new_property_proxy_field_type is not None, "invalid property_type specified" (new_property_proxy, created_property_proxy) = QPropertyProxy.objects.get_or_create( # these fields are the "defining" ones (other fields can change below w/out creating new proxies) ontology=self, model_proxy=model_proxy, name=new_property_proxy_name, cim_id=new_property_proxy_id, field_type=new_property_proxy_field_type, ) category_id = ontology_content.get("category_id") new_property_proxy.category_id = category_id new_property_proxy.category_proxy = find_in_sequence(lambda c: c.cim_id == category_id, model_proxy.category_proxies.all()) new_property_proxy.order = new_property_proxy_order new_property_proxy.is_meta = ontology_content.get("is_meta", False) new_property_proxy.is_nillable = ontology_content.get("is_nillable", False) new_property_proxy.is_hierarchical = ontology_content.get("is_hierarchical", False) new_property_proxy_documentation = ontology_content.get("documentation") if new_property_proxy_documentation: new_property_proxy.documentation = remove_spaces_and_linebreaks(new_property_proxy_documentation) new_property_proxy_cardinality = re.split("\.|,", ontology_content.get("cardinality")) # TODO: DECIDE ONCE-AND-FOR-ALL IF "cardinality" IS SPLIT ON '.' OR ',' new_property_proxy.cardinality_min = new_property_proxy_cardinality[0] new_property_proxy.cardinality_max = new_property_proxy_cardinality[1] new_property_proxy.values = ontology_content.get("values") if new_property_proxy_field_type == QPropertyTypes.ATOMIC: new_property_proxy_atomic_type_type = ontology_content.get("atomic_type") if new_property_proxy_atomic_type_type == "STRING": new_property_proxy_atomic_type_type = "DEFAULT" new_property_proxy_atomic_type = QAtomicTypes.get(new_property_proxy_atomic_type_type) assert new_property_proxy_atomic_type is not None, "invalid atomic_type specified" new_property_proxy.atomic_type = new_property_proxy_atomic_type elif new_property_proxy_field_type == QPropertyTypes.ENUMERATION: new_property_proxy.enumeration_is_open = ontology_content.get("enumeration_is_open") new_property_proxy.enumeration_choices = ontology_content.get("enumeration_members") else: # new_property_proxy_field_type == QPropertyTypes.RELATIONSHIP new_property_proxy.relationship_target_names = ontology_content.get("relationship_targets") # target_names are set now; target_models are set later in "QPropertyProxy.reset" new_property_proxy.save() return new_property_proxy
def parse_ontology_content_category(self, ontology_content, new_category_proxy_order, model_proxy): new_category_proxy_name = ontology_content["name"] new_category_proxy_id = ontology_content["id"] (new_category_proxy, created_category_proxy) = QCategoryProxy.objects.get_or_create( # these fields are the "defining" ones (other fields can change below w/out creating new proxies) ontology=self, model_proxy=model_proxy, name=new_category_proxy_name, cim_id=new_category_proxy_id, ) new_category_proxy.order = new_category_proxy_order new_category_proxy_documentation = ontology_content.get("documentation") if new_category_proxy_documentation: new_category_proxy.documentation = remove_spaces_and_linebreaks(new_category_proxy_documentation) new_category_proxy.save() return new_category_proxy
def register_cim1(self, **kwargs): request = kwargs.pop("request", None) try: self.file.open() ontology_content = et.parse(self.file) self.file.close() except IOError: msg = "Error opening file: %s" % self.file if request: messages.add_message(request, messages.ERROR, msg) return recategorization_needed = False old_model_proxies = list(self.model_proxies.all()) # list forces qs evaluation immediately new_model_proxies = [] for i, model_proxy in enumerate(xpath_fix(ontology_content, "//classes/class")): model_proxy_ontology = self model_proxy_name = xpath_fix(model_proxy, "name/text()")[0] model_proxy_stereotype = get_index(xpath_fix(model_proxy, "@stereotype"), 0) model_proxy_namespace = get_index(xpath_fix(model_proxy, "@namespace"), 0) model_proxy_package = get_index(xpath_fix(model_proxy, "@package"), 0) model_proxy_documentation = get_index(xpath_fix(model_proxy, "description/text()"), 0) if model_proxy_documentation: model_proxy_documentation = remove_spaces_and_linebreaks(model_proxy_documentation) else: model_proxy_documentation = u"" (new_model_proxy, created_model_proxy) = QModelProxy.objects.get_or_create( ontology=model_proxy_ontology, name=model_proxy_name, ) if created_model_proxy: recategorization_needed = True new_model_proxy.order = i + 1 new_model_proxy.stereotype = model_proxy_stereotype new_model_proxy.namespace = model_proxy_namespace new_model_proxy.package = model_proxy_package new_model_proxy.documentation = model_proxy_documentation new_model_proxy.save() new_model_proxies.append(new_model_proxy) old_property_proxies = list(new_model_proxy.standard_properties.all()) # list forces qs evaluation immediately new_property_proxies = [] for j, property_proxy in enumerate(xpath_fix(model_proxy, "attributes/attribute")): property_proxy_name = re.sub(r'\.', '_', str(xpath_fix(property_proxy, "name/text()")[0])) property_proxy_field_type = xpath_fix(property_proxy, "type/text()")[0] property_proxy_is_label = get_index(xpath_fix(property_proxy, "@is_label"), 0) property_proxy_stereotype = get_index(xpath_fix(property_proxy, "@stereotype"), 0) property_proxy_namespace = get_index(xpath_fix(property_proxy, "@namespace"), 0) property_proxy_required = get_index(xpath_fix(property_proxy, "@required"), 0) property_proxy_documentation = get_index(xpath_fix(property_proxy, "description/text()"), 0) if property_proxy_documentation: property_proxy_documentation = remove_spaces_and_linebreaks(property_proxy_documentation) else: property_proxy_documentation = u"" property_proxy_atomic_type = get_index(xpath_fix(property_proxy, "atomic/atomic_type/text()"), 0) if property_proxy_atomic_type: if property_proxy_atomic_type == u"STRING": property_proxy_atomic_type = u"DEFAULT" property_proxy_atomic_type = QAtomicPropertyTypes.get(property_proxy_atomic_type) property_proxy_enumeration_choices = [] for property_proxy_enumeration_choice in xpath_fix(property_proxy, "enumeration/choice"): property_proxy_enumeration_choices.append(xpath_fix(property_proxy_enumeration_choice, "text()")[0]) property_proxy_relationship_cardinality_min = get_index(xpath_fix(property_proxy, "relationship/cardinality/@min"), 0) property_proxy_relationship_cardinality_max = get_index(xpath_fix(property_proxy, "relationship/cardinality/@max"), 0) property_proxy_relationship_target_name = get_index(xpath_fix(property_proxy, "relationship/target/text()"), 0) (new_property_proxy, created_property) = QStandardPropertyProxy.objects.get_or_create( model_proxy=new_model_proxy, name=property_proxy_name, field_type=property_proxy_field_type ) if created_property: recategorization_needed = True new_property_proxy.order = j + 1 new_property_proxy.documentation = property_proxy_documentation new_property_proxy.is_label = property_proxy_is_label == "true" new_property_proxy.stereotype = property_proxy_stereotype new_property_proxy.namespace = property_proxy_namespace if property_proxy_field_type == QPropertyTypes.RELATIONSHIP: if property_proxy_relationship_cardinality_min and property_proxy_relationship_cardinality_max: new_property_proxy.cardinality = u"%s|%s" % (property_proxy_relationship_cardinality_min, property_proxy_relationship_cardinality_max) else: if property_proxy_required: new_property_proxy.cardinality = u"1|1" new_property_proxy.atomic_type = property_proxy_atomic_type new_property_proxy.enumeration_choices = "|".join(property_proxy_enumeration_choices) new_property_proxy.relationship_target_name = property_proxy_relationship_target_name new_property_proxy.save() new_property_proxies.append(new_property_proxy) # if there's anything in old_property_proxies not in new_property_proxies, delete it for old_property_proxy in old_property_proxies: if old_property_proxy not in new_property_proxies: old_property_proxy.delete() new_model_proxy.save() # save parent again for the m2m relationship # if there's anything in old_model_proxies not in new_model_proxies, delete it for old_model_proxy in old_model_proxies: if old_model_proxy not in new_model_proxies: old_model_proxy.delete() # reset whatever's left for model_proxy in QModelProxy.objects.filter(ontology=self): for property_proxy in model_proxy.standard_properties.all(): property_proxy.reset() property_proxy.save() if recategorization_needed: msg = "Since you are re-registering an existing version, you will also have to re-register the corresponding categorization" if request: messages.add_message(request, messages.WARNING, msg)
def parse_ontology_content_model(self, ontology_content, new_model_proxy_order): new_model_proxy_name = ontology_content["name"] new_model_proxy_package = ontology_content["package"] # a SPECIALIZATION model ought to have an explicit id; a SCHEMA model can just create one dynamically new_model_proxy_id = ontology_content.get("id", "{}.{}".format(self.key, new_model_proxy_name)) parent_model_proxy = None if self.parent: try: parent_model_proxy = self.parent.model_proxies.get(package=new_model_proxy_package, name=new_model_proxy_name) except QModelProxy.DoesNotExist: # not everything in a specialization has to be based on a parent model, right? pass (new_model_proxy, created_model_proxy) = QModelProxy.objects.get_or_create( # these fields are the "defining" ones (other fields can change below w/out creating new proxies) ontology=self, name=new_model_proxy_name, package=new_model_proxy_package, cim_id=new_model_proxy_id, ) new_model_proxy.order = new_model_proxy_order new_model_proxy.is_document = ontology_content.get("is_document", False) new_model_proxy.is_meta = ontology_content.get("is_meta", False) new_model_proxy_documentation = ontology_content.get("documentation") if new_model_proxy_documentation: new_model_proxy.documentation = remove_spaces_and_linebreaks(new_model_proxy_documentation) new_model_proxy_label = ontology_content.get("label") if new_model_proxy_label is None and parent_model_proxy is not None: new_model_proxy_label = parent_model_proxy.label new_model_proxy.label = new_model_proxy_label new_model_proxy.save() # ...now add any categories... old_category_proxies = list(new_model_proxy.category_proxies.all()) new_category_proxies = [] inherited_categories = ontology_content["categories"]["inherited"] # inherited categories are included at the start excluded_categories = ontology_content["categories"]["excluded"] # excluded categories don't have to be uesd at all defined_categories = ontology_content["categories"]["defined"] # defined categories are added as normal if parent_model_proxy: for inherited_category_order, inherited_category_proxy in enumerate(parent_model_proxy.category_proxies.filter(name__in=inherited_categories), start=1): new_model_proxy.category_proxies.add(inherited_category_proxy) new_category_proxies.append(inherited_category_proxy) else: assert len(inherited_categories) == 0, "it makes no sense to specify 'inherited_categories' w/out providing a base model" for ontology_category_order, ontology_category in enumerate(defined_categories, start=len(new_category_proxies) + 1): new_category_proxy = self.parse_ontology_content_category(ontology_category, ontology_category_order, new_model_proxy) new_category_proxies.append(new_category_proxy) # TODO: ONLY DELETE A category_proxy IF THERE ARE NO OTHER MODELS (FROM ANY ONTOLOGY) LINKED TO IT for old_category_proxy in old_category_proxies: if old_category_proxy not in new_category_proxies: old_category_proxy.delete() # (don't forget to create a placeholder category for properties that are uncategorized) uncategorized_category_proxy, created_uncategorized_category_proxy = QCategoryProxy.objects.get_or_create( ontology=self, model_proxy=new_model_proxy, name=UNCATEGORIZED_CATEGORY_PROXY_NAME, is_uncategorized=True, ) if created_uncategorized_category_proxy: uncategorized_category_proxy.order = len(new_category_proxies) + 1 uncategorized_category_proxy.save() new_category_proxies.append(uncategorized_category_proxy) # ...now add any properties... old_property_proxies = list(new_model_proxy.property_proxies.all()) new_property_proxies = [] inherited_properties = ontology_content["properties"]["inherited"] # inherited properties are included at the start excluded_properties = ontology_content["properties"]["excluded"] # excluded properties don't have to be uesd at all defined_properties = ontology_content["properties"]["defined"] # defined properties are added as normal if parent_model_proxy: for inherited_property_order, inherited_property_proxy in enumerate(parent_model_proxy.property_proxies.filter(name__in=inherited_properties), start=1): new_model_proxy.property_proxies.add(inherited_property_proxy) new_property_proxies.append(inherited_property_proxy) else: assert len(inherited_properties) == 0, "it makes no sense to specify 'inherited_properties' w/out providing a base model" for ontology_property_order, ontology_property in enumerate(defined_properties, start=len(new_property_proxies) + 1): new_property_proxy = self.parse_ontology_content_property(ontology_property, ontology_property_order, new_model_proxy) new_property_proxies.append(new_property_proxy) # TODO: ONLY DELETE A property_proxy IF THERE ARE NO OTHER MODELS (FROM ANY ONTOLOGY) LINKED TO IT for old_property_proxy in old_property_proxies: if old_property_proxy not in new_property_proxies: old_property_proxy.delete() return new_model_proxy
def parse_ontology_content(self, ontology_content): # 1st do some logical checks on the content... # name should match ontology_name = ontology_content.get("name") if self.name != ontology_name: msg = "The name of this ontology instance does not match that found in the QConfig file" raise QError(msg) # version should match(ish) ontology_version = ontology_content.get("version") if self.version.major() != Version(ontology_version).major(): msg = "The major version of this ontology instance does not match that found in the QConfig file" raise QError(msg) # documentation can be overwritten ontology_documentation = ontology_content.get("documentation") if ontology_documentation: self.documentation = remove_spaces_and_linebreaks(ontology_documentation) # type should match... ontology_type = QOntologyTypes.get(ontology_content.get("ontology_type")) assert ontology_type is not None, "invalid ontology_type specified" if self.ontology_type != ontology_type: msg = "The ontology_type of this ontology instance does not match that found in the QConfig file" raise QError(msg) # if specified, parent must match (and it must be specified for SPECIALIZATIONS) ontology_base_key = ontology_content.get("ontology_base") if ontology_base_key: ontology_base = QOntology.objects.has_key(ontology_base_key).first() # (self.parent.is_registered will already have been checked by the "register" fn) if self.parent != ontology_base: msg = "The ontology_base of this ontology instance does not match that found in the QConfig file" raise QError(msg) elif ontology_type == QOntologyTypes.SPECIALIZATION: msg = "A SPECIALIZATION must include an ontology_base" raise QError(msg) # now create / setup all of the proxies contained in this ontology... old_model_proxies = list(self.model_proxies.all()) new_model_proxies = [] inherited_classes = ontology_content["classes"]["inherited"] # inherited classes are included at the start excluded_classes = ontology_content["classes"]["excluded"] # excluded classes don't have to be used at all defined_classes = ontology_content["classes"]["defined"] # defined classes are added as normal # AS OF V0.17.0, PROXIES ARE NOT CONSTRAINED BY ONTOLOGY; # THEREFORE THERE IS NO NEED TO COPY INHERITED PROXIES ACROSS # (THAT'S WHY I DON'T NEED "inherited_model_proxies" BELOW) # if self.parent: # inherited_model_proxies = self.parent.model_proxies.in_fully_qualified_names(inherited_classes) assert len(inherited_classes) == 0 for ontology_model_order, ontology_model in enumerate(defined_classes, start=len(new_model_proxies)+1): new_model_proxy = self.parse_ontology_content_model(ontology_model, ontology_model_order) new_model_proxies.append(new_model_proxy) # if there's anything in old_model_proxies not in new_model_proxies, delete it... for old_model_proxy in old_model_proxies: if old_model_proxy not in new_model_proxies: old_model_proxy.delete() # reset whatever's left... for model_proxy in QModelProxy.objects.filter(ontology=self): model_proxy.reset(force_save=True) for category_proxy in model_proxy.category_proxies.filter(ontology=self): category_proxy.reset(force_save=True) for property_proxy in model_proxy.property_proxies.filter(ontology=self): property_proxy.reset(force_save=True)
def create_component_proxy(self, component_proxy_node, parent_component_proxy=None): """ recursively create component proxies, keeping track of their hierarchy :param component_proxy_node: :param parent_component_proxy: :return: """ self.component_order += 1 component_proxy_vocabulary = self component_proxy_name = get_index(xpath_fix(component_proxy_node, "@name"), 0) component_proxy_order = self.component_order component_proxy_documentation = get_index(xpath_fix(component_proxy_node, "definition/text()"), 0) if component_proxy_documentation: component_proxy_documentation = remove_spaces_and_linebreaks(component_proxy_documentation) (new_component_proxy, created_component_proxy) = QComponentProxy.objects.get_or_create( vocabulary=component_proxy_vocabulary, name=component_proxy_name, parent=parent_component_proxy ) new_component_proxy.documentation = component_proxy_documentation new_component_proxy.order = component_proxy_order new_component_proxy.save() old_category_proxies = list(new_component_proxy.category_proxies.all()) # list forces qs evaluation immediately new_category_proxies = [] category_proxy_component = new_component_proxy for i, category_proxy_node in enumerate(xpath_fix(component_proxy_node, "./parametergroup")): category_proxy_name = xpath_fix(category_proxy_node, "@name")[0] category_proxy_key = slugify(category_proxy_name) category_proxy_order = i + 1 category_proxy_documentation = get_index(xpath_fix(category_proxy_node, "definition/text()"), 0) if category_proxy_documentation: category_proxy_documentation = remove_spaces_and_linebreaks(category_proxy_documentation) (new_category_proxy, created_category_proxy) = QScientificCategoryProxy.objects.get_or_create( component_proxy=category_proxy_component, name=category_proxy_name ) new_category_proxy.documentation = category_proxy_documentation new_category_proxy.order = category_proxy_order new_category_proxy.key = category_proxy_key new_category_proxy.save() new_category_proxies.append(new_category_proxy) old_property_proxies = list(new_category_proxy.properties.all()) # list forces qs evaluation immediately new_property_proxies = [] property_proxy_component = new_component_proxy property_proxy_category = new_category_proxy for j, property_proxy_node in enumerate(xpath_fix(category_proxy_node, "./parameter")): property_proxy_name = get_index(xpath_fix(property_proxy_node, "@name"), 0) property_proxy_choice = get_index(xpath_fix(property_proxy_node, "@choice"), 0) property_proxy_order = j + 1 property_proxy_documentation = get_index(xpath_fix(property_proxy_node, "definition/text()"), 0) if property_proxy_documentation: property_proxy_documentation = remove_spaces_and_linebreaks(property_proxy_documentation) property_proxy_enumeration_values = [] for property_proxy_enumeration_value in xpath_fix(property_proxy_node, "value"): property_proxy_enumeration_value_name = get_index(xpath_fix(property_proxy_enumeration_value, "@name"), 0) if property_proxy_enumeration_value_name: property_proxy_enumeration_values.append(property_proxy_enumeration_value_name) (new_property_proxy, created_property_proxy) = QScientificPropertyProxy.objects.get_or_create( component_proxy=property_proxy_component, category=property_proxy_category, name=property_proxy_name, ) new_property_proxy.choice = property_proxy_choice new_property_proxy.documentation = property_proxy_documentation new_property_proxy.order = property_proxy_order new_property_proxy.enumeration_choices = "|".join(property_proxy_enumeration_values) new_property_proxy.save() new_property_proxies.append(new_property_proxy) # if there's anything in old_property_proxies not in new_property_proxies, delete it for old_property_proxy in old_property_proxies: if old_property_proxy not in new_property_proxies: old_property_proxy.delete() # reset whatever's left for property_proxy in QScientificPropertyProxy.objects.filter(component_proxy=new_component_proxy, category=new_category_proxy): property_proxy.reset() property_proxy.save() # if there's anything in old_category_proxies not in new_category_proxies, delete it for old_category_proxy in old_category_proxies: if old_category_proxy not in new_category_proxies: old_category_proxy.delete() # recurse for child_component_proxy_node in xpath_fix(component_proxy_node, "./component"): self.create_component_proxy(child_component_proxy_node, new_component_proxy) # (do this last in case any m2m fields are added recursively) self.new_component_proxies.append(new_component_proxy)
def register(self, **kwargs): request = kwargs.pop("request", None) try: self.file.open() categorization_content = et.parse(self.file) self.file.close() except IOError: msg = "Error opening file: %s" % self.file if request: messages.add_message(request, messages.ERROR, msg) return ontologies = self.ontologies.all() if not ontologies: msg = "QCategorization '%s' has not been associated with any ontologies. It's kind of silly to register it now." % (self) if request: messages.add_message(request, messages.WARNING, msg) else: print(msg) old_category_proxies = list(self.category_proxies.all()) # list forces qs evaluation immediately new_category_proxies = [] for i, category_proxy in enumerate(xpath_fix(categorization_content, "//category")): category_proxy_categorization = self category_proxy_name = get_index(xpath_fix(category_proxy, "name/text()"), 0) category_proxy_key = get_index(xpath_fix(category_proxy, "key/text()"), 0) category_proxy_order = get_index(xpath_fix(category_proxy, 'order/text()'), 0) category_proxy_documentation = get_index(xpath_fix(category_proxy, "description/text()"), 0) if category_proxy_documentation: category_proxy_documentation = remove_spaces_and_linebreaks(category_proxy_documentation) (new_category_proxy, created_category) = QStandardCategoryProxy.objects.get_or_create( categorization=category_proxy_categorization, name=category_proxy_name, ) new_category_proxy.documentation = category_proxy_documentation new_category_proxy.key = category_proxy_key or slugify(category_proxy_name) new_category_proxy.order = category_proxy_order or i if not created_category: # remove any existing relationships (going to replace them during this registration)... new_category_proxy.properties.clear() for j, field in enumerate(xpath_fix(categorization_content, "//field[category_key='%s']" % new_category_proxy.key)): model_name = get_index(xpath_fix(field, "./ancestor::model/name/text()"), 0) field_name = get_index(xpath_fix(field, "name/text()"), 0) for ontology in ontologies: try: model_proxy = ontology.model_proxies.get(name__iexact=model_name) property_proxy = model_proxy.standard_properties.get(name__iexact=field_name) new_category_proxy.properties.add(property_proxy) except QModelProxy.DoesNotExist: msg = "Unable to find QModel '%s' specified in QCategorization '%s'" % (model_name, self) if request: messages.add_message(request, messages.WARNING, msg) else: print(msg) pass except QStandardPropertyProxy.DoesNotExist: msg = "Unable to find QStandardProperty '%s' specified in QCategorization '%s'" % (field_name, self) if request: messages.add_message(request, messages.WARNING, msg) else: print(msg) pass new_category_proxy.save() new_category_proxies.append(new_category_proxy) self.is_registered = True self.last_registered_version = self.version
def parse_schema(self, **kwargs): """ registers a CIM2 ontology schema QXML file :param kwargs: :return: """ request = kwargs.pop("request", None) try: self.file.open() ontology_content = et.parse(self.file) self.file.close() except IOError as e: msg = "Error opening file: {0}".format(self.file) if request: messages.add_message(request, messages.ERROR, msg) raise e recategorization_needed = False # name can be anything... ontology_name = get_index(xpath_fix(ontology_content, "name/text()"), 0) # version should match(ish) the instance field... ontology_version = get_index(xpath_fix(ontology_content, "version/text()"), 0) if self.version.major() != Version(ontology_version).major(): msg = "The major version of this ontology instance does not match the major version of the QXML file" if request: messages.add_message(request, messages.WARNING, msg) # description can overwrite the instance field... ontology_description = get_index(xpath_fix(ontology_content, "description/text()"), 0) if ontology_description: self.description = remove_spaces_and_linebreaks(ontology_description) old_model_proxies = list(self.model_proxies.all()) # list forces qs evaluation immediately new_model_proxies = [] for i, model_proxy in enumerate(xpath_fix(ontology_content, "//classes/class"), start=1): model_proxy_package = xpath_fix(model_proxy, "@package")[0] model_proxy_schema = self model_proxy_name = xpath_fix(model_proxy, "name/text()")[0] model_proxy_stereotype = get_index(xpath_fix(model_proxy, "@stereotype"), 0) model_proxy_documentation = get_index(xpath_fix(model_proxy, "description/text()"), 0) if model_proxy_documentation: model_proxy_documentation = remove_spaces_and_linebreaks(model_proxy_documentation) else: model_proxy_documentation = u"" (new_model_proxy, created_model_proxy) = QModelProxy.objects.get_or_create( package=model_proxy_package, ontology=model_proxy_schema, name=model_proxy_name ) if created_model_proxy: recategorization_needed = True new_model_proxy.order = i new_model_proxy.stereotype = model_proxy_stereotype new_model_proxy.documentation = model_proxy_documentation new_model_proxy.save() new_model_proxies.append(new_model_proxy) old_property_proxies = list(new_model_proxy.property_proxies.all()) # list forces qs evaluation immediately new_property_proxies = [] for j, property_proxy in enumerate(xpath_fix(model_proxy, "attributes/attribute"), start=1): property_proxy_name = re.sub(r"\.", "_", str(xpath_fix(property_proxy, "name/text()")[0])) property_proxy_field_type = xpath_fix(property_proxy, "type/text()")[0] property_proxy_stereotype = get_index(xpath_fix(property_proxy, "@stereotype"), 0) property_proxy_documentation = get_index(xpath_fix(property_proxy, "description/text()"), 0) if property_proxy_documentation: property_proxy_documentation = remove_spaces_and_linebreaks(property_proxy_documentation) else: property_proxy_documentation = u"" property_proxy_cardinality_min = get_index(xpath_fix(property_proxy, "cardinality/@min"), 0) property_proxy_cardinality_max = get_index(xpath_fix(property_proxy, "cardinality/@max"), 0) property_proxy_is_nillable = get_index(xpath_fix(property_proxy, "@is_nillable"), 0) (new_property_proxy, created_property) = QPropertyProxy.objects.get_or_create( model_proxy=new_model_proxy, name=property_proxy_name, field_type=property_proxy_field_type ) if created_property: recategorization_needed = True new_property_proxy.order = j new_property_proxy.documentation = property_proxy_documentation new_property_proxy.stereotype = property_proxy_stereotype new_property_proxy.cardinality = "{0}|{1}".format( property_proxy_cardinality_min, property_proxy_cardinality_max if property_proxy_cardinality_max != "N" else "*", ) new_property_proxy.is_nillable = property_proxy_is_nillable # atomic properties... property_proxy_atomic_type = get_index(xpath_fix(property_proxy, "atomic/atomic_type/text()"), 0) if property_proxy_atomic_type: if property_proxy_atomic_type == u"STRING": property_proxy_atomic_type = u"DEFAULT" property_proxy_atomic_type = QAtomicPropertyTypes.get(property_proxy_atomic_type) new_property_proxy.atomic_type = property_proxy_atomic_type # relationship properties... property_proxy_relationship_target_names = "|".join( # note that each target_name is fully-qualified xpath_fix(property_proxy, "relationship/targets/target/text()") ) new_property_proxy.relationship_target_names = property_proxy_relationship_target_names # enumeration properties... property_proxy_enumeration_is_open = get_index(xpath_fix(property_proxy, "enumeration/@is_open"), 0) property_proxy_enumeration_is_multi = get_index(xpath_fix(property_proxy, "enumeration/@is_multi"), 0) if property_proxy_enumeration_is_open: new_property_proxy.enumeration_is_open = property_proxy_enumeration_is_open == "true" if property_proxy_enumeration_is_multi: new_property_proxy.enumeration_is_multi = property_proxy_enumeration_is_multi == "true" property_proxy_enumeration = [] for k, enumeration_member_proxy in enumerate( xpath_fix(property_proxy, "enumeration/choices/choice"), start=1 ): enumeration_member_proxy_value = get_index(xpath_fix(enumeration_member_proxy, "value/text()"), 0) enumeration_member_proxy_documentation = get_index( xpath_fix(enumeration_member_proxy, "description/text()"), 0 ) property_proxy_enumeration_member = { "order": k, "value": enumeration_member_proxy_value, "name": enumeration_member_proxy_value, "documentation": enumeration_member_proxy_documentation, } property_proxy_enumeration.append(property_proxy_enumeration_member) new_property_proxy.enumeration = property_proxy_enumeration new_property_proxy.save() new_property_proxies.append(new_property_proxy) # if there's anything in old_property_proxies not in new_property_proxies, delete it for old_property_proxy in old_property_proxies: if old_property_proxy not in new_property_proxies: old_property_proxy.delete() new_model_proxy.save() # save parent again for the m2m relationship # if there's anything in old_model_proxies not in new_model_proxies, delete it for old_model_proxy in old_model_proxies: if old_model_proxy not in new_model_proxies: old_model_proxy.delete() # reset whatever's left for model_proxy in QModelProxy.objects.filter(ontology=self): for property_proxy in model_proxy.property_proxies.all(): property_proxy.reset() property_proxy.save() if recategorization_needed: msg = "Since you are re-registering an existing version, you will also have to re-register the corresponding categorization" if request: messages.add_message(request, messages.WARNING, msg)