def sparql():
    """
        A POST or GET method to query the Open Annotations index with a SPARQL Query

        This method has READ access to the Annotations index.

        Required parameters:

          query:      The SPARQL query to execute

    """
    sparql_xml_results = ""
    try:
        if request.method == 'POST':
            q = request.form.get('query', None)
        else:
            q = request.args.get('query', None)

        query = QueryFactory.create(String(q))

        # Start dataset READ transaction
        dataset = TDBFactory.createDataset(app.config['STORE_LOCATION'])
        dataset.begin(ReadWrite.READ)
        try:
            qexec = QueryExecutionFactory.create(query, dataset)
            results = qexec.execSelect()
            try:
                sparql_xml_results = ResultSetFormatter.asXMLString(results)
            finally:
                qexec.close()
        finally:
            dataset.end()

    except AnnotationError, ex:
        return jsonify({'value' : ex.value, 'trace' : traceback.format_stack()})
    def test_store_creation(self):

        from com.hp.hpl.jena.tdb import TDBFactory
        from java.io import ByteArrayInputStream
        from java.lang import String

        db_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'OAC-testing.tdb')
        dataset = TDBFactory.createDataset(db_path)
        # Make sure the store was created
        assert os.path.isdir(db_path)

        # Make InputStream triples
        rdf_text = '<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="info:fedora/changeme:651"><rdf:type rdf:resource="oa:Annotation"></rdf:type><oa:hasBody xmlns:oa="http://www.w3.org/ns/openannotation/core/" rdf:resource="info:fedora/changeme:650"></oa:hasBody><oa:modelVersion xmlns:oa="http://www.w3.org/ns/openannotation/core/" rdf:resource="http://www.openannotation.org/spec/core/20120509.html"></oa:modelVersion><oa:generated xmlns:oa="http://www.w3.org/ns/openannotation/core/">2012-06-07T03:50:55.993000Z</oa:generated></rdf:Description><rdf:Description rdf:about="info:fedora/changeme:650"><rdf:type rdf:resource="oa:Body"></rdf:type><dc:format xmlns:dc="http://purl.org/dc/elements/1.1/">text/xml</dc:format></rdf:Description></rdf:RDF>'
        rdfxml = String(rdf_text)
        input_stream = ByteArrayInputStream(rdfxml.getBytes())

        model = dataset.getDefaultModel()
        model.begin()
        model.read(input_stream, None)
        model.commit()
        model.close()
        # Were all of the triples added?
        assert model.size() == 6

        shutil.rmtree(db_path)
        # Was the store removed?
        assert not os.path.isdir(db_path)
def rebuild():
    """
        A GET method that will rebuild the internal TDB index
        with all of the Annotation objects in Fedora 
    """
    try:
        query = "prefix fm: <info:fedora/fedora-system:def/model#> select ?s where {?s fm:hasModel <info:fedora/%s> }" \
                 % app.config.get('DEFUALT_ANNOTATION_CONTENT_MODEL')
        all_pids = (p.lstrip('info:fedora/') for p in Fedora.get_sparql_query_resuts(query))
        result, mimetype = Annotation.serialize(all_pids, format='nt', check_object=False)

        dataset = TDBFactory.createDataset(app.config['STORE_LOCATION'])

        # Remove all entries from the default model
        dataset.begin(ReadWrite.WRITE)
        try:
            model = dataset.getDefaultModel()
            model.begin()
            model.removeAll()
            model.commit()
            model.close()
            dataset.commit()
        except Exception, exc:
            raise
        finally:
            dataset.end()
            TDB.sync(dataset)

        # Load the triples
        dataset.begin(ReadWrite.WRITE)
        try:
            model = dataset.getDefaultModel()
            model.begin()
            n3_input_stream = ByteArrayInputStream(String(result).getBytes())            
            model.read(n3_input_stream, None, "N-TRIPLE")
            model.commit()
            model.close()
            dataset.commit() 
        except Exception, exc:
            raise
def rebuild_one():
    """
        A POST method that will rebuild the internal TDB index
        with a specific PID from Fedora
    """

    pid = request.form.get('pid', None)
    if pid is None:
        raise AnnotationError("Please pass a PID parameter to the rebuild POST request")

    print  "calling 'rebuild_one' with PID: %s" % pid

    try:
        # Get PID from Fedora and serialize it
        result, mimetype = Annotation.serialize([pid], format='nt', check_object=True)

        # Don't do anything if this there are no serialization results 
        # ie. was not an Annotation object

        dataset = TDBFactory.createDataset(app.config['STORE_LOCATION'])

        # Remove all triples from TDB involving this PID using SPARQL
        # This was my first attempt, but the SPARQL query does not
        # seem to be working.  Using the Jena API (below) also works.
        """
        query = "DELETE { ?s ?p ?o } WHERE { <info:fedora/%s> ?p ?o }" % pid
        update = UpdateFactory.create(String(query))
        dataset.begin(ReadWrite.WRITE)
        try:
            graph_store = GraphStoreFactory.create(dataset.getDefaultModel())
            update_processor = UpdateExecutionFactory.create(update, graph_store)
            results = update_processor.execute()
        except Exception, exc:
            raise
        finally:
            dataset.end()
            TDB.sync(dataset)
        """

        # Remove all triples from TDB involving this PID using Jena API
        # Start dataset WRITE transaction
        dataset.begin(ReadWrite.WRITE)
        try:
            resource = ResourceFactory.createResource("info:fedora/%s" % pid)
            model = dataset.getDefaultModel()
            model.removeAll(resource, None, None)
            model.commit()
            model.close()
            dataset.commit() 
        except Exception, exc:
            raise
        finally:
            dataset.end()
            TDB.sync(dataset)

        # Add new triples to TDB
        dataset.begin(ReadWrite.WRITE)
        try:
            model = dataset.getDefaultModel()
            model.begin()
            n3_input_stream = ByteArrayInputStream(String(result).getBytes())            
            model.read(n3_input_stream, None, "N-TRIPLE")
            model.commit()
            model.close()
            dataset.commit() 
        except Exception, exc:
            raise
