示例#1
0
 def _generalize_gp(self):
     # Create a filtered graph pattern from the request one (general_gp)
     general_gp = GraphPattern()
     for new_tp in map(lambda x: self._remove_tp_filters(x), self._graph_pattern):
         general_gp.add(new_tp)
     if self._filter_mapping:
         # Store the filter mapping
         self._pipe.hmset('{}filters'.format(self._request_key), self._filter_mapping)
     return general_gp
示例#2
0
 def __check_gp_mappings(self, gp=None):
     """
     Used in _save method. Seeks matches with some fragment already registered
     :param gp: By default, _graph_pattern attribute is used when gp is None
     :return: The matching fragment id and the mapping dictionary or None if there is no matching
     """
     if gp is None:
         gp = self._graph_pattern
     gp_keys = r.keys('{}:*:gp'.format(self._fragments_key))
     for gpk in gp_keys:
         stored_gp = GraphPattern(r.smembers(gpk))
         mapping = stored_gp.mapping(gp)
         if mapping:
             return gpk.split(':')[-2], mapping
     return None
示例#3
0
    def __init__(self):
        """
        Prepares the pattern graph object which will store the one that is contained in the
        request
        """
        super(FragmentRequest, self).__init__()
        self.__request_graph = CGraph()
        self.__request_graph.bind('stoa', STOA)
        self.__preferred_labels = set([])
        self.__variable_labels = {}
        self._graph_pattern = GraphPattern()

        # Copy Agora prefixes to the pattern graph
        try:
            prefixes = _agora_client.prefixes
            for p in prefixes:
                self.__request_graph.bind(p, prefixes[p])
        except Exception as e:
            raise EnvironmentError(e.message)
