From 6a930f6d7db3719dc3ff232f2dcbfeef7cbb3a6e Mon Sep 17 00:00:00 2001 From: Stian Soiland-Reyes Date: Tue, 28 May 2013 14:17:24 +0100 Subject: [PATCH] RDF support for REST service: FOAF profile Implemented by adding org.orcid.api.common.writer.rdf.RDFMessageBodyWriter and modified org.orcid.api.common.OrcidApiService to allow text/turtle and application/rdf-xml for viewBioDetailsRdf by simply translating the XML JAXB bean into RDF. Thus existing visibility checks etc. should work. No write support from RDF is planned as it could get tricky if the RDF contained additional statements that would have to be either thrown away or stored somewhere per ORCID. The implementations of OrcidApiService have been modified in both orcid-pub-web and orcid-api-web - TODO: Do we really need various methods like viewBioDetailsRdf and viewBioDetailsJson, or just change them to have multiple @Produces ? The remaining REST services have not yet been RDFized, doing this for orcid-works requires some thoughts as to what existing vocabularies and terms should be used - for instance BIBO ontology or simply dcterms:bibliographicReferences etc. Example of RDF document: ``` c:\Users\stain>curl -H "Accept: text/turtle" http://localhost:8080/orcid-pub-web/0000-0002-0222-5559 @prefix rdfs: . @prefix prov: . @prefix foaf: . @prefix pav: . @prefix owl: . @prefix xsd: . @prefix rdf: . a foaf:PersonalProfileDocument , foaf:OnlineAccount ; rdfs:label "0000-0002-0222-5559" ; pav:createdBy ; pav:createdOn "2013-05-24T16:14:43.885+01:00"^^xsd:dateTime ; pav:createdWith ; pav:lastUpdateOn "2013-05-25T20:32:37.295+01:00"^^xsd:dateTime ; prov:generatedAtTime "2013-05-25T20:32:37.295+01:00"^^xsd:dateTime ; prov:wasAttributedTo ; foaf:accountName "0000-0002-0222-5559" ; foaf:accountServiceHomepage ; foaf:maker ; foaf:primaryTopic . a foaf:Person , prov:Person ; rdfs:label "Johnnye Does" ; foaf:account ; foaf:familyName "Doe" ; foaf:givenName "John" ; foaf:mbox , , ; foaf:name "Johnnye Does" ; foaf:page , ; foaf:plan """I am a very interesting person with several lines of biography""" ; foaf:publications . ``` This corresponds to the XML: ``` c:\Users\stain>curl -H "Accept: application/xml" http://localhost:8080/orcid-pub-web/0000-0002-0222-5559 1.0.14 0000-0002-0222-5559 http://localhost:8080/orcid-web/0000-0002-0222-5559 website 2013-05-24T16:14:43.885+01:00 2013-05-25T20:32:37.295+01:00 true John Doe Johnnye Does Old Johnny I am a very interesting person with several lines of biography http://homepage.example.com/ Other http://work.example.org/ otheremail@example.com oldemail@example.com johndoe@example.com some keywords, entered, here orcid.org/0000-0001-9842-9718 ``` RDF notes ========= Vocabularies: * foaf: http://xmlns.com/foaf/0.1/ * pav: http://purl.org/pav/ * prov: http://www.w3.org/ns/prov# An ORCID (e.g. ) is presented as a [http://xmlns.com/foaf/spec/#term_Person](foaf:Person), with foaf:givenName, foaf:familyName, foaf:mbox, etc. The ORCID identifier represents the person (and not his record) and can be used directly in Linked Data for attribution and provenance. The ORCID record is identified as - in the REST interface both of these URIs return the same RDF (and XML), but the distinction is that the second identifies the ORCID record at orcid.org. Thus creation date of the record, [purl.org/pav/html#http://purl.org/pav/createdOn](pav:createdOn), is when the user registered on ORCID (the submission-date in XML), and if the record was created on the website, then the person is also listed as the pav:createdBy, foaf:maker and prov:wasAttributedTo. If the ORCID has been claimed, then this will be a foaf:PersonalProfileDocument - this is only the case if the user has actually claimed (and presumably curated) the ORCID record, even if it was imported through the API. See https://github.com/stain/ORCID-Source/tree/rdf for individual commits. Squashed commit of the following: commit 20795bc7591e6038238d551fdd4c3e62800c2615 Author: Stian Soiland-Reyes Date: Tue May 28 14:14:46 2013 +0100 RDF: Ignore uriinfo if null (for unit test) commit 9f3c198d882396630cf67749a7470b1398bbe5de Merge: 1c8c576 e001319 Author: Stian Soiland-Reyes Date: Tue May 28 14:08:09 2013 +0100 Merge branch 'dev-rdf' into rdf commit e001319a2663cf681653a6e8c069da7ddee7155f Author: Stian Soiland-Reyes Date: Tue May 28 13:49:08 2013 +0100 RDF support for orcid - FOAF profile presents a simple FOAF profile for REST requests. Implemented by adding org.orcid.api.common.writer.rdf.RDFMessageBodyWriter and modified org.orcid.api.common.OrcidApiService to allow text/turtle and application/rdf-xml for viewBioDetailsRdf by simply translating the XML JAXB bean into RDF. Thus existing visibility checks etc. should work. No write support from RDF is planned as it could get tricky if the RDF contained additional statements that would have to be either thrown away or stored somewhere per ORCID. The implementations of OrcidApiService have been modified in both orcid-pub-web and orcid-api-web - TODO: Do we really need various methods like viewBioDetailsRdf and viewBioDetailsJson, or just change them to have multiple @Produces ? The remaining REST services have not yet been RDFized, doing this for orcid-works requires some thoughts as to what existing vocabularies and terms should be used - for instance BIBO ontology or simply dcterms:bibliographicReferences etc. Example of RDF document: c:\Users\stain>curl -H "Accept: text/turtle" http://localhost:8080/orcid-pub-web/0000-0002-0222-5559 @prefix rdfs: . @prefix prov: . @prefix foaf: . @prefix pav: . @prefix owl: . @prefix xsd: . @prefix rdf: . a foaf:PersonalProfileDocument , foaf:OnlineAccount ; rdfs:label "0000-0002-0222-5559" ; pav:createdBy ; pav:createdOn "2013-05-24T16:14:43.885+01:00"^^xsd:dateTime ; pav:createdWith ; pav:lastUpdateOn "2013-05-25T20:32:37.295+01:00"^^xsd:dateTime ; prov:generatedAtTime "2013-05-25T20:32:37.295+01:00"^^xsd:dateTime ; prov:wasAttributedTo ; foaf:accountName "0000-0002-0222-5559" ; foaf:accountServiceHomepage ; foaf:maker ; foaf:primaryTopic . a foaf:Person , prov:Person ; rdfs:label "Johnnye Does" ; foaf:account ; foaf:familyName "Doe" ; foaf:givenName "John" ; foaf:mbox , , ; foaf:name "Johnnye Does" ; foaf:page , ; foaf:plan """I am a very interesting person with several lines of biography""" ; foaf:publications . This corresponds to the XML: c:\Users\stain>curl -H "Accept: application/xml" http://localhost:8080/orcid-pub-web/0000-0002-0222-5559 1.0.14 0000-0002-0222-5559 http://localhost:8080/orcid-web/0000-0002-0222-5559 website 2013-05-24T16:14:43.885+01:00 2013-05-25T20:32:37.295+01:00 true John Doe Johnnye Does Old Johnny I am a very interesting person with several lines of biography http://homepage.example.com/ Other http://work.example.org/ otheremail@example.com oldemail@example.com johndoe@example.com some keywords, entered, here orcid.org/0000-0001-9842-9718 RDF notes ========= Vocabularies: * foaf: http://xmlns.com/foaf/0.1/ * pav: http://purl.org/pav/ * prov: http://www.w3.org/ns/prov# An ORCID (e.g. ) is presented as a [http://xmlns.com/foaf/spec/#term_Person](foaf:Person), with foaf:givenName, foaf:familyName, foaf:mbox, etc. The ORCID identifier represents the person (and not his record) and can be used directly in Linked Data for attribution and provenance. The ORCID record is identified as - in the REST interface both of these URIs return the same RDF (and XML), but the distinction is that the second identifies the ORCID record at orcid.org. Thus creation date of the record, [purl.org/pav/html#http://purl.org/pav/createdOn](pav:createdOn), is when the user registered on ORCID (the submission-date in XML), and if the record was created on the website, then the person is also listed as the pav:createdBy, foaf:maker and prov:wasAttributedTo. If the ORCID has been claimed, then this will be a foaf:PersonalProfileDocument - this is only the case if the user has actually claimed (and presumably curated) the ORCID record, even if it was imported through the API. See https://github.com/stain/ORCID-Source/tree/rdf for individual commits. Squashed commit of the following: commit 1c8c57634d7f4f9fb1c3fcec5c018a962c10cd41 Author: Stian Soiland-Reyes Date: Tue May 28 13:48:04 2013 +0100 RDF: dates for ORCID record modifications commit 1a89cbb0946c12737f108f0d51638e918a6489e5 Author: Stian Soiland-Reyes Date: Tue May 28 12:41:38 2013 +0100 provenance of ORCID account (when was it last modified?) commit ed2db405975df414abd9f2610ddd0b26ea7dd764 Author: Stian Soiland-Reyes Date: Tue May 28 11:04:18 2013 +0100 RDF: publication link to XML repr rather than HTML commit 1a91ed53ad75c8a7b8d179b13153f91bee6619ac Author: Stian Soiland-Reyes Date: Tue May 28 11:02:06 2013 +0100 RDF: Error representation (with relative URI). Publications. commit 8744ea973f0351813f6545b1c6c336bf4bb7a107 Author: Stian Soiland-Reyes Date: Sun May 26 11:37:34 2013 +0100 load pav and prov ontologies for provenance commit 06057ab9b0230d9fdff843ac83bc9090df251faf Author: Stian Soiland-Reyes Date: Sat May 25 20:35:13 2013 +0100 Refactored methods per section of XML bean commit 22c405d6b5603fdab7628413ffa6a973e7a0bebf Author: Stian Soiland-Reyes Date: Fri May 24 17:57:40 2013 +0100 orcid as foaf account commit 490760fa344d473cf90cf1eaa7036c267b6eb51d Author: Stian Soiland-Reyes Date: Fri May 24 17:02:58 2013 +0100 Don't forget foaf:Person! commit b6f91eb3629e7175a3643198c478a64a6f435e70 Author: Stian Soiland-Reyes Date: Fri May 24 17:00:53 2013 +0100 Load FOAF separately and add as import (avoids printing all of foaf!) commit cbfd2fc305800f991255717b5d49682f4a8a1eb1 Author: Stian Soiland-Reyes Date: Fri May 24 16:47:29 2013 +0100 Tests for RDFMessageBodyWriter commit db9db1a931bca2ddf0ab295f0de812ef55295fd1 Author: Stian Soiland-Reyes Date: Fri May 24 16:47:11 2013 +0100 FOAF ontology Downloaded from http://xmlns.com/foaf/0.1/ as application/rdf+xml commit 4bab8c07b04629a8c16d3c06ae90f55792b19682 Author: Stian Soiland-Reyes Date: Fri May 24 16:46:43 2013 +0100 Media Type done correctly commit 01bd12546ac52bbeedf7f83344deb0527c4db2ae Author: Stian Soiland-Reyes Date: Fri May 24 16:26:03 2013 +0100 Removed orcid-api-rdf dependency commit 226c9d6ab7d4ac5479d671f244fe49e715134185 Author: Stian Soiland-Reyes Date: Fri May 24 16:24:49 2013 +0100 Remove silly debug exception :) commit d08fac9ab358707c9a843be6a1c0b94cae48be40 Author: Stian Soiland-Reyes Date: Fri May 24 16:24:29 2013 +0100 Moved RDFMessageBody to orcid-api-common commit 6373e21f5b9cd5dd29b4a8e62b38a2cb6b46174c Author: Stian Soiland-Reyes Date: Fri May 24 14:02:34 2013 +0100 RDF: Charset versions of text/turtle and text/n3 separate commit 3c5223952cc88498c14ba4024fdffab1307dbe19 Author: Stian Soiland-Reyes Date: Fri May 24 14:02:06 2013 +0100 Load FOAF locally, and only once commit f13be2f0b8f5c07ccbb17c1687111fb945ba6da5 Author: Stian Soiland-Reyes Date: Fri May 24 10:37:40 2013 +0100 Include basedir and relativePath commit 228a7ac6a2cd91b46576c80a958c8ab3e74c80a8 Author: Stian Soiland-Reyes Date: Thu May 23 22:15:57 2013 +0100 Turtle support? commit a6065516328e1d36990c0d81530500cbe9f12b3b Author: Stian Soiland-Reyes Date: Thu May 23 22:11:13 2013 +0100 Moved RDF writer to orcid-api-rdf so it can be maintained more loosely commit 558a1d7e5f28d2a3fa1a9c7fa4a0e43db672dbb6 Author: Stian Soiland-Reyes Date: Thu May 23 21:49:35 2013 +0100 get URL for orcID not orcIDID commit 3fa8e0e8422ae2a5c3453011132d5232e0c1b7f3 Author: Stian Soiland-Reyes Date: Thu May 23 21:46:47 2013 +0100 nullchecks commit 3691fa396aec024481d5a6390b36192954f0855d Author: Stian Soiland-Reyes Date: Thu May 23 21:30:42 2013 +0100 Moved RDF transformation to RDFMessageBodyWriter commit 720106262ff782193ccd6ca6ff5c05ae350dad85 Author: Stian Soiland-Reyes Date: Thu May 23 20:21:51 2013 +0100 Jena-based RDF wrapper commit b5faeea48e8ca839f2eb368cad9d8de357365d9d Author: Stian Soiland-Reyes Date: Thu May 23 19:32:34 2013 +0100 Clone of HTML Writer commit 695b55d6f47367da6c6953c261866d6241b42106 Author: Stian Soiland-Reyes Date: Thu May 23 19:32:20 2013 +0100 Ignore RDF test for now, so build passest commit 682ea05d96d912f5990455cc7205c148a7af7cc8 Author: Stian Soiland-Reyes Date: Thu May 23 19:31:54 2013 +0100 Temporarily Break HTML Writer - is it used? :) commit aee172131dc89cf8cb2eb83492583539aa9f1827 Author: Stian Soiland-Reyes Date: Wed May 22 11:26:51 2013 +0100 RDF: Test for RDF/XML entity commit cf1fc194e0f72ad2669b1a2c63432467b874ad6c Author: Stian Soiland-Reyes Date: Wed May 22 10:22:40 2013 +0100 RDF: Remove unused methods in RDFTest commit 115d4c39643efa82109634198ceb185131ed78b8 Author: Stian Soiland-Reyes Date: Wed May 22 10:17:50 2013 +0100 RDF: Skeleton viewBioDetailsRdf and viewBioDetailsTurtle commit 63673c86704a57f273bbee3c306e9fffb54fcee3 Author: Stian Soiland-Reyes Date: Wed May 22 10:03:00 2013 +0100 Clone T1OrcidApiServiceImplMetricsTest to test RDF commit 1c8c57634d7f4f9fb1c3fcec5c018a962c10cd41 Author: Stian Soiland-Reyes Date: Tue May 28 13:48:04 2013 +0100 RDF: dates for ORCID record modifications commit 1a89cbb0946c12737f108f0d51638e918a6489e5 Author: Stian Soiland-Reyes Date: Tue May 28 12:41:38 2013 +0100 provenance of ORCID account (when was it last modified?) commit ed2db405975df414abd9f2610ddd0b26ea7dd764 Author: Stian Soiland-Reyes Date: Tue May 28 11:04:18 2013 +0100 RDF: publication link to XML repr rather than HTML commit 1a91ed53ad75c8a7b8d179b13153f91bee6619ac Author: Stian Soiland-Reyes Date: Tue May 28 11:02:06 2013 +0100 RDF: Error representation (with relative URI). Publications. commit 8744ea973f0351813f6545b1c6c336bf4bb7a107 Author: Stian Soiland-Reyes Date: Sun May 26 11:37:34 2013 +0100 load pav and prov ontologies for provenance commit 06057ab9b0230d9fdff843ac83bc9090df251faf Author: Stian Soiland-Reyes Date: Sat May 25 20:35:13 2013 +0100 Refactored methods per section of XML bean commit 22c405d6b5603fdab7628413ffa6a973e7a0bebf Author: Stian Soiland-Reyes Date: Fri May 24 17:57:40 2013 +0100 orcid as foaf account commit 490760fa344d473cf90cf1eaa7036c267b6eb51d Author: Stian Soiland-Reyes Date: Fri May 24 17:02:58 2013 +0100 Don't forget foaf:Person! commit b6f91eb3629e7175a3643198c478a64a6f435e70 Author: Stian Soiland-Reyes Date: Fri May 24 17:00:53 2013 +0100 Load FOAF separately and add as import (avoids printing all of foaf!) commit cbfd2fc305800f991255717b5d49682f4a8a1eb1 Author: Stian Soiland-Reyes Date: Fri May 24 16:47:29 2013 +0100 Tests for RDFMessageBodyWriter commit db9db1a931bca2ddf0ab295f0de812ef55295fd1 Author: Stian Soiland-Reyes Date: Fri May 24 16:47:11 2013 +0100 FOAF ontology Downloaded from http://xmlns.com/foaf/0.1/ as application/rdf+xml commit 4bab8c07b04629a8c16d3c06ae90f55792b19682 Author: Stian Soiland-Reyes Date: Fri May 24 16:46:43 2013 +0100 Media Type done correctly commit 01bd12546ac52bbeedf7f83344deb0527c4db2ae Author: Stian Soiland-Reyes Date: Fri May 24 16:26:03 2013 +0100 Removed orcid-api-rdf dependency commit 226c9d6ab7d4ac5479d671f244fe49e715134185 Author: Stian Soiland-Reyes Date: Fri May 24 16:24:49 2013 +0100 Remove silly debug exception :) commit d08fac9ab358707c9a843be6a1c0b94cae48be40 Author: Stian Soiland-Reyes Date: Fri May 24 16:24:29 2013 +0100 Moved RDFMessageBody to orcid-api-common commit 6373e21f5b9cd5dd29b4a8e62b38a2cb6b46174c Author: Stian Soiland-Reyes Date: Fri May 24 14:02:34 2013 +0100 RDF: Charset versions of text/turtle and text/n3 separate commit 3c5223952cc88498c14ba4024fdffab1307dbe19 Author: Stian Soiland-Reyes Date: Fri May 24 14:02:06 2013 +0100 Load FOAF locally, and only once commit f13be2f0b8f5c07ccbb17c1687111fb945ba6da5 Author: Stian Soiland-Reyes Date: Fri May 24 10:37:40 2013 +0100 Include basedir and relativePath commit 228a7ac6a2cd91b46576c80a958c8ab3e74c80a8 Author: Stian Soiland-Reyes Date: Thu May 23 22:15:57 2013 +0100 Turtle support? commit a6065516328e1d36990c0d81530500cbe9f12b3b Author: Stian Soiland-Reyes Date: Thu May 23 22:11:13 2013 +0100 Moved RDF writer to orcid-api-rdf so it can be maintained more loosely commit 558a1d7e5f28d2a3fa1a9c7fa4a0e43db672dbb6 Author: Stian Soiland-Reyes Date: Thu May 23 21:49:35 2013 +0100 get URL for orcID not orcIDID commit 3fa8e0e8422ae2a5c3453011132d5232e0c1b7f3 Author: Stian Soiland-Reyes Date: Thu May 23 21:46:47 2013 +0100 nullchecks commit 3691fa396aec024481d5a6390b36192954f0855d Author: Stian Soiland-Reyes Date: Thu May 23 21:30:42 2013 +0100 Moved RDF transformation to RDFMessageBodyWriter commit 720106262ff782193ccd6ca6ff5c05ae350dad85 Author: Stian Soiland-Reyes Date: Thu May 23 20:21:51 2013 +0100 Jena-based RDF wrapper commit b5faeea48e8ca839f2eb368cad9d8de357365d9d Author: Stian Soiland-Reyes Date: Thu May 23 19:32:34 2013 +0100 Clone of HTML Writer commit 695b55d6f47367da6c6953c261866d6241b42106 Author: Stian Soiland-Reyes Date: Thu May 23 19:32:20 2013 +0100 Ignore RDF test for now, so build passest commit 682ea05d96d912f5990455cc7205c148a7af7cc8 Author: Stian Soiland-Reyes Date: Thu May 23 19:31:54 2013 +0100 Temporarily Break HTML Writer - is it used? :) commit aee172131dc89cf8cb2eb83492583539aa9f1827 Author: Stian Soiland-Reyes Date: Wed May 22 11:26:51 2013 +0100 RDF: Test for RDF/XML entity commit cf1fc194e0f72ad2669b1a2c63432467b874ad6c Author: Stian Soiland-Reyes Date: Wed May 22 10:22:40 2013 +0100 RDF: Remove unused methods in RDFTest commit 115d4c39643efa82109634198ceb185131ed78b8 Author: Stian Soiland-Reyes Date: Wed May 22 10:17:50 2013 +0100 RDF: Skeleton viewBioDetailsRdf and viewBioDetailsTurtle commit 63673c86704a57f273bbee3c306e9fffb54fcee3 Author: Stian Soiland-Reyes Date: Wed May 22 10:03:00 2013 +0100 Clone T1OrcidApiServiceImplMetricsTest to test RDF --- orcid-api-common/pom.xml | 4 + .../orcid/api/common/OrcidApiConstants.java | 6 + .../org/orcid/api/common/OrcidApiService.java | 27 + .../writer/rdf/RDFMessageBodyWriter.java | 604 ++++++ .../org/orcid/api/common/writer/rdf/foaf.rdf | 606 ++++++ .../org/orcid/api/common/writer/rdf/pav.rdf | 552 +++++ .../orcid/api/common/writer/rdf/prov-o.rdf | 1788 +++++++++++++++++ .../api/common/writer/rdf/RDFWriterTest.java | 106 + .../api/t2/server/T2OrcidApiServiceImpl.java | 37 + .../t2/integration/T2OrcidApiClientImpl.java | 26 + orcid-pub-web/pom.xml | 1 + .../api/t1/server/T1OrcidApiServiceImpl.java | 65 +- .../t1/integration/T1OrcidApiClientImpl.java | 26 + pom.xml | 5 + 14 files changed, 3844 insertions(+), 9 deletions(-) create mode 100644 orcid-api-common/src/main/java/org/orcid/api/common/writer/rdf/RDFMessageBodyWriter.java create mode 100644 orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/foaf.rdf create mode 100644 orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/pav.rdf create mode 100644 orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/prov-o.rdf create mode 100644 orcid-api-common/src/test/java/org/orcid/api/common/writer/rdf/RDFWriterTest.java diff --git a/orcid-api-common/pom.xml b/orcid-api-common/pom.xml index 3a2e1e48399..2d7a5c92a4c 100644 --- a/orcid-api-common/pom.xml +++ b/orcid-api-common/pom.xml @@ -79,6 +79,10 @@ org.hibernate hibernate-validator + + org.apache.jena + jena-core + diff --git a/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiConstants.java b/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiConstants.java index 1e0eb332142..2b291e11da0 100644 --- a/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiConstants.java +++ b/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiConstants.java @@ -31,6 +31,12 @@ public class OrcidApiConstants { public static final String ORCID_XML = "application/orcid+xml; qs=3"; public static final String ORCID_JSON = "application/orcid+json; qs=2"; + public static final String TEXT_TURTLE = "text/turtle; qs=3"; + public static final String TEXT_TURTLE_UTF8 = "text/turtle; charset=utf8; qs=3"; + public static final String TEXT_N3 = "text/n3; qs=2"; + public static final String TEXT_N3_UTF8 = "text/n3; charset=utf8; qs=2"; + + public static final String APPLICATION_RDFXML = "application/rdf+xml; qs=2"; public static final String VND_ORCID_XML = "application/vnd.orcid+xml; qs=5"; public static final String VND_ORCID_JSON = "application/vnd.orcid+json; qs=4"; diff --git a/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiService.java b/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiService.java index 090de1b823f..66936876707 100644 --- a/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiService.java +++ b/orcid-api-common/src/main/java/org/orcid/api/common/OrcidApiService.java @@ -77,6 +77,33 @@ public interface OrcidApiService { @Path(BIO_PATH) T viewBioDetailsJson(@PathParam("orcid") String orcid); + /** + * GETs the RDF/XML representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF/XML representation of the ORCID record + */ + @GET + @Produces(value = { APPLICATION_RDFXML }) + @Path(BIO_PATH) + T viewBioDetailsRdf(@PathParam("orcid") String orcid); + + + /** + * GETs the RDF Turtle representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF Turtle representation of the ORCID record + */ + @GET + @Produces(value = { TEXT_N3, TEXT_TURTLE }) + @Path(BIO_PATH) + T viewBioDetailsTurtle(@PathParam("orcid") String orcid); + /** * GETs the HTML representation of the ORCID external identifiers * diff --git a/orcid-api-common/src/main/java/org/orcid/api/common/writer/rdf/RDFMessageBodyWriter.java b/orcid-api-common/src/main/java/org/orcid/api/common/writer/rdf/RDFMessageBodyWriter.java new file mode 100644 index 00000000000..01c49020d34 --- /dev/null +++ b/orcid-api-common/src/main/java/org/orcid/api/common/writer/rdf/RDFMessageBodyWriter.java @@ -0,0 +1,604 @@ +/** + * ============================================================================= + * + * ORCID (R) Open Source + * http://orcid.org + * + * Copyright (c) 2012-2013 ORCID, Inc. + * Licensed under an MIT-Style License (MIT) + * http://orcid.org/open-source-license + * + * This copyright and license information (including a link to the full license) + * shall be included in its entirety in all copies or substantial portion of + * the software. + * + * ============================================================================= + */ +package org.orcid.api.common.writer.rdf; + +import static org.orcid.api.common.OrcidApiConstants.APPLICATION_RDFXML; +import static org.orcid.api.common.OrcidApiConstants.PROFILE_POST_PATH; +import static org.orcid.api.common.OrcidApiConstants.TEXT_N3; +import static org.orcid.api.common.OrcidApiConstants.TEXT_TURTLE; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; + +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.orcid.api.common.OrcidApiService; +import org.orcid.jaxb.model.message.Address; +import org.orcid.jaxb.model.message.Biography; +import org.orcid.jaxb.model.message.ContactDetails; +import org.orcid.jaxb.model.message.Email; +import org.orcid.jaxb.model.message.ErrorDesc; +import org.orcid.jaxb.model.message.LastModifiedDate; +import org.orcid.jaxb.model.message.OrcidBio; +import org.orcid.jaxb.model.message.OrcidHistory; +import org.orcid.jaxb.model.message.OrcidMessage; +import org.orcid.jaxb.model.message.OrcidProfile; +import org.orcid.jaxb.model.message.PersonalDetails; +import org.orcid.jaxb.model.message.ResearcherUrl; +import org.orcid.jaxb.model.message.ResearcherUrls; +import org.springframework.beans.factory.annotation.Value; + +import com.hp.hpl.jena.datatypes.xsd.XSDDatatype; +import com.hp.hpl.jena.ontology.DatatypeProperty; +import com.hp.hpl.jena.ontology.Individual; +import com.hp.hpl.jena.ontology.ObjectProperty; +import com.hp.hpl.jena.ontology.OntClass; +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.Ontology; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.ModelFactory; + +/** + * 2013 ORCID + * + * @author Stian Soiland-Reyes + */ +@Provider +@Produces( { APPLICATION_RDFXML, TEXT_TURTLE, TEXT_N3 }) +public class RDFMessageBodyWriter implements MessageBodyWriter { + + private static final String MEMBER_API = "https://api.orcid.org/"; + private static final String EN = "en"; + private static final String FOAF_RDF = "foaf.rdf"; + private static final String PAV = "http://purl.org/pav/"; + private static final String PAV_RDF = "pav.rdf"; + private static final String PROV_O_RDF = "prov-o.rdf"; + private static final String PROV = "http://www.w3.org/ns/prov#"; + private static final String PROV_O = "http://www.w3.org/ns/prov-o#"; + private static final String FOAF_0_1 = "http://xmlns.com/foaf/0.1/"; + protected static final String TMP_BASE = "app://614879b4-48c3-45ab-a828-2a72e43f80d9/"; + private static final Charset UTF8 = Charset.forName("UTF-8"); + + private DatatypeProperty foafName; + private DatatypeProperty foafGivenName; + private DatatypeProperty foafFamilyName; + private OntClass foafPerson; + private OntClass foafOnlineAccount; + private ObjectProperty foafAccount; + private ObjectProperty foafAccountServiceHomepage; + + @Value("${org.orcid.core.baseUri:http://orcid.org}") + private String baseUri = "http://orcid.org"; + private DatatypeProperty foafAccountName; + private ObjectProperty foafPrimaryTopic; + private ObjectProperty foafPublications; + private OntClass foafPersonalProfileDocument; + private OntModel prov; + private OntModel foaf; + private OntModel pav; + + @Context + private UriInfo uriInfo; + private ObjectProperty pavCreatedWith; + private ObjectProperty pavCreatedBy; + private OntClass provPerson; + private OntClass provSoftwareAgent; + private OntClass provAgent; + private ObjectProperty provWasAttributedTo; + private DatatypeProperty provGeneratedAt; + private ObjectProperty pavCuratedBy; + private ObjectProperty foafMbox; + private ObjectProperty foafMaker; + private DatatypeProperty foafPlan; + private ObjectProperty foafPage; + private ObjectProperty foafHomepage; + private ObjectProperty foafBasedNear; + private DatatypeProperty pavLastUpdateAt; + private ObjectProperty provAlternateOf; + private ObjectProperty pavImportedBy; + private DatatypeProperty pavCreatedOn; + private DatatypeProperty provInvalidatedAt; + private DatatypeProperty pavContributedOn; + + + /** + * Ascertain if the MessageBodyWriter supports a particular type. + * + * @param type + * the class of object that is to be written. + * @param genericType + * the type of object to be written, obtained either by + * reflection of a resource method return type or via inspection + * of the returned instance. + * {@link javax.ws.rs.core.GenericEntity} provides a way to + * specify this information at runtime. + * @param annotations + * an array of the annotations on the resource method that + * returns the object. + * @param mediaType + * the media type of the HTTP entity. + * @return true if the type is supported, otherwise false. + */ + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return OrcidMessage.class.isAssignableFrom(type); + } + + /** + * Called before writeTo to ascertain the length in bytes of + * the serialized form of t. A non-negative return value is + * used in a HTTP Content-Length header. + * + * @param message + * the instance to write + * @param type + * the class of object that is to be written. + * @param genericType + * the type of object to be written, obtained either by + * reflection of a resource method return type or by inspection + * of the returned instance. + * {@link javax.ws.rs.core.GenericEntity} provides a way to + * specify this information at runtime. + * @param annotations + * an array of the annotations on the resource method that + * returns the object. + * @param mediaType + * the media type of the HTTP entity. + * @return length in bytes or -1 if the length cannot be determined in + * advance + */ + @Override + public long getSize(OrcidMessage message, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + // TODO: Can we calculate the size in advance? + // It would mean buffering up the actual RDF + return -1; + } + + /** + * Write a type to an HTTP response. The response header map is mutable but + * any changes must be made before writing to the output stream since the + * headers will be flushed prior to writing the response body. + * + * @param message + * the instance to write. + * @param type + * the class of object that is to be written. + * @param genericType + * the type of object to be written, obtained either by + * reflection of a resource method return type or by inspection + * of the returned instance. + * {@link javax.ws.rs.core.GenericEntity} provides a way to + * specify this information at runtime. + * @param annotations + * an array of the annotations on the resource method that + * returns the object. + * @param mediaType + * the media type of the HTTP entity. + * @param httpHeaders + * a mutable map of the HTTP response headers. + * @param entityStream + * the {@link java.io.OutputStream} for the HTTP entity. The + * implementation should not close the output stream. + * @throws java.io.IOException + * if an IO error arises + * @throws javax.ws.rs.WebApplicationException + * if a specific HTTP error response needs to be produced. Only + * effective if thrown prior to the response being committed. + */ + @Override + public void writeTo(OrcidMessage xml, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { + + OntModel m = getOntModel(); + + if (xml.getErrorDesc() != null) { + describeError(xml.getErrorDesc(), m); + } + + OrcidProfile orcidProfile = xml.getOrcidProfile(); + System.out.println(httpHeaders); + if (orcidProfile != null) { + Individual person = describePerson(orcidProfile, m); + if (person != null) { + Individual account = describeAccount(orcidProfile, m, person); + } + } + MediaType rdfXml = new MediaType("application", "rdf+xml"); + if (mediaType.isCompatible(rdfXml)) { + m.write(entityStream, "RDF/XML", TMP_BASE); + } else { + // Silly workaround to generate relative URIs + + + // The below would not correctly relativize according to TMP_BASE + // https://issues.apache.org/jira/browse/JENA-132 + // m.write(entityStream, "N3", TMP_BASE); + + StringWriter writer = new StringWriter(); + m.write(writer, "N3", TMP_BASE); + String relativizedTurtle = writer.toString().replace(TMP_BASE, ""); + entityStream.write(relativizedTurtle.getBytes(UTF8)); + } + } + + protected void describeError(ErrorDesc errorDesc, OntModel m) { + String error = errorDesc.getContent(); + Individual root = m.createIndividual(TMP_BASE, null); + root.setLabel("Error", EN); + root.setComment(error, EN); + } + + private Individual describeAccount(OrcidProfile orcidProfile, OntModel m, Individual person) { + // Add /orcid-profile to identify the profile itself + String orcidProfileUri = orcidProfile.getOrcidId() + PROFILE_POST_PATH; + + Individual account = m.createIndividual(orcidProfileUri, foafOnlineAccount); + person.addProperty(foafAccount, account); + Individual webSite = null; + if (baseUri != null) { + webSite = m.createIndividual(baseUri, null); + account.addProperty(foafAccountServiceHomepage, webSite); + } + String orcId = orcidProfile.getOrcid().getValue(); + account.addProperty(foafAccountName, orcId); + account.addLabel(orcId, null); + + // The account as a potential foaf:PersonalProfileDocument + account.addProperty(foafPrimaryTopic, person); + OrcidHistory history = orcidProfile.getOrcidHistory(); + if (history != null) { + if (history.isClaimed().booleanValue()) { + // Set account as PersonalProfileDocument + account.addRDFType(foafPersonalProfileDocument); + account.addProperty(foafMaker, person); + + } + // Who made the profile? + switch (history.getCreationMethod()) { + case WEBSITE: + account.addProperty(pavCreatedBy, person); + account.addProperty(provWasAttributedTo, person); + if (webSite != null) { + account.addProperty(pavCreatedWith, webSite); + } + break; + case API: + Individual api = m.createIndividual(MEMBER_API, provSoftwareAgent); + account.addProperty(pavImportedBy, api); + + if (history.isClaimed().booleanValue()) { + account.addProperty(pavCuratedBy, person); + } + + + break; + default: + // Some unknown agent! + account.addProperty(pavCreatedWith, m.createIndividual(null, provAgent)); + } + + if (history.getLastModifiedDate() != null) { + Literal when = calendarAsLiteral(history.getLastModifiedDate().getValue(), m); + account.addLiteral(pavLastUpdateAt, when); + account.addLiteral(provGeneratedAt, when); + } + if (history.getSubmissionDate() != null) { + account.addLiteral(pavCreatedOn, + calendarAsLiteral(history.getSubmissionDate().getValue(), m)); + } + if (history.getCompletionDate() != null) { + account.addLiteral(pavContributedOn, calendarAsLiteral(history.getDeactivationDate().getValue(), m)); + } + if (history.getDeactivationDate() != null) { + account.addLiteral(provInvalidatedAt, calendarAsLiteral(history.getDeactivationDate().getValue(), m)); + } + + } + + if (uriInfo != null) { + // Links to publications resource + UriBuilder builder = uriInfo.getBaseUriBuilder(); + // CHECK - does this get orcid-pub-web vs. orcid-web etc. wrong? + URI worksDetails = builder.path(OrcidApiService.class, "viewWorksDetailsXml").build(orcId); + person.addProperty(foafPublications, m.createIndividual(worksDetails.toASCIIString(), null)); + } + + return account; + } + + private Literal calendarAsLiteral(XMLGregorianCalendar cal, OntModel m) { + return m.createTypedLiteral(cal.toXMLFormat(), XSDDatatype.XSDdateTime); + } + + private Individual describePerson(OrcidProfile orcidProfile, OntModel m) { + String orcidUri = orcidProfile.getOrcidId(); + Individual person = m.createIndividual(orcidUri, foafPerson); + person.addRDFType(provPerson); + + if (orcidProfile.getOrcidBio() == null) { + return person; + } + OrcidBio orcidBio = orcidProfile.getOrcidBio(); + if (orcidBio == null) { + return person; + } + + describePersonalDetails(orcidBio.getPersonalDetails(), person, m); + describeContactDetails(orcidBio.getContactDetails(), person, m); + describeBiography(orcidBio.getBiography(), person, m); + describeResearcherUrls(orcidBio.getResearcherUrls(), person, m); + return person; + } + + private void describeResearcherUrls(ResearcherUrls researcherUrls, Individual person, OntModel m) { + if (researcherUrls == null || researcherUrls.getResearcherUrl() == null) { + return; + } + for (ResearcherUrl url : researcherUrls.getResearcherUrl()) { + Individual page = m.createIndividual(url.getUrl().getValue(), null); + if (isHomePage(url)) { + person.addProperty(foafHomepage, page); + } else if(isFoaf(url)) { + // TODO: Is this the proper way to link to other FOAF URIs? + // What if we want to link to the URL of the other FOAF *Profile*? + + // Note: We don't dear to do owl:sameAs or prov:specializationOf + // as we don't know the extent of the other FOAF profile - we'll + // suffice to say it's an alternate view of the same person + person.addProperty(provAlternateOf, page); + page.addRDFType(foafPerson); + page.addRDFType(provPerson); + person.addSeeAlso(page); + } else { + person.addProperty(foafPage, page); + } + } + } + + private boolean isFoaf(ResearcherUrl url) { + if (url.getUrlName() == null || url.getUrlName().getContent() == null) { + return false; + } + return url.getUrlName().getContent().equalsIgnoreCase("foaf"); + } + + /** + * There's no indication in ORCID if the URL is a homepage or some other + * page, so we'll guess based on it's name, it be something similar to + * "home page". + */ + private boolean isHomePage(ResearcherUrl url) { + if (url.getUrlName() == null || url.getUrlName().getContent() == null) { + return false; + } + String name = url.getUrlName().getContent().toLowerCase(); + List candidates = Arrays.asList("homepage", "home", "home page", "personal", + "personal homepage", "personal home page"); + return candidates.contains(name); + } + + private void describeBiography(Biography biography, Individual person, OntModel m) { + if (biography != null) { + // FIXME: Which language is the biography written in? Can't assume EN + person.addProperty(foafPlan, biography.getContent()); + } + } + + private void describeContactDetails(ContactDetails contactDetails, Individual person, OntModel m) { + if (contactDetails == null) { + return; + } + + List emails = contactDetails.getEmail(); + if (emails != null) { + for (Email email : emails) { + if (email.isCurrent()) { + + Individual mbox = m.createIndividual("mailto:" + email.getValue(), null); + person.addProperty(foafMbox, mbox); + } + } + } + + Address addr = contactDetails.getAddress(); + if (addr != null) { + if (addr.getCountry() != null) { + String country = addr.getCountry().getContent(); + // TODO: Add a proper 'country' property + Individual position = m.createIndividual(null, null); + position.addLabel(country, null); + position.addComment("Country code: " + country, EN); + person.addProperty(foafBasedNear, position); + } + } + } + + private void describePersonalDetails(PersonalDetails personalDetails, Individual person, OntModel m) { + if (personalDetails == null) { + return; + } + + if (personalDetails.getCreditName() != null) { + String creditName = personalDetails.getCreditName().getContent(); + person.addProperty(foafName, creditName); + person.addLabel(creditName, null); + } else if (personalDetails.getGivenNames() != null && personalDetails.getFamilyName() != null ){ + // Naive combination assuming givenNames ~= first name and familyName ~= lastName + // See http://www.w3.org/International/questions/qa-personal-names for further + // considerations -- we don't report this as foaf:name as we can't be sure + // NOTE: ORCID gui is westernized asking for "First name" and + // "Last name" and assuming the above mapping + String label = personalDetails.getGivenNames() + " " + personalDetails.getFamilyName(); + person.addLabel(label, null); + } + + if (personalDetails.getGivenNames() != null) { + person.addProperty(foafGivenName, personalDetails.getGivenNames().getContent()); + } + if (personalDetails.getFamilyName() != null) { + person.addProperty(foafFamilyName, personalDetails.getFamilyName().getContent()); + } + + } + + protected OntModel getOntModel() { + if (foaf == null) { + loadFoaf(); + } + if (prov == null) { + loadProv(); + } + if (pav == null) { + loadPav(); + } + + + OntModel ontModel = ModelFactory.createOntologyModel(); + ontModel.setNsPrefix("foaf", FOAF_0_1); + ontModel.setNsPrefix("prov", PROV); + ontModel.setNsPrefix("pav", PAV); + //ontModel.getDocumentManager().loadImports(foaf.getOntModel()); + return ontModel; + } + + protected synchronized void loadPav() { + if (pav != null) { + return; + } + OntModel ontModel = loadOntologyFromClasspath(PAV_RDF, PAV); + + pavCreatedBy = ontModel.getObjectProperty(PAV + "createdBy"); + pavCuratedBy = ontModel.getObjectProperty(PAV + "curatedBy"); + pavImportedBy = ontModel.getObjectProperty(PAV + "importedBy"); + pavCreatedWith = ontModel.getObjectProperty(PAV + "createdWith"); + + pavCreatedOn = ontModel.getDatatypeProperty(PAV + "createdOn"); + pavLastUpdateAt = ontModel.getDatatypeProperty(PAV + "lastUpdateOn"); + pavContributedOn = ontModel.getDatatypeProperty(PAV + "contributedOn"); + + checkNotNull(pavCreatedBy, pavCuratedBy, pavImportedBy, pavCreatedWith, + pavCreatedOn, pavLastUpdateAt, pavContributedOn); + pav = ontModel; + } + + private void checkNotNull(Object... possiblyNulls) { + int i=0; + for (Object check : possiblyNulls) { + if (check == null) { + throw new IllegalStateException("Could not load item #" + i); + } + i++; + } + + } + + protected synchronized void loadProv() { + if (prov != null) { + return; + } + OntModel ontModel = loadOntologyFromClasspath(PROV_O_RDF, PROV_O); + + provPerson = ontModel.getOntClass(PROV + "Person"); + provAgent = ontModel.getOntClass(PROV + "Agent"); + provSoftwareAgent = ontModel.getOntClass(PROV + "SoftwareAgent"); + provWasAttributedTo = ontModel.getObjectProperty(PROV + "wasAttributedTo"); + provAlternateOf = ontModel.getObjectProperty(PROV + "alternateOf"); + provGeneratedAt = ontModel.getDatatypeProperty(PROV + "generatedAtTime"); + provInvalidatedAt = ontModel.getDatatypeProperty(PROV + "invalidatedAtTime"); + + checkNotNull(provPerson, provAgent, provSoftwareAgent, provWasAttributedTo, provAlternateOf, provGeneratedAt, provInvalidatedAt); + prov = ontModel; + } + + protected OntModel loadOntologyFromClasspath(String classPathUri, String uri) { + OntModel ontModel = ModelFactory.createOntologyModel(); + + // Load from classpath + InputStream inStream = getClass().getResourceAsStream(classPathUri); + if (inStream == null) { + throw new IllegalArgumentException("Can't load " + classPathUri); + } + Ontology ontology = ontModel.createOntology(uri); + ontModel.read(inStream, uri); + return ontModel; + } + + protected synchronized void loadFoaf() { + if (foaf != null) { + return; + } + + OntModel ontModel = loadOntologyFromClasspath(FOAF_RDF, FOAF_0_1); + + // foaf = ontModel.getOntology(FOAF_0_1); + + // classes from foaf + foafPerson = ontModel.getOntClass(FOAF_0_1 + "Person"); + foafOnlineAccount = ontModel.getOntClass(FOAF_0_1 + "OnlineAccount"); + foafPersonalProfileDocument = ontModel.getOntClass(FOAF_0_1 + "PersonalProfileDocument"); + + // properties from foaf + foafName = ontModel.getDatatypeProperty(FOAF_0_1 + "name"); + foafGivenName = ontModel.getDatatypeProperty(FOAF_0_1 + "givenName"); + foafFamilyName = ontModel.getDatatypeProperty(FOAF_0_1 + "familyName"); + foafAccountName = ontModel.getDatatypeProperty(FOAF_0_1 + "accountName"); + foafPlan = ontModel.getDatatypeProperty(FOAF_0_1 + "plan"); + foafMbox = ontModel.getObjectProperty(FOAF_0_1 + "mbox"); + foafBasedNear = ontModel.getObjectProperty(FOAF_0_1 + "based_near"); + + + foafPrimaryTopic = ontModel.getObjectProperty(FOAF_0_1 + "primaryTopic"); + foafMaker = ontModel.getObjectProperty(FOAF_0_1 + "maker"); + foafPage = ontModel.getObjectProperty(FOAF_0_1 + "page"); + foafHomepage = ontModel.getObjectProperty(FOAF_0_1 + "homepage"); + foafPublications = ontModel.getObjectProperty(FOAF_0_1 + "publications"); + + foafAccount = ontModel.getObjectProperty(FOAF_0_1 + "account"); + foafAccountServiceHomepage = ontModel.getObjectProperty(FOAF_0_1 + "accountServiceHomepage"); + + checkNotNull(foafPerson,foafOnlineAccount,foafPersonalProfileDocument, foafName, foafGivenName, foafFamilyName, foafAccountName, + foafPlan, foafMbox, foafBasedNear, foafPrimaryTopic, foafMaker, foafPage, foafHomepage, foafPublications, foafAccount, + foafAccountServiceHomepage); + + foaf = ontModel; + } + + public UriInfo getUriInfo() { + return uriInfo; + } + + public void setUriInfo(UriInfo uriInfo) { + this.uriInfo = uriInfo; + } +} diff --git a/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/foaf.rdf b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/foaf.rdf new file mode 100644 index 00000000000..83b59129060 --- /dev/null +++ b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/foaf.rdf @@ -0,0 +1,606 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Label Property + A foaf:LabelProperty is any RDF property with texual values that serve as labels. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/pav.rdf b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/pav.rdf new file mode 100644 index 00000000000..d5bbbd7ef6d --- /dev/null +++ b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/pav.rdf @@ -0,0 +1,552 @@ + + + + + + + + + + + + + + +]> + + + + + + Provenance, Authoring and Versioning (PAV) + 2.1.1 + 2013-03-26T14:49:00Z + Marco Ocana + Paolo Ciccarese + Stian Soiland-Reyes + application/rdf+xml + en + 2013-03-27T16:03:24Z + PAV - Provenance, Authoring and Versioning + PAV is a lightweight ontology for tracking Provenance, Authoring and Versioning. PAV specializes the W3C provenance ontology PROV-O in order to describe authorship, curation and digital creation of online resources. + +This ontology describes the defined PAV properties and their usage. Note that PAV does not define any explicit classes or domain/ranges, as every property is meant to be used directly on the described online resource. + PAV supplies terms for distinguishing between the different roles of the agents contributing content in current web based systems: contributors, authors, curators and digital artifact creators. The ontology also provides terms for tracking provenance of digital entities that are published on the web and then accessed, transformed and consumed. In order to support broader interoperability, PAV specializes the general purpose W3C PROV provenance model (PROV-O). + +PAV distinguishes between the data related to the digital artifact - named Provenance - and those related to the actual knowledge creation and therefore to the intellectual property aspects – named Authoring. The Versioning axis describes the evolution of digital entities in time. + +Using PAV, descriptions can define the Authors that originate or gave existence to the work that is expressed in the digital resource (pav:authoredBy); curators (pav:curatedBy) who are content specialists responsible for shaping the expression in an appropriate format, and contributors (super-property pav:contributedBy) that provided some help in conceiving the resource or in the expressed knowledge creation/extraction. + +These provenance aspects can be detailed with dates using pav:curatedOn, pav:authoredOn, etc. Further details about the creation activities, such as different authors contributing specific parts of the resource at different dates are out of scope for PAV and should be defined using vocabularies like PROV-O and additional intermediate entities to describe the different states. + +For resources based on other resources, PAV allows specification of direct retrieval (pav:retrievedFrom), import through transformations (pav:importedFrom) and sources that were merely consulted (pav:sourceAccessedAt). These aspects can also define the agents responsible using pav:retrievedBy, pav:importedBy and pav:sourceAccessedBy. Version information can be specified using pav:previousVersion and pav:version. + +The creation of the digital representation, for instance an RDF graph, can in many cases be different from the authorship of the knowledge, and in PAV this digital creation is specified using pav:createdBy, pav:createdWith and pav:createdOn. + +PAV 2.1 updates PAV 2.0 with PROV-O specializations and more detailed descriptions of the defined terms. Note that PROV-O is not imported directly by this ontology as PAV can be used independent of PROV. PAV 2 is based on PAV 1.2 but in a new namespace ( http://purl.org/pav/ ). Terms compatible with 1.2 are indicated in this ontology using owl:equivalentProperty. + +The ontology IRI http://purl.org/pav/ always resolve to the latest version of PAV 2. Particular versionIRIs such as http://purl.org/pav/2.1 can be used by clients to force imports of a particular version - note however that all terms are defined directly in the http://purl.org/pav/ namespace. + +The goal of PAV is to provide a lightweight, straight forward way to give the essential information about authorship, provenance and versioning, and therefore these properties are described directly on the published resource. As such, PAV does not define any classes or restrict domain/ranges, as all properties are applicable to any online resource. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Authored by + An agent that originated or gave existence to the work that is expressed by the digital resource. + +The author of the content of a resource may be different from the creator of the resource representation (although they are often the same). See pav:createdBy for a discussion. + +The date of authoring can be expressed using pav:authoredOn - note however in the case of multiple authors that there is no relationship in PAV identifying which agent contributed when or what. If capturing such lineage is desired, it should be additionally expressed using activity-centric provenance vocabularies, for instance with prov:wasGeneratedBy and prov:qualifiedAssocation. + + + + + + + + + + + + Contributed by + The resource was contributed to by the given agent. + +The agent provided any sort of help in conceiving the work that is expressed by the digital artifact. Superproperty of pav:authoredBy and pav:curatedBy. + +Note that as pav:contributedBy identifies only agents that contributed to the work, knowledge or intellectual property, and not agents that made the digital artifact or representation (pav:createdBy), thus this property can be considered more precise than dct:contributor. See pav:createdBy for a discussion. + +The date of contribution can be expressed using pav:contributedOn - note however in the case of multiple contributors that there is no relationship in PAV identifying which agent contributed when or what. If capturing such lineage is desired, it should be additionally expressed using activity-centric provenance vocabularies, for instance with prov:wasGeneratedBy and prov:qualifiedAssocation. + + + + + + + + + + + + Created at + The geo-location of the agents when creating the resource (pav:createdBy). For instance a photographer takes a picture of the Eiffel Tower while standing in front of it. + + + + + + + + + Created by + An agent primary responsible for making the digital artifact or resource representation. + +This property is distinct from forming the content, which is indicated with pav:contributedBy or its subproperties; pav:authoredBy, which identifies who authored the knowledge expressed by this resource; and pav:curatedBy, which identifies who curated the knowledge into its current form. + +pav:createdBy is more specific than dct:createdBy - which might or might not be interpreted to cover this creator. + +For instance, the author wrote 'this species has bigger wings than normal' in his log book. The curator, going through the log book and identifying important knowledge, formalizes this as 'locus perculus has wingspan > 0.5m'. The creator enters this knowledge as a digital resource in the knowledge system, thus creating the digital artifact (say as JSON, RDF, XML or HTML). + +A different example is a news article. pav:authoredBy indicates the journalist who wrote the article. pav:contributedBy can indicate the artist who added an illustration. pav:curatedBy can indicate the editor who made the article conform to the news paper's style. pav:createdBy can indicate who put the article on the web site. + +The software tool used by the creator to make the digital resource (say Protege, Wordpress or OpenOffice) can be indicated with pav:createdWith. + +The date the digital resource was created can be indicated with pav:createdOn. + +The location the agent was at when creating the digital resource can be made using pav:createdAt. + + + + + + + + + + + + + + Created with + The software/tool used by the creator (pav:createdBy) when making the digital resource, for instance a word processor or an annotation tool. A more independent software agent that creates the resource without direct interaction by a human creator should instead should instead by indicated using pav:createdBy. + + + + + + + + + + + Curated by + An agent specialist responsible for shaping the expression in an appropriate format. Often the primary agent responsible for ensuring the quality of the representation. + +The curator may be different from the creator of the author (pav:authoredBy) and the creator of the digital resource (pav:createdBy). + +The date of curating can be expressed using pav:curatedOn - note however in the case of multiple curators that there is no relationship in PAV identifying which agent contributed when or what. If capturing such lineage is desired, it should be additionally expressed using activity-centric provenance vocabularies, for instance with prov:wasGeneratedBy and prov:qualifiedAssocation. + + + + + + + + + + + + Curates + true + Provided for backwards compatibility with PAV 1.2 only. Use instead the inverse pav:curatedBy. + + + + + + + + + Derived from + Derived from a different resource. Derivation conserns itself with derived knowledge. If this resource has the same content as the other resource, but has simply been transcribed to fit a different model (like XML -> RDF or SQL -> CVS), use pav:importedFrom. If a resource was simply retrieved, use pav:retrievedFrom. If the content has however been further refined or modified, pav:derivedFrom should be used. + +Details about who performed the derivation may be indicated with pav:contributedBy and its subproperties. + + + + + + + + + + + + Imported by + An entity responsible for importing the data. + +The importer is usually a software entity which has done the transcription from the original source. +Note that pav:importedBy may overlap with pav:createdWith. + +The source for the import should be given with pav:importedFrom. The time of the import should be given with pav:importedOn. + +See pav:importedFrom for a discussion of import vs. retrieve vs. derived. + + + + + + + + + + + Imported from + The original source of imported information. + +Import means that the content has been preserved, but transcribed somehow, for instance to fit a different representation model. Examples of import are when the original was JSON and the current resource is RDF, or where the original was an document scan, and this resource is the plain text found through OCR. + +The imported resource does not have to be complete, but should be consistent with the knowledge conveyed by the original resource. + +If additional knowledge has been contributed, pav:derivedFrom would be more appropriate. + +If the resource has been copied verbatim from the original representation (e.g. downloaded), use pav:retrievedFrom. + +To indicate which agent(s) performed the import, use pav:importedBy. Use pav:importedOn to indicate when it happened. + + + + + + + + + + + + + + Previous version + The previous version of a resource in a lineage. For instance a news article updated to correct factual information would point to the previous version of the article with pav:previousVersion. If however the content has significantly changed so that the two resources no longer share lineage (say a new news article that talks about the same facts), they should be related using pav:derivedFrom. + +A version number of this resource can be provided using the data property pav:version. + + + + + + + + + + + + Provided by + The original provider of the encoded information (e.g. PubMed, UniProt, Science Commons). + +The provider might not coincide with the dct:publisher, which would describe the current publisher of the resource. For instance if the resource was retrieved, imported or derived from a source, that source was published by the original provider. pav:providedBy provides a shortcut to indicate the original provider on the new resource. + + + + + + + + + Retrieved by + An entity responsible for retrieving the data from an external source. + +The retrieving agent is usually a software entity, which has done the retrieval from the original source without performing any transcription. + +The source that was retrieved should be given with pav:retrievedFrom. The time of the retrieval should be indicated using pav:retrievedOn. + +See pav:importedFrom for a discussion of import vs. retrieve vs. derived. + + + + + + + + + + Retrieved from + The URI where a resource has been retrieved from. + +Retrieval indicates that this resource has the same representation as the original resource. If the resource has been somewhat transformed, use pav:importedFrom instead. + +The time of the retrieval should be indicated using pav:retrievedOn. The agent may be indicated with pav:retrievedBy. + + + + + + + + + + + Source accessed at + The resource is related to a given source which was accessed or consulted (but not retrieved, imported or derived from). This access can be detailed with pav:sourceAccessedBy and pav:sourceAccessedOn. + +For instance, a curator (pav:curatedBy) might have consulted figures in a published paper to confirm that a dataset was correctly pav:importedFrom the paper's supplementary CSV file. + + + + + + + + + + + + + + Source accessed by + The resource is related to a source which was accessed or consulted +by the given agent. The source(s) should be specified using pav:sourceAccessedAt, and the time with pav:sourceAccessedOn. + +For instance, the given agent could be a curator (also pav:curatedBy) which consulted figures in a published paper to confirm that a dataset was correctly pav:importedFrom the paper's supplementary CSV file. + + + + + + + + + + + + + + + + Authored on + The date this resource was authored. + +pav:authoredBy gives the authoring agent. + +Note that pav:authoredOn is different from pav:createdOn, although they are often the same. See pav:createdBy for a discussion. + + + + + + + + + + + + Contributed on + The date this resource was contributed to. + +pav:contributedBy provides the agent(s) that contributed. + + + + + + + + + + Created On + The date of creation of the resource. + +pav:createdBy provides the agent(s) that created the resource. + + + + + + + + + + + + Curated on + The date this resource was curated. + +pav:curatedBy gives the agent(s) that performed the curation. + + + + + + + + + + Imported on + The date this resource was imported from a source (pav:importedFrom). + +Note that pav:importedOn may overlap with pav:createdOn, but in cases where they differ, the import time indicates the time of the retrieval and transcription of the original source, while the creation time indicates when the final resource was made, for instance after user approval. + +If the source is later reimported, this should be indicated with pav:lastRefreshedOn. + +The source of the import should be given with pav:importedFrom. The agent that performed the import should be given with pav:importedBy. + +See pav:importedFrom for a discussion about import vs. retrieval. + + + + + + + + + + + + Last refreshed on + The date of the last re-import of the resource. This property is used in addition to pav:importedOn if this version has been updated due to a re-import. If the re-import created a new resource rather than refreshing an existing, then pav:importedOn should be used together with pav:previousVersion. + + + + + + + + + + + + + + Last updated on + The date of the last update of the resource. An update is a change which did not warrant making a new resource related using pav:previousVersion, for instance correcting a spelling mistake. + + + + + + + + + + + + Retrieved on + The date the source for this resource was retrieved. + +The source that was retrieved should be indicated with pav:retrievedFrom. The agent that performed the retrieval may be specified with pav:retrievedBy. + + + + + + + + + + + + Source accessed on + The resource is related to a source which was originally accessed or consulted on the given date as part of creating or authoring the resource. The source(s) should be specified using pav:sourceAccessedAt. If the source is subsequently checked again (say to verify validity), this should be indicated with pav:sourceLastAccessedOn. + +In the case multiple sources being accessed at different times or by different agents, PAV does not distinguish who accessed when what. If such details are required, they may be provided by additionally using prov:qualifiedInfluence. + + + + + + + + + + + + + + + Source last accessed on + The resource is related to a source which was last accessed or consulted on the given date. The source(s) should be specified using pav:sourceAccessedAt. Usage of this property indicates that the source has been checked previously, which the initial time should be indicated with pav:sourceAccessedOn. + +This property can be useful together with pav:lastRefreshedOn or pav:lastUpdateOn in order to indicate a re-import or update, but could also be used alone, for instance when a source was simply verified and no further action was taken for the resource, + + + + + + + + + + + + + Version + The version number of a resource. This is a freetext string, typical values are "1.5" or "21". The URI identifying the previous version can be provided using prov:previousVersion. + + + + + + + + + + + + + diff --git a/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/prov-o.rdf b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/prov-o.rdf new file mode 100644 index 00000000000..1e9896a56c9 --- /dev/null +++ b/orcid-api-common/src/main/resources/org/orcid/api/common/writer/rdf/prov-o.rdf @@ -0,0 +1,1788 @@ + + + + + + + +]> + + + + + W3C PROVenance Interchange Ontology (PROV-O) + Recommendation version 2013-04-30 + This document is published by the Provenance Working Group (http://www.w3.org/2011/prov/wiki/Main_Page). + +If you wish to make comments regarding this document, please send them to public-prov-comments@w3.org (subscribe public-prov-comments-request@w3.org, archives http://lists.w3.org/Archives/Public/public-prov-comments/). All feedback is welcome. + + + + + + + + + + + + + + Classes and properties used to qualify relationships are annotated with prov:unqualifiedForm to indicate the property used to assert an unqualified provenance relation. + + + + + wasRevisionOf + derivations + A revision is a derivation that revises an entity into a revised version. + hadRevision + expanded + + + + + + + + + + + + + + A definition quoted from PROV-DM or PROV-CONSTRAINTS that describes the concept expressed with this OWL term. + + + + A note by the OWL development team about how this term expresses the PROV-DM concept, or how it should be used in context of semantic web or linked data. + + + + + + + + PROV-O does not define all property inverses. The directionalities defined in PROV-O should be given preference over those not defined. However, if users wish to name the inverse of a PROV-O property, the local name given by prov:inverse should be used. + + + + + + + + + A reference to the principal section of the PROV-CONSTRAINTS document that describes this concept. + + + + + + + + + specializationOf + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-specialization + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-specialization + alternate + generalizationOf + expanded + An entity that is a specialization of another shares all aspects of the latter, and additionally presents more specific aspects of the same thing as the latter. In particular, the lifetime of the entity being specialized contains that of any specialization. Examples of aspects include a time period, an abstraction, and a context associated with the entity. + + + + + A reference to the principal section of the PROV-DM document that describes this concept. + + + + + Classify prov-o terms into three categories, including 'starting-point', 'qualifed', and 'extended'. This classification is used by the prov-o html document to gently introduce prov-o terms to its users. + + + + The position that this OWL term should be listed within documentation. The scope of the documentation (e.g., among all terms, among terms within a prov:category, among properties applying to a particular class, etc.) is unspecified. + + + + + When the prov-o term does not have a definition drawn from prov-dm, and the prov-o editor provides one. + + + + + Classify prov-o terms into six components according to prov-dm, including 'agents-responsibility', 'alternate', 'annotations', 'collections', 'derivations', and 'entities-activities'. This classification is used so that readers of prov-o specification can find its correspondence with the prov-dm specification. + + + + This annotation property links a subproperty of prov:wasInfluencedBy with the subclass of prov:Influence and the qualifying property that are used to qualify it. + +Example annotation: + + prov:wasGeneratedBy prov:qualifiedForm prov:qualifiedGeneration, prov:Generation . + +Then this unqualified assertion: + + :entity1 prov:wasGeneratedBy :activity1 . + +can be qualified by adding: + + :entity1 prov:qualifiedGeneration :entity1Gen . + :entity1Gen + a prov:Generation, prov:Influence; + prov:activity :activity1; + :customValue 1337 . + +Note how the value of the unqualified influence (prov:wasGeneratedBy :activity1) is mirrored as the value of the prov:activity (or prov:entity, or prov:agent) property on the influence class. + + + + + + A reference to the principal section of the PROV-DM document that describes this concept. + + + + + + + + + + + + + + + actedOnBehalfOf + agents-responsibility + hadDelegate + An object property to express the accountability of an agent towards another agent. The subordinate agent acted on behalf of the responsible agent in an actual activity. + starting-point + + + + + + + + + + + + + + + + + + activity + The prov:activity property references an prov:Activity which influenced a resource. This property applies to an prov:ActivityInfluence, which is given by a subproperty of prov:qualifiedInfluence from the influenced prov:Entity, prov:Activity or prov:Agent. + activityOfInfluence + This property behaves in spirit like rdf:object; it references the object of a prov:wasInfluencedBy triple. + qualified + + + + + + + + + + + + agent + The prov:agent property references an prov:Agent which influenced a resource. This property applies to an prov:AgentInfluence, which is given by a subproperty of prov:qualifiedInfluence from the influenced prov:Entity, prov:Activity or prov:Agent. + agentOfInfluence + This property behaves in spirit like rdf:object; it references the object of a prov:wasInfluencedBy triple. + qualified + + + + + + + + + + + + alternateOf + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-alternate + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-alternate + Two alternate entities present aspects of the same thing. These aspects may be the same or different, and the alternate entities may or may not overlap in time. + expanded + alternate + alternateOf + + + + + + + + + + + + atLocation + The Location of any resource. + locationOf + The naming of prov:atLocation parallels prov:atTime, and is not named prov:hadLocation to avoid conflicting with the convention that prov:had* properties are used on prov:Influence classes. + This property has multiple RDFS domains to suit multiple OWL Profiles. See <a href="#owl-profile">PROV-O OWL Profile</a>. + This property is not functional because the many values could be at a variety of granularies (In this building, in this room, in that chair). + expanded + + + + + + + + + + + + + + + + + + + + + entity + The prov:entity property references an prov:Entity which influenced a resource. This property applies to an prov:EntityInfluence, which is given by a subproperty of prov:qualifiedInfluence from the influenced prov:Entity, prov:Activity or prov:Agent. + entityOfInfluence + This property behaves in spirit like rdf:object; it references the object of a prov:wasInfluencedBy triple. + qualified + + + + + + + + + + + + generated + entities-activities + wasGeneratedBy + expanded + prov:generated is one of few inverse property defined, to allow Activity-oriented assertions in addition to Entity-oriented assertions. + + + + + + + + + + + + + + hadActivity + This property has multiple RDFS domains to suit multiple OWL Profiles. See <a href="#owl-profile">PROV-O OWL Profile</a>. + The _optional_ Activity of an Influence, which used, generated, invalidated, or was the responsibility of some Entity. This property is _not_ used by ActivityInfluence (use prov:activity instead). + The multiple rdfs:domain assertions are intended. One is simpler and works for OWL-RL, the union is more specific but is not recognized by OWL-RL. + derivations + qualified + wasActivityOfInfluence + + + + + + + + + + + + + + + + + + + + + + hadGeneration + generatedAsDerivation + qualified + The _optional_ Generation involved in an Entity's Derivation. + derivations + + + + + + + + + + + + hadMember + expanded + expanded + wasMemberOf + + + + + + + + A collection is an entity that provides a structure to some constituents, which are themselves entities. These constituents are said to be member of the collections. + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-collection + + + + + + + + + + + hadPlan + qualified + agents-responsibility + wasPlanOf + The _optional_ Plan adopted by an Agent in Association with some Activity. Plan specifications are out of the scope of this specification. + + + + + + + + + + + + hadPrimarySource + derivations + expanded + wasPrimarySourceOf + + + + + + + + + + + + + hadPrimarySource property is a particular case of wasDerivedFrom (see http://www.w3.org/TR/prov-dm/#term-original-source) that aims to give credit to the source that originated some information. + + + + + + + + + + + hadRole + agents-responsibility + wasRoleIn + This property has multiple RDFS domains to suit multiple OWL Profiles. See <a href="#owl-profile">PROV-O OWL Profile</a>. + qualified + The _optional_ Role that an Entity assumed in the context of an Activity. For example, :baking prov:used :spoon; prov:qualified [ a prov:Usage; prov:entity :spoon; prov:hadRole roles:mixing_implement ]. + prov:hadRole references the Role (i.e. the function of an entity with respect to an activity), in the context of an instantaneous usage, generation, association, start, and end. + + + + + + + + + + + + + + + + + + + + hadUsage + qualified + The _optional_ Usage involved in an Entity's Derivation. + wasUsedInDerivation + derivations + + + + + + + + + + + + influenced + wasInfluencedBy + agents-responsibility + expanded + + + + + + + + + + + influencer + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-influence + qualified + hadInfluence + Subproperties of prov:influencer are used to cite the object of an unqualified PROV-O triple whose predicate is a subproperty of prov:wasInfluencedBy (e.g. prov:used, prov:wasGeneratedBy). prov:influencer is used much like rdf:object is used. + This property and its subproperties are used in the same way as the rdf:object property, i.e. to reference the object of an unqualified prov:wasInfluencedBy or prov:influenced triple. + This property is used as part of the qualified influence pattern. Subclasses of prov:Influence use these subproperties to reference the resource (Entity, Agent, or Activity) whose influence is being qualified. + + + + + + + + + + + invalidated + expanded + wasInvalidatedBy + entities-activities + prov:invalidated is one of few inverse property defined, to allow Activity-oriented assertions in addition to Entity-oriented assertions. + + + + + + + + + + + + + + qualifiedAssociation + qualifiedAssociationOf + If this Activity prov:wasAssociatedWith Agent :ag, then it can qualify the Association using prov:qualifiedAssociation [ a prov:Association; prov:agent :ag; :foo :bar ]. + agents-responsibility + qualified + + + + + + + + + + + + + + qualifiedAttribution + qualifiedAttributionOf + qualified + agents-responsibility + If this Entity prov:wasAttributedTo Agent :ag, then it can qualify how it was influenced using prov:qualifiedAttribution [ a prov:Attribution; prov:agent :ag; :foo :bar ]. + + + + + + + + + + + + + + qualifiedCommunication + qualifiedCommunicationOf + entities-activities + If this Activity prov:wasInformedBy Activity :a, then it can qualify how it was influenced using prov:qualifiedCommunication [ a prov:Communication; prov:activity :a; :foo :bar ]. + qualified + + + + + + + + + + + + + + qualifiedDelegation + qualified + If this Agent prov:actedOnBehalfOf Agent :ag, then it can qualify how with prov:qualifiedResponsibility [ a prov:Responsibility; prov:agent :ag; :foo :bar ]. + qualifiedDelegationOf + agents-responsibility + + + + + + + + + + + + + + qualifiedDerivation + derivations + qualified + If this Entity prov:wasDerivedFrom Entity :e, then it can qualify how it was derived using prov:qualifiedDerivation [ a prov:Derivation; prov:entity :e; :foo :bar ]. + qualifiedDerivationOf + + + + + + + + + + + + + + qualifiedEnd + qualified + qualifiedEndOf + entities-activities + If this Activity prov:wasEndedBy Entity :e1, then it can qualify how it was ended using prov:qualifiedEnd [ a prov:End; prov:entity :e1; :foo :bar ]. + + + + + + + + + + + + + + qualifiedGeneration + qualifiedGenerationOf + entities-activities + qualified + If this Activity prov:generated Entity :e, then it can qualify how it performed the Generation using prov:qualifiedGeneration [ a prov:Generation; prov:entity :e; :foo :bar ]. + + + + + + + + + + + + + + qualifiedInfluence + Because prov:qualifiedInfluence is a broad relation, the more specific relations (qualifiedCommunication, qualifiedDelegation, qualifiedEnd, etc.) should be used when applicable. + qualified + qualifiedInfluenceOf + derivations + + + + + + + + + + + + + + + + + + + + + qualifiedInvalidation + If this Entity prov:wasInvalidatedBy Activity :a, then it can qualify how it was invalidated using prov:qualifiedInvalidation [ a prov:Invalidation; prov:activity :a; :foo :bar ]. + entities-activities + qualified + qualifiedInvalidationOf + + + + + + + + + + + + + + qualifiedPrimarySource + If this Entity prov:hadPrimarySource Entity :e, then it can qualify how using prov:qualifiedPrimarySource [ a prov:PrimarySource; prov:entity :e; :foo :bar ]. + derivations + qualified + qualifiedSourceOf + + + + + + + + + + + + + + qualifiedQuotation + qualified + qualifiedQuotationOf + If this Entity prov:wasQuotedFrom Entity :e, then it can qualify how using prov:qualifiedQuotation [ a prov:Quotation; prov:entity :e; :foo :bar ]. + derivations + + + + + + + + + + + + + + qualifiedRevision + If this Entity prov:wasRevisionOf Entity :e, then it can qualify how it was revised using prov:qualifiedRevision [ a prov:Revision; prov:entity :e; :foo :bar ]. + qualified + revisedEntity + derivations + + + + + + + + + + + + + + qualifiedStart + qualifiedStartOf + qualified + entities-activities + If this Activity prov:wasStartedBy Entity :e1, then it can qualify how it was started using prov:qualifiedStart [ a prov:Start; prov:entity :e1; :foo :bar ]. + + + + + + + + + + + + + + qualifiedUsage + qualified + qualifiedUsingActivity + entities-activities + If this Activity prov:used Entity :e, then it can qualify how it used it using prov:qualifiedUsage [ a prov:Usage; prov:entity :e; :foo :bar ]. + + + + + + + + + + + + + + specializationOf + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-specialization + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-specialization + alternate + expanded + generalizationOf + An entity that is a specialization of another shares all aspects of the latter, and additionally presents more specific aspects of the same thing as the latter. In particular, the lifetime of the entity being specialized contains that of any specialization. Examples of aspects include a time period, an abstraction, and a context associated with the entity. + + + + + + + + + + + + + used + wasUsedBy + A prov:Entity that was used by this prov:Activity. For example, :baking prov:used :spoon, :egg, :oven . + starting-point + entities-activities + + + + + + + + + + + + + + + + + + wasAssociatedWith + agents-responsibility + wasAssociateFor + An prov:Agent that had some (unspecified) responsibility for the occurrence of this prov:Activity. + starting-point + + + + + + + + + + + + + + + + + + wasAttributedTo + agents-responsibility + starting-point + contributed + Attribution is the ascribing of an entity to an agent. + Attribution is the ascribing of an entity to an agent. + + + + + + + + + + + + + Attribution is a particular case of trace (see http://www.w3.org/TR/prov-dm/#concept-trace), in the sense that it links an entity to the agent that ascribed it. + IF wasAttributedTo(e2,ag1,aAttr) holds, THEN wasInfluencedBy(e2,ag1) also holds. + + + + + + + + + + + wasDerivedFrom + hadDerivation + A derivation is a transformation of an entity into another, an update of an entity resulting in a new one, or the construction of a new entity based on a pre-existing entity. + starting-point + The more specific subproperties of prov:wasDerivedFrom (i.e., prov:wasQuotedFrom, prov:wasRevisionOf, prov:hadPrimarySource) should be used when applicable. + derivations + + + + + + + + + + + + + Derivation is a particular case of trace (see http://www.w3.org/TR/prov-dm/#term-trace), since it links an entity to another entity that contributed to its existence. + + + + + + + + + + + wasEndedBy + expanded + entities-activities + End is when an activity is deemed to have ended. An end may refer to an entity, known as trigger, that terminated the activity. + ended + + + + + + + + + + + + + + + + + + wasGeneratedBy + generated + starting-point + entities-activities + + + + + + + + + + + + + + + + + + wasInfluencedBy + Because prov:wasInfluencedBy is a broad relation, its more specific subproperties (e.g. prov:wasInformedBy, prov:actedOnBehalfOf, prov:wasEndedBy, etc.) should be used when applicable. + The sub-properties of prov:wasInfluencedBy can be elaborated in more detail using the Qualification Pattern. For example, the binary relation :baking prov:used :spoon can be qualified by asserting :baking prov:qualifiedUsage [ a prov:Usage; prov:entity :spoon; prov:atLocation :kitchen ] . + +Subproperties of prov:wasInfluencedBy may also be asserted directly without being qualified. + +prov:wasInfluencedBy should not be used without also using one of its subproperties. + + This property has multiple RDFS domains to suit multiple OWL Profiles. See <a href="#owl-profile">PROV-O OWL Profile</a>. + qualified + influenced + agents-responsibility + + + + + + + + + + + + + + + + + + + + + + + + + influencer: an identifier (o1) for an ancestor entity, activity, or agent that the former depends on; + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-influence + + + + + + + + + + + + + + influencee: an identifier (o2) for an entity, activity, or agent; + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-influence + + + + + + + + + + + + + + + + + + + wasInformedBy + informed + An activity a2 is dependent on or informed by another activity a1, by way of some unspecified entity that is generated by a1 and used by a2. + starting-point + entities-activities + + + + + + + + + + + + + + + + + + wasInvalidatedBy + entities-activities + invalidated + expanded + + + + + + + + + + + + + + + + + + wasQuotedFrom + expanded + derivations + quotedAs + An entity is derived from an original entity by copying, or 'quoting', some or all of it. + + + + + + + + + + + + + Quotation is a particular case of derivation (see http://www.w3.org/TR/prov-dm/#term-quotation) in which an entity is derived from an original entity by copying, or "quoting", some or all of it. + + + + + + + + + + + wasRevisionOf + A revision is a derivation that revises an entity into a revised version. + derivations + hadRevision + expanded + + + + + + + + + + + + + Revision is a derivation (see http://www.w3.org/TR/prov-dm/#term-Revision). Moreover, according to +http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#term-Revision 23 April 2012 'wasRevisionOf is a strict sub-relation of wasDerivedFrom since two entities e2 and e1 may satisfy wasDerivedFrom(e2,e1) without being a variant of each other.' + + + + + + + + + + + wasStartedBy + started + expanded + entities-activities + Start is when an activity is deemed to have started. A start may refer to an entity, known as trigger, that initiated the activity. + + + + + + + + + + + + + + + + + + + + + + + atTime + entities-activities + qualified + The time at which an InstantaneousEvent occurred, in the form of xsd:dateTime. + + + + + + + + + + + + + + + + endedAtTime + entities-activities + It is the intent that the property chain holds: (prov:qualifiedEnd o prov:atTime) rdfs:subPropertyOf prov:endedAtTime. + The time at which an activity ended. See also prov:startedAtTime. + starting-point + + + + + + + + + + + + + generatedAtTime + expanded + entities-activities + It is the intent that the property chain holds: (prov:qualifiedGeneration o prov:atTime) rdfs:subPropertyOf prov:generatedAtTime. + The time at which an entity was completely created and is available for use. + + + + + + + + + + + + + invalidatedAtTime + It is the intent that the property chain holds: (prov:qualifiedInvalidation o prov:atTime) rdfs:subPropertyOf prov:invalidatedAtTime. + expanded + The time at which an entity was invalidated (i.e., no longer usable). + entities-activities + + + + + + + + + + + + + startedAtTime + starting-point + It is the intent that the property chain holds: (prov:qualifiedStart o prov:atTime) rdfs:subPropertyOf prov:startedAtTime. + entities-activities + The time at which an activity started. See also prov:endedAtTime. + + + + + + + + + + + + + value + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-attribute-value + expanded + The editor's definition comes from http://www.w3.org/TR/rdf-primer/#rdfvalue + Provides a value that is a direct representation of an entity. + entities-activities + This property serves the same purpose as rdf:value, but has been reintroduced to avoid some of the definitional ambiguity in the RDF specification (specifically, 'may be used in describing structured values'). + + + + + + + + + + + + + + + + + + + + + Activity + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Activity + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Activity + entities-activities + starting-point + An activity is something that occurs over a period of time and acts upon or with entities; it may include consuming, processing, transforming, modifying, relocating, using, or generating entities. + + + + + + + + + ActivityInfluence + + + + + 0 + + + + ActivitiyInfluence is the capacity of an activity to have an effect on the character, development, or behavior of another by means of generation, invalidation, communication, or other. + ActivityInfluence provides additional descriptions of an Activity's binary influence upon any other kind of resource. Instances of ActivityInfluence use the prov:activity property to cite the influencing Activity. + It is not recommended that the type ActivityInfluence be asserted without also asserting one of its more specific subclasses. + qualified + + + + + + + + + + Agent + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-agent + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Agent + An agent is something that bears some form of responsibility for an activity taking place, for the existence of an entity, or for another agent's activity. + starting-point + agents-responsibility + + + + + + + + + AgentInfluence + + AgentInfluence is the capacity of an agent to have an effect on the character, development, or behavior of another by means of attribution, association, delegation, or other. + AgentInfluence provides additional descriptions of an Agent's binary influence upon any other kind of resource. Instances of AgentInfluence use the prov:agent property to cite the influencing Agent. + qualified + It is not recommended that the type AgentInfluence be asserted without also asserting one of its more specific subclasses. + + + + + + + + + + Association + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Association + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Association + agents-responsibility + An instance of prov:Association provides additional descriptions about the binary prov:wasAssociatedWith relation from an prov:Activity to some prov:Agent that had some responsiblity for it. For example, :baking prov:wasAssociatedWith :baker; prov:qualifiedAssociation [ a prov:Association; prov:agent :baker; :foo :bar ]. + qualified + An activity association is an assignment of responsibility to an agent for an activity, indicating that the agent had a role in the activity. It further allows for a plan to be specified, which is the plan intended by the agent to achieve some goals in the context of this activity. + + + + + + + + + + Attribution + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-attribution + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-attribution + An instance of prov:Attribution provides additional descriptions about the binary prov:wasAttributedTo relation from an prov:Entity to some prov:Agent that had some responsible for it. For example, :cake prov:wasAttributedTo :baker; prov:qualifiedAttribution [ a prov:Attribution; prov:entity :baker; :foo :bar ]. + Attribution is the ascribing of an entity to an agent. + +When an entity e is attributed to agent ag, entity e was generated by some unspecified activity that in turn was associated to agent ag. Thus, this relation is useful when the activity is not known, or irrelevant. + qualified + agents-responsibility + + + + + + + + + + Bundle + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-bundle-entity + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-bundle-declaration + expanded + A bundle is a named set of provenance descriptions, and is itself an Entity, so allowing provenance of provenance to be expressed. + Note that there are kinds of bundles (e.g. handwritten letters, audio recordings, etc.) that are not expressed in PROV-O, but can be still be described by PROV-O. + + + + + + + + + Collection + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-collection + collections + expanded + A collection is an entity that provides a structure to some constituents, which are themselves entities. These constituents are said to be member of the collections. + + + + + + + + + Communication + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Communication + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-wasInformedBy + entities-activities + qualified + An instance of prov:Communication provides additional descriptions about the binary prov:wasInformedBy relation from an informed prov:Activity to the prov:Activity that informed it. For example, :you_jumping_off_bridge prov:wasInformedBy :everyone_else_jumping_off_bridge; prov:qualifiedCommunication [ a prov:Communication; prov:activity :everyone_else_jumping_off_bridge; :foo :bar ]. + Communication is the exchange of an entity by two activities, one activity using the entity generated by the other. + + + + + + + + + + Delegation + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-delegation + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-delegation + qualified + An instance of prov:Delegation provides additional descriptions about the binary prov:actedOnBehalfOf relation from a performing prov:Agent to some prov:Agent for whom it was performed. For example, :mixing prov:wasAssociatedWith :toddler . :toddler prov:actedOnBehalfOf :mother; prov:qualifiedDelegation [ a prov:Delegation; prov:entity :mother; :foo :bar ]. + Delegation is the assignment of authority and responsibility to an agent (by itself or by another agent) to carry out a specific activity as a delegate or representative, while the agent it acts on behalf of retains some responsibility for the outcome of the delegated work. + +For example, a student acted on behalf of his supervisor, who acted on behalf of the department chair, who acted on behalf of the university; all those agents are responsible in some way for the activity that took place but we do not say explicitly who bears responsibility and to what degree. + agents-responsibility + + + + + + + + + + Derivation + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Derivation + http://www.w3.org/TR/2013/REC-prov-n-20130430/#Derivation-Relation + A derivation is a transformation of an entity into another, an update of an entity resulting in a new one, or the construction of a new entity based on a pre-existing entity. + derivations + An instance of prov:Derivation provides additional descriptions about the binary prov:wasDerivedFrom relation from some derived prov:Entity to another prov:Entity from which it was derived. For example, :chewed_bubble_gum prov:wasDerivedFrom :unwrapped_bubble_gum; prov:qualifiedDerivation [ a prov:Derivation; prov:entity :unwrapped_bubble_gum; :foo :bar ]. + The more specific forms of prov:Derivation (i.e., prov:Revision, prov:Quotation, prov:PrimarySource) should be asserted if they apply. + qualified + + + + + + + + + + EmptyCollection + + expanded + collections + An empty collection is a collection without members. + + + + + + + + + End + + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-End + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-End + An instance of prov:End provides additional descriptions about the binary prov:wasEndedBy relation from some ended prov:Activity to an prov:Entity that ended it. For example, :ball_game prov:wasEndedBy :buzzer; prov:qualifiedEnd [ a prov:End; prov:entity :buzzer; :foo :bar; prov:atTime '2012-03-09T08:05:08-05:00'^^xsd:dateTime ]. + qualified + End is when an activity is deemed to have been ended by an entity, known as trigger. The activity no longer exists after its end. Any usage, generation, or invalidation involving an activity precedes the activity's end. An end may refer to a trigger entity that terminated the activity, or to an activity, known as ender that generated the trigger. + entities-activities + + + + + + + + + + Entity + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-entity + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Entity + entities-activities + An entity is a physical, digital, conceptual, or other kind of thing with some fixed aspects; entities may be real or imaginary. + starting-point + + + + + + + + + EntityInfluence + + EntityInfluence is the capacity of an entity to have an effect on the character, development, or behavior of another by means of usage, start, end, derivation, or other. + EntityInfluence provides additional descriptions of an Entity's binary influence upon any other kind of resource. Instances of EntityInfluence use the prov:entity property to cite the influencing Entity. + It is not recommended that the type EntityInfluence be asserted without also asserting one of its more specific subclasses. + qualified + + + + + + + + + + Generation + + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Generation + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Generation + An instance of prov:Generation provides additional descriptions about the binary prov:wasGeneratedBy relation from a generated prov:Entity to the prov:Activity that generated it. For example, :cake prov:wasGeneratedBy :baking; prov:qualifiedGeneration [ a prov:Generation; prov:activity :baking; :foo :bar ]. + qualified + entities-activities + Generation is the completion of production of a new entity by an activity. This entity did not exist before generation and becomes available for usage after this generation. + + + + + + + + + + Influence + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-influence + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-influence + derivations + An instance of prov:Influence provides additional descriptions about the binary prov:wasInfluencedBy relation from some influenced Activity, Entity, or Agent to the influencing Activity, Entity, or Agent. For example, :stomach_ache prov:wasInfluencedBy :spoon; prov:qualifiedInfluence [ a prov:Influence; prov:entity :spoon; :foo :bar ] . Because prov:Influence is a broad relation, the more specific relations (Communication, Delegation, End, etc.) should be used when applicable. + Because prov:Influence is a broad relation, its most specific subclasses (e.g. prov:Communication, prov:Delegation, prov:End, prov:Revision, etc.) should be used when applicable. + qualified + Influence is the capacity of an entity, activity, or agent to have an effect on the character, development, or behavior of another by means of usage, start, end, generation, invalidation, communication, derivation, attribution, association, or delegation. + + + + + + + + + + InstantaneousEvent + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#dfn-event + entities-activities + An instantaneous event, or event for short, happens in the world and marks a change in the world, in its activities and in its entities. The term 'event' is commonly used in process algebra with a similar meaning. Events represent communications or interactions; they are assumed to be atomic and instantaneous. + The PROV data model is implicitly based on a notion of instantaneous events (or just events), that mark transitions in the world. Events include generation, usage, or invalidation of entities, as well as starting or ending of activities. This notion of event is not first-class in the data model, but it is useful for explaining its other concepts and its semantics. + qualified + + + + + + + + + Invalidation + + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Invalidation + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Invalidation + entities-activities + Invalidation is the start of the destruction, cessation, or expiry of an existing entity by an activity. The entity is no longer available for use (or further invalidation) after invalidation. Any generation or usage of an entity precedes its invalidation. + qualified + An instance of prov:Invalidation provides additional descriptions about the binary prov:wasInvalidatedBy relation from an invalidated prov:Entity to the prov:Activity that invalidated it. For example, :uncracked_egg prov:wasInvalidatedBy :baking; prov:qualifiedInvalidation [ a prov:Invalidation; prov:activity :baking; :foo :bar ]. + + + + + + + + + + Location + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-attribute-location + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-attribute + A location can be an identifiable geographic place (ISO 19112), but it can also be a non-geographic place such as a directory, row, or column. As such, there are numerous ways in which location can be expressed, such as by a coordinate, address, landmark, and so forth. + expanded + + + + + + + + + + Organization + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-agent + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-types + An organization is a social or legal institution such as a company, society, etc. + expanded + agents-responsibility + + + + + + + + + Person + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-agent + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-types + expanded + agents-responsibility + Person agents are people. + + + + + + + + + Plan + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Association + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Association + A plan is an entity that represents a set of actions or steps intended by one or more agents to achieve some goals. + expanded + There exist no prescriptive requirement on the nature of plans, their representation, the actions or steps they consist of, or their intended goals. Since plans may evolve over time, it may become necessary to track their provenance, so plans themselves are entities. Representing the plan explicitly in the provenance can be useful for various tasks: for example, to validate the execution as represented in the provenance record, to manage expectation failures, or to provide explanations. + qualified + agents-responsibility + + + + + + + + + PrimarySource + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-primary-source + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-original-source + qualified + derivations + A primary source for a topic refers to something produced by some agent with direct experience and knowledge about the topic, at the time of the topic's study, without benefit from hindsight. + +Because of the directness of primary sources, they 'speak for themselves' in ways that cannot be captured through the filter of secondary sources. As such, it is important for secondary sources to reference those primary sources from which they were derived, so that their reliability can be investigated. + +A primary source relation is a particular case of derivation of secondary materials from their primary sources. It is recognized that the determination of primary sources can be up to interpretation, and should be done according to conventions accepted within the application's domain. + An instance of prov:PrimarySource provides additional descriptions about the binary prov:hadPrimarySource relation from some secondary prov:Entity to an earlier, primary prov:Entity. For example, :blog prov:hadPrimarySource :newsArticle; prov:qualifiedPrimarySource [ a prov:PrimarySource; prov:entity :newsArticle; :foo :bar ] . + + + + + + + + + + Quotation + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-quotation + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-quotation + An instance of prov:Quotation provides additional descriptions about the binary prov:wasQuotedFrom relation from some taken prov:Entity from an earlier, larger prov:Entity. For example, :here_is_looking_at_you_kid prov:wasQuotedFrom :casablanca_script; prov:qualifiedQuotation [ a prov:Quotation; prov:entity :casablanca_script; :foo :bar ]. + derivations + qualified + A quotation is the repeat of (some or all of) an entity, such as text or image, by someone who may or may not be its original author. Quotation is a particular case of derivation. + + + + + + + + + + Revision + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-revision + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Revision + derivations + qualified + A revision is a derivation for which the resulting entity is a revised version of some original. The implication here is that the resulting entity contains substantial content from the original. Revision is a particular case of derivation. + An instance of prov:Revision provides additional descriptions about the binary prov:wasRevisionOf relation from some newer prov:Entity to an earlier prov:Entity. For example, :draft_2 prov:wasRevisionOf :draft_1; prov:qualifiedRevision [ a prov:Revision; prov:entity :draft_1; :foo :bar ]. + + + + + + + + + + Role + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-attribute-role + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-attribute + A role is the function of an entity or agent with respect to an activity, in the context of a usage, generation, invalidation, association, start, and end. + qualified + agents-responsibility + + + + + + + + + + SoftwareAgent + + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-agent + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-types + agents-responsibility + A software agent is running software. + expanded + + + + + + + + + Start + + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Start + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Start + entities-activities + qualified + An instance of prov:Start provides additional descriptions about the binary prov:wasStartedBy relation from some started prov:Activity to an prov:Entity that started it. For example, :foot_race prov:wasStartedBy :bang; prov:qualifiedStart [ a prov:Start; prov:entity :bang; :foo :bar; prov:atTime '2012-03-09T08:05:08-05:00'^^xsd:dateTime ] . + Start is when an activity is deemed to have been started by an entity, known as trigger. The activity did not exist before its start. Any usage, generation, or invalidation involving an activity follows the activity's start. A start may refer to a trigger entity that set off the activity, or to an activity, known as starter, that generated the trigger. + + + + + + + + + + Usage + + + http://www.w3.org/TR/2013/REC-prov-constraints-20130430/#prov-dm-constraints-fig + http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Usage + http://www.w3.org/TR/2013/REC-prov-n-20130430/#expression-Usage + An instance of prov:Usage provides additional descriptions about the binary prov:used relation from some prov:Activity to an prov:Entity that it used. For example, :keynote prov:used :podium; prov:qualifiedUsage [ a prov:Usage; prov:entity :podium; :foo :bar ]. + Usage is the beginning of utilizing an entity by an activity. Before usage, the activity had not begun to utilize this entity and could not have been affected by the entity. + qualified + entities-activities + + + + + + + + + + + + + + + EmptyCollection + expanded + collections + An empty collection is a collection without members. + + + + + + + + diff --git a/orcid-api-common/src/test/java/org/orcid/api/common/writer/rdf/RDFWriterTest.java b/orcid-api-common/src/test/java/org/orcid/api/common/writer/rdf/RDFWriterTest.java new file mode 100644 index 00000000000..11dc7f6d952 --- /dev/null +++ b/orcid-api-common/src/test/java/org/orcid/api/common/writer/rdf/RDFWriterTest.java @@ -0,0 +1,106 @@ +/** + * ============================================================================= + * + * ORCID (R) Open Source + * http://orcid.org + * + * Copyright (c) 2012-2013 ORCID, Inc. + * Licensed under an MIT-Style License (MIT) + * http://orcid.org/open-source-license + * + * This copyright and license information (including a link to the full license) + * shall be included in its entirety in all copies or substantial portion of + * the software. + * + * ============================================================================= + */ +package org.orcid.api.common.writer.rdf; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.PathSegment; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.junit.Test; +import org.orcid.jaxb.model.message.ContactDetails; +import org.orcid.jaxb.model.message.CreditName; +import org.orcid.jaxb.model.message.Email; +import org.orcid.jaxb.model.message.FamilyName; +import org.orcid.jaxb.model.message.GivenNames; +import org.orcid.jaxb.model.message.OrcidBio; +import org.orcid.jaxb.model.message.OrcidMessage; +import org.orcid.jaxb.model.message.OrcidProfile; +import org.orcid.jaxb.model.message.OtherNames; +import org.orcid.jaxb.model.message.PersonalDetails; + +//@RunWith(SpringJUnit4ClassRunner.class) +//@ContextConfiguration(locations = { "classpath:orcid-t1-web-context.xml" }) +public class RDFWriterTest { + + private RDFMessageBodyWriter rdfWriter = new RDFMessageBodyWriter(); + + private OrcidMessage fakeBio() { + OrcidMessage orcidMessage = new OrcidMessage(); + OrcidProfile orcidProfile1 = new OrcidProfile(); + orcidProfile1.setOrcidId("http://orcid.example.com/000-1337"); + orcidProfile1.setOrcid("000-1337"); + OrcidBio bio = new OrcidBio(); + orcidProfile1.setOrcidBio(bio); + PersonalDetails personal = new PersonalDetails(); + bio.setPersonalDetails(personal); + personal.setFamilyName(new FamilyName("Doe")); + personal.setCreditName(new CreditName("John F Doe")); + personal.setGivenNames(new GivenNames("John")); + personal.setOtherNames(new OtherNames()); + personal.getOtherNames().addOtherName("Johnny"); + personal.getOtherNames().addOtherName("Mr Doe"); + + bio.setContactDetails(new ContactDetails()); + bio.getContactDetails().setEmail(Arrays.asList(new Email("john@example.org"), new Email("doe@example.com"))); + + + orcidMessage.setOrcidProfile(orcidProfile1); + return orcidMessage; + + } + + @Test + public void writeRdfXML() throws Exception { + + ByteArrayOutputStream entityStream = new ByteArrayOutputStream(1024); + + rdfWriter.writeTo(fakeBio(), OrcidMessage.class, null, null, new MediaType("application", "rdf+xml"), null, entityStream); + + String str = entityStream.toString("utf-8"); + System.out.println(str); + assertTrue(str.contains("http://orcid.example.com/000-1337")); + assertTrue(str.contains("foaf:name>John F")); + assertTrue(str.contains("rdf:about")); + assertFalse(str.contains("subClassOf")); + } + + @Test + public void writeTurte() throws Exception { + + ByteArrayOutputStream entityStream = new ByteArrayOutputStream(1024); + rdfWriter.writeTo(fakeBio(), OrcidMessage.class, null, null, new MediaType("text", "turtle"), null, entityStream); + + String str = entityStream.toString("utf-8"); + System.out.println(str); + assertTrue(str.contains("")); + assertTrue(str.contains("foaf:Person")); + assertTrue(str.contains("foaf:name \"John F")); + assertFalse(str.contains("subClassOf")); + } + + +} diff --git a/orcid-api-web/src/main/java/org/orcid/api/t2/server/T2OrcidApiServiceImpl.java b/orcid-api-web/src/main/java/org/orcid/api/t2/server/T2OrcidApiServiceImpl.java index 859b2c1b6c0..4e805cab84d 100644 --- a/orcid-api-web/src/main/java/org/orcid/api/t2/server/T2OrcidApiServiceImpl.java +++ b/orcid-api-web/src/main/java/org/orcid/api/t2/server/T2OrcidApiServiceImpl.java @@ -16,6 +16,7 @@ */ package org.orcid.api.t2.server; +import static org.orcid.api.common.OrcidApiConstants.APPLICATION_RDFXML; import static org.orcid.api.common.OrcidApiConstants.BIO_PATH; import static org.orcid.api.common.OrcidApiConstants.BIO_SEARCH_PATH; import static org.orcid.api.common.OrcidApiConstants.EXTERNAL_IDENTIFIER_PATH; @@ -25,6 +26,8 @@ import static org.orcid.api.common.OrcidApiConstants.PROFILE_GET_PATH; import static org.orcid.api.common.OrcidApiConstants.PROFILE_POST_PATH; import static org.orcid.api.common.OrcidApiConstants.STATUS_PATH; +import static org.orcid.api.common.OrcidApiConstants.TEXT_N3; +import static org.orcid.api.common.OrcidApiConstants.TEXT_TURTLE; import static org.orcid.api.common.OrcidApiConstants.VND_ORCID_JSON; import static org.orcid.api.common.OrcidApiConstants.VND_ORCID_XML; import static org.orcid.api.common.OrcidApiConstants.WEBHOOKS_PATH; @@ -159,6 +162,40 @@ public Response viewBioDetailsJson(@PathParam("orcid") String orcid) { return serviceDelegator.findBioDetails(orcid); } + /** + * GETs the RDF Turtle representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF Turtle representation of the ORCID record + */ + @Override + @GET + @Produces(value = { TEXT_N3, TEXT_TURTLE }) + @Path(BIO_PATH) + public Response viewBioDetailsTurtle(@PathParam("orcid") String orcid) { + T2_GET_REQUESTS.inc(); + return serviceDelegator.findBioDetails(orcid); + } + + /** + * GETs the RDF/XML representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF/XML representation of the ORCID record + */ + @Override + @GET + @Produces(value = { APPLICATION_RDFXML }) + @Path(BIO_PATH) + public Response viewBioDetailsRdf(@PathParam("orcid") String orcid) { + T2_GET_REQUESTS.inc(); + return serviceDelegator.findBioDetails(orcid); + } + /** * GETs the HTML representation of the ORCID external identifiers * diff --git a/orcid-api-web/src/test/java/org/orcid/api/t2/integration/T2OrcidApiClientImpl.java b/orcid-api-web/src/test/java/org/orcid/api/t2/integration/T2OrcidApiClientImpl.java index 9e22a808cc2..266e0af5484 100644 --- a/orcid-api-web/src/test/java/org/orcid/api/t2/integration/T2OrcidApiClientImpl.java +++ b/orcid-api-web/src/test/java/org/orcid/api/t2/integration/T2OrcidApiClientImpl.java @@ -249,6 +249,32 @@ public ClientResponse viewBioDetailsJson(@PathParam("orcid") String orcid) { return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), VND_ORCID_JSON); } + /** + * GETs the RDF/XML representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF/XML representation of the ORCID record + */ + @Override + public ClientResponse viewBioDetailsRdf(@PathParam("orcid") String orcid) { + return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), APPLICATION_RDFXML); + } + + /** + * GETs the RDF Turtle representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF Turtle representation of the ORCID record + */ + @Override + public ClientResponse viewBioDetailsTurtle(@PathParam("orcid") String orcid) { + return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), TEXT_TURTLE); + } + /** * GETs the HTML representation of the ORCID external identifiers * diff --git a/orcid-pub-web/pom.xml b/orcid-pub-web/pom.xml index 46af24944b0..d0257fa7bbe 100644 --- a/orcid-pub-web/pom.xml +++ b/orcid-pub-web/pom.xml @@ -32,6 +32,7 @@ orcid-api-common ${project.parent.version} + ${project.groupId} orcid-utils diff --git a/orcid-pub-web/src/main/java/org/orcid/api/t1/server/T1OrcidApiServiceImpl.java b/orcid-pub-web/src/main/java/org/orcid/api/t1/server/T1OrcidApiServiceImpl.java index 44d82f03c73..df69aa1969f 100644 --- a/orcid-pub-web/src/main/java/org/orcid/api/t1/server/T1OrcidApiServiceImpl.java +++ b/orcid-pub-web/src/main/java/org/orcid/api/t1/server/T1OrcidApiServiceImpl.java @@ -16,13 +16,22 @@ */ package org.orcid.api.t1.server; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Counter; +import static org.orcid.api.common.OrcidApiConstants.APPLICATION_RDFXML; +import static org.orcid.api.common.OrcidApiConstants.BIO_PATH; +import static org.orcid.api.common.OrcidApiConstants.BIO_SEARCH_PATH; +import static org.orcid.api.common.OrcidApiConstants.EXTERNAL_IDENTIFIER_PATH; +import static org.orcid.api.common.OrcidApiConstants.ORCID_JSON; +import static org.orcid.api.common.OrcidApiConstants.ORCID_XML; +import static org.orcid.api.common.OrcidApiConstants.PROFILE_GET_PATH; +import static org.orcid.api.common.OrcidApiConstants.STATUS_PATH; +import static org.orcid.api.common.OrcidApiConstants.TEXT_N3; +import static org.orcid.api.common.OrcidApiConstants.TEXT_TURTLE; +import static org.orcid.api.common.OrcidApiConstants.VND_ORCID_JSON; +import static org.orcid.api.common.OrcidApiConstants.VND_ORCID_XML; +import static org.orcid.api.common.OrcidApiConstants.WORKS_PATH; -import org.orcid.api.common.OrcidApiService; -import org.orcid.api.common.delegator.OrcidApiServiceDelegator; -import org.orcid.jaxb.model.message.OrcidMessage; -import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; import javax.annotation.Resource; import javax.ws.rs.GET; @@ -33,10 +42,14 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.util.List; -import java.util.Map; -import static org.orcid.api.common.OrcidApiConstants.*; +import org.orcid.api.common.OrcidApiService; +import org.orcid.api.common.delegator.OrcidApiServiceDelegator; +import org.orcid.jaxb.model.message.OrcidMessage; +import org.springframework.stereotype.Component; + +import com.yammer.metrics.Metrics; +import com.yammer.metrics.core.Counter; /** * Copyright 2011-2012 ORCID @@ -110,6 +123,40 @@ public Response viewBioDetailsXml(@PathParam("orcid") String orcid) { T1_GET_REQUESTS.inc(); return serviceDelegator.findBioDetails(orcid); } + + /** + * GETs the RDF/XML representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF/XML representation of the ORCID record + */ + @Override + @GET + @Produces(value = { APPLICATION_RDFXML }) + @Path(BIO_PATH) + public Response viewBioDetailsRdf(@PathParam("orcid") String orcid) { + T1_GET_REQUESTS.inc(); + return serviceDelegator.findBioDetails(orcid); + } + + + /** + * GETs the RDF Turtle representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF Turtle representation of the ORCID record + */ + @GET + @Produces(value = { TEXT_N3, TEXT_TURTLE }) + @Path(BIO_PATH) + public Response viewBioDetailsTurtle(@PathParam("orcid") String orcid) { + T1_GET_REQUESTS.inc(); + return serviceDelegator.findBioDetails(orcid); + } /** * GETs the JSON representation of the ORCID record containing only the diff --git a/orcid-pub-web/src/test/java/org/orcid/api/t1/integration/T1OrcidApiClientImpl.java b/orcid-pub-web/src/test/java/org/orcid/api/t1/integration/T1OrcidApiClientImpl.java index aec17de2879..8360c962137 100644 --- a/orcid-pub-web/src/test/java/org/orcid/api/t1/integration/T1OrcidApiClientImpl.java +++ b/orcid-pub-web/src/test/java/org/orcid/api/t1/integration/T1OrcidApiClientImpl.java @@ -72,6 +72,32 @@ public ClientResponse viewBioDetailsHtml(@PathParam("orcid") String orcid) { public ClientResponse viewBioDetailsXml(@PathParam("orcid") String orcid) { return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), VND_ORCID_XML); } + + /** + * GETs the RDF/XML representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF/XML representation of the ORCID record + */ + @Override + public ClientResponse viewBioDetailsRdf(@PathParam("orcid") String orcid) { + return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), APPLICATION_RDFXML); + } + + /** + * GETs the RDF Turtle representation of the ORCID record containing only the + * Biography details + * + * @param orcid + * the ORCID that corresponds to the user's record + * @return the RDF Turtle representation of the ORCID record + */ + @Override + public ClientResponse viewBioDetailsTurtle(@PathParam("orcid") String orcid) { + return orcidClientHelper.getClientResponse(UriBuilder.fromPath(BIO_PATH_NO_REGEX).build(orcid), TEXT_TURTLE); + } /** * GETs the JSON representation of the ORCID record containing only the diff --git a/pom.xml b/pom.xml index b5b8faa67a3..3ea11361f73 100644 --- a/pom.xml +++ b/pom.xml @@ -923,6 +923,11 @@ the software. 2.13.0 test + + org.apache.jena + jena-core + 2.10.1 +