def create():
    """
        A POST method that creates an Annotation (A-1) object
        based on a number of parameters.

        Required Parameters:

        source_uri:             The URI for the whole target object

        dc_title:               Dublin Core title associated with the annotation, 
                                i.e. "dublin core title goes here" 

        body_inline             Plain text string to store as the body

            OR

        body_content:           Contents of the body (XML, text, json, etc.)
            AND
        body_mimetype:          Mimetype of the body_content

            OR

        body_uri:               URI pointing to the body of the annotation


        Optional Parameters:

        annotator:              A string representing a user ID (0 or more)
                                ie. 'Charly'

        generator:              A string representing what generated the annotation
                                ie. 'Web Client'

        oax_style_uri:          A URI for a XSLT stylesheet used to render the whole target object. (0 or 1)

        oa_selector:            A string with the selector value(0 or 1)

        oa_selector_type_uri:   Required if an oa_selector is passed in
                                ie. oa:Fragment

        fragment_type:          URI describing the oa_selector type  Optional and only used if
                                an oa_selector is passed in.
                                ie. 'http://www.w3.org/TR/xpath/'

        body_content_model:     A string representing the body's content model
                                ie. 'tei-annotation'


        Will create 1 or 2 Fedora objects.  One will represent the actual annotation (A-1)
        and one will be the body of text that annotates the Fedora object (B-1).

        >>> import urllib
        >>> import urllib2
        >>> post_url = "http://localhost:5000/create"
        >>> params = { 
                "source_uri"    : "test:1#xpointer('/foo')",
                "body_content"  : "<TEI><body>text body</body></TEI>",
                "body_mimetype" : "text/xml",
                "dc_title"      : "Open Annotation Collaboration Annotation object (A-1)"
            }
        >>> encoded_data = urllib.urlencode( params )
        >>> request = urllib2.Request( post_url, encoded_data )
        >>> response = urllib2.urlopen( request )
        >>> print response.read()
        {
          "errors": [],
          "body_pid": "changeme:180",
          "annotation_pid": "changeme:181"
        }
    """

    try:
        annote = Annotation(source_uri = request.form.get('source_uri'),
                            dc_title = request.form.get('dc_title'),
                            annotated = datetime.utcnow(),
                            body_inline = request.form.get('body_inline', None),
                            body_content = request.form.get('body_content', None),
                            body_mimetype = request.form.get('body_mimetype', None),
                            body_uri = request.form.get('body_uri', None),
                            body_content_model = request.form.get('body_content_model', None),
                            annotator = request.form.get('annotator', None),
                            generator = request.form.get('generator', None),
                            oax_style_uri = request.form.get('oax_style_uri', None),
                            oa_selector = request.form.get('oa_selector', None),
                            oa_selector_type_uri = request.form.get('oa_selector_type_uri', None),
                            fragment_type = request.form.get('fragment_type', None))
        
        annote.create()
        annote.submit()
        if annote.validate():
            # Start dataset transaction
            dataset = TDBFactory.createDataset(app.config['STORE_LOCATION'])
            dataset.begin(ReadWrite.WRITE)
            try:
                model = dataset.getDefaultModel()
                model.begin()
                if annote.annotation_rdf is not None:
                    anno_input_stream = ByteArrayInputStream(String(tostring(annote.annotation_rdf)).getBytes())
                    model.read(anno_input_stream, None)
                    anno_input_stream.close()
                if annote.specific_target_rdf_element is not None:
                    spectaget_input_stream = ByteArrayInputStream(String(tostring(annote.specific_target_rdf_element)).getBytes())
                    model.read(spectaget_input_stream, None)
                    spectaget_input_stream.close()
                if annote.selector_rdf_element is not None:
                    selector_input_stream = ByteArrayInputStream(String(tostring(annote.selector_rdf_element)).getBytes())
                    model.read(selector_input_stream, None)
                    selector_input_stream.close()
                if annote.rels_ext_rdf_element is not None:
                    relsext_input_stream = ByteArrayInputStream(String(tostring(annote.rels_ext_rdf_element)).getBytes())
                    model.read(relsext_input_stream, None)
                    relsext_input_stream.close()
                if annote.body_inline_rdf_element is not None:
                    body_inline_input_stream = ByteArrayInputStream(String(tostring(annote.body_inline_rdf_element)).getBytes())
                    model.read(body_inline_input_stream, None)
                    body_inline_input_stream.close()
                model.commit()
                model.close()
                dataset.commit() 
            except Exception, exc:
                raise
            finally:
                dataset.end()
                TDB.sync(dataset)