예제 #1
0
def q_realization_add_relationship_value(request):
    valid_request, msg = validate_request(request)
    if not valid_request:
        return HttpResponseForbidden(msg)

    target_proxy_id = request.POST.get("target_proxy_id")
    property_key = request.POST.get("key")

    session_key = get_key_from_request(request)
    cached_realizations_key = "{0}_realizations".format(session_key)

    cached_realizations = get_cached_object(request.session, cached_realizations_key)
    if not cached_realizations:
        msg = "unable to locate cached_realizations"
        raise QError(msg)

    property = get_property_realization_by_fn(
        lambda r: r.get_key() == property_key,
        cached_realizations
    )
    if not property:
        raise QError("unable to find property w/ key='{0}'".format(property_key))

    target_proxy = QModelProxy.objects.get(id=target_proxy_id)
    new_model_realization = get_new_realizations(
        project=cached_realizations.project,
        ontology=cached_realizations.ontology,
        model_proxy=target_proxy,
        key=target_proxy.name,
    )

    # double-check that adding this model to this property makes sense...
    assert target_proxy in property.proxy.relationship_target_models.all()
    assert property.get_cardinality_max() == '*' or property.relationship_values(manager="allow_unsaved_relationship_values_manager").count() < int(property.get_cardinality_max())

    # add the model...
    property.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(new_model_realization)
    with allow_unsaved_fk(QModel, ["relationship_property"]):
        # in theory, Django doesn't store unsaved relationship
        # the custom manager above gets around this for the m2m relationship (property to model) and it is what I ought to use
        # however, in order to work my way up the realization hierarchy I need access to the reverse of that relationship
        # which is a fk relationship; hence this extra bit of code (which only exists so that "model_realizations.py#QRealization.get_parent_model_realization" works)
        new_model_realization.relationship_property = property

    # re-cache the changed realizations...
    request.session[cached_realizations_key] = cached_realizations

    # and return a serialized version of that model...
    new_model_realization_serialization = serialize_new_realizations(new_model_realization)
    return JsonResponse(new_model_realization_serialization)
def create_models_from_components(component_node, model_parameters, models=[], **kwargs):
    """
    recursively look through mppt components to recreate that hierarchy in models
    :param component_node:
    :param model_parameters:
    :param models:
    :return: None
    """
    title = model_parameters["title"]
    model_parameters["title"] = title[:title.index(" : ")] + " : " + component_node.name
    model_parameters["component_key"] = component_node.get_key()
    model_parameters["is_root"] = kwargs.pop("is_root", False)

    with allow_unsaved_fk(MetadataModel, ["parent", ]):
        model = MetadataModel(**model_parameters)
        models.append(model)
        for child_component in component_node.get_children():
            model_parameters["parent"] = model
            create_models_from_components(child_component,model_parameters,models)
