Exemplo n.º 1
0
def lodge_reportingsystem():
    """Insert a ReportingSystem into the provenance _database"""
    # only accept RDF documents
    acceptable_mimes = LDAPI.get_rdf_mimetypes_list()
    ct = request.content_type
    if ct not in acceptable_mimes:
        return api_functions.client_error_response(
            'The ReportingSystem posted is not encoded with a valid RDF Content-Type. Must be one of: '
            + ', '.join(acceptable_mimes) + '.')

    # validate ReportingSystem
    rs = class_reportingsystems.IncomingReportingSystem(request)
    if not rs.valid():
        return api_functions.client_error_response(
            'The ReportingSystem posted is not valid for the following reasons: '
            + ', '.join(rs.error_messages) + '.')

    # get the ReportingSystem's URI
    rs.determine_uri()

    rs.generate_named_graph_metadata()

    # store the ReportingSystem
    if not rs.stored():
        return api_functions.server_error_response(
            'ReportingSystem posted is valid but cannot be stored for the following reasons: '
            + ', '.join(rs.error_messages) + '.')

    # reply to sender
    return Response(rs.uri, status=201, mimetype='text/plain')
Exemplo n.º 2
0
def lodge_agent():
    """Insert an Agent into the provenance _database"""
    # only accept RDF documents
    acceptable_mimes = LDAPI.get_rdf_mimetypes_list()
    ct = request.content_type
    if ct not in acceptable_mimes:
        return api_functions.client_error_response(
            'The Agent posted is not encoded with a valid RDF Content-Type. Must be one of: '
            + ', '.join(acceptable_mimes) + '.')

    # validate Agent
    sr = class_agents.IncomingAgent(request.data, request.content_type)
    if not sr.valid():
        return api_functions.client_error_response(
            'The Agent posted is not valid for the following reasons: ' +
            ', '.join(sr.error_messages) + '.')

    # get the Agent's URI
    sr.determine_uri()

    # store the Agent
    if not sr.stored():
        return api_functions.server_error_response(
            'The Agent posted is valid but cannot be stored for the following reasons: '
            + ', '.join(sr.error_messages) + '.')

    # reply to sender
    return Response(sr.uri, status=201, mimetype='text/plain')
Exemplo n.º 3
0
 def render(self, view, mimetype):
     if view == 'neighbours':
         if mimetype in LDAPI.get_rdf_mimetypes_list():
             return self._neighbours_rdf(mimetype)
         elif mimetype == 'text/html':
             self._get_details()
             return self._neighbours_html()
     elif view == 'prov':
         if mimetype in LDAPI.get_rdf_mimetypes_list():
             return Response(self._prov_rdf().serialize(
                 format=LDAPI.get_rdf_parser_for_mimetype(mimetype)),
                             status=200,
                             mimetype=mimetype)
         elif mimetype == 'text/html':
             self._get_details()
             return self._prov_html()
Exemplo n.º 4
0
 def render(self, view, mimetype):
     if view == 'neighbours':
         # no work to be done as we have already loaded the triples
         if mimetype in LDAPI.get_rdf_mimetypes_list():
             return self._neighbours_rdf(mimetype)
         elif mimetype == 'text/html':
             self._get_details()
             return self._neighbours_html()
     elif view == 'prov':
         if mimetype in LDAPI.get_rdf_mimetypes_list():
             return Response(self._prov_rdf().serialize(
                 format=LDAPI.get_rdf_parser_for_mimetype(mimetype)),
                             status=200,
                             mimetype=mimetype)
         # TODO: pre-render the viz.js image and serve static image
         # elif mimetype == 'image/svg':
         #     return Response(
         #
         #     )
         elif mimetype == 'text/html':
             self._get_details()
             return self._prov_html()