示例#4
0
class FragmentRequest(DeliveryRequest):
    def __init__(self):
        """
        Prepares the pattern graph object which will store the one that is contained in the
        request
        """
        super(FragmentRequest, self).__init__()
        self.__request_graph = CGraph()
        self.__request_graph.bind('stoa', STOA)
        self.__preferred_labels = set([])
        self.__variable_labels = {}
        self._graph_pattern = GraphPattern()

        # Copy Agora prefixes to the pattern graph
        try:
            prefixes = _agora_client.prefixes
            for p in prefixes:
                self.__request_graph.bind(p, prefixes[p])
        except Exception as e:
            raise EnvironmentError(e.message)

    def _extract_content(self, request_type=None):
        super(FragmentRequest, self)._extract_content(request_type)

        # Firstly, it looks for all Variables that are inside the request
        variables = set(self._graph.subjects(RDF.type, STOA.Variable))
        if not variables:
            raise SyntaxError('There are no variables specified for this request')
        _log.debug(
            'Found {} variables in the the fragment pattern'.format(len(variables)))

        # Secondly, try to identify all links between variables (avoiding cycles)
        visited = set([])
        for v in variables:
            self.__request_graph.add((v, RDF.type, STOA.Variable))
            self.__follow_variable(v, visited=visited)

        # Thirdly, the request graph is filtered and the request pattern only contains
        # the relevant nodes and their relations

        # Finally, an Agora-compliant Graph Pattern is created and offered as a property
        self.__build_graph_pattern()

        _log.debug('Extracted (fragment) pattern graph:\n{}'.format(self.__request_graph.serialize(format='turtle')))

        q_res = self._graph.query("""SELECT ?r ?ud ?ag ?ue WHERE {
                                OPTIONAL { ?r stoa:expectedUpdatingDelay ?ud }
                                OPTIONAL { ?r stoa:allowGeneralisation ?ag }
                                OPTIONAL { ?r stoa:updateOnEvents ?ue }
                             }""")
        q_res = list(q_res)
        if len(q_res) > 1:
            raise SyntaxError('Wrong number of parameters were defined')

        fragment_params = q_res.pop()
        if any(fragment_params):
            try:
                parent_node, updating_delay, allow_gen, update_events = fragment_params
                if parent_node != self._request_node:
                    raise SyntaxError('Invalid parent node for stoa:expectedUpdatingDelay')
                if updating_delay is not None:
                    self._fields['updating_delay'] = updating_delay.toPython()
                if allow_gen is not None:
                    self._fields['allow_gen'] = allow_gen.toPython()
                if update_events is not None:
                    self._fields['update_events'] = update_events.toPython()
            except IndexError:
                pass

    def __n3(self, elm):
        """
        :param elm: The element to be n3-formatted
        :return: The n3 representation of elm
        """
        return elm.n3(self.__request_graph.namespace_manager)

    def __follow_variable(self, variable_node, visited=None):
        """
        Recursively follows one variable node of the request graph
        :param variable_node: Starting node
        :param visited: Track of visited variable nodes
        :return:
        """

        def add_pattern_link(node, triple):
            type_triple = (node, RDF.type, STOA.Variable)
            condition = type_triple in self._graph
            if condition:
                self.__request_graph.add(type_triple)
            elif isinstance(node, URIRef):
                condition = True
            if condition:
                if triple not in self.__request_graph:
                    self.__request_graph.add(triple)
                    _log.debug('New pattern link: {}'.format(triple))
            return condition

        if visited is None:
            visited = set([])
        visited.add(variable_node)
        subject_pattern = self._graph.subject_predicates(variable_node)
        for (n, pr) in subject_pattern:
            if add_pattern_link(n, (n, pr, variable_node)) and n not in visited:
                self.__follow_variable(n, visited)

        object_pattern = self._graph.predicate_objects(variable_node)
        for (pr, n) in object_pattern:
            if add_pattern_link(n, (variable_node, pr, n)):
                if n not in visited:
                    self.__follow_variable(n, visited)
            elif n != STOA.Variable:
                self.__request_graph.add((variable_node, pr, n))

    def __build_graph_pattern(self):
        """
        Creates a GraphPattern with all the identified (Agora compliant) triple patterns
        in the request graph
        """

        def preferred_label():
            # Each variable may have a property STOA.label that specifies its desired label
            labels = list(self.__request_graph.objects(v, STOA.label))
            p_label = labels.pop() if len(labels) == 1 else ''
            if p_label:
                self.__preferred_labels.add(str(p_label))
            return p_label if p_label.startswith('?') else '?v{}'.format(i)

        # Populates a dictionary with all variables and their labels
        variables = self.__request_graph.subjects(RDF.type, STOA.Variable)
        for i, v in enumerate(variables):
            self.__variable_labels[v] = preferred_label()

        # For each variable, generates one triple pattern per relation with other nodes as either subject or object
        for v in self.__variable_labels.keys():
            v_in = self.__request_graph.subject_predicates(v)
            for (s, pr) in v_in:
                s_part = self.__variable_labels[s] if s in self.__variable_labels else self.__n3(s)
                self._graph_pattern.add(u'{} {} {}'.format(s_part, self.__n3(pr), self.__variable_labels[v]))
            v_out = self.__request_graph.predicate_objects(v)
            for (pr, o) in [_ for _ in v_out if _[1] != STOA.Variable and not _[0].startswith(STOA)]:
                o_part = self.__variable_labels[o] if o in self.__variable_labels else (
                    '"{}"'.format(o) if isinstance(o, Literal) else self.__n3(o))
                p_part = self.__n3(pr) if pr != RDF.type else 'a'
                self._graph_pattern.add(u'{} {} {}'.format(self.__variable_labels[v], p_part, o_part))

    @property
    def pattern(self):
        """
        :return: The request graph pattern
        """
        return self._graph_pattern

    @property
    def preferred_labels(self):
        """
        :return: The variable preferred labels
        """
        return self.__preferred_labels

    @property
    def variable_labels(self):
        """
        :return: All variable labels
        """
        return self.__variable_labels.values()

    def variable_label(self, n):
        label = self.__variable_labels.get(n, None)
        if isinstance(label, Literal):
            label = label.toPython()
        return label

    @property
    def updating_delay(self):
        return self._fields.get('updating_delay', None)

    @property
    def allow_generalisation(self):
        return self._fields.get('allow_gen', False)

    @property
    def update_on_events(self):
        return self._fields.get('update_events', False)