Fedora-Jena Integration

Jena (Fuseki) is an RDF triplestore used to provide a SPARQL endpoint for the collection. The following routes consist mostly of converting a FoXML record into RDF/XML and then into a serialized N3 format suitable for using in a SPARQL INSERT DATA query. The conversion from FoXML to RDF+XML is done with the xslt component, while the conversion from RDF+XML to N3 is done with the help of an external Python script and the exec component.

Objects are stored in multiple Jena TDB stores in order to handle access control: objects available to the public go into acdc-public while those restricted to authenticated users go into acdc-authn.

<camelContext id="jena-routes" xmlns="http://camel.apache.org/schema/spring"
    xmlns:foxml="info:fedora/fedora-system:def/foxml#"
    xmlns:xacml="urn:oasis:names:tc:xacml:1.0:policy">
  <route id="jena-delete">
    <description>Route for deleting an item from Jena</description>
    <from uri="vm:jena.delete"/>
    <log message="deleting item from Jena" loggingLevel="INFO"/>
    <setBody>
      <simple>
        DELETE { ?s ?p ?o } 
        WHERE { ?s ?p ?o . 
                FILTER (?s = &lt;http://acdc.amherst.edu/id/${header.pid}&gt; ) . }
      </simple>
    </setBody>      
    <multicast>
      <to uri="seda:jena.delete.authn"/>
      <to uri="seda:jena.delete.public"/>
    </multicast>
  </route>
 
  <route id="jena-public-delete">
    <description>Set the datastore to acdc-public</description>
    <from uri="seda:jena.delete.public"/>
    <setHeader headerName="datastore">
      <constant>acdc-public</constant>
    </setHeader>
    <to uri="seda:jena.http"/>
  </route>
 
  <route id="jena-authn-delete">
    <description>Set the datastore to acdc-authn</description>
    <from uri="seda:jena.delete.authn"/>
    <setHeader headerName="datastore">
      <constant>acdc-authn</constant>
    </setHeader>
    <to uri="seda:jena.http"/>
  </route>
 
  <route id="jena-http">
    <description>Send message body to Fuseki endpoint</description>
    <from uri="seda:jena.http"/>
    <log message="Sending ${header.pid} data to Fuseki: ${header.datastore}"/>
    <setHeader headerName="Exchange.HTTP_METHOD">
      <constant>POST</constant>
    </setHeader>
    <setHeader headerName="Exchange.CONTENT_TYPE">
    <constant>application/sparql-update</constant>
    </setHeader>
    <setHeader headerName="Exchange.HTTP_PATH">
      <simple>/${header.datastore}/update</simple>
    </setHeader>
    <to uri="http4://fuseki-host:3030/"/>
  </route>
 
  <route id="jena-update">
    <description>Route for updating an item in Jena</description>
    <from uri="vm:jena.update"/>
    <log message="update/insert ${header.pid}" loggingLevel="INFO"/>
    <choice>
      <!-- limits on api-a, filter on authenticated user -->
      <when>
            <xpath>/foxml:datastream[@ID='POLICY']/foxml:datastreamVersion[last()]/foxml:xmlContent/xacml:Policy//xacml:Rule[@Effect='Deny']//xacml:ActionAttributeDesignator[@AttributeId='urn:fedora:names:fedora:2.1:action:api']/parent::node()/xacml:AttributeValue[normalize-space(text())='urn:fedora:names:fedora:2.1:action:api-a']</xpath>
        <filter>
          <xpath>/foxml:datastream[@ID='POLICY']/foxml:datastreamVersion[last()]/foxml:xmlContent/xacml:Policy//xacml:Rule[@Effect='Deny']//xacml:ActionAttributeDesignator[@AttributeId ='urn:fedora:names:fedora:2.1:action:api']/parent::node()/xacml:AttributeValue[normalize-space(text())='urn:fedora:names:fedora:2.1:action:api-a']/ancestor::xacml:Rule/xacml:Condition[@FunctionId='urn:oasis:names:tc:xacml:1.0:function:not']//xacml:Apply[@FunctionId='urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of']/xacml:SubjectAttributeDesignator[@AttributeId='fedoraRole']/parent::node()/xacml:Apply/xacml:AttributeValue[text()=$fedoraRole]</xpath>
          <to uri="seda:jena.insert"/>
        </filter>
      </when>
      <!-- no limits on api-a -->
      <otherwise>
        <to uri="seda:jena.rdfize"/>
      </otherwise>
    </choice>
  </route>
 
  <route id="jena-rdfize">
    <description>Add item to Jena</description>
    <from uri="seda:jena.rdfize"/>
    <log message="converting ${header.pid} to RDF"/>
    <to uri="xslt:file:///path/to/foxml2rdf.xsl"/>
    <to uri="exec:///path/to/rdf2n3.py"/>
    <setBody>
      <simple>
        DELETE { ?s ?p ?o } 
        WHERE { ?s ?p ?o . 
                FILTER (?s = &lt;http://acdc.amherst.edu/id/${header.pid}&gt; ) . }
        ${body}
      </simple>
    </setBody>
    <multicast>
      <to uri="seda:jena.insert.authn"/>
      <to uri="seda:jena.insert.public"/>
    </multicast>
  </route>
 
  <route id="jena-authn">
    <description>Define headers for an authn-protected item</description>
    <from uri="seda:jena.insert.authn"/>
    <setHeader headerName="datastore">
      <constant>acdc-authn</constant>
    </setHeader>
    <setHeader headerName="fedoraRole">
      <constant>authenticated user</constant>
    </setHeader>
    <to uri="seda:jena.http"/>
  </route>
 
  <route id="jena-public">
    <description>Define headers for a public item</description>
    <from uri="seda:jena.insert.public"/>
    <setHeader headerName="datastore">
      <constant>acdc-public</constant>
    </setHeader>
    <setHeader headerName="fedoraRole">
      <constant>anonymous user</constant>
    </setHeader>
    <to uri="seda:jena.http"/>
  </route>
</camelContext>
jena-routes.txt · Last modified: 2013/03/26 13:02 by acoburn@amherst.edu
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International