def get_new_customization_set(project=None, ontology=None, proxy=None, vocabularies=[]):
    """

    """

    model_customization = QModelCustomization(ontology=ontology, proxy=proxy, project=project)
    model_customization.reset(proxy)

    vocabulary_customizations = []
    for i, vocabulary in enumerate(vocabularies):
        with allow_unsaved_fk(QModelCustomizationVocabulary, ["model_customization"]):
            vocabulary_customization = QModelCustomizationVocabulary(
                model_customization=model_customization, vocabulary=vocabulary, order=i + 1, active=True
            )
        vocabulary_customizations.append(vocabulary_customization)

    standard_category_customizations = []
    for standard_category_proxy in ontology.categorization.category_proxies.all():
        with allow_unsaved_fk(QStandardCategoryCustomization, ["model_customization"]):
            standard_category_customization = QStandardCategoryCustomization(
                model_customization=model_customization, proxy=standard_category_proxy
            )
            standard_category_customization.reset(standard_category_proxy)
        standard_category_customizations.append(standard_category_customization)

    standard_property_customizations = []
    for standard_property_proxy in proxy.standard_properties.all():
        with allow_unsaved_fk(
            QStandardPropertyCustomization, ["model_customization", "category", "relationship_subform_customization"]
        ):
            standard_property_customization = QStandardPropertyCustomization(
                model_customization=model_customization,
                proxy=standard_property_proxy,
                category=find_in_sequence(
                    lambda category: category.proxy.has_property(standard_property_proxy),
                    standard_category_customizations,
                ),
            )
            standard_property_customization.reset(standard_property_proxy)
            # HERE BEGINS THE SUBFORM BIT
            if standard_property_customization.use_subform():
                subform_customization_set = get_new_customization_set(
                    project=project,
                    ontology=ontology,
                    proxy=standard_property_proxy.relationship_target_model,
                    vocabularies=[],  # NO VOCABULARIES USED IN SUBFORMS ?
                )
                standard_property_customization.relationship_subform_customization = subform_customization_set[
                    "model_customization"
                ]
                # this is important; I do not have access to unsaved m2m fields, but I can set an attribute on the instance
                standard_property_customization.relationship_subform_customization_set = subform_customization_set
            # HERE ENDS THE SUBFORM BIT
        standard_property_customizations.append(standard_property_customization)

    scientific_category_customizations = []
    scientific_property_customizations = []
    for vocabulary in vocabularies:
        vocabulary_key = vocabulary.get_key()
        for component in vocabulary.component_proxies.all():
            component_key = component.get_key()
            n_categories = len(scientific_category_customizations)
            for scientific_category_proxy in component.category_proxies.all():
                with allow_unsaved_fk(QScientificCategoryCustomization, ["model_customization"]):
                    scientific_category_customization = QScientificCategoryCustomization(
                        model_customization=model_customization,
                        proxy=scientific_category_proxy,
                        vocabulary_key=vocabulary_key,
                        component_key=component_key,
                    )
                    scientific_category_customization.reset(scientific_category_proxy, reset_keys=False)
                scientific_category_customizations.append(scientific_category_customization)
            n_properties = len(scientific_property_customizations)
            for scientific_property_proxy in component.scientific_property_proxies.all():
                with allow_unsaved_fk(QScientificPropertyCustomization, ["category", "model_customization"]):
                    scientific_property_customization = QScientificPropertyCustomization(
                        model_customization=model_customization,
                        proxy=scientific_property_proxy,
                        vocabulary_key=vocabulary_key,
                        component_key=component_key,
                        category=find_in_sequence(
                            lambda category: category.proxy.has_property(scientific_property_proxy),
                            scientific_category_customizations[n_categories - 1 :],
                        ),  # ignore the previous categories
                    )
                    scientific_property_customization.reset(scientific_property_proxy, reset_keys=False)
                scientific_property_customizations.append(scientific_property_customization)

    customization_set = {
        "model_customization": model_customization,
        "vocabulary_customizations": vocabulary_customizations,
        "standard_category_customizations": standard_category_customizations,
        "standard_property_customizations": standard_property_customizations,
        "scientific_category_customizations": scientific_category_customizations,
        "scientific_property_customizations": scientific_property_customizations,
    }

    return customization_set
