Esempio n. 1
0
	def __init__(self,graph) :
		"""
		@param graph: the graph to be modified
		"""
		self.lit_to_bnode = {}
		self.bnode_to_lit = {}
		self.graph        = graph
		
		to_be_removed = []
		to_be_added   = []
		for t in self.graph :
			(subj,pred,obj) = t
			# This is supposed to be a "proper" graph, so only the obj may be a literal
			if isinstance(obj,rdflibLiteral) :
				# In any case, this should be removed:
				if t not in to_be_removed : to_be_removed.append(t)
				# Check if a BNode has already been associated with that literal
				obj_st = _LiteralStructure(obj)
				found = False
				for l in self.lit_to_bnode.keys() :					
					if obj_st.lex == l.lex and obj_st.dt == l.dt and obj_st.lang == l.lang :
						t1 = (subj, pred, self.lit_to_bnode[l])
						to_be_added.append(t1)
						found = True
						break
				if found == False :
					# the bnode has to be created
					bn = BNode()
					# store this in the internal administration
					self.lit_to_bnode[obj_st] = bn
					self.bnode_to_lit[bn] = obj_st
					# modify the graph
					to_be_added.append((subj,pred,bn))
					to_be_added.append((bn,type,Literal))
					# Furthermore: a plain literal should be identified with a corresponding xsd:string and vice versa, 
					# cf, RDFS Semantics document
					if obj_st.dt == None and obj_st.lang == None :
						newLit = rdflibLiteral(obj_st.lex,datatype = ns_xsd["string"])
						new_obj_st = _LiteralStructure(newLit)
						new_obj_st.dt = ns_xsd["string"]
						bn2 = BNode()
						self.lit_to_bnode[new_obj_st] = bn2
						self.bnode_to_lit[bn2] = new_obj_st
						to_be_added.append((subj,pred,bn2))
						to_be_added.append((bn2,type,Literal))
					elif obj_st.dt == ns_xsd["string"] :
						newLit = rdflibLiteral(obj_st.lex,datatype = None)
						new_obj_st = _LiteralStructure(obj)
						new_obj_st.dt = None
						bn2 = BNode()
						self.lit_to_bnode[new_obj_st] = bn2
						self.bnode_to_lit[bn2] = new_obj_st
						to_be_added.append((subj,pred,bn2))
						to_be_added.append((bn2,type,Literal))			
		
		# Do the real modifications
		self._massageGraph(to_be_removed,to_be_added)
Esempio n. 2
0
    def __init__(self, graph, closure):
        """
        @param graph: the graph to be modified
        """
        self.lit_to_bnode = {}
        self.bnode_to_lit = {}
        self.graph = graph

        to_be_added = set()
        _add_bnode = partial(add_bnode, self, to_be_added)

        # This is supposed to be a "proper" graph, so get the triples which
        # object is a literal. All of them will be removed from graph and
        # replaced with the ones stored in `to_be_added` variable.
        to_be_removed = [
            t for t in self.graph if isinstance(t[2], rdflibLiteral)
        ]
        for t in to_be_removed:
            (subj, pred, obj) = t
            # Test the validity of the datatype
            if obj.datatype:
                converter = AltXSDToPYTHON.get(obj.datatype, identity)
                try:
                    converter(text_type(obj))
                except ValueError:
                    closure.add_error(
                        "Lexical value of the literal '%s' does not match its datatype (%s)"
                        % (text_type(obj), obj.datatype))

            # Check if a BNode has already been associated with that literal
            obj_st = _LiteralStructure(obj)
            items = (b for l, b in self.lit_to_bnode.items() if l == obj_st)
            l_bnode = next(items, None)
            if l_bnode:
                to_be_added.add((subj, pred, l_bnode))
            else:
                _add_bnode(subj, pred, obj_st)
                # Furthermore: a plain literal should be identified with a corresponding xsd:string and vice versa,
                # cf, RDFS Semantics document
                if obj_st.dt is None and obj_st.lang is None:
                    newLit = rdflibLiteral(obj_st.lex,
                                           datatype=ns_xsd["string"])
                    new_obj_st = _LiteralStructure(newLit)
                    new_obj_st.dt = ns_xsd["string"]
                    _add_bnode(subj, pred, new_obj_st)
                elif obj_st.dt == ns_xsd["string"]:
                    newLit = rdflibLiteral(obj_st.lex, datatype=None)
                    new_obj_st = _LiteralStructure(newLit)
                    # new_obj_st = _LiteralStructure(obj) # Was this the correct one, or was this an old bug?
                    new_obj_st.dt = None
                    _add_bnode(subj, pred, new_obj_st)

        # Do the real modifications
        self._massageGraph(to_be_removed, to_be_added)