Exemplo n.º 5
0
def lodge_report():
    """Insert a Report into the provenance database

    This function should be edited if any custom actions are to be undertaken by PROMS on reciept of a Report, such as
    Ppingbacks
    """
    # only accept RDF documents
    acceptable_mimes = LDAPI.get_rdf_mimetypes_list()
    ct = request.content_type
    if ct not in acceptable_mimes:
        return api_functions.client_error_response(
            'The Report posted is not encoded with a valid RDF Content-Type. Must be one of: '
            + ', '.join(acceptable_mimes) + '.')

    # validate Report, using the controller validator class, IncomingReport
    r = class_reports.IncomingReport(request)
    if not r.valid():
        return api_functions.client_error_response(
            'The Report posted is not valid for the following reasons: ' +
            ', '.join(r.error_messages) + '.')

    # generate Named Graph metadata
    r.determine_uri()
    r.generate_named_graph_metadata()

    # store the Report
    # since it is valid and NG metadata has been built, we can store it
    if not r.stored():
        return api_functions.server_error_response(
            'Report posted is valid but cannot be stored for the following reasons: '
            + ', '.join(r.error_messages) + '.')

    # Custom Actions
    # Only try to any custom actions, e.g. Pingbacks, if the module is turned on
    if conf.MODULES.get('pingbacks').get('valid'):
        # kick off any Pingbacks for this Report, as per chosen Pingbacks strategies
        # TODO: split Pingbacks process off into another thread
        from modules.pingbacks.engine import Engine
        e = Engine(r.graph, r.uri, url_for('modelx.instance'),
                   url_for('.sparql'))

    # reply to sender
    return r.uri, 201
Exemplo n.º 6
0
 def render(self, view, mimetype):
     if view == 'reg':
         # is an RDF format requested?
         if mimetype in LDAPI.get_rdf_mimetypes_list():
             # it is an RDF format so make the graph for serialization
             self._make_dpr_graph(view)
             rdflib_format = LDAPI.get_rdf_parser_for_mimetype(mimetype)
             return Response(self.g.serialize(format=rdflib_format),
                             status=200,
                             mimetype=mimetype)
         elif mimetype == 'text/html':
             return render_template(
                 'class_register.html',
                 class_name=self.request.args.get('_uri'),
                 register=self.register)
     else:
         return Response(
             'The requested model model is not valid for this class',
             status=400,
             mimetype='text/plain')
Exemplo n.º 7
0
def lodge_report():
    """Insert a Report into the provenance database"""
    # only accept RDF documents
    acceptable_mimes = LDAPI.get_rdf_mimetypes_list()
    ct = request.content_type
    if ct not in acceptable_mimes:
        return api_functions.client_error_response(
            'The Report posted is not encoded with a valid RDF Content-Type. Must be one of: '
            + ', '.join(acceptable_mimes) + '.')

    # validate Report
    r = class_reports.IncomingReport(request)
    print(str(r))
    if not r.valid():
        return api_functions.client_error_response(
            'The Report posted is not valid for the following reasons: ' +
            ', '.join(r.error_messages) + '.')

    # get the Report's URI
    r.determine_uri()

    r.generate_named_graph_metadata()

    # store the Report
    if not r.stored():
        return api_functions.server_error_response(
            'Report posted is valid but cannot be stored for the following reasons: '
            + ', '.join(r.error_messages) + '.')

    # kick off any Pingbacks for this Report, as per chosen Pingbacks strategies
    # TODO: split this off into another thread
    from modules.pingbacks.engine import Engine
    e = Engine(r.graph, r.uri, url_for('modelx.instance'), url_for('.sparql'))

    # reply to sender
    return r.uri, 201