def q_realization_add_relationship_value(request):

    # check the request was valid...
    valid_request, msg = validate_request(request)
    if not valid_request:
        return HttpResponseForbidden(msg)

    target_proxy_id = request.POST.get("target_proxy_id")
    property_key = request.POST.get("key")

    session_key = get_key_from_request(request)
    cached_realizations_key = "{0}_realizations".format(session_key)

    cached_realizations = get_cached_object(request.session, cached_realizations_key)
    if not cached_realizations:
        msg = "unable to locate cached_realizations"
        return HttpResponseBadRequest(msg)

    # do some sanity checks...

    # check the realization to add to exists...
    property_realization = get_property_realization_by_key(property_key, cached_realizations)
    if not property_realization:
        msg = "unable to find a QPropertyRealization with a key of '{0}'".format(property_key)
        return HttpResponseBadRequest(msg)

    # check that the target to add exists...
    try:
        target_proxy = QModelProxy.objects.get(id=target_proxy_id)
    except QModelProxy.DoesNotExist:
        msg = "unable to find a QModelProxy with an id of '{0}'".format(target_proxy_id)
        return HttpResponseBadRequest(msg)

    # check that it makes sense to add this target...
    if target_proxy not in property_realization.proxy.relationship_target_models.all():
        msg = "you are trying to add the wrong type of QModelRealization to this QPropertyRealization"
        return HttpResponseBadRequest(msg)
    if (not property_realization.is_infinite) and (property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").count() >= property_realization.cardinality_max):
        msg = "you have already added the maximum amount of QModelRealizations to this QPropertyRealization"
        return HttpResponseBadRequest(msg)

    # check the user has permission to modify the realization...
    current_user = request.user
    project = cached_realizations.project
    if project.authenticated:
        if not current_user.is_authenticated() or not is_member_of(current_user, project):
            msg = "{0} does not have permission to modify a realization".format(current_user)
            return HttpResponseForbidden(msg)

    # ...okay, sanity checks are over

    # now create the model...
    new_model_realization = get_new_realizations(
        project=project,
        ontology=target_proxy.ontology,
        model_proxy=target_proxy,
        key=target_proxy.name,
    )
    # now add the model...
    property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(new_model_realization)
    with allow_unsaved_fk(QModelRealization, ["relationship_property"]):
        # the custom manager above ("allow_unsaved_relationship_values_manager") lets me cope w/ an unsaved m2m relationship - it is what I ought to use
        # however, some fns ("QRealization.get_root_realization") needs access to the reverse of that relationship; hence this extra bit of code
        new_model_realization.relationship_property = property_realization
    request.session[cached_realizations_key] = cached_realizations

    # finally return a serialized version of that model...
    new_model_realization_serialization = serialize_realizations(new_model_realization)
    return JsonResponse(new_model_realization_serialization)
def get_new_realizations(project=None, ontology=None, model_proxy=None, **kwargs):
    # unlike w/ customizations, I do not create the entire possible set all at once
    # instead I just deal w/ the minimum number of properties (based on cardinality)
    # infinite recursion is therefore avoided; not by re-using previously created models
    # as with customizations, but by only creating a finite amount of models
    # hooray!

    parent_property = kwargs.pop("parent_property", None)
    if parent_property is not None:
        is_active = parent_property.is_required
    else:
        is_active = True
    model_realization = QModelRealization(
        project=project,
        proxy=model_proxy,
        version="0.0.0",
        is_active=is_active
    )
    model_realization.reset()

    category_realizations = []
    # TODO: IS THERE A MORE EFFICIENT WAY TO DO THIS?
    # gets _all_ of the categories that are relevant to this model...
    used_category_proxies = [p.category_proxy for p in model_proxy.property_proxies.all()]
    category_proxies = set(model_proxy.category_proxies.all())
    category_proxies.update(used_category_proxies)
    # for category_proxy in model_proxy.category_proxies.all():
    for category_proxy_order, category_proxy in enumerate(category_proxies):
        with allow_unsaved_fk(QCategoryRealization, ["model"]):
            category_realization = QCategoryRealization(
                proxy=category_proxy,
                model=model_realization,
                order=category_proxy_order,
            )
            category_realization.reset()
        category_realizations.append(category_realization)
    model_realization.categories(manager="allow_unsaved_categories_manager").add_potentially_unsaved(*category_realizations)

    property_realizations = []
    for property_proxy_order, property_proxy in enumerate(model_proxy.property_proxies.all()):
        property_category_realization = find_in_sequence(
            lambda c: c.proxy == property_proxy.category_proxy,
            category_realizations
        )
        with allow_unsaved_fk(QPropertyRealization, ["model", "category"]):
            property_realization = QPropertyRealization(
                proxy=property_proxy,
                field_type=property_proxy.field_type,    # TODO: I AM HAVING TO PASS "field_type" SO THAT IT'S SET IN "__init__" IN ORDER TO SETUP ANY ENUMERATIONS;
                model=model_realization,                 # TODO: AN ALTERNATIVE WOULD BE TO CALL "reset" FROM "__init__" WHENEVER "is_new" IS True.
                category=property_category_realization,
                order=property_proxy_order,
            )
            property_realization.reset()
            property_category_realization.properties(manager="allow_unsaved_category_properties_manager").add_potentially_unsaved(property_realization)
            # here begins the icky bit
            if property_realization.field_type == QPropertyTypes.RELATIONSHIP and property_realization.is_hierarchical:  # property_realization.is_required:
                target_relationship_values = []
                # TODO: IF I WERE TO PRE-CREATE ALL RELATIONSHIPS THEN HERE IS WHERE I WOULD DO IT
                # TODO: BUT THAT WOULD BE MIND-BOGGLINGLY COMPLEX...
                # TODO: ...B/C I WOULD NEED TO KNOW IN ADVANCE WHAT TYPES OF RELATIONSHIPS TO CREATE IN THE CASE OF MULTIPLE TYPES OF TARGETS;
                # TODO: AS IT IS, I GET AROUND THIS BY ONLY PRE-CREATING SPECIALIZATIONS WHICH ARE EXPLICIT IN THEIR TARGET PROXIES
                # TODO: BUT I STILL CANNOT HANDLE THIS FOR NON-SPECIALIZED PROXIES
                if property_realization.has_specialized_values:

                    # assert property_realization.cardinality_min == len(property_proxy.values)

                    for target_model_proxy_id in property_proxy.values:
                        target_model_proxy = property_proxy.relationship_target_models.get(cim_id=target_model_proxy_id)
                        kwargs.update({"parent_property": property_realization})
                        with allow_unsaved_fk(QModelRealization, ["relationship_property"]):  # this lets me access the parent property of a model
                            new_model_realization = get_new_realizations(
                                project=project,
                                ontology=target_model_proxy.ontology,
                                model_proxy=target_model_proxy,
                                **kwargs
                            )
                            new_model_realization.relationship_property = property_realization
                        target_relationship_values.append(new_model_realization)
                    property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(*target_relationship_values)

                # here ends the icky bit
        property_realizations.append(property_realization)
    model_realization.properties(manager="allow_unsaved_properties_manager").add_potentially_unsaved(*property_realizations)

    return model_realization
예제 #6
0
def get_new_customizations(project=None, ontology=None, model_proxy=None, **kwargs):

    key = kwargs.pop("key")
    customizations = kwargs.pop("customizations", {})

    # TODO: CHANGE THIS TO USE GUIDS INSTEAD OF NAMES FOR KEYS
    # TODO: TRY TO REWRITE THIS TO USE "prefix" AGAIN (INSTEAD OF EXPLICIT "key")

    model_proxy_key = key
    if model_proxy_key not in customizations:
        model_customization = QModelCustomization(
            project=project,
            ontology=ontology,
            proxy=model_proxy,
        )
        model_customization.reset()
        customizations[model_proxy_key] = model_customization
    else:
        model_customization = customizations[model_proxy_key]

    category_customizations = []
    for catgegory_proxy in ontology.categorization.category_proxies.all():
        category_proxy_key = "{0}.{1}".format(model_proxy_key, catgegory_proxy.name)
        with allow_unsaved_fk(QCategoryCustomization, ["model_customization"]):
            if category_proxy_key not in customizations:
                category_customization = QCategoryCustomization(
                    proxy=catgegory_proxy,
                    model_customization=model_customization,
                )
                category_customization.reset()
                customizations[category_proxy_key] = category_customization
            else:
                category_customization = customizations[category_proxy_key]
        category_customizations.append(category_customization)
    # assert category_customizations[-1].proxy == ontology.categorization.get_uncategorized_category_proxy()
    model_customization.category_customizations(manager="allow_unsaved_category_customizations_manager").add_potentially_unsaved(*category_customizations)

    property_customizations = []
    for property_proxy in model_proxy.property_proxies.all():
        property_proxy_key = "{0}.{1}".format(model_proxy_key, property_proxy.name)
        with allow_unsaved_fk(QPropertyCustomization, ["model_customization", "category"]):
            # close this context manager before using the custom related manager
            # (too much hackery at once)
            if property_proxy_key not in customizations:
                category_customization = find_in_sequence(
                    lambda c: c.proxy.has_property(property_proxy),
                    category_customizations
                )
                property_customization = QPropertyCustomization(
                    proxy=property_proxy,
                    model_customization=model_customization,
                    category=category_customization,
                )
                property_customization.reset()
                category_customization.property_customizations(manager="allow_unsaved_categories_manager").add_potentially_unsaved(property_customization)
                customizations[property_proxy_key] = property_customization
            else:
                property_customization = customizations[property_proxy_key]
        property_customizations.append(property_customization)

        ############################
        # here begins the icky bit #
        ############################

        if property_customization.use_subforms():
            subform_key = "{0}.{1}".format(model_proxy.name, property_proxy.name)  # this property in this model (only 1 level deep)
            target_model_customizations = []
            for target_model_proxy in property_proxy.relationship_target_models.all():
                target_model_proxy_key = "{0}.{1}".format(subform_key, target_model_proxy.name)
                if target_model_proxy_key not in customizations:
                    target_model_customization = get_new_customizations(
                        project=project,
                        ontology=ontology,
                        model_proxy=target_model_proxy,
                        key=target_model_proxy_key,
                        customizations=customizations,
                    )
                else:
                    target_model_customization = customizations[target_model_proxy_key]

                target_model_customizations.append(target_model_customization)
            property_customization.relationship_target_model_customizations(manager="allow_unsaved_relationship_target_model_customizations_manager").add_potentially_unsaved(*target_model_customizations)

        ##########################
        # here ends the icky bit #
        ##########################

        model_customization.property_customizations(manager="allow_unsaved_property_customizations_manager").add_potentially_unsaved(*property_customizations)

    return customizations[model_proxy_key]
def get_new_realization_set(project=None, ontology=None, model_proxy=None, standard_property_proxies=[], scientific_property_proxies=[], model_customizer=None, vocabularies=[]):

        models = []
        model_parameters = {
            "project" : project,
            'version' : ontology,
            "proxy" : model_proxy,
        }

        if model_customizer.model_show_hierarchy or len(vocabularies) == 0:
            # setup the root model...
            model = MetadataModel(**model_parameters)
            model.vocabulary_key = DEFAULT_VOCABULARY_KEY
            model.component_key = DEFAULT_COMPONENT_KEY
            model.title = model_customizer.model_root_component
            model.is_root = True
            models.append(model)

        for vocabulary in vocabularies:
            if model_customizer.model_show_hierarchy:
                model_parameters["parent"] = model
            else:
                model_parameters.pop("parent", None)
            model_parameters["vocabulary_key"] = vocabulary.get_key()
            components = vocabulary.component_proxies.all()
            if components:
                # recursively go through the components of each vocabulary,
                # adding corresponding models to the list
                root_component = components[0].get_root()
                model_parameters["title"] = u"%s : %s" % (vocabulary.name, root_component.name)
                create_models_from_components(
                    root_component,
                    model_parameters,
                    models,
                    # is_root will be False in all instances except the 1st time this is called
                    # for a component w/ no hierarchy
                    is_root=not model_customizer.model_show_hierarchy,
                )

        standard_properties = {}
        scientific_properties = {}
        for i, model in enumerate(models):
            model.reset()

            property_key = model.get_model_key()
            # since this is _not_ being created in the context of a subform,
            # each model in models corresponds to a separate component and will therefore have a unique key

            standard_properties[property_key] = []
            for standard_property_proxy in standard_property_proxies:
                with allow_unsaved_fk(MetadataStandardProperty, ["model", ]):
                    standard_property = MetadataStandardProperty(proxy=standard_property_proxy,model=model)
                    standard_property.reset()
                standard_properties[property_key].append(standard_property)

            scientific_properties[property_key] = []
            try:
                for scientific_property_proxy in scientific_property_proxies[property_key]:
                    with allow_unsaved_fk(MetadataScientificProperty, ["model", ]):
                        scientific_property = MetadataScientificProperty(proxy=scientific_property_proxy,model=model)
                        scientific_property.reset()
                    scientific_properties[property_key].append(scientific_property)
            except KeyError:
                # there were no scientific properties associated w/ this component (or, rather, no components associated w/ this vocabulary)
                # that's okay,
                scientific_properties[property_key] = []

        realization_set = {
            "models": models,
            "standard_properties": standard_properties,
            "scientific_properties": scientific_properties,
        }

        return realization_set
def get_new_subrealization_set(project, version, model_proxy, standard_property_proxies, scientific_property_proxies, model_customizer, vocabularies, parent_vocabulary_key, parent_component_key):
    """creates the full set of realizations required for a particular project/version/proxy combination w/ a specified list of vocabs"""

    model_parameters = {
        "project": project,
        "version": version,
        "proxy": model_proxy,
    }
    # setup the root model...
    model = MetadataModel(**model_parameters)
    model.vocabulary_key = parent_vocabulary_key
    model.component_key = parent_component_key
    model.is_root = True

    if model_customizer.model_show_hierarchy:
        # TODO: DON'T LIKE DOING THIS HERE
        model.title = model_customizer.model_root_component

    # it has to go in a list in-case
    #  is part of a hierarchy
    # (the formsets assume a hierarchy; if not, it will just be a formset w/ 1 form)
    models = []
    models.append(model)

    for vocabulary in vocabularies:
        model_parameters["vocabulary_key"] = vocabulary.get_key()
        components = vocabulary.component_proxies.all()
        if components:
            # recursively go through the components of each vocabulary
            # adding corresponding models to the list
            root_component = components[0].get_root()
            model_parameters["parent"] = model
            model_parameters["title"] = u"%s : %s" % (vocabulary.name, root_component.name)
            create_models_from_components(root_component, model_parameters, models)

    standard_properties = {}
    scientific_properties = {}
    for i, model in enumerate(models):
        model.reset()

        property_key = model.get_model_key()
        # since this _is_ being created in the context of a subform,
        # then all models will correspond to the same component (ie: the component of the "parent" model of the property w/ subforms)
        # so I add a counter to make it unique (and using the format "-i" keeps it consistent w/ how forms & formsets work in Django)
        property_key += "-%s" % (i)

        standard_properties[property_key] = []
        for standard_property_proxy in standard_property_proxies:
            with allow_unsaved_fk(MetadataStandardProperty, ["model", ]):
                standard_property = MetadataStandardProperty(proxy=standard_property_proxy,model=model)
                standard_property.reset()
            standard_properties[property_key].append(standard_property)

        scientific_properties[property_key] = []
        try:
            for scientific_property_proxy in scientific_property_proxies[property_key]:
                with allow_unsaved_fk(MetadataScientificProperty, ["model", ]):
                    scientific_property = MetadataScientificProperty(proxy=scientific_property_proxy,model=model)
                    scientific_property.reset()
                scientific_properties[property_key].append(scientific_property)
        except KeyError:
            # there were no scientific properties associated w/ this component (or, rather, no components associated w/ this vocabulary)
            # that's okay,
            scientific_properties[property_key] = []

    realization_set = {
        "models": models,
        "standard_properties": standard_properties,
        "scientific_properties": scientific_properties,
    }

    return realization_set