Esempio n. 3
0
	def restore(self) :
		"""
		This method is to be invoked at the end of the forward chain processing. It restores literals (whenever possible)
		to their original self...
		"""	
		to_be_removed = []
		to_be_added   = []
		for t in self.graph :
			(subj, pred, obj) = t
			# The two cases, namely when the literal appears in subject or object positions, should be treated differently
			if subj in self.bnode_to_lit :
				# well... there may be to cases here: either this is the original tuple stating that
				# this bnode is a literal, or it is the result of an inference. In both cases, the tuple must
				# be removed from the result without any further action
				if t not in to_be_removed:
					to_be_removed.append(t)
			elif obj in self.bnode_to_lit:
				# This is where the exchange should take place: put back the real literal into the graph, removing the proxy one
				if t not in to_be_removed:
					to_be_removed.append(t)
				# This is an additional thing due to the latest change of literal handling in RDF concepts.
				# If a literal is an xsd:string then a plain literal is put in its place for the purpose of serialization...
				lit = self.bnode_to_lit[obj].lit
				if lit.datatype is not None and lit.datatype == ns_xsd["string"]:
					lit = rdflibLiteral(str(lit))
				to_be_added.append((subj, pred, lit))
				
		# Do the real modifications
		self._massageGraph(to_be_removed, to_be_added)
Esempio n. 4
0
    def restore(self):
        """
        This method is to be invoked at the end of the forward chain processing. It restores literals (whenever
        possible) to their original self...
        """
        to_be_removed = set()
        to_be_added = set()
        for t in self.graph:
            (subj, pred, obj) = t
            # The two cases, namely when the literal appears in subject or object positions, should be treated
            # differently
            if subj in self.bnode_to_lit:
                # well... there may be to cases here: either this is the original tuple stating that
                # this bnode is a literal, or it is the result of an inference. In both cases, the tuple must
                # be removed from the result without any further action
                to_be_removed.add(t)
            elif obj in self.bnode_to_lit:
                # This is where the exchange should take place: put back the real literal into the graph, removing the
                # proxy one
                to_be_removed.add(t)
                # This is an additional thing due to the latest change of literal handling in RDF concepts.
                # If a literal is an xsd:string then a plain literal is put in its place for the purpose of
                # serialization...
                lit = self.bnode_to_lit[obj].lit
                if lit.datatype is not None and lit.datatype == ns_xsd[
                        "string"]:
                    lit = rdflibLiteral(text_type(lit))
                to_be_added.add((subj, pred, lit))

        # Do the real modifications
        self._massageGraph(to_be_removed, to_be_added)
Esempio n. 5
0
    def closure(self):
        """
        Generate the closure the graph. This is the real 'core'.

        The processing rules store new triples via the separate method :func:`.Core.store_triple` which stores
        them in the :code:`added_triples` array. If that array is empty at the end of a cycle,
        it means that the whole process can be stopped.

        If required, the relevant axiomatic triples are added to the graph before processing in cycles. Similarly
        the exchange of literals against bnodes is also done in this step (and restored after all cycles are over).
        """
        self.pre_process()

        # Handling the axiomatic triples. In general, this means adding all tuples in the list that
        # forwarded, and those include RDF or RDFS. In both cases the relevant parts of the container axioms should also
        # be added.
        if self.axioms:
            self.add_axioms()

        # Add the datatype axioms, if needed (note that this makes use of the literal proxies, the order of the call
        # is important!
        if self.daxioms:
            self.add_d_axioms()

        self.flush_stored_triples()

        # Get first the 'one-time rules', ie, those that do not need an extra round in cycles down the line
        self.one_time_rules()
        self.flush_stored_triples()

        # Go cyclically through all rules until no change happens
        new_cycle = True
        cycle_num = 0
        while new_cycle:
            # yes, there was a change, let us go again
            cycle_num += 1

            # DEBUG: print the cycle number out
            if self._debug:
                print("----- Cycle #:%d" % cycle_num)

            # go through all rules, and collect the replies (to see whether any change has been done)
            # the new triples to be added are collected separately not to interfere with
            # the current graph yet
            self.empty_stored_triples()

            # Execute all the rules; these might fill up the added triples array
            for t in self.graph:
                self.rules(t, cycle_num)

            # Add the tuples to the graph (if necessary, that is). If any new triple has been generated, a new cycle
            # will be necessary...
            new_cycle = len(self.added_triples) > 0

            for t in self.added_triples:
                self.graph.add(t)

        self.post_process()
        self.flush_stored_triples()

        # Add possible error messages
        if self.error_messages:
            # I am not sure this is the right vocabulary to use for this purpose, but I haven't found anything!
            # I could, of course, come up with my own, but I am not sure that would be kosher...
            ERRNS = Namespace("http://www.daml.org/2002/03/agents/agent-ont#")
            self.graph.bind("err","http://www.daml.org/2002/03/agents/agent-ont#")
            for m in self.error_messages:
                message = BNode()
                self.graph.add((message, rdf_type, ERRNS['ErrorMessage']))
                self.graph.add((message, ERRNS['error'], rdflibLiteral(m)))
Esempio n. 6
0
    def closure(self):
        """
        Generate the closure the graph. This is the real 'core'.

        The processing rules store new triples via the separate method :func:`.Core.store_triple` which stores
        them in the :code:`added_triples` array. If that array is empty at the end of a cycle,
        it means that the whole process can be stopped.

        If required, the relevant axiomatic triples are added to the graph before processing in cycles. Similarly
        the exchange of literals against bnodes is also done in this step (and restored after all cycles are over).
        """
        self.pre_process()

        # Handling the axiomatic triples. In general, this means adding all tuples in the list that
        # forwarded, and those include RDF or RDFS. In both cases the relevant parts of the container axioms should also
        # be added.
        if self.axioms:
            self.add_axioms()

        # Add the datatype axioms, if needed (note that this makes use of the literal proxies, the order of the call
        # is important!
        if self.daxioms:
            self.add_d_axioms()

        self.flush_stored_triples()

        # Get first the 'one-time rules', ie, those that do not need an extra round in cycles down the line
        self.one_time_rules()
        self.flush_stored_triples()

        # Go cyclically through all rules until no change happens
        new_cycle = True
        cycle_num = 0
        while new_cycle:
            # yes, there was a change, let us go again
            cycle_num += 1

            # DEBUG: print the cycle number out
            if self._debug:
                print("----- Cycle #:%d" % cycle_num)

            # go through all rules, and collect the replies (to see whether any change has been done)
            # the new triples to be added are collected separately not to interfere with
            # the current graph yet
            self.empty_stored_triples()

            # Execute all the rules; these might fill up the added triples array
            for t in self.graph:
                self.rules(t, cycle_num)

            # Add the tuples to the graph (if necessary, that is). If any new triple has been generated, a new cycle
            # will be necessary...
            new_cycle = len(self.added_triples) > 0

            for t in self.added_triples:
                self.graph.add(t)

        self.post_process()
        self.flush_stored_triples()

        # Add possible error messages
        if self.error_messages:
            # I am not sure this is the right vocabulary to use for this purpose, but I haven't found anything!
            # I could, of course, come up with my own, but I am not sure that would be kosher...
            ERRNS = Namespace("http://www.daml.org/2002/03/agents/agent-ont#")
            self.graph.bind("err",
                            "http://www.daml.org/2002/03/agents/agent-ont#")
            for m in self.error_messages:
                message = BNode()
                self.graph.add((message, rdf_type, ERRNS['ErrorMessage']))
                self.graph.add((message, ERRNS['error'], rdflibLiteral(m)))
Esempio n. 7
0
	def __init__(self, graph, closure) :
		"""
		@param graph: the graph to be modified
		"""
		self.lit_to_bnode = {}
		self.bnode_to_lit = {}
		self.graph        = graph
		
		to_be_removed = []
		to_be_added   = []
		for t in self.graph :
			(subj, pred, obj) = t
			# This is supposed to be a "proper" graph, so only the obj may be a literal
			if isinstance(obj, rdflibLiteral):
				# Test the validity of the datatype
				if obj.datatype:
					try:
						AltXSDToPYTHON[obj.datatype](str(obj))
					except ValueError:
						closure.add_error("Lexical value of the literal '%s' does not match its datatype (%s)" % (str(obj), obj.datatype))

				# In any case, this should be removed:
				if t not in to_be_removed:
					to_be_removed.append(t)
				# Check if a BNode has already been associated with that literal
				obj_st = _LiteralStructure(obj)
				found = False
				for l in self.lit_to_bnode.keys() :					
					if obj_st.lex == l.lex and obj_st.dt == l.dt and obj_st.lang == l.lang :
						t1 = (subj, pred, self.lit_to_bnode[l])
						to_be_added.append(t1)
						found = True
						break
				if not found:
					# the bnode has to be created
					bn = BNode()
					# store this in the internal administration
					self.lit_to_bnode[obj_st] = bn
					self.bnode_to_lit[bn] = obj_st
					# modify the graph
					to_be_added.append((subj, pred, bn))
					to_be_added.append((bn, type, Literal))
					# Furthermore: a plain literal should be identified with a corresponding xsd:string and vice versa, 
					# cf, RDFS Semantics document
					if obj_st.dt is None and obj_st.lang is None:
						newLit = rdflibLiteral(obj_st.lex, datatype=ns_xsd["string"])
						new_obj_st = _LiteralStructure(newLit)
						new_obj_st.dt = ns_xsd["string"]
						bn2 = BNode()
						self.lit_to_bnode[new_obj_st] = bn2
						self.bnode_to_lit[bn2] = new_obj_st
						to_be_added.append((subj, pred, bn2))
						to_be_added.append((bn2, type, Literal))
					elif obj_st.dt == ns_xsd["string"]:
						newLit = rdflibLiteral(obj_st.lex, datatype=None)
						new_obj_st = _LiteralStructure(newLit)
						# new_obj_st = _LiteralStructure(obj) # Was this the correct one, or was this an old bug?
						new_obj_st.dt = None
						bn2 = BNode()
						self.lit_to_bnode[new_obj_st] = bn2
						self.bnode_to_lit[bn2] = new_obj_st
						to_be_added.append((subj, pred, bn2))
						to_be_added.append((bn2, type, Literal))
		
		# Do the real modifications
		self._massageGraph(to_be_removed, to_be_added)
Esempio n. 8
0
    def __init__(self, graph, closure):
        """
        @param graph: the graph to be modified
        """
        self.lit_to_bnode = {}
        self.bnode_to_lit = {}
        self.graph = graph

        to_be_removed = []
        to_be_added = []
        for t in self.graph:
            (subj, pred, obj) = t
            # This is supposed to be a "proper" graph, so only the obj may be a literal
            if isinstance(obj, rdflibLiteral):
                # Test the validity of the datatype
                if obj.datatype:
                    try:
                        converter = AltXSDToPYTHON[obj.datatype]
                    except KeyError:
                        converter = lambda v: v
                    try:
                        converter(text_type(obj))
                    except ValueError:
                        closure.add_error(
                            "Lexical value of the literal '%s' does not match its datatype (%s)"
                            % (text_type(obj), obj.datatype))

                # In any case, this should be removed:
                if t not in to_be_removed:
                    to_be_removed.append(t)
                # Check if a BNode has already been associated with that literal
                obj_st = _LiteralStructure(obj)
                found = False
                for l in list(self.lit_to_bnode.keys()):
                    if obj_st.lex == l.lex and obj_st.dt == l.dt and obj_st.lang == l.lang:
                        t1 = (subj, pred, self.lit_to_bnode[l])
                        to_be_added.append(t1)
                        found = True
                        break
                if not found:
                    # the bnode has to be created
                    bn = BNode()
                    # store this in the internal administration
                    self.lit_to_bnode[obj_st] = bn
                    self.bnode_to_lit[bn] = obj_st
                    # modify the graph
                    to_be_added.append((subj, pred, bn))
                    to_be_added.append((bn, type, Literal))
                    # Furthermore: a plain literal should be identified with a corresponding xsd:string and vice versa,
                    # cf, RDFS Semantics document
                    if obj_st.dt is None and obj_st.lang is None:
                        newLit = rdflibLiteral(obj_st.lex,
                                               datatype=ns_xsd["string"])
                        new_obj_st = _LiteralStructure(newLit)
                        new_obj_st.dt = ns_xsd["string"]
                        bn2 = BNode()
                        self.lit_to_bnode[new_obj_st] = bn2
                        self.bnode_to_lit[bn2] = new_obj_st
                        to_be_added.append((subj, pred, bn2))
                        to_be_added.append((bn2, type, Literal))
                    elif obj_st.dt == ns_xsd["string"]:
                        newLit = rdflibLiteral(obj_st.lex, datatype=None)
                        new_obj_st = _LiteralStructure(newLit)
                        # new_obj_st = _LiteralStructure(obj) # Was this the correct one, or was this an old bug?
                        new_obj_st.dt = None
                        bn2 = BNode()
                        self.lit_to_bnode[new_obj_st] = bn2
                        self.bnode_to_lit[bn2] = new_obj_st
                        to_be_added.append((subj, pred, bn2))
                        to_be_added.append((bn2, type, Literal))

        # Do the real modifications
        self._massageGraph(to_be_removed, to_be_added)