@prefix this: . @prefix sub: . @prefix np: . @prefix grlc: . @prefix dct: . @prefix nt: . @prefix npx: . @prefix xsd: . @prefix rdfs: . @prefix orcid: . @prefix prov: . @prefix foaf: . sub:Head { this: a np:Nanopublication; np:hasAssertion sub:assertion; np:hasProvenance sub:provenance; np:hasPublicationInfo sub:pubinfo . } sub:assertion { sub:get-cv-entries-for-person a grlc:grlc-query; dct:description "Returns the career history of a given person as a single timeline: positions held and academic degrees awarded, interleaved by year. The entryKind column says which of the two a row is. Positions carry a start year and, unless still held, an end year; degrees carry the year they were conferred as the start year. This query runs against the full repository rather than a type-specific one because it spans two types."; dct:license ; rdfs:label "Get CV entries for person"; grlc:endpoint ; grlc:sparql """prefix rdfs: prefix dct: prefix np: prefix npa: prefix npx: prefix wd: prefix vivo: select ?entry ?entry_label ?entryKind ?organization ?organization_label ?unit ?startYear ?endYear ?np (\"^\" as ?np_label) where { graph npa:graph { ?np npa:hasValidSignatureForPublicKeyHash ?pubkey . filter not exists { ?npx npx:invalidates ?np ; npa:hasValidSignatureForPublicKeyHash ?pubkey . } filter not exists { ?np npx:hasNanopubType npx:ExampleNanopub . } ?np np:hasAssertion ?a . ?np np:hasPublicationInfo ?pi . ?np npx:introduces ?entry . } { # A position: held from a start year, open-ended while still held. graph ?a { ?entry a vivo:Position . ?_person_iri wd:P39 ?entry . optional { ?entry wd:P108 ?organization . } optional { ?entry wd:P580 ?startYear . } optional { ?entry wd:P582 ?endYear . } } bind(\"position\" as ?entryKind) } union { # A degree: conferred in one year, which becomes the start year so that both # kinds sort on the same axis. graph ?a { ?entry a vivo:AwardedDegree . ?_person_iri wd:P512 ?entry . optional { ?entry wd:P69 ?organization . } optional { ?entry dct:issued ?startYear . } } bind(\"degree\" as ?entryKind) } optional { graph ?a { ?entry rdfs:label ?entry_label . } } optional { graph ?a { ?entry dct:description ?unit . } } # Organization labels live in pubinfo. OPTIONAL wraps GRAPH, never the reverse. optional { graph ?pi { ?organization rdfs:label ?organization_label . } } } order by desc(?startYear) desc(?endYear)""" . } sub:provenance { sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . } sub:pubinfo { orcid:0000-0002-1267-0234 foaf:name "Tobias Kuhn" . this: dct:created "2026-08-28T17:52:14Z"^^xsd:dateTime; dct:creator orcid:0000-0002-1267-0234; dct:license ; npx:introduces sub:get-cv-entries-for-person; rdfs:label "Get CV entries for person"; nt:wasCreatedFromProvenanceTemplate ; nt:wasCreatedFromPubinfoTemplate , , ; nt:wasCreatedFromTemplate . sub:sig npx:hasAlgorithm "RSA"; npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; npx:hasSignature "P9iKZhORQHFr0LfrJF5LaygxbvxIG+c1tBbHmvDfEHxSQz7pd88+2SUMQ53AsT+6Dx7c0YA/8q60VJDb7ng+1EeTS0PwJW7NBobBiRi6Bk53pkyYOiXb3kZ507L4UvzHQNUK9Xw2aFY9HQM/kli+clB1cS+WMlGij0grAaQxfTo="; npx:hasSignatureTarget this:; npx:signedBy orcid:0000-0002-1267-0234 . }