Exemplo n.º 8
0
def render_alternates_view(class_uri, class_uri_encoded, instance_uri,
                           instance_uri_encoded, views_formats, mimetype):
    """Renders an HTML table, a JSON object string or a serialised RDF representation of the alternate views of an
    object"""
    if mimetype == 'application/json':
        del views_formats[
            'renderer']  # the renderer used is not for public consumption!
        return Response(json.dumps(views_formats),
                        status=200,
                        mimetype='application/json')
    elif mimetype in LDAPI.get_rdf_mimetypes_list():
        g = Graph()
        LDAPI_O = Namespace('http://promsns.org/def/ldapi#')
        g.bind('ldapi', LDAPI_O)
        DCT = Namespace('http://purl.org/dc/terms/')
        g.bind('dct', DCT)

        class_uri_ref = URIRef(uriparse.unquote_plus(class_uri))

        if instance_uri:
            instance_uri_ref = URIRef(instance_uri)
            g.add((instance_uri_ref, RDF.type, class_uri_ref))
        else:
            g.add((class_uri_ref, RDF.type, LDAPI_O.ApiResource))

        # alternates model
        alternates_view = BNode()
        g.add((alternates_view, RDF.type, LDAPI_O.View))
        g.add((alternates_view, DCT.title,
               Literal('alternates', datatype=XSD.string)))
        g.add((class_uri_ref, LDAPI_O.view, alternates_view))

        # default model
        default_view = BNode()
        g.add((default_view, DCT.title, Literal('default',
                                                datatype=XSD.string)))
        g.add((class_uri_ref, LDAPI_O.defaultView, default_view))
        default_title = views_formats['default']

        # the ApiResource is incorrectly assigned to the class URI
        for view_name, formats in views_formats.items():
            if view_name == 'alternates':
                for f in formats:
                    g.add((alternates_view,
                           URIRef('http://purl.org/dc/terms/format'),
                           Literal(f, datatype=XSD.string)))
            elif view_name == 'default':
                pass
            elif view_name == 'renderer':
                pass
            else:
                x = BNode()
                if view_name == default_title:
                    g.add((default_view, RDF.type, x))
                g.add((class_uri_ref, LDAPI_O.view, x))
                g.add((x, DCT.title, Literal(view_name, datatype=XSD.string)))
                for f in formats:
                    g.add((x, URIRef('http://purl.org/dc/terms/format'),
                           Literal(f, datatype=XSD.string)))

        rdflib_format = [
            item[1] for item in LDAPI.MIMETYPES_PARSERS if item[0] == mimetype
        ][0]
        return Response(g.serialize(format=rdflib_format),
                        status=200,
                        mimetype=mimetype)
    else:  # HTML
        return render_template('alternates_view.html',
                               class_uri=class_uri,
                               class_uri_encoded=class_uri_encoded,
                               instance_uri=instance_uri,
                               instance_uri_encoded=instance_uri_encoded,
                               views_formats=views_formats)
Exemplo n.º 9
0
class IncomingPingback(IncomingClass):
    acceptable_mimes = LDAPI.get_rdf_mimetypes_list() + ['text/uri-list']

    def __init__(self, request):
        IncomingClass.__init__(self, request)

        self.pingback_endpoint = request.url

        self.determine_uri()
        self._generate_named_graph_uri()

    def valid(self):
        """Validates an incoming Pingback using direct tests using the Pingbacks RuleSet"""
        # PROV Pingbacks can only be of mimtype text/uri-list
        if self.request.mimetype == 'text/uri-list':
            print((self.request.headers))
            conformant_pingback = ProvPingback(self.request)

            # ensure that this Pingback has the URI(s) of the Resource(s) it is for
            if self.request.args.get('resource_uri') is None:
                error_message = 'No resource URI is indicated for this pingback. Pingbacks sent to a PROMS Server ' \
                                'instance must be posted to ' \
                                'http://{POROMS_INTANCE}/function/lodge-pingback?resource_uri={RESOURCE_URI}'
                if self.error_messages is not None:
                    self.error_messages.append(error_message)
                else:
                    self.error_messages = [error_message]

                return False
            elif not LDAPI.is_a_uri(self.request.args.get('resource_uri')):
                error_message = 'The resource URI indicated for this pingback does not validate as a URI'
                if self.error_messages is not None:
                    self.error_messages.append(error_message)
                else:
                    self.error_messages = [error_message]

                return False

        # PROMS Pingbacks can only be of an RDF mimetype
        else:
            conformant_pingback = PromsPingback(self.request, self.pingback_endpoint)

        if not conformant_pingback.passed:
            self.error_messages = conformant_pingback.fail_reasons
            return False

        return True

    def determine_uri(self):
        pass  # no need for this!

    def _generate_named_graph_uri(self):
        self.named_graph_uri = settings.PINGBACK_NAMED_GRAPH_BASE_URI + str(uuid.uuid4())

    def convert_pingback_to_rdf(self):
        # the URI of the Named Graph for this Pingback must have been generated before doing this
        # so we can refer to the graph
        if self.named_graph_uri is not None:
            self.graph = Graph()
            # PROV Pingbacks can only be of mimtype text/uri-list
            if self.request.mimetype == 'text/uri-list':
                self._convert_prov_pingback_to_rdf()
            # PROMS Pingbacks can only be of an RDF mimetype
            else:
                self._convert_proms_pingback_to_rdf()
        else:
            raise Exception('The Incoming Pingback must have had a URI generated for it by PROMS Server before the data'
                            'for it is stored. The function determine_uri() generated the URI.')

    def _convert_prov_pingback_to_rdf(self):
        # every URI in the PROV-AQ message is treated as a provenance statement about the resource
        PROV = Namespace('http://www.w3.org/ns/prov#')
        self.graph.bind('prov', PROV)

        for uri_line in self.request.data.split('\n'):
            self.graph.add((
                URIRef(self.request.args.get('resource_uri')),
                PROV.has_provenance,
                URIRef(uri_line)
            ))

        # if there are Link headers about other resources, create DCT provenance indicators for them too
        if self.request.headers.get('Link'):
            for link_header in self.request.headers.get('Link').split(','):
                uri, rel, anchor = link_header.split(';')
                self.graph.add((
                    URIRef(uri.strip('<>')),
                    URIRef(rel.strip().replace('rel=', '').strip('"')),
                    URIRef(anchor.strip().replace('anchor=', '').strip('"'))
                ))

    def _convert_proms_pingback_to_rdf(self):
        PROMS = Namespace('http://promsns.org/def/proms#')
        self.graph.bind('proms', PROMS)

        # type this pingback specifically
        self.graph.add((
            URIRef(self.named_graph_uri),
            RDF.type,
            PROMS.PromsPingback
        ))

        # convert the data to RDF (just de-serialise it)
        self.graph += Graph().parse(
            data=self.request.data,
            format=LDAPI.get_rdf_parser_for_mimetype(self.request.mimetype)
        )

    def generate_named_graph_metadata(self):
        # add graph metadata, regardless of the type of Pingback
        PROV = Namespace('http://www.w3.org/ns/prov#')
        self.graph.bind('prov', PROV)

        PROMS = Namespace('http://promsns.org/def/proms#')
        self.graph.bind('proms', PROMS)

        DCT = Namespace('http://purl.org/dc/terms/')
        self.graph.bind('dct', DCT)

        # ... the date this Pingback was sent to this PROMS Server
        self.graph.add((
            URIRef(self.named_graph_uri),
            DCT.dateSubmitted,
            Literal(datetime.now().isoformat(), datatype=XSD.dateTime)
        ))
        # ... who contributed this Pingback
        self.graph.add((
            URIRef(self.named_graph_uri),
            DCT.contributor,
            URIRef(self.request.remote_addr)
        ))

        # TODO: add other useful metadata variables gleaned from the HTTP message headers

        # PROV Pingbacks can only be of mimtype text/uri-list
        if self.request.mimetype == 'text/uri-list':
            self._generate_prov_pingback_named_graph_metadata()
        else:
            self._generate_proms_pingback_named_graph_metadata()

    def _generate_prov_pingback_named_graph_metadata(self):
        PROMS = Namespace('http://promsns.org/def/proms#')
        self.graph.bind('proms', PROMS)

        # type this pingback specifically
        self.graph.add((
            URIRef(self.named_graph_uri),
            RDF.type,
            PROMS.ProvAqPingbackNamedGraph
        ))

    def _generate_proms_pingback_named_graph_metadata(self):
        PROMS = Namespace('http://promsns.org/def/proms#')
        self.graph.bind('proms', PROMS)

        # type this pingback specifically
        self.graph.add((
            URIRef(self.named_graph_uri),
            RDF.type,
            PROMS.PromsPingbackNamedGraph
        ))