From 2ecc5310caaf2402d31040bba074a3dd924601a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Fri, 12 Dec 2025 15:37:42 +0100 Subject: [PATCH 01/64] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7c0b2d1ed..f63745991 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.atomgraph linkeddatahub - 5.1.0 + 5.1.1-SNAPSHOT ${packaging.type} AtomGraph LinkedDataHub From 864183eda5de8442525f1b32ba3ea0297f193ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Fri, 12 Dec 2025 23:24:15 +0100 Subject: [PATCH 02/64] Simplified client-side refresh after OAuth login --- .../com/atomgraph/linkeddatahub/xsl/client.xsl | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl index 3a615bdfa..e3f35cd31 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl @@ -296,22 +296,8 @@ WHERE - - - - - - + + From 27bf9cee7f7ec930d8ac9647f07288abc0a5116c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Sun, 14 Dec 2025 11:44:36 +0100 Subject: [PATCH 03/64] Make sure proxy passes on the response status --- README.md | 2 +- http-tests/proxy/GET-proxied-403.sh | 36 ++++++++ .../server/model/impl/ProxyResourceBase.java | 82 ++++++++++++++++++- 3 files changed, 117 insertions(+), 3 deletions(-) create mode 100755 http-tests/proxy/GET-proxied-403.sh diff --git a/README.md b/README.md index 18ee07e3e..11a2c4642 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ The options are described in more detail in the [configuration documentation](ht If you need to start fresh and wipe the existing setup (e.g. after configuring a new base URI), you can do that using ```shell - sudo rm -rf data uploads && docker-compose down -v + sudo rm -rf fuseki uploads ssl datasets && docker-compose down -v ``` _:warning: This will **remove the persisted data and files** as well as Docker volumes._ diff --git a/http-tests/proxy/GET-proxied-403.sh b/http-tests/proxy/GET-proxied-403.sh new file mode 100755 index 000000000..04eadb652 --- /dev/null +++ b/http-tests/proxy/GET-proxied-403.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# add agent to the readers group to be able to read documents + +add-agent-to-group.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --agent "$AGENT_URI" \ + "${ADMIN_BASE_URL}acl/groups/readers/" + +# Test that status codes are correctly proxied through +# Generate a random UUID for a non-existing resource +random_uuid=$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen) +non_existing_uri="${END_USER_BASE_URL}${random_uuid}/" + +# Attempt to proxy a non-existing document on the END_USER_BASE_URL +# This should return 403 Forbidden (not found resources return 403 in LinkedDataHub) +http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ + -G \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -H 'Accept: application/n-triples' \ + --data-urlencode "uri=${non_existing_uri}" \ + "$END_USER_BASE_URL" || true) + +# Verify that the proxied status code matches the backend status code (403) +if [ "$http_status" != "403" ]; then + echo "Expected HTTP 403 Forbidden for non-existing proxied document, got: $http_status" + exit 1 +fi diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java index 420a78a95..b590e424a 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java @@ -18,8 +18,11 @@ import com.atomgraph.client.MediaTypes; import com.atomgraph.client.util.DataManager; +import com.atomgraph.client.util.HTMLMediaTypePredicate; import com.atomgraph.client.vocabulary.AC; import com.atomgraph.core.exception.BadGatewayException; +import com.atomgraph.core.util.ModelUtils; +import com.atomgraph.core.util.ResultSetUtils; import com.atomgraph.linkeddatahub.apps.model.Dataset; import com.atomgraph.linkeddatahub.client.LinkedDataClient; import com.atomgraph.linkeddatahub.client.filter.auth.IDTokenDelegationFilter; @@ -52,15 +55,22 @@ import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.container.ContainerRequestContext; import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.EntityTag; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.Response.StatusType; import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.UriInfo; +import jakarta.ws.rs.core.Variant; import jakarta.ws.rs.ext.Providers; import org.apache.jena.query.ResultSet; +import org.apache.jena.query.ResultSetRewindable; import org.apache.jena.rdf.model.Model; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFLanguages; +import org.apache.jena.riot.resultset.ResultSetReaderRegistry; import org.apache.jena.util.FileManager; import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException; @@ -207,9 +217,77 @@ public Invocation.Builder getBuilder(WebTarget target) @Override public Response getResponse(Response clientResponse) { - if (clientResponse.getMediaType() == null) return Response.status(clientResponse.getStatus()).build(); + return getResponse(clientResponse, clientResponse.getStatusInfo()); + } + + public Response getResponse(Response clientResponse, StatusType statusType) + { + MediaType formatType = new MediaType(clientResponse.getMediaType().getType(), clientResponse.getMediaType().getSubtype()); // discard charset param + Lang lang = RDFLanguages.contentTypeToLang(formatType.toString()); + + // check if we got SPARQL results first + if (lang != null && ResultSetReaderRegistry.isRegistered(lang)) + { + ResultSetRewindable results = clientResponse.readEntity(ResultSetRewindable.class); + return getResponse(results, statusType); + } + + // fallback to RDF graph + Model description = clientResponse.readEntity(Model.class); + return getResponse(description, statusType); + } + + /** + * Returns response for the given RDF model. + * TO-DO: move down to Web-Client + * + * @param model RDF model + * @param statusType response status + * @return response object + */ + public Response getResponse(Model model, StatusType statusType) + { + List variants = com.atomgraph.core.model.impl.Response.getVariants(getWritableMediaTypes(Model.class), + getLanguages(), + getEncodings()); + + return new com.atomgraph.core.model.impl.Response(getRequest(), + model, + null, + new EntityTag(Long.toHexString(ModelUtils.hashModel(model))), + variants, + new HTMLMediaTypePredicate()). + getResponseBuilder(). + status(statusType). + build(); + } + + /** + * Returns response for the given SPARQL results. + * TO-DO: move down to Web-Client + * + * @param resultSet SPARQL results + * @param statusType response status + * @return response object + */ + public Response getResponse(ResultSetRewindable resultSet, StatusType statusType) + { + long hash = ResultSetUtils.hashResultSet(resultSet); + resultSet.reset(); + + List variants = com.atomgraph.core.model.impl.Response.getVariants(getWritableMediaTypes(ResultSet.class), + getLanguages(), + getEncodings()); - return super.getResponse(clientResponse); + return new com.atomgraph.core.model.impl.Response(getRequest(), + resultSet, + null, + new EntityTag(Long.toHexString(hash)), + variants, + new HTMLMediaTypePredicate()). + getResponseBuilder(). + status(statusType). + build(); } /** From 21d2ab088448dba8163c2176f5095c18628ffe48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Sun, 14 Dec 2025 12:12:38 +0100 Subject: [PATCH 04/64] NPE fix --- http-tests/proxy/POST-proxied-form.sh | 2 +- .../linkeddatahub/server/model/impl/ProxyResourceBase.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/http-tests/proxy/POST-proxied-form.sh b/http-tests/proxy/POST-proxied-form.sh index 9bfec095d..167bd1f72 100755 --- a/http-tests/proxy/POST-proxied-form.sh +++ b/http-tests/proxy/POST-proxied-form.sh @@ -19,7 +19,7 @@ add-agent-to-group.sh \ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -X POST \ - -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ -H 'Content-Type: application/x-www-form-urlencoded' \ -H 'Accept: application/rdf+xml' \ --url-query "uri=${ADMIN_BASE_URL}clear" \ diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java index b590e424a..a1cc2f4dd 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java @@ -217,6 +217,8 @@ public Invocation.Builder getBuilder(WebTarget target) @Override public Response getResponse(Response clientResponse) { + if (clientResponse.getMediaType() == null) return Response.status(clientResponse.getStatus()).build(); + return getResponse(clientResponse, clientResponse.getStatusInfo()); } @@ -224,7 +226,7 @@ public Response getResponse(Response clientResponse, StatusType statusType) { MediaType formatType = new MediaType(clientResponse.getMediaType().getType(), clientResponse.getMediaType().getSubtype()); // discard charset param Lang lang = RDFLanguages.contentTypeToLang(formatType.toString()); - + // check if we got SPARQL results first if (lang != null && ResultSetReaderRegistry.isRegistered(lang)) { From a7399f3cdad78d5e4a3166d4d30f50b791ffa287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= Date: Sun, 21 Dec 2025 00:18:15 +0200 Subject: [PATCH 05/64] `ldh:origin` renamed to `lapp:origin` --- config/system.trig | 4 +- http-tests/config/system.trig | 8 +- platform/select-root-services.rq | 4 +- .../atomgraph/linkeddatahub/Application.java | 4 +- .../apps/model/impl/ApplicationImpl.java | 3 +- .../linkeddatahub/vocabulary/LAPP.java | 3 + .../linkeddatahub/vocabulary/LDH.java | 3 - .../linkeddatahub/writer/XSLTWriterBase.java | 2 +- .../com/atomgraph/linkeddatahub/lapp.ttl | 82 ++++++++----------- .../xsl/bootstrap/2.3.2/client/functions.xsl | 6 +- .../xsl/bootstrap/2.3.2/client/modal.xsl | 8 +- .../xsl/bootstrap/2.3.2/layout.xsl | 38 ++++----- .../atomgraph/linkeddatahub/xsl/client.xsl | 6 +- 13 files changed, 81 insertions(+), 90 deletions(-) diff --git a/config/system.trig b/config/system.trig index 647f582c7..48e43ed77 100644 --- a/config/system.trig +++ b/config/system.trig @@ -18,7 +18,7 @@ a lapp:Application, lapp:AdminApplication ; dct:title "LinkedDataHub admin" ; # ldt:base ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; ac:stylesheet ; @@ -38,7 +38,7 @@ a lapp:Application, lapp:EndUserApplication ; dct:title "LinkedDataHub" ; # ldt:base ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; lapp:adminApplication ; diff --git a/http-tests/config/system.trig b/http-tests/config/system.trig index 47ed5c76a..a5d0e33e7 100644 --- a/http-tests/config/system.trig +++ b/http-tests/config/system.trig @@ -18,7 +18,7 @@ a lapp:Application, lapp:AdminApplication ; dct:title "LinkedDataHub admin" ; # ldt:base ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; ac:stylesheet ; @@ -38,7 +38,7 @@ a lapp:Application, lapp:EndUserApplication ; dct:title "LinkedDataHub" ; # ldt:base ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; lapp:adminApplication ; @@ -57,7 +57,7 @@ a lapp:Application, lapp:AdminApplication ; dct:title "Test admin" ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; ac:stylesheet ; @@ -76,7 +76,7 @@ a lapp:Application, lapp:EndUserApplication ; dct:title "Test" ; - ldh:origin ; + lapp:origin ; ldt:ontology ; ldt:service ; lapp:adminApplication ; diff --git a/platform/select-root-services.rq b/platform/select-root-services.rq index 2a307e4e1..4c6d67546 100644 --- a/platform/select-root-services.rq +++ b/platform/select-root-services.rq @@ -7,11 +7,11 @@ PREFIX foaf: SELECT ?endUserApp ?endUserOrigin ?endUserQuadStore ?endUserEndpoint ?endUserAuthUser ?endUserAuthPwd ?endUserMaker ?adminApp ?adminOrigin ?adminQuadStore ?adminEndpoint ?adminAuthUser ?adminAuthPwd ?adminMaker { - ?endUserApp ldh:origin ?endUserOrigin ; + ?endUserApp lapp:origin ?endUserOrigin ; ldt:service ?endUserService ; lapp:adminApplication ?adminApp . ?adminApp ldt:service ?adminService ; - ldh:origin ?adminOrigin . + lapp:origin ?adminOrigin . ?endUserService a:quadStore ?endUserQuadStore ; sd:endpoint ?endUserEndpoint . ?adminService a:quadStore ?adminQuadStore ; diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index eeebe124a..986c5e3c7 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -1309,9 +1309,9 @@ public Resource getAppByOrigin(Model model, Resource type, URI absolutePath) Resource app = it.next(); // Use origin-based matching - return immediately on match since origins are unique - if (app.hasProperty(LDH.origin)) + if (app.hasProperty(LAPP.origin)) { - URI appOriginURI = URI.create(app.getPropertyResourceValue(LDH.origin).getURI()); + URI appOriginURI = URI.create(app.getPropertyResourceValue(LAPP.origin).getURI()); String normalizedAppOrigin = normalizeOrigin(appOriginURI); if (requestOrigin.equals(normalizedAppOrigin)) return app; diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java index 4a0c956f8..043b18d90 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java @@ -21,7 +21,6 @@ import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.vocabulary.FOAF; import com.atomgraph.linkeddatahub.vocabulary.LAPP; -import com.atomgraph.linkeddatahub.vocabulary.LDH; import com.atomgraph.server.vocabulary.LDT; import jakarta.ws.rs.core.UriBuilder; import org.apache.jena.enhanced.EnhGraph; @@ -69,7 +68,7 @@ public URI getBaseURI() @Override public Resource getOrigin() { - return getPropertyResourceValue(LDH.origin); + return getPropertyResourceValue(LAPP.origin); } @Override diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java index 6e0c49a11..fe51bdd86 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java +++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java @@ -82,4 +82,7 @@ public static String getURI() /** Read-only property */ public static final DatatypeProperty allowRead = m_model.createDatatypeProperty( NS + "allowRead" ); + /** Origin property for subdomain-based application matching */ + public static final ObjectProperty origin = m_model.createObjectProperty(NS + "origin"); + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java index cea639a6a..555ffdce5 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java +++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java @@ -101,9 +101,6 @@ public static String getURI() /** Service property */ public static final ObjectProperty service = m_model.createObjectProperty( NS + "service" ); - /** Origin property for subdomain-based application matching */ - public static final ObjectProperty origin = m_model.createObjectProperty( NS + "origin" ); - /** * For shape property */ public static final ObjectProperty forShape = m_model.createObjectProperty( NS + "forShape" ); diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java index 89b574dfb..49ff9130e 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java +++ b/src/main/java/com/atomgraph/linkeddatahub/writer/XSLTWriterBase.java @@ -138,7 +138,7 @@ public Map getParameters(MultivaluedMap", app); params.put(new QName("ldt", LDT.base.getNameSpace(), LDT.base.getLocalName()), new XdmAtomicValue(app.getBaseURI())); - params.put(new QName("ldh", LDH.origin.getNameSpace(), LDH.origin.getLocalName()), new XdmAtomicValue(app.getOriginURI())); + params.put(new QName("lapp", LAPP.origin.getNameSpace(), LAPP.origin.getLocalName()), new XdmAtomicValue(app.getOriginURI())); params.put(new QName("ldt", LDT.ontology.getNameSpace(), LDT.ontology.getLocalName()), new XdmAtomicValue(URI.create(app.getOntology().getURI()))); params.put(new QName("lapp", LAPP.Application.getNameSpace(), LAPP.Application.getLocalName()), getXsltExecutable().getProcessor().newDocumentBuilder().build(getSource(getAppModel(app, true)))); diff --git a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl index 81402fb3d..77c6c15fe 100644 --- a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl +++ b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl @@ -82,22 +82,22 @@ :Application a rdfs:Class, owl:Class ; rdfs:subClassOf ldt:Application ; spin:constructor :ApplicationConstructor ; - spin:constraint :OneBasePerHostName, :StartsWithHTTPS, + spin:constraint :StartsWithHTTPS, :ValidOrigin, [ a ldh:MissingPropertyValue ; - rdfs:label "Missing base URI" ; - sp:arg1 ldt:base + rdfs:label "Missing origin URI" ; + sp:arg1 :origin ] ; rdfs:label "Application" ; - rdfs:comment "An application represents a data space identified by its base URI, in which application resource URIs are relative to the base URI. The only application interface (API) is read-write RESTful Linked data, backed by an RDF dataset accessible as a SPARQL 1.1 service. Application structure is defined in an ontology, which can import other ontologies." ; + rdfs:comment "An application represents a data space identified by its origin URI, in which application resource URIs are relative to the origin URI. The only application interface (API) is read-write RESTful Linked data, backed by an RDF dataset accessible as a SPARQL 1.1 service. Application structure is defined in an ontology, which can import other ontologies." ; rdfs:isDefinedBy : . :ApplicationConstructor a ldh:Constructor ; sp:text """ - PREFIX ldt: + PREFIX lapp: PREFIX rdfs: CONSTRUCT { - $this ldt:base [ a rdfs:Resource ] . + $this lapp:origin [ a rdfs:Resource ] . } WHERE { }""" ; @@ -166,47 +166,28 @@ # CONSTRAINTS :StartsWithHTTPS a sp:Construct ; - rdfs:label "ldt:base starts with https://" ; - sp:text """ -PREFIX ldt: -PREFIX spin: -PREFIX rdfs: - -CONSTRUCT { - _:c0 a spin:ConstraintViolation . - _:c0 spin:violationRoot ?this . - _:c0 spin:violationPath ldt:base . - _:c0 rdfs:label "Application base URI must start with https://" . -} -WHERE { - ?this ldt:base ?base - FILTER ( ! strstarts(str(?base), "https://") ) -}""" ; - rdfs:isDefinedBy : . - -:BasePathMatchesRegex a sp:Construct ; - rdfs:label "Base URI path does not match regex" ; + rdfs:label "lapp:origin starts with https://" ; sp:text """ -PREFIX ldt: +PREFIX lapp: PREFIX spin: PREFIX rdfs: CONSTRUCT { _:c0 a spin:ConstraintViolation . _:c0 spin:violationRoot ?this . - _:c0 spin:violationPath ldt:base . + _:c0 spin:violationPath lapp:origin . + _:c0 rdfs:label "Application origin URI must start with https://" . } WHERE { - ?this ldt:base ?base - BIND(strafter(strafter(str(?base), "//"), "/") AS ?path) - FILTER (!regex(?path, ?arg1, "i")) + ?this lapp:origin ?origin + FILTER ( ! strstarts(str(?origin), "https://") ) }""" ; rdfs:isDefinedBy : . -:OneBasePerHostName a sp:Construct ; # TO-DO: turn into spin:Template - rdfs:label "One ldt:base per hostname" ; +:ValidOrigin a sp:Construct ; + rdfs:label "Origin must not have trailing slash and must have hostname" ; sp:text """ -PREFIX ldt: +PREFIX lapp: PREFIX spin: PREFIX rdfs: @@ -214,18 +195,27 @@ CONSTRUCT { _:c0 a spin:ConstraintViolation . _:c0 spin:violationRoot ?this . - _:c0 spin:violationPath ldt:base . - _:c0 rdfs:label "Only one base per hostname is allowed" . + _:c0 spin:violationPath lapp:origin . + _:c0 rdfs:label ?message . } WHERE - { ?this ldt:base ?base - { SELECT ?this - WHERE - { ?this ldt:base ?base - BIND(strbefore(strafter(str(?base), "//"), "/") AS ?hostname) - } - GROUP BY ?this ?hostname - HAVING ( COUNT(?hostname) > 1 ) - } - }""" ; + { + ?this lapp:origin ?origin . + + BIND(STRAFTER(str(?origin), "//") AS ?afterScheme) + BIND(IF(CONTAINS(?afterScheme, "/"), + STRBEFORE(?afterScheme, "/"), + ?afterScheme) AS ?hostname) + + BIND( + IF(STRENDS(str(?origin), "/"), + "Origin URL must not end with a trailing slash", + IF(?hostname = "", + "Origin URL must have a non-empty hostname", + "")) AS ?message + ) + + FILTER(?message != "") + } +""" ; rdfs:isDefinedBy : . \ No newline at end of file diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl index 5f67d49a4..a411b137b 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl @@ -1,5 +1,6 @@ @@ -22,6 +23,7 @@ xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:json="http://www.w3.org/2005/xpath-functions" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:fn="http://www.w3.org/2005/xpath-functions" +xmlns:lapp="&lapp;" xmlns:ac="∾" xmlns:ldh="&ldh;" xmlns:rdf="&rdf;" @@ -53,7 +55,7 @@ exclude-result-prefixes="#all" - + @@ -61,7 +63,7 @@ exclude-result-prefixes="#all" - + diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl index ea021a509..4f63577a7 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl @@ -1,5 +1,6 @@ @@ -29,6 +30,7 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:json="http://www.w3.org/2005/xpath-functions" xmlns:array="http://www.w3.org/2005/xpath-functions/array" +xmlns:lapp="&lapp;" xmlns:ac="∾" xmlns:ldh="&ldh;" xmlns:rdf="&rdf;" @@ -344,7 +346,7 @@ LIMIT 10 - + @@ -414,7 +416,7 @@ LIMIT 10 - +
URL-based access @@ -714,7 +716,7 @@ LIMIT 10 - + diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl index 0f2909839..8b8f21876 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl @@ -100,7 +100,7 @@ exclude-result-prefixes="#all"> - + @@ -163,15 +163,13 @@ LIMIT 100 ; - ?base + { { ?app ?origin } UNION - { ?resource a ; - ?endpoint + { ?service ?endpoint } } } @@ -272,9 +270,9 @@ LIMIT 100 - <xsl:if test="$lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]"> + <xsl:if test="$lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]"> <xsl:value-of> - <xsl:apply-templates select="$lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]" mode="ac:label"/> + <xsl:apply-templates select="$lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]" mode="ac:label"/> </xsl:value-of> <xsl:text> - </xsl:text> </xsl:if> @@ -331,8 +329,8 @@ LIMIT 100 </xsl:for-each> </xsl:for-each> - <xsl:if test="$lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]"> - <meta property="og:site_name" content="{ac:label($lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin])}"/> + <xsl:if test="$lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]"> + <meta property="og:site_name" content="{ac:label($lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin])}"/> </xsl:if> </xsl:template> @@ -555,12 +553,12 @@ LIMIT 100 <xsl:template match="rdf:RDF | srx:sparql" mode="bs2:Brand"> <a class="brand" href="{$ldt:base}"> - <xsl:if test="$lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]/rdf:type/@rdf:resource = '&lapp;AdminApplication'"> + <xsl:if test="$lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/rdf:type/@rdf:resource = '&lapp;AdminApplication'"> <xsl:attribute name="class" select="'brand admin'"/> </xsl:if> <xsl:value-of> - <xsl:apply-templates select="$lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]" mode="ac:label"/> + <xsl:apply-templates select="$lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]" mode="ac:label"/> </xsl:value-of> </a> </xsl:template> @@ -719,14 +717,14 @@ LIMIT 100 </button> <ul class="dropdown-menu pull-right"> <xsl:variable name="apps" select="document($app-request-uri)" as="document-node()"/> - <xsl:for-each select="$apps//*[ldh:origin/@rdf:resource]"> + <xsl:for-each select="$apps//*[lapp:origin/@rdf:resource]"> <xsl:sort select="ac:label(.)" order="ascending" lang="{$ldt:lang}"/> <li> <!-- <xsl:if test="$active"> <xsl:attribute name="class" select="'active'"/> </xsl:if>--> - <a href="{ldh:origin/@rdf:resource}" title="{ldh:origin/@rdf:resource}"> + <a href="{lapp:origin/@rdf:resource}" title="{lapp:origin/@rdf:resource}"> <xsl:apply-templates select="." mode="ac:label"/> </a> </li> @@ -768,7 +766,7 @@ LIMIT 100 <xsl:param name="google-signup" select="exists($google:clientID)" as="xs:boolean"/> <xsl:param name="orcid-signup" select="exists($orcid:clientID)" as="xs:boolean"/> <xsl:param name="webid-signup" select="$ldhc:enableWebIDSignUp" as="xs:boolean"/> - <xsl:param name="webid-signup-uri" select="resolve-uri('sign%20up', $lapp:Application//*[rdf:type/@rdf:resource = '&lapp;AdminApplication']/ldh:origin/@rdf:resource)" as="xs:anyURI"/> + <xsl:param name="webid-signup-uri" select="resolve-uri('sign%20up', $lapp:Application//*[rdf:type/@rdf:resource = '&lapp;AdminApplication']/lapp:origin/@rdf:resource)" as="xs:anyURI"/> <!-- OAuth providers dropdown --> <xsl:if test="$google-signup or $orcid-signup"> @@ -807,7 +805,7 @@ LIMIT 100 <!-- WebID signup - separate button --> <xsl:if test="$webid-signup"> <div class="pull-right"> - <a class="btn btn-primary" href="{if (not(starts-with($ldt:base, $ldh:origin))) then ac:build-uri((), map{ 'uri': string($webid-signup-uri) }) else $webid-signup-uri}"> + <a class="btn btn-primary" href="{if (not(starts-with($ldt:base, $lapp:origin))) then ac:build-uri((), map{ 'uri': string($webid-signup-uri) }) else $webid-signup-uri}"> <xsl:value-of> <xsl:apply-templates select="key('resources', 'sign-up', document('translations.rdf'))" mode="ac:label"/> </xsl:value-of> @@ -818,7 +816,7 @@ LIMIT 100 <xsl:template match="*" mode="bs2:SignUp"/> - <xsl:template match="*[ldh:origin/@rdf:resource]" mode="bs2:AppListItem"> + <xsl:template match="*[lapp:origin/@rdf:resource]" mode="bs2:AppListItem"> <xsl:param name="active" as="xs:boolean?"/> <li> @@ -826,7 +824,7 @@ LIMIT 100 <xsl:attribute name="class" select="'active'"/> </xsl:if> - <a href="{ldh:origin/@rdf:resource}" title="{ldh:origin/@rdf:resource}"> + <a href="{lapp:origin/@rdf:resource}" title="{lapp:origin/@rdf:resource}"> <xsl:value-of> <xsl:apply-templates select="." mode="ac:label"/> </xsl:value-of> @@ -1249,10 +1247,10 @@ LIMIT 100 </button> <ul class="dropdown-menu"> - <xsl:if test="$foaf:Agent//@rdf:about and $lapp:Application//*[ldh:origin/@rdf:resource = $ldh:origin]/rdf:type/@rdf:resource = '&lapp;EndUserApplication'"> + <xsl:if test="$foaf:Agent//@rdf:about and $lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/rdf:type/@rdf:resource = '&lapp;EndUserApplication'"> <li> <xsl:for-each select="$lapp:Application"> - <a href="{key('resources', //*[ldh:origin/@rdf:resource = $ldh:origin]/lapp:adminApplication/(@rdf:resource, @rdf:nodeID))/ldh:origin/@rdf:resource}" target="_blank"> + <a href="{key('resources', //*[lapp:origin/@rdf:resource = $lapp:origin]/lapp:adminApplication/(@rdf:resource, @rdf:nodeID))/lapp:origin/@rdf:resource}" target="_blank"> <xsl:value-of> <xsl:apply-templates select="key('resources', 'administration', document('translations.rdf'))" mode="ac:label"/> </xsl:value-of> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl index e3f35cd31..ef4d1ff92 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl @@ -510,11 +510,11 @@ WHERE <xsl:result-document href="#breadcrumb-nav" method="ixsl:replace-content"> <!-- show label if the resource is external --> <xsl:if test="not(starts-with($uri, $ldt:base))"> - <xsl:variable name="app" select="ixsl:get(ixsl:window(), 'LinkedDataHub.apps')//rdf:Description[ldh:origin/@rdf:resource = ldh:origin(ldt:base())]" as="element()?"/> + <xsl:variable name="app" select="ixsl:get(ixsl:window(), 'LinkedDataHub.apps')//rdf:Description[lapp:origin/@rdf:resource = lapp:origin(ldt:base())]" as="element()?"/> <xsl:choose> <!-- if a known app matches $uri, show link to its ldt:base --> <xsl:when test="$app"> - <a href="{$app/ldh:origin/@rdf:resource}" class="label label-info pull-left"> + <a href="{$app/lapp:origin/@rdf:resource}" class="label label-info pull-left"> <xsl:apply-templates select="$app" mode="ac:label"/> </a> </xsl:when> @@ -750,7 +750,7 @@ WHERE <xsl:when test="starts-with(?media-type, 'application/xhtml+xml')"> <xsl:variable name="endpoint-link" select="tokenize(?headers?link, ',')[contains(., '&sd;endpoint')]" as="xs:string?"/> <xsl:variable name="endpoint" select="if ($endpoint-link) then xs:anyURI(substring-before(substring-after(substring-before($endpoint-link, ';'), '<'), '>')) else ()" as="xs:anyURI?"/> - <xsl:variable name="base" select="ldh:origin($href)" as="xs:anyURI"/> + <xsl:variable name="base" select="lapp:origin($href)" as="xs:anyURI"/> <!-- set new base URI if the current app has changed --> <xsl:if test="not($base = ldt:base())"> <xsl:message>Application change. Base URI: <xsl:value-of select="$base"/></xsl:message> From b385d45b3fc6307783003c76bef82aac72ee366d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 22 Dec 2025 14:53:32 +0200 Subject: [PATCH 06/64] Replaced document-level layout mode tabs with a mode dropdown --- .../com/atomgraph/linkeddatahub/ldh.ttl | 4 ++ .../atomgraph/linkeddatahub/css/bootstrap.css | 4 ++ .../xsl/bootstrap/2.3.2/admin/signup.xsl | 4 +- .../xsl/bootstrap/2.3.2/client/form.xsl | 2 +- .../xsl/bootstrap/2.3.2/client/functions.xsl | 8 ++- .../xsl/bootstrap/2.3.2/document.xsl | 67 ++++++++++++++----- .../xsl/bootstrap/2.3.2/layout.xsl | 29 ++++---- .../xsl/bootstrap/2.3.2/resource.xsl | 27 ++++++-- .../atomgraph/linkeddatahub/xsl/client.xsl | 2 +- 9 files changed, 100 insertions(+), 47 deletions(-) diff --git a/src/main/resources/com/atomgraph/linkeddatahub/ldh.ttl b/src/main/resources/com/atomgraph/linkeddatahub/ldh.ttl index 60227e530..00fd5770b 100644 --- a/src/main/resources/com/atomgraph/linkeddatahub/ldh.ttl +++ b/src/main/resources/com/atomgraph/linkeddatahub/ldh.ttl @@ -522,6 +522,10 @@ ac:Timeline a rdfs:Class, owl:Class ; # individuals +:ContentMode a ac:Mode ; + rdfs:label "Content" ; + rdfs:isDefinedBy : . + ac:ChartMode a ac:Mode, ac:ContainerMode ; rdfs:label "Chart" ; rdfs:isDefinedBy ac: . diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css index 24ee6b806..9977dcbbe 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css @@ -64,9 +64,13 @@ li button.btn-edit-constructors, li button.btn-add-data, li button.btn-add-ontol .btn.dropdown-toggle.btn-map { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_map_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } .btn.dropdown-toggle.btn-graph { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_blur_on_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } .btn.dropdown-toggle.btn-query { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_code_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.btn.dropdown-toggle.btn-content { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/view_list_black_24dp.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.btn.dropdown-toggle.btn-chart { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_show_chart_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.dropdown-menu > li > a.btn-content { background-image: url('../icons/view_list_black_24dp.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-read { background-image: url('../icons/ic_details_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-edit { background-image: url('../icons/ic_create_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-map { background-image: url('../icons/ic_map_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } +.dropdown-menu > li > a.btn-chart { background-image: url('../icons/ic_show_chart_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-graph { background-image: url('../icons/ic_blur_on_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-query { background-image: url('../icons/ic_code_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } #doc-tree { display: none; width: 15%; position: fixed; left: 0; top: 106px; height: calc(100% - 106px); } diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/signup.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/signup.xsl index 6e56358fb..196a41081 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/signup.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/signup.xsl @@ -59,8 +59,8 @@ exclude-result-prefixes="#all"> <!-- hide "Add data" button which otherwise would be shown because acl:Append is allowed for signup --> <xsl:template match="rdf:RDF[ac:absolute-path(ldh:request-uri()) = resolve-uri(encode-for-uri('sign up'), $ldt:base)]" mode="bs2:AddData" priority="2" use-when="system-property('xsl:product-name') = 'SAXON'"/> - - <xsl:template match="rdf:RDF[ac:absolute-path(ldh:request-uri()) = resolve-uri(encode-for-uri('sign up'), $ldt:base)]" mode="bs2:ModeTabs" priority="2" use-when="system-property('xsl:product-name') = 'SAXON'"/> + + <xsl:template match="rdf:RDF[ac:absolute-path(ldh:request-uri()) = resolve-uri(encode-for-uri('sign up'), $ldt:base)]" mode="bs2:ModeList" priority="2" use-when="system-property('xsl:product-name') = 'SAXON'"/> <!-- disable the right nav (backlinks etc.) --> <xsl:template match="*[*][@rdf:about or @rdf:nodeID][ac:absolute-path(ldh:request-uri()) = resolve-uri(encode-for-uri('sign up'), $ldt:base)]" mode="bs2:Right" use-when="system-property('xsl:product-name') = 'SAXON'"/> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl index b04c4fa8f..9e71186f8 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl @@ -298,7 +298,7 @@ WHERE <!-- open a form for document editing --> - <xsl:template match="div[contains-token(@class, 'navbar')]//div[@id = 'doc-controls']//button[contains-token(@class, 'btn-edit')]" mode="ixsl:onclick"> + <xsl:template match="div[contains-token(@class, 'action-bar')]//button[contains-token(@class, 'btn-edit')]" mode="ixsl:onclick"> <xsl:param name="about" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> <!-- editing the current document resources --> <xsl:param name="method" select="'patch'" as="xs:string"/> <xsl:param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl index a411b137b..5731d47c9 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/functions.xsl @@ -76,7 +76,9 @@ exclude-result-prefixes="#all" </xsl:function> <xsl:function name="ac:mode" as="xs:anyURI*"> - <xsl:variable name="nav-tab-class" select="id('layout-modes', ixsl:page())/li[contains-token(@class, 'active')]/@class" as="xs:string"/> + <xsl:variable name="mode-button" select="id('layout-modes', ixsl:page())" as="element()?"/> + <xsl:variable name="dropdown-menu" select="$mode-button/following-sibling::ul[contains-token(@class, 'dropdown-menu')]" as="element()?"/> + <xsl:variable name="active-item-class" select="$dropdown-menu/li[contains-token(@class, 'active')]/@class" as="xs:string?"/> <xsl:variable name="mode-classes" as="map(xs:string, xs:string)"> <xsl:map> <xsl:map-entry key="'content-mode'" select="'&ldh;ContentMode'"/> @@ -86,8 +88,8 @@ exclude-result-prefixes="#all" <xsl:map-entry key="'graph-mode'" select="'∾GraphMode'"/> </xsl:map> </xsl:variable> - <xsl:variable name="mode-class" select="map:keys($mode-classes)[contains-token($nav-tab-class, .)]" as="xs:string"/> - <xsl:sequence select="xs:anyURI(map:get($mode-classes, $mode-class))"/> + <xsl:variable name="mode-class" select="map:keys($mode-classes)[contains-token($active-item-class, .)]" as="xs:string?"/> + <xsl:sequence select="if ($mode-class) then xs:anyURI(map:get($mode-classes, $mode-class)) else ()"/> </xsl:function> <xsl:function name="sd:endpoint" as="xs:anyURI"> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl index 6dd88aa65..0c4a1a9d9 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl @@ -132,29 +132,62 @@ extension-element-prefixes="ixsl" </div> </xsl:template> - <!-- MODE TABS --> - - <xsl:template match="rdf:RDF" mode="bs2:ModeTabs" use-when="system-property('xsl:product-name') = 'SAXON'"> + <!-- MODE LIST --> + + <xsl:template match="rdf:RDF" mode="bs2:ModeList" priority="2" use-when="system-property('xsl:product-name') = 'SAXON'"> <xsl:param name="has-content" as="xs:boolean"/> <xsl:param name="active-mode" as="xs:anyURI?"/> <xsl:param name="ajax-rendering" select="true()" as="xs:boolean"/> - <xsl:param name="absolute-path" select="ac:absolute-path(ldh:request-uri())" as="xs:anyURI"/> <!-- make sure mode tabs always link to the local document (not the proxy-loaded doc) --> + <xsl:param name="absolute-path" select="ac:absolute-path(ldh:request-uri())" as="xs:anyURI"/> <xsl:param name="base-uri" select="ldh:base-uri(.)" as="xs:anyURI"/> <xsl:param name="id" select="'layout-modes'" as="xs:string?"/> - <xsl:param name="class" select="'nav nav-tabs offset2 span7'" as="xs:string?"/> - <div class="row-fluid"> - <ul> + <div class="btn-group pull-right"> + <button type="button" title="{ac:label(key('resources', '∾Mode', document(ac:document-uri('∾'))))}"> <xsl:if test="$id"> <xsl:attribute name="id" select="$id"/> </xsl:if> - <xsl:if test="$class"> - <xsl:attribute name="class" select="$class"/> - </xsl:if> - + + <xsl:choose> + <xsl:when test="$active-mode = '&ldh;ContentMode'"> + <xsl:apply-templates select="key('resources', '&ldh;ContentMode', document(ac:document-uri('&ldh;')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$active-mode = '∾ReadMode'"> + <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$active-mode = '∾MapMode'"> + <xsl:apply-templates select="key('resources', '∾MapMode', document(ac:document-uri('∾')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$active-mode = '∾ChartMode'"> + <xsl:apply-templates select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$active-mode = '∾GraphMode'"> + <xsl:apply-templates select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + <xsl:text> </xsl:text> + <span class="caret"></span> + </button> + + <ul class="dropdown-menu"> <li class="content-mode{if ((empty($active-mode) and $has-content) or $active-mode = '&ldh;ContentMode') then ' active' else() }"> - <!-- make sure mode tabs always link to the local document (not the proxy-loaded doc) --> <a href="{ldh:href(ac:document-uri(ldh:base-uri(.)), ldh:query-params(xs:anyURI('&ldh;ContentMode')))}"> + <xsl:apply-templates select="key('resources', '&ldh;ContentMode', document(ac:document-uri('&ldh;')))" mode="ldh:logo"/> <xsl:value-of> <xsl:apply-templates select="key('resources', 'content', document('translations.rdf'))" mode="ac:label"/> </xsl:value-of> @@ -162,14 +195,14 @@ extension-element-prefixes="ixsl" </li> <xsl:for-each select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeTabsItem"> + <xsl:apply-templates select="." mode="bs2:ModeListItem"> <xsl:with-param name="active" select="@rdf:about = $active-mode or (empty($active-mode) and not($has-content))"/> <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> <xsl:with-param name="base-uri" select="$base-uri"/> </xsl:apply-templates> </xsl:for-each> <xsl:for-each select="key('resources', '∾MapMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeTabsItem"> + <xsl:apply-templates select="." mode="bs2:ModeListItem"> <xsl:with-param name="active" select="@rdf:about = $active-mode"/> <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> <xsl:with-param name="base-uri" select="$base-uri"/> @@ -177,7 +210,7 @@ extension-element-prefixes="ixsl" </xsl:for-each> <xsl:if test="$ajax-rendering"> <xsl:for-each select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeTabsItem"> + <xsl:apply-templates select="." mode="bs2:ModeListItem"> <xsl:with-param name="active" select="@rdf:about = $active-mode"/> <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> <xsl:with-param name="base-uri" select="$base-uri"/> @@ -185,7 +218,7 @@ extension-element-prefixes="ixsl" </xsl:for-each> </xsl:if> <xsl:for-each select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeTabsItem"> + <xsl:apply-templates select="." mode="bs2:ModeListItem"> <xsl:with-param name="active" select="@rdf:about = $active-mode"/> <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> <xsl:with-param name="base-uri" select="$base-uri"/> @@ -194,7 +227,7 @@ extension-element-prefixes="ixsl" </ul> </div> </xsl:template> - + <!-- CONTENT LIST --> <xsl:template match="rdf:RDF" mode="ldh:ContentList"> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl index 8b8f21876..14cdf1a60 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl @@ -647,12 +647,6 @@ LIMIT 100 <div id="doc-controls" class="span4"> <xsl:apply-templates select="key('resources', ac:absolute-path(ldh:base-uri(.)))" mode="bs2:Timestamp"/> - - <xsl:if test="$acl:mode = '&acl;Write'"> - <button type="button" class="btn btn-edit pull-right"> - <xsl:apply-templates select="key('resources', '∾EditMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </button> - </xsl:if> </div> </div> </div> @@ -669,12 +663,18 @@ LIMIT 100 <xsl:if test="$class"> <xsl:attribute name="class" select="$class"/> </xsl:if> - + <xsl:apply-templates select="." mode="bs2:MediaTypeList"> <xsl:with-param name="uri" select="ac:absolute-path(ldh:base-uri(.))"/> </xsl:apply-templates> <xsl:apply-templates select="." mode="bs2:NavBarActions"/> + + <xsl:apply-templates select="." mode="bs2:ModeList"> + <xsl:with-param name="has-content" select="$has-content"/> + <xsl:with-param name="active-mode" select="$ac:mode"/> + <xsl:with-param name="ajax-rendering" select="$ldh:ajaxRendering"/> + </xsl:apply-templates> </div> </xsl:template> @@ -867,12 +867,6 @@ LIMIT 100 <xsl:if test="exists($typeof)"> <xsl:attribute name="typeof" select="string-join($typeof, ' ')"/> </xsl:if> - - <xsl:apply-templates select="." mode="bs2:ModeTabs"> - <xsl:with-param name="has-content" select="$has-content"/> - <xsl:with-param name="active-mode" select="$ac:mode"/> - <xsl:with-param name="ajax-rendering" select="$ldh:ajaxRendering"/> - </xsl:apply-templates> <xsl:choose> <!-- error responses always rendered in bs2:Row mode, no matter what $ac:mode specifies --> @@ -917,9 +911,6 @@ LIMIT 100 </xsl:choose> </div> </xsl:template> - - <!-- don't show document-level tabs if the response returned an error or if we're in EditMode --> - <xsl:template match="rdf:RDF[key('resources-by-type', '&http;Response')]" mode="bs2:ModeTabs" priority="1"/> <xsl:template match="srx:sparql" mode="bs2:ContentBody"> <xsl:param name="id" select="'content-body'" as="xs:string?"/> @@ -1211,6 +1202,12 @@ LIMIT 100 <xsl:apply-templates select="key('resources', '&acl;Access', document(ac:document-uri('&acl;')))" mode="ac:label"/> </button> </div> + + <xsl:if test="$acl:mode = '&acl;Write'"> + <button type="button" class="btn btn-edit pull-right"> + <xsl:apply-templates select="key('resources', '∾EditMode', document(ac:document-uri('∾')))" mode="ac:label"/> + </button> + </xsl:if> </xsl:if> </xsl:template> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl index a4780e334..354241ca9 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl @@ -261,21 +261,33 @@ extension-element-prefixes="ixsl" <xsl:attribute name="class" select="concat($class, ' ', 'btn-agent')"/> </xsl:template> + <xsl:template match="*[@rdf:about = '&ldh;ContentMode']" mode="ldh:logo"> + <xsl:param name="class" as="xs:string?"/> + + <xsl:attribute name="class" select="concat($class, ' ', 'btn-content')"/> + </xsl:template> + <xsl:template match="*[@rdf:about = '∾ReadMode']" mode="ldh:logo"> <xsl:param name="class" as="xs:string?"/> - + <xsl:attribute name="class" select="concat($class, ' ', 'btn-read')"/> </xsl:template> <xsl:template match="*[@rdf:about = '∾MapMode']" mode="ldh:logo"> <xsl:param name="class" as="xs:string?"/> - + <xsl:attribute name="class" select="concat($class, ' ', 'btn-map')"/> </xsl:template> + <xsl:template match="*[@rdf:about = '∾ChartMode']" mode="ldh:logo"> + <xsl:param name="class" as="xs:string?"/> + + <xsl:attribute name="class" select="concat($class, ' ', 'btn-chart')"/> + </xsl:template> + <xsl:template match="*[@rdf:about = '∾GraphMode']" mode="ldh:logo"> <xsl:param name="class" as="xs:string?"/> - + <xsl:attribute name="class" select="concat($class, ' ', 'btn-graph')"/> </xsl:template> @@ -397,9 +409,9 @@ extension-element-prefixes="ixsl" </div> </xsl:template> - <!-- MODE TABS --> - - <xsl:template match="*[@rdf:about]" mode="bs2:ModeTabsItem"> + <!-- MODE LIST --> + + <xsl:template match="*[@rdf:about]" mode="bs2:ModeListItem"> <xsl:param name="absolute-path" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI" tunnel="yes"/> <xsl:param name="base-uri" as="xs:anyURI?"/> <xsl:param name="active" as="xs:boolean"/> @@ -420,13 +432,14 @@ extension-element-prefixes="ixsl" </xsl:if> <a href="{ldh:href(ac:document-uri($base-uri), ldh:query-params(xs:anyURI(@rdf:about)))}"> + <xsl:apply-templates select="." mode="ldh:logo"/> <xsl:value-of> <xsl:apply-templates select="." mode="ac:label"/> </xsl:value-of> </a> </li> </xsl:template> - + <!-- DEFAULT --> <!-- embed file content --> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl index ef4d1ff92..44f3a7599 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl @@ -835,7 +835,7 @@ WHERE <xsl:if test="$push-state"> <xsl:call-template name="ldh:PushState"> - <xsl:with-param name="href" select="ldh:href($href, map{})"/> + <xsl:with-param name="href" select="ldh:href($href, ldh:query-params(ac:mode()))"/> <xsl:with-param name="title" select="/html/head/title"/> <xsl:with-param name="container" select="$container"/> </xsl:call-template> From 816bfd7dcb7f6cd998935bed7ecc8c79b0f05ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 23 Dec 2025 18:10:01 +0100 Subject: [PATCH 07/64] View mode tabs replaced with a dropdown Improved mode rendering templates --- .../atomgraph/linkeddatahub/css/bootstrap.css | 6 + .../xsl/bootstrap/2.3.2/client/block/view.xsl | 131 +++++++----------- .../xsl/bootstrap/2.3.2/document.xsl | 64 ++------- .../xsl/bootstrap/2.3.2/resource.xsl | 49 +++---- 4 files changed, 83 insertions(+), 167 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css index 9977dcbbe..4a8f2e490 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css @@ -66,6 +66,9 @@ li button.btn-edit-constructors, li button.btn-add-data, li button.btn-add-ontol .btn.dropdown-toggle.btn-query { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_code_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } .btn.dropdown-toggle.btn-content { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/view_list_black_24dp.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } .btn.dropdown-toggle.btn-chart { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_show_chart_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.btn.dropdown-toggle.btn-list { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/view_list_black_24dp.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.btn.dropdown-toggle.btn-table { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_border_all_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } +.btn.dropdown-toggle.btn-grid { text-align: right; font-size: 0; color: transparent; background-image: url('../icons/ic_grid_on_black_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 64px; } .dropdown-menu > li > a.btn-content { background-image: url('../icons/view_list_black_24dp.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-read { background-image: url('../icons/ic_details_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-edit { background-image: url('../icons/ic_create_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } @@ -73,6 +76,9 @@ li button.btn-edit-constructors, li button.btn-add-data, li button.btn-add-ontol .dropdown-menu > li > a.btn-chart { background-image: url('../icons/ic_show_chart_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-graph { background-image: url('../icons/ic_blur_on_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } .dropdown-menu > li > a.btn-query { background-image: url('../icons/ic_code_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } +.dropdown-menu > li > a.btn-list { background-image: url('../icons/view_list_black_24dp.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } +.dropdown-menu > li > a.btn-table { background-image: url('../icons/ic_border_all_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } +.dropdown-menu > li > a.btn-grid { background-image: url('../icons/ic_grid_on_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding: 5px 5px 5px 40px; } #doc-tree { display: none; width: 15%; position: fixed; left: 0; top: 106px; height: calc(100% - 106px); } @media (max-width: 979px) { diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl index 8db2c10f2..129bae35c 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl @@ -441,83 +441,46 @@ exclude-result-prefixes="#all" </xsl:if> </xsl:template> - <!-- view mode tabs --> - - <xsl:template name="bs2:ViewModeTabs"> - <xsl:param name="active-mode" as="xs:anyURI"/> - - <ul class="nav nav-tabs view-mode-nav-tabs"> - <li class="read-mode"> - <xsl:if test="$active-mode = '∾ReadMode'"> - <xsl:attribute name="class" select="'read-mode active'"/> - </xsl:if> + <!-- view mode dropdown --> - <a> - <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="list-mode"> - <xsl:if test="$active-mode = '∾ListMode'"> - <xsl:attribute name="class" select="'list-mode active'"/> - </xsl:if> - - <a> - <xsl:apply-templates select="key('resources', '∾ListMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾ListMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="table-mode"> - <xsl:if test="$active-mode = '∾TableMode'"> - <xsl:attribute name="class" select="'table-mode active'"/> - </xsl:if> + <xsl:template name="bs2:ViewModeList"> + <xsl:param name="active-mode" as="xs:anyURI"/> + <xsl:param name="id" select="'view-modes'" as="xs:string?"/> + <xsl:param name="mode-button-classes" as="map(xs:string, xs:string)"> + <xsl:map> + <xsl:map-entry key="'∾ReadMode'" select="'btn-read'"/> + <xsl:map-entry key="'∾ListMode'" select="'btn-list'"/> + <xsl:map-entry key="'∾TableMode'" select="'btn-table'"/> + <xsl:map-entry key="'∾GridMode'" select="'btn-grid'"/> + <xsl:map-entry key="'∾ChartMode'" select="'btn-chart'"/> + <xsl:map-entry key="'∾MapMode'" select="'btn-map'"/> + <xsl:map-entry key="'∾GraphMode'" select="'btn-graph'"/> + </xsl:map> + </xsl:param> - <a> - <xsl:apply-templates select="key('resources', '∾TableMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾TableMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="grid-mode"> - <xsl:if test="$active-mode = '∾GridMode'"> - <xsl:attribute name="class" select="'grid-mode active'"/> + <div class="btn-group pull-right"> + <button type="button" title="{ac:label(key('resources', '∾Mode', document(ac:document-uri('∾'))))}"> + <xsl:if test="$id"> + <xsl:attribute name="id" select="$id"/> </xsl:if> - <a> - <xsl:apply-templates select="key('resources', '∾GridMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾GridMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="chart-mode"> - <xsl:if test="$active-mode = '∾ChartMode'"> - <xsl:attribute name="class" select="'chart-mode active'"/> - </xsl:if> + <xsl:attribute name="class" select="'btn dropdown-toggle ' || (map:get($mode-button-classes, string($active-mode)), 'btn-read')[1]"/> - <a> - <xsl:apply-templates select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="map-mode"> - <xsl:if test="$active-mode = '∾MapMode'"> - <xsl:attribute name="class" select="'map-mode active'"/> - </xsl:if> + <xsl:text> </xsl:text> + <span class="caret"></span> + </button> - <a> - <xsl:apply-templates select="key('resources', '∾MapMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾MapMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - <li class="graph-mode"> - <xsl:if test="$active-mode = '∾GraphMode'"> - <xsl:attribute name="class" select="'graph-mode active'"/> - </xsl:if> - - <a> - <xsl:apply-templates select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))" mode="ldh:logo"/> - <xsl:apply-templates select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))" mode="ac:label"/> - </a> - </li> - </ul> + <ul class="dropdown-menu view-mode-list"> + <xsl:for-each select="('∾ReadMode', '∾ListMode', '∾TableMode', '∾GridMode', '∾ChartMode', '∾MapMode', '∾GraphMode')"> + <xsl:for-each select="key('resources', ., document(ac:document-uri('∾')))"> + <xsl:apply-templates select="." mode="bs2:ModeListItem"> + <xsl:with-param name="active" select="@rdf:about = $active-mode"/> + <xsl:with-param name="href" select="()"/> + </xsl:apply-templates> + </xsl:for-each> + </xsl:for-each> + </ul> + </div> </xsl:template> <!-- render view --> @@ -748,6 +711,10 @@ exclude-result-prefixes="#all" <xsl:value-of select="$container/descendant::*[@property = '&dct;title']"/> </h2> + <xsl:call-template name="bs2:ViewModeList"> + <xsl:with-param name="active-mode" select="$active-mode"/> + </xsl:call-template> + <div class="pull-right"> <form class="form-inline"> <label for="{$order-by-container-id}"> @@ -790,10 +757,6 @@ exclude-result-prefixes="#all" <div> <p id="{$result-count-container-id}" class="result-count"/> - <xsl:call-template name="bs2:ViewModeTabs"> - <xsl:with-param name="active-mode" select="$active-mode"/> - </xsl:call-template> - <div id="{$container-results-id}" class="container-results"></div> </div> </xsl:result-document> @@ -1146,9 +1109,9 @@ exclude-result-prefixes="#all" <!-- EVENT LISTENERS --> - <!-- view mode tabs --> - - <xsl:template match="*[@typeof]//div/ul[contains-token(@class, 'view-mode-nav-tabs')]/li[not(contains-token(@class, 'active'))]/a" mode="ixsl:onclick"> + <!-- view mode dropdown --> + + <xsl:template match="*[@typeof]//ul[contains-token(@class, 'view-mode-list')]/li[not(contains-token(@class, 'active'))]/a" mode="ixsl:onclick"> <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> @@ -1203,7 +1166,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="select-string" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-query')" as="xs:string"/> <xsl:variable name="select-xml" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-xml')" as="document-node()"/> @@ -1253,7 +1216,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="select-string" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-query')" as="xs:string"/> <xsl:variable name="select-xml" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-xml')" as="document-node()"/> @@ -1302,7 +1265,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="predicate" select="ixsl:get(., 'value')" as="xs:anyURI?"/> <xsl:variable name="select-string" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-query')" as="xs:string"/> @@ -1352,7 +1315,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="desc" select="contains(@class, 'btn-order-by-desc')" as="xs:boolean"/> <xsl:variable name="select-string" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-query')" as="xs:string"/> @@ -1498,7 +1461,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="var-name" select="@name" as="xs:string"/> <!-- collect the values/types/datatypes of all checked inputs within this facet and build an array of maps --> @@ -1549,7 +1512,7 @@ exclude-result-prefixes="#all" <xsl:variable name="block" select="ancestor::div[contains-token(@class, 'block')][1]" as="element()"/> <xsl:variable name="container" select="ancestor::div[@typeof][1]" as="element()"/> <xsl:variable name="block-uri" select="xs:anyURI($block/@about)" as="xs:anyURI"/> - <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-nav-tabs')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> + <xsl:variable name="active-class" select="tokenize($container//ul[contains-token(@class, 'view-mode-list')]/li[contains-token(@class, 'active')]/@class, ' ')[not(. = 'active')]" as="xs:string"/> <xsl:variable name="active-mode" select="map:get($class-modes, $active-class)" as="xs:anyURI"/> <xsl:variable name="predicate" select="input/@value" as="xs:anyURI"/> <xsl:variable name="select-string" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $block-uri || '`'), 'select-query')" as="xs:string"/> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl index 0c4a1a9d9..ebd5c61ec 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/document.xsl @@ -148,38 +148,10 @@ extension-element-prefixes="ixsl" <xsl:attribute name="id" select="$id"/> </xsl:if> - <xsl:choose> - <xsl:when test="$active-mode = '&ldh;ContentMode'"> - <xsl:apply-templates select="key('resources', '&ldh;ContentMode', document(ac:document-uri('&ldh;')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:when> - <xsl:when test="$active-mode = '∾ReadMode'"> - <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:when> - <xsl:when test="$active-mode = '∾MapMode'"> - <xsl:apply-templates select="key('resources', '∾MapMode', document(ac:document-uri('∾')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:when> - <xsl:when test="$active-mode = '∾ChartMode'"> - <xsl:apply-templates select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:when> - <xsl:when test="$active-mode = '∾GraphMode'"> - <xsl:apply-templates select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))" mode="ldh:logo"> - <xsl:with-param name="class" select="'btn dropdown-toggle'"/> - </xsl:apply-templates> - </xsl:otherwise> - </xsl:choose> + <xsl:variable name="effective-mode" select="if ($active-mode) then $active-mode else '∾ReadMode'" as="xs:anyURI"/> + <xsl:apply-templates select="key('resources', $effective-mode, document(ac:document-uri(string($effective-mode))))" mode="ldh:logo"> + <xsl:with-param name="class" select="'btn dropdown-toggle'"/> + </xsl:apply-templates> <xsl:text> </xsl:text> <span class="caret"></span> </button> @@ -194,35 +166,15 @@ extension-element-prefixes="ixsl" </a> </li> - <xsl:for-each select="key('resources', '∾ReadMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeListItem"> - <xsl:with-param name="active" select="@rdf:about = $active-mode or (empty($active-mode) and not($has-content))"/> - <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> - <xsl:with-param name="base-uri" select="$base-uri"/> - </xsl:apply-templates> - </xsl:for-each> - <xsl:for-each select="key('resources', '∾MapMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeListItem"> - <xsl:with-param name="active" select="@rdf:about = $active-mode"/> - <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> - <xsl:with-param name="base-uri" select="$base-uri"/> - </xsl:apply-templates> - </xsl:for-each> - <xsl:if test="$ajax-rendering"> - <xsl:for-each select="key('resources', '∾ChartMode', document(ac:document-uri('∾')))"> + <xsl:for-each select="('∾ReadMode', '∾MapMode', if ($ajax-rendering) then '∾ChartMode' else (), '∾GraphMode')"> + <xsl:variable name="mode-uri" select="." as="xs:string"/> + <xsl:for-each select="key('resources', $mode-uri, document(ac:document-uri('∾')))"> <xsl:apply-templates select="." mode="bs2:ModeListItem"> - <xsl:with-param name="active" select="@rdf:about = $active-mode"/> + <xsl:with-param name="active" select="if (@rdf:about = '∾ReadMode') then (@rdf:about = $active-mode or (empty($active-mode) and not($has-content))) else @rdf:about = $active-mode"/> <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> <xsl:with-param name="base-uri" select="$base-uri"/> </xsl:apply-templates> </xsl:for-each> - </xsl:if> - <xsl:for-each select="key('resources', '∾GraphMode', document(ac:document-uri('∾')))"> - <xsl:apply-templates select="." mode="bs2:ModeListItem"> - <xsl:with-param name="active" select="@rdf:about = $active-mode"/> - <xsl:with-param name="absolute-path" select="$absolute-path" tunnel="yes"/> - <xsl:with-param name="base-uri" select="$base-uri"/> - </xsl:apply-templates> </xsl:for-each> </ul> </div> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl index 354241ca9..dfa0b2d41 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/resource.xsl @@ -261,34 +261,22 @@ extension-element-prefixes="ixsl" <xsl:attribute name="class" select="concat($class, ' ', 'btn-agent')"/> </xsl:template> - <xsl:template match="*[@rdf:about = '&ldh;ContentMode']" mode="ldh:logo"> - <xsl:param name="class" as="xs:string?"/> - - <xsl:attribute name="class" select="concat($class, ' ', 'btn-content')"/> - </xsl:template> - - <xsl:template match="*[@rdf:about = '∾ReadMode']" mode="ldh:logo"> - <xsl:param name="class" as="xs:string?"/> - - <xsl:attribute name="class" select="concat($class, ' ', 'btn-read')"/> - </xsl:template> - - <xsl:template match="*[@rdf:about = '∾MapMode']" mode="ldh:logo"> - <xsl:param name="class" as="xs:string?"/> - - <xsl:attribute name="class" select="concat($class, ' ', 'btn-map')"/> - </xsl:template> - - <xsl:template match="*[@rdf:about = '∾ChartMode']" mode="ldh:logo"> - <xsl:param name="class" as="xs:string?"/> - - <xsl:attribute name="class" select="concat($class, ' ', 'btn-chart')"/> - </xsl:template> - - <xsl:template match="*[@rdf:about = '∾GraphMode']" mode="ldh:logo"> + <xsl:template match="*[@rdf:about = ('&ldh;ContentMode', '∾ReadMode', '∾ListMode', '∾TableMode', '∾GridMode', '∾MapMode', '∾ChartMode', '∾GraphMode')]" mode="ldh:logo"> <xsl:param name="class" as="xs:string?"/> + <xsl:param name="mode-logo-classes" as="map(xs:string, xs:string)"> + <xsl:map> + <xsl:map-entry key="'&ldh;ContentMode'" select="'btn-content'"/> + <xsl:map-entry key="'∾ReadMode'" select="'btn-read'"/> + <xsl:map-entry key="'∾ListMode'" select="'btn-list'"/> + <xsl:map-entry key="'∾TableMode'" select="'btn-table'"/> + <xsl:map-entry key="'∾GridMode'" select="'btn-grid'"/> + <xsl:map-entry key="'∾MapMode'" select="'btn-map'"/> + <xsl:map-entry key="'∾ChartMode'" select="'btn-chart'"/> + <xsl:map-entry key="'∾GraphMode'" select="'btn-graph'"/> + </xsl:map> + </xsl:param> - <xsl:attribute name="class" select="concat($class, ' ', 'btn-graph')"/> + <xsl:attribute name="class" select="concat($class, ' ', map:get($mode-logo-classes, @rdf:about))"/> </xsl:template> <xsl:template match="*[@rdf:about = '∾QueryEditorMode']" mode="ldh:logo"> @@ -415,10 +403,14 @@ extension-element-prefixes="ixsl" <xsl:param name="absolute-path" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI" tunnel="yes"/> <xsl:param name="base-uri" as="xs:anyURI?"/> <xsl:param name="active" as="xs:boolean"/> + <xsl:param name="href" select="ldh:href(ac:document-uri($base-uri), ldh:query-params(xs:anyURI(@rdf:about)))" as="xs:anyURI?"/> <xsl:param name="mode-classes" as="map(xs:string, xs:string)"> <xsl:map> <xsl:map-entry key="'&ldh;ContentMode'" select="'content-mode'"/> <xsl:map-entry key="'∾ReadMode'" select="'read-mode'"/> + <xsl:map-entry key="'∾ListMode'" select="'list-mode'"/> + <xsl:map-entry key="'∾TableMode'" select="'table-mode'"/> + <xsl:map-entry key="'∾GridMode'" select="'grid-mode'"/> <xsl:map-entry key="'∾MapMode'" select="'map-mode'"/> <xsl:map-entry key="'∾ChartMode'" select="'chart-mode'"/> <xsl:map-entry key="'∾GraphMode'" select="'graph-mode'"/> @@ -431,7 +423,10 @@ extension-element-prefixes="ixsl" <xsl:attribute name="class" select="$class"/> </xsl:if> - <a href="{ldh:href(ac:document-uri($base-uri), ldh:query-params(xs:anyURI(@rdf:about)))}"> + <a> + <xsl:if test="$href"> + <xsl:attribute name="href" select="$href"/> + </xsl:if> <xsl:apply-templates select="." mode="ldh:logo"/> <xsl:value-of> <xsl:apply-templates select="." mode="ac:label"/> From 70a0b1232e839ae6ca35520b3fe1edc0a449a7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Wed, 24 Dec 2025 10:47:47 +0100 Subject: [PATCH 08/64] Optional view heading --- .../xsl/bootstrap/2.3.2/client/block/view.xsl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl index 129bae35c..3ebcc4766 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl @@ -707,9 +707,11 @@ exclude-result-prefixes="#all" <!-- first time rendering the view results --> <xsl:if test="$initial-load"> <xsl:result-document href="?." method="ixsl:replace-content"> - <h2> - <xsl:value-of select="$container/descendant::*[@property = '&dct;title']"/> - </h2> + <xsl:where-populated> + <h2> + <xsl:value-of select="$container/descendant::*[@property = '&dct;title']"/> + </h2> + </xsl:where-populated> <xsl:call-template name="bs2:ViewModeList"> <xsl:with-param name="active-mode" select="$active-mode"/> From 0a7398fbccf339dd3efe619bd0728ed58fad5bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Thu, 1 Jan 2026 20:23:15 +0100 Subject: [PATCH 09/64] Fixed connection leaks --- .../atomgraph/linkeddatahub/resource/admin/Clear.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java index 01a8b19c9..67c25cd0f 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java @@ -91,12 +91,18 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer { URI ontologyDocURI = UriBuilder.fromUri(ontologyURI).fragment(null).build(); // skip fragment from the ontology URI to get its graph URI if (log.isDebugEnabled()) log.debug("Purge ontology document with URI '{}' from frontend proxy cache", ontologyDocURI); - purge(getApplication().getFrontendProxy(), ontologyDocURI.toString()); + try (Response response = purge(getApplication().getFrontendProxy(), ontologyDocURI.toString())) + { + // Response automatically closed by try-with-resources + } } if (getApplication().getService().getBackendProxy() != null) { if (log.isDebugEnabled()) log.debug("Ban ontology with URI '{}' from backend proxy cache", ontologyURI); - ban(getApplication().getService().getBackendProxy(), ontologyURI); + try (Response response = ban(getApplication().getService().getBackendProxy(), ontologyURI)) + { + // Response automatically closed by try-with-resources + } } // !!! we need to reload the ontology model before returning a response, to make sure the next request already gets the new version !!! From 9af745db61a010ff365515583743969436cbb903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 2 Jan 2026 22:04:42 +0100 Subject: [PATCH 10/64] Closing client responss HTTP test fixes --- CLAUDE.md | 24 ++++++++++++++++++- http-tests/document-hierarchy/PUT-twice.sh | 9 ++++--- .../linkeddatahub/resource/Generate.java | 7 ++++-- .../linkeddatahub/resource/admin/SignUp.java | 8 ++++++- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d442892f8..564e2500f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,4 +112,26 @@ export PATH="$(find bin -type d -exec realpath {} \; | tr '\n' ':')$PATH" - XSLT stylesheets are processed during build to inline XML entities - Saxon-JS SEF files are generated during Maven package phase for client-side XSLT - WebID certificates are required for authenticated API access -- The system expects Jena CLI tools to be available (`JENA_HOME` environment variable) \ No newline at end of file +- The system expects Jena CLI tools to be available (`JENA_HOME` environment variable) + +## Debugging Test Failures + +When HTTP tests fail: +1. NEVER speculate about failures - always add debug output first +2. Add echo statements showing: + - The actual values being tested + - The expected values + - HTTP response codes and bodies where relevant +3. Run the test to see actual output +4. Only then diagnose and fix + +Example debug pattern: +```bash +result=$(curl ...) +expected="..." +echo "DEBUG: Expected: $expected" +echo "DEBUG: Got: $result" +if [ "$result" != "$expected" ]; then +echo "DEBUG: Mismatch!" +exit 1 +fi diff --git a/http-tests/document-hierarchy/PUT-twice.sh b/http-tests/document-hierarchy/PUT-twice.sh index d61a2954b..807678104 100755 --- a/http-tests/document-hierarchy/PUT-twice.sh +++ b/http-tests/document-hierarchy/PUT-twice.sh @@ -52,9 +52,12 @@ EOF # check that the old document metadata is gone -curl -k -f -s -G \ +response=$(curl -k -f -s -G \ -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ -H "Accept: application/n-triples" \ "$END_USER_BASE_URL" \ -| tr -d '\n' \ -| grep -v '"old object"' > /dev/null \ No newline at end of file +| tr -d '\n') + +if echo "$response" | grep -q '"old object"'; then + exit 1 +fi \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java index 0d7704308..a296dbbb0 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java @@ -159,8 +159,11 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") } // ban the parent container URI from proxy cache to make sure the next query using it will be fresh (e.g. SELECT that loads children) - ban(getApplication().getService().getBackendProxy(), parent.getURI()); - + try (Response response = ban(getApplication().getService().getBackendProxy(), parent.getURI())) + { + // Response automatically closed by try-with-resources + } + return Response.ok().build(); } finally diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java index 95b22305b..c8f65f42a 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java @@ -288,7 +288,13 @@ public Response post(Model agentModel, @QueryParam("default") @DefaultValue("fal } // purge agent lookup from proxy cache - if (getAgentService().getBackendProxy() != null) ban(getAgentService().getBackendProxy(), mbox.getURI()); + if (getAgentService().getBackendProxy() != null) + { + try (Response response = ban(getAgentService().getBackendProxy(), mbox.getURI())) + { + // Response automatically closed by try-with-resources + } + } // remove secretary WebID from cache getSystem().getEventBus().post(new com.atomgraph.linkeddatahub.server.event.SignUp(getSystem().getSecretaryWebIDURI())); From 9e6cfb007a537c071125f638d2a27d1399eee2f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 2 Jan 2026 23:23:29 +0100 Subject: [PATCH 11/64] Test fix --- http-tests/admin/GET-agent-mbox-html.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/http-tests/admin/GET-agent-mbox-html.sh b/http-tests/admin/GET-agent-mbox-html.sh index 3a4ddae48..6d7d0ed4d 100755 --- a/http-tests/admin/GET-agent-mbox-html.sh +++ b/http-tests/admin/GET-agent-mbox-html.sh @@ -14,7 +14,9 @@ html=$(curl -k -f -s -N \ # check that the description does *not* include foaf:mbox property -echo "$html" | grep -v "http://xmlns.com/foaf/0.1/mbox" > /dev/null +if echo "$html" | grep -q 'http://xmlns.com/foaf/0.1/mbox[^_]'; then + exit 1 +fi # check that the description includes foaf:mbox_sha1sum property From 7b58db2e144765c5eef9c62ba4598786d2f81be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 2 Jan 2026 23:27:46 +0100 Subject: [PATCH 12/64] LinkedDataHub packages (#259) * Package model and initial implementation * Removed `PackageManager` * HTTP unit tests for packages * Package implementation and test fixes * Import fix * Ontology import fixes * Package installation fixes * Renamed script * Removed `/transform` from publicly allowed endpoints * Package test fixes * Added getter * Refactored `XSLTMasterUpdater` * Refactored `XSLTMasterUpdater` * Updated SKOS package ontology * Fixed class filename * Added SKOS import to the SKOS package ontology Renamed endpoint classes Removed VIVO ontology * Additional install/uninstall tests * Undo `patch` method changes * Replaced `LinkedDataClient` with `GraphStoreClient` Server and Web-Client bumps `InstallPackage` and `UnistallPackage` use GSP `PATCH` method to add/remove `owl:imports` triple * Core SNAPSHOT bump * Updated POM * `PATCH` update fixes HTTP test fixes * Response closure fixes Use try-with-resources consistently * Package ontology URI fix * Test fix * Varnish ban fix in `ClearOntology` * HTTP test fixes --- bin/admin/{model => ontologies}/add-class.sh | 0 .../{model => ontologies}/add-construct.sh | 0 .../add-property-constraint.sh | 0 .../{model => ontologies}/add-restriction.sh | 0 bin/admin/{model => ontologies}/add-select.sh | 0 .../{model => ontologies}/create-ontology.sh | 0 .../{model => ontologies}/import-ontology.sh | 0 bin/admin/packages/install-package.sh | 103 + config/system.trig | 3 +- .../admin/packages/install-package-400.sh | 16 + .../admin/packages/install-package-403.sh | 16 + .../admin/packages/install-package-422.sh | 18 + .../packages/install-package-ontology.sh | 35 + .../packages/install-package-stylesheet.sh | 28 + .../install-uninstall-package-ontology.sh | 53 + .../install-uninstall-package-stylesheet.sh | 48 + .../admin/packages/uninstall-package-400.sh | 16 + .../packages/uninstall-package-ontology.sh | 48 + .../packages/uninstall-package-stylesheet.sh | 44 + http-tests/config/system.trig | 2 - platform/datasets/admin.trig | 38 +- pom.xml | 8 +- .../atomgraph/linkeddatahub/Application.java | 24 +- .../linkeddatahub/apps/model/Application.java | 16 +- .../linkeddatahub/apps/model/Package.java | 54 + .../apps/model/impl/ApplicationImpl.java | 30 +- .../apps/model/impl/PackageImpl.java | 88 + .../model/impl/PackageImplementation.java | 56 + ...dDataClient.java => GraphStoreClient.java} | 133 +- .../linkeddatahub/imports/ImportExecutor.java | 34 +- .../linkeddatahub/imports/QueryLoader.java | 26 +- .../imports/stream/RDFGraphStoreOutput.java | 61 +- .../imports/stream/StreamRDFOutputWriter.java | 18 +- .../stream/csv/CSVGraphStoreOutput.java | 8 +- .../stream/csv/CSVGraphStoreOutputWriter.java | 18 +- .../stream/csv/CSVGraphStoreRowProcessor.java | 37 +- .../stream/csv/ClientResponseSupplier.java | 26 +- .../linkeddatahub/model/impl/ServiceImpl.java | 12 +- .../atomgraph/linkeddatahub/resource/Add.java | 10 +- .../linkeddatahub/resource/Generate.java | 6 +- .../linkeddatahub/resource/Graph.java | 11 +- .../linkeddatahub/resource/Transform.java | 16 +- .../admin/{Clear.java => ClearOntology.java} | 79 +- .../resource/admin/pkg/InstallPackage.java | 470 + .../resource/admin/pkg/UninstallPackage.java | 413 + .../server/event/AuthorizationCreated.java | 16 +- .../response/CacheInvalidationFilter.java | 20 +- .../server/io/ValidatingModelProvider.java | 6 +- .../server/model/impl/Dispatcher.java | 30 +- .../server/model/impl/GraphStoreImpl.java | 6 +- .../server/model/impl/ProxyResourceBase.java | 4 +- .../linkeddatahub/server/util/UriPath.java | 76 + .../server/util/XSLTMasterUpdater.java | 165 + .../linkeddatahub/vocabulary/LAPP.java | 5 +- .../linkeddatahub/vocabulary/LDH.java | 4 +- .../writer/factory/DataManagerFactory.java | 6 +- .../writer/impl/DataManagerImpl.java | 8 +- .../com/atomgraph/linkeddatahub/lapp.ttl | 7 + .../com/atomgraph/linkeddatahub/vivo.owl | 12563 ---------------- .../linkeddatahub/packages/skos/layout.xsl | 61 + .../com/linkeddatahub/packages/skos/ns.ttl | 186 + .../linkeddatahub/packages/skos/package.ttl | 20 + src/main/resources/location-mapping.ttl | 4 +- src/main/resources/prefix-mapping.ttl | 6 +- src/main/webapp/WEB-INF/web.xml | 2 +- src/main/webapp/static/xsl/admin/layout.xsl | 12 + src/main/webapp/static/xsl/layout.xsl | 12 + 67 files changed, 2507 insertions(+), 12834 deletions(-) rename bin/admin/{model => ontologies}/add-class.sh (100%) rename bin/admin/{model => ontologies}/add-construct.sh (100%) rename bin/admin/{model => ontologies}/add-property-constraint.sh (100%) rename bin/admin/{model => ontologies}/add-restriction.sh (100%) rename bin/admin/{model => ontologies}/add-select.sh (100%) rename bin/admin/{model => ontologies}/create-ontology.sh (100%) rename bin/admin/{model => ontologies}/import-ontology.sh (100%) create mode 100755 bin/admin/packages/install-package.sh create mode 100755 http-tests/admin/packages/install-package-400.sh create mode 100755 http-tests/admin/packages/install-package-403.sh create mode 100755 http-tests/admin/packages/install-package-422.sh create mode 100755 http-tests/admin/packages/install-package-ontology.sh create mode 100755 http-tests/admin/packages/install-package-stylesheet.sh create mode 100755 http-tests/admin/packages/install-uninstall-package-ontology.sh create mode 100755 http-tests/admin/packages/install-uninstall-package-stylesheet.sh create mode 100755 http-tests/admin/packages/uninstall-package-400.sh create mode 100755 http-tests/admin/packages/uninstall-package-ontology.sh create mode 100755 http-tests/admin/packages/uninstall-package-stylesheet.sh create mode 100644 src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImplementation.java rename src/main/java/com/atomgraph/linkeddatahub/client/{LinkedDataClient.java => GraphStoreClient.java} (62%) rename src/main/java/com/atomgraph/linkeddatahub/resource/admin/{Clear.java => ClearOntology.java} (72%) create mode 100644 src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java delete mode 100644 src/main/resources/com/atomgraph/linkeddatahub/vivo.owl create mode 100644 src/main/resources/com/linkeddatahub/packages/skos/layout.xsl create mode 100644 src/main/resources/com/linkeddatahub/packages/skos/ns.ttl create mode 100644 src/main/resources/com/linkeddatahub/packages/skos/package.ttl create mode 100644 src/main/webapp/static/xsl/admin/layout.xsl create mode 100644 src/main/webapp/static/xsl/layout.xsl diff --git a/bin/admin/model/add-class.sh b/bin/admin/ontologies/add-class.sh similarity index 100% rename from bin/admin/model/add-class.sh rename to bin/admin/ontologies/add-class.sh diff --git a/bin/admin/model/add-construct.sh b/bin/admin/ontologies/add-construct.sh similarity index 100% rename from bin/admin/model/add-construct.sh rename to bin/admin/ontologies/add-construct.sh diff --git a/bin/admin/model/add-property-constraint.sh b/bin/admin/ontologies/add-property-constraint.sh similarity index 100% rename from bin/admin/model/add-property-constraint.sh rename to bin/admin/ontologies/add-property-constraint.sh diff --git a/bin/admin/model/add-restriction.sh b/bin/admin/ontologies/add-restriction.sh similarity index 100% rename from bin/admin/model/add-restriction.sh rename to bin/admin/ontologies/add-restriction.sh diff --git a/bin/admin/model/add-select.sh b/bin/admin/ontologies/add-select.sh similarity index 100% rename from bin/admin/model/add-select.sh rename to bin/admin/ontologies/add-select.sh diff --git a/bin/admin/model/create-ontology.sh b/bin/admin/ontologies/create-ontology.sh similarity index 100% rename from bin/admin/model/create-ontology.sh rename to bin/admin/ontologies/create-ontology.sh diff --git a/bin/admin/model/import-ontology.sh b/bin/admin/ontologies/import-ontology.sh similarity index 100% rename from bin/admin/model/import-ontology.sh rename to bin/admin/ontologies/import-ontology.sh diff --git a/bin/admin/packages/install-package.sh b/bin/admin/packages/install-package.sh new file mode 100755 index 000000000..d4316dc1f --- /dev/null +++ b/bin/admin/packages/install-package.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +print_usage() +{ + printf "Installs a LinkedDataHub package.\n" + printf "\n" + printf "Usage: %s options\n" "$0" + printf "\n" + printf "Options:\n" + printf " -b, --base BASE_URL Base URL of the application\n" + printf " -f, --cert-pem-file CERT_FILE .pem file with the WebID certificate of the agent\n" + printf " -p, --cert-password CERT_PASSWORD Password of the WebID certificate\n" + printf " --proxy PROXY_URL The host this request will be proxied through (optional)\n" + printf " --package PACKAGE_URI URI of the package to install (e.g., https://packages.linkeddatahub.com/skos/#this)\n" + printf "\n" + printf "Example:\n" + printf " %s -b https://localhost:4443/ -f ssl/owner/cert.pem -p Password --package https://packages.linkeddatahub.com/skos/#this\n" "$0" +} + +hash curl 2>/dev/null || { echo >&2 "curl not on \$PATH. Aborting."; exit 1; } + +unknown=() +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + -b|--base) + base="$2" + shift # past argument + shift # past value + ;; + -f|--cert-pem-file) + cert_pem_file="$2" + shift # past argument + shift # past value + ;; + -p|--cert-password) + cert_password="$2" + shift # past argument + shift # past value + ;; + --proxy) + proxy="$2" + shift # past argument + shift # past value + ;; + --package) + package_uri="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + unknown+=("$1") # save it in an array for later + shift # past argument + ;; + esac +done +set -- "${unknown[@]}" # restore args + +if [ -z "$base" ] ; then + print_usage + exit 1 +fi +if [ -z "$cert_pem_file" ] ; then + print_usage + exit 1 +fi +if [ -z "$cert_password" ] ; then + print_usage + exit 1 +fi +if [ -z "$package_uri" ] ; then + print_usage + exit 1 +fi + +# Convert base URL to admin base URL +admin_uri() { + local uri="$1" + echo "$uri" | sed 's|://|://admin.|' +} + +admin_base=$(admin_uri "$base") +target_url="${admin_base}packages/install" + +if [ -n "$proxy" ]; then + admin_proxy=$(admin_uri "$proxy") + # rewrite target hostname to proxy hostname + url_host=$(echo "$target_url" | cut -d '/' -f 1,2,3) + proxy_host=$(echo "$admin_proxy" | cut -d '/' -f 1,2,3) + final_url="${target_url/$url_host/$proxy_host}" +else + final_url="$target_url" +fi + +# POST to packages/install endpoint +curl -k -w "%{http_code}\n" -E "${cert_pem_file}":"${cert_password}" \ + -X POST \ + -H "Accept: text/turtle" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=${package_uri}" \ + "${final_url}" diff --git a/config/system.trig b/config/system.trig index 48e43ed77..21cd69615 100644 --- a/config/system.trig +++ b/config/system.trig @@ -21,7 +21,7 @@ lapp:origin <https://admin.localhost:4443> ; ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; ldt:service <urn:linkeddatahub:services/admin> ; - ac:stylesheet <static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl> ; + ac:stylesheet <static/xsl/admin/layout.xsl> ; lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; lapp:frontendProxy <http://varnish-frontend:6060/> . @@ -41,6 +41,7 @@ lapp:origin <https://localhost:4443> ; ldt:ontology <https://localhost:4443/ns#> ; ldt:service <urn:linkeddatahub:services/end-user> ; + ac:stylesheet <static/xsl/layout.xsl> ; lapp:adminApplication <urn:linkeddatahub:apps/admin> ; lapp:frontendProxy <http://varnish-frontend:6060/> ; lapp:public true . diff --git a/http-tests/admin/packages/install-package-400.sh b/http-tests/admin/packages/install-package-400.sh new file mode 100755 index 000000000..d77736d15 --- /dev/null +++ b/http-tests/admin/packages/install-package-400.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Missing package-uri parameter should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_BAD_REQUEST" diff --git a/http-tests/admin/packages/install-package-403.sh b/http-tests/admin/packages/install-package-403.sh new file mode 100755 index 000000000..6cba48572 --- /dev/null +++ b/http-tests/admin/packages/install-package-403.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Unauthorized access (without certificate) should return 403 Forbidden +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=https://packages.linkeddatahub.com/skos/#this" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/admin/packages/install-package-422.sh b/http-tests/admin/packages/install-package-422.sh new file mode 100755 index 000000000..fac379586 --- /dev/null +++ b/http-tests/admin/packages/install-package-422.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Invalid/non-existent package URI should return 422 Unprocessable Entity +# (package loading failed) +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=https://packages.linkeddatahub.com/nonexistent/#package" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_UNPROCESSABLE_ENTITY" diff --git a/http-tests/admin/packages/install-package-ontology.sh b/http-tests/admin/packages/install-package-ontology.sh new file mode 100755 index 000000000..fa90359fe --- /dev/null +++ b/http-tests/admin/packages/install-package-ontology.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" +package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" +namespace_ontology_uri="${END_USER_BASE_URL}ns#" + +# install package via POST to packages/install endpoint +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify owl:imports triple was added to namespace graph +curl -k -s \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}ns" \ +| grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" + +# verify package ontology document was created (hash of package ontology URI) +package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" \ +| grep -qE "^($STATUS_OK|$STATUS_NOT_MODIFIED)$" diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh new file mode 100755 index 000000000..d79a3401c --- /dev/null +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" + +# install package via POST to packages/install endpoint +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package stylesheet was installed (should return 200) +curl -k -f -s -o /dev/null \ + "$END_USER_BASE_URL"static/com/linkeddatahub/packages/skos/layout.xsl + +# verify master stylesheet was regenerated and includes package import +curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ + | grep -q "com/linkeddatahub/packages/skos/layout.xsl" diff --git a/http-tests/admin/packages/install-uninstall-package-ontology.sh b/http-tests/admin/packages/install-uninstall-package-ontology.sh new file mode 100755 index 000000000..47d1e2b19 --- /dev/null +++ b/http-tests/admin/packages/install-uninstall-package-ontology.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" +package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" +namespace_ontology_uri="${END_USER_BASE_URL}ns#" + +# install package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "$ADMIN_BASE_URL"packages/install \ +| grep -q "$STATUS_SEE_OTHER" + +# verify owl:imports triple was added +curl -k -s \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}ns" \ +| grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" + +# verify package ontology document exists +package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) +curl -k -f -s -o /dev/null \ + "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" + +# uninstall package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "$ADMIN_BASE_URL"packages/uninstall \ +| grep -q "$STATUS_SEE_OTHER" + +# verify owl:imports triple was removed +ns_after=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") +if echo "$ns_after" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>"; then + exit 1 +fi + +# verify package ontology document was deleted +curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" \ +| grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh new file mode 100755 index 000000000..be547bdc2 --- /dev/null +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" + +# install package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "$ADMIN_BASE_URL"packages/install \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package stylesheet was installed (should return 200) +curl -k -f -s -o /dev/null \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" + +# verify master stylesheet includes package +curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl \ + | grep -q "com/linkeddatahub/packages/skos/layout.xsl" + +# uninstall package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "$ADMIN_BASE_URL"packages/uninstall \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package stylesheet was deleted (should return 404) +curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ +| grep -q "$STATUS_NOT_FOUND" + +# verify master stylesheet no longer includes package +master_xsl=$(curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl) +if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then + exit 1 +fi diff --git a/http-tests/admin/packages/uninstall-package-400.sh b/http-tests/admin/packages/uninstall-package-400.sh new file mode 100755 index 000000000..50129dd8d --- /dev/null +++ b/http-tests/admin/packages/uninstall-package-400.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Missing package-uri parameter should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + "${ADMIN_BASE_URL}packages/uninstall" \ +| grep -q "$STATUS_BAD_REQUEST" diff --git a/http-tests/admin/packages/uninstall-package-ontology.sh b/http-tests/admin/packages/uninstall-package-ontology.sh new file mode 100755 index 000000000..f73515d27 --- /dev/null +++ b/http-tests/admin/packages/uninstall-package-ontology.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" +package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" +namespace_ontology_uri="${END_USER_BASE_URL}ns#" + +# first install the package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify owl:imports triple exists before uninstall +ns_before=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") +echo "$ns_before" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" + +# uninstall package via POST to packages/uninstall endpoint +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/uninstall" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify owl:imports triple was removed from namespace graph +ns_after=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") +if echo "$ns_after" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>"; then + exit 1 +fi + +# verify package ontology document was deleted +package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) +ontology_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/") +echo "$ontology_status" | grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh new file mode 100755 index 000000000..67ced2c8a --- /dev/null +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# test package URI (SKOS package) +package_uri="https://packages.linkeddatahub.com/skos/#this" + +# first install the package +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package stylesheet exists before uninstall (should return 200) +curl -k -f -s -o /dev/null \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" + +# uninstall package via POST to packages/uninstall endpoint +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=$package_uri" \ + "${ADMIN_BASE_URL}packages/uninstall" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package stylesheet was deleted (should return 404) +curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ +| grep -q "$STATUS_NOT_FOUND" + +# verify master stylesheet was regenerated without package import +master_xsl=$(curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl) +if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then + exit 1 +fi diff --git a/http-tests/config/system.trig b/http-tests/config/system.trig index a5d0e33e7..277499e5d 100644 --- a/http-tests/config/system.trig +++ b/http-tests/config/system.trig @@ -21,7 +21,6 @@ lapp:origin <https://admin.localhost:4443> ; ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; ldt:service <urn:linkeddatahub:services/admin> ; - ac:stylesheet <static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl> ; lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; lapp:frontendProxy <http://varnish-frontend:6060/> . @@ -60,7 +59,6 @@ lapp:origin <https://admin.test.localhost:4443> ; ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; ldt:service <urn:linkeddatahub:services/test/admin> ; - ac:stylesheet <static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl> ; lapp:endUserApplication <urn:linkeddatahub:apps/test/end-user> ; lapp:frontendProxy <http://varnish-frontend:6060/> . diff --git a/platform/datasets/admin.trig b/platform/datasets/admin.trig index 111123be6..4756fa90b 100644 --- a/platform/datasets/admin.trig +++ b/platform/datasets/admin.trig @@ -699,7 +699,7 @@ WHERE rdfs:label "Full control" ; rdfs:comment "Allows full read/write access to all application resources" ; acl:accessToClass dh:Item, dh:Container, def:Root ; - acl:accessTo <clear>, <transform> ; + acl:accessTo <clear>, <transform>, <packages/install>, <packages/uninstall> ; acl:mode acl:Read, acl:Append, acl:Write, acl:Control ; acl:agentGroup <acl/groups/owners/#this> . @@ -755,6 +755,42 @@ WHERE } +### PACKAGES ### + +# ENDPOINTS + +<packages/install> +{ + + <packages/install> a foaf:Document ; + dct:title "Install package endpoint" . + +} + +<packages/uninstall> +{ + + <packages/uninstall> a foaf:Document ; + dct:title "Uninstall package endpoint" . + +} + +# CONTAINERS + +<packages/> +{ + + <packages/> a dh:Container ; + sioc:has_parent <> ; + dct:title "Packages" ; + dct:description "Manage installed packages" ; + rdf:_1 <packages/#select-children> . + + <packages/#select-children> a ldh:Object ; + rdf:value ldh:ChildrenView . + +} + ### ONTOLOGIES ### # CONTAINERS diff --git a/pom.xml b/pom.xml index f63745991..68c4e799b 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ <groupId>com.atomgraph</groupId> <artifactId>linkeddatahub</artifactId> - <version>5.1.1-SNAPSHOT</version> + <version>5.1.2-SNAPSHOT</version> <packaging>${packaging.type}</packaging> <name>AtomGraph LinkedDataHub</name> @@ -130,18 +130,18 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>server</artifactId> - <version>4.1.12</version> + <version>4.1.15-SNAPSHOT</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.7</version> + <version>4.2.10-SNAPSHOT</version> <classifier>classes</classifier> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.7</version> + <version>4.2.10-SNAPSHOT</version> <type>war</type> </dependency> <!-- required by jsonld-java - version same as Jersey's HTTP Client --> diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index 986c5e3c7..bafcc2ef5 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -67,7 +67,7 @@ import com.atomgraph.linkeddatahub.writer.factory.xslt.XsltExecutableSupplier; import com.atomgraph.linkeddatahub.writer.factory.XsltExecutableSupplierFactory; import com.atomgraph.client.util.XsltResolver; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.client.filter.ClientUriRewriteFilter; import com.atomgraph.linkeddatahub.client.filter.grddl.YouTubeGRDDLFilter; import com.atomgraph.linkeddatahub.imports.ImportExecutor; @@ -723,6 +723,7 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType BuiltinPersonalities.model.add(EndUserApplication.class, new com.atomgraph.linkeddatahub.apps.model.end_user.impl.ApplicationImplementation()); BuiltinPersonalities.model.add(com.atomgraph.linkeddatahub.apps.model.Application.class, new com.atomgraph.linkeddatahub.apps.model.impl.ApplicationImplementation()); BuiltinPersonalities.model.add(com.atomgraph.linkeddatahub.apps.model.Dataset.class, new com.atomgraph.linkeddatahub.apps.model.impl.DatasetImplementation()); + BuiltinPersonalities.model.add(com.atomgraph.linkeddatahub.apps.model.Package.class, new com.atomgraph.linkeddatahub.apps.model.impl.PackageImplementation()); BuiltinPersonalities.model.add(Service.class, new com.atomgraph.linkeddatahub.model.impl.ServiceImplementation(noCertClient, mediaTypes, maxGetRequestSize)); BuiltinPersonalities.model.add(Import.class, ImportImpl.factory); BuiltinPersonalities.model.add(RDFImport.class, RDFImportImpl.factory); @@ -731,7 +732,7 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType // TO-DO: config property for cacheModelLoads endUserOntModelSpecs = new HashMap<>(); - dataManager = new DataManagerImpl(locationMapper, new HashMap<>(), LinkedDataClient.create(client, mediaTypes), cacheModelLoads, preemptiveAuth, resolvingUncached); + dataManager = new DataManagerImpl(locationMapper, new HashMap<>(), GraphStoreClient.create(client, mediaTypes), cacheModelLoads, preemptiveAuth, resolvingUncached); ontModelSpec = OntModelSpec.OWL_MEM_RDFS_INF; ontModelSpec.setImportModelGetter(dataManager); OntDocumentManager.getInstance().setFileManager((FileManager)dataManager); @@ -806,7 +807,7 @@ protected PasswordAuthentication getPasswordAuthentication() xsltComp = xsltProc.newXsltCompiler(); xsltComp.setParameter(new QName("ldh", LDH.base.getNameSpace(), LDH.base.getLocalName()), new XdmAtomicValue(baseURI)); - xsltComp.setURIResolver(new XsltResolver(LocationMapper.get(), new HashMap<>(), LinkedDataClient.create(client, mediaTypes), false, false, true)); // default Xerces parser does not support HTTPS + xsltComp.setURIResolver(new XsltResolver(LocationMapper.get(), new HashMap<>(), GraphStoreClient.create(client, mediaTypes), false, false, true)); // default Xerces parser does not support HTTPS xsltExec = xsltComp.compile(stylesheet); } catch (FileNotFoundException ex) @@ -1198,7 +1199,7 @@ public void handleAuthorizationCreated(AuthorizationCreated event) throws Messag { Resource agent = auth.getPropertyResourceValue(ACL.agent); // make sure the client has WebID delegation enabled, otherwise it will not have authenticated access - Model agentModel = event.getLinkedDataClient().getModel(agent.getURI()); + Model agentModel = event.getGraphStoreClient().getModel(agent.getURI()); if (!agentModel.containsResource(agent)) throw new IllegalStateException("Could not load agent's <" + agent.getURI() + "> description"); agent = agentModel.getResource(agent.getURI()); @@ -1419,11 +1420,11 @@ public Map<Integer, Resource> getLengthMap(Map<URI, Resource> apps) * @param service current SPARQL service * @param adminService current admin SPARQL service * @param baseURI application's base URI - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public void submitImport(CSVImport csvImport, com.atomgraph.linkeddatahub.apps.model.Application app, Service service, Service adminService, String baseURI, LinkedDataClient ldc) + public void submitImport(CSVImport csvImport, com.atomgraph.linkeddatahub.apps.model.Application app, Service service, Service adminService, String baseURI, GraphStoreClient gsc) { - new ImportExecutor(importThreadPool).start(service, adminService, baseURI, ldc, csvImport); + new ImportExecutor(importThreadPool).start(service, adminService, baseURI, gsc, csvImport); } /** @@ -1434,11 +1435,11 @@ public void submitImport(CSVImport csvImport, com.atomgraph.linkeddatahub.apps.m * @param service current SPARQL service * @param adminService current admin SPARQL service * @param baseURI application's base URI - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public void submitImport(RDFImport rdfImport, com.atomgraph.linkeddatahub.apps.model.Application app, Service service, Service adminService, String baseURI, LinkedDataClient ldc) + public void submitImport(RDFImport rdfImport, com.atomgraph.linkeddatahub.apps.model.Application app, Service service, Service adminService, String baseURI, GraphStoreClient gsc) { - new ImportExecutor(importThreadPool).start(service, adminService, baseURI, ldc, rdfImport); + new ImportExecutor(importThreadPool).start(service, adminService, baseURI, gsc, rdfImport); } /** @@ -1715,8 +1716,7 @@ public OntModelSpec getOntModelSpec(EndUserApplication app) { OntModelSpec appOntModelSpec = new OntModelSpec(OntModelSpec.OWL_MEM_RDFS_INF); appOntModelSpec.setDocumentManager(new OntDocumentManager()); - appOntModelSpec.getDocumentManager().setFileManager( - new DataManagerImpl(LocationMapper.get(), new HashMap<>(), LinkedDataClient.create(getClient(), getMediaTypes()), true, isPreemptiveAuth(), isResolvingUncached())); + appOntModelSpec.getDocumentManager().setFileManager(new DataManagerImpl(LocationMapper.get(), new HashMap<>(), GraphStoreClient.create(getClient(), getMediaTypes()), true, isPreemptiveAuth(), isResolvingUncached())); getEndUserOntModelSpecs().put(app.getURI(), appOntModelSpec); } diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/Application.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Application.java index 699066916..1832b7ad9 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/apps/model/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Application.java @@ -30,11 +30,6 @@ public interface Application extends Resource, com.atomgraph.core.model.Application { - /** - * The relative path of the content-addressed file container. - */ - public static final String UPLOADS_PATH = "uploads"; - /** * Returns the application's namespace ontology. * @@ -108,9 +103,16 @@ public interface Application extends Resource, com.atomgraph.core.model.Applicat /** * Returns frontend proxy's cache URI resource. - * + * * @return RDF resource */ Resource getFrontendProxy(); - + + /** + * Returns the set of packages imported by this application. + * + * @return set of package resources + */ + java.util.Set<Resource> getImportedPackages(); + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java new file mode 100644 index 000000000..4ad8b71e5 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java @@ -0,0 +1,54 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.apps.model; + +import org.apache.jena.rdf.model.Resource; + +/** + * A LinkedDataHub package containing an ontology and optional XSLT stylesheet. + * Packages provide reusable vocabulary support with custom templates and rendering. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public interface Package extends Resource +{ + + /** + * Returns the package's ontology resource. + * The ontology file (ns.ttl) contains RDF vocabulary classes/properties and template blocks. + * + * @return ontology resource, or null if not specified + */ + Resource getOntology(); + + /** + * Returns the package's stylesheet resource. + * The stylesheet file (layout.xsl) contains XSLT templates for custom rendering. + * + * @return stylesheet resource, or null if not specified + */ + Resource getStylesheet(); + + /** + * Returns the packages imported by this package. + * Packages can transitively import other packages via ldh:import property. + * + * @return set of imported package resources + */ + java.util.Set<Resource> getImportedPackages(); + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java index 043b18d90..c10e7f31e 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/ApplicationImpl.java @@ -21,14 +21,18 @@ import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.vocabulary.FOAF; import com.atomgraph.linkeddatahub.vocabulary.LAPP; +import com.atomgraph.linkeddatahub.vocabulary.LDH; import com.atomgraph.server.vocabulary.LDT; import jakarta.ws.rs.core.UriBuilder; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.StmtIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URI; +import java.util.HashSet; +import java.util.Set; import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.impl.ResourceImpl; @@ -117,9 +121,9 @@ public Resource getFrontendProxy() public boolean isReadAllowed() { Statement stmt = getProperty(LAPP.allowRead); - + if (stmt != null) return stmt.getBoolean(); - + return false; } @@ -128,4 +132,26 @@ public UriBuilder getUriBuilder() { return UriBuilder.fromUri(getOriginURI()); } + + @Override + public Set<Resource> getImportedPackages() + { + Set<Resource> packages = new HashSet<>(); + StmtIterator it = listProperties(LDH.importPackage); + try + { + while (it.hasNext()) + { + Statement stmt = it.next(); + if (stmt.getObject().isResource()) + packages.add(stmt.getResource()); + } + } + finally + { + it.close(); + } + return packages; + } + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java new file mode 100644 index 000000000..a431ee262 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java @@ -0,0 +1,88 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.apps.model.impl; + +import com.atomgraph.client.vocabulary.AC; +import com.atomgraph.linkeddatahub.apps.model.Package; +import com.atomgraph.linkeddatahub.vocabulary.LDH; +import com.atomgraph.server.vocabulary.LDT; +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.graph.Node; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.rdf.model.impl.ResourceImpl; + +import java.util.HashSet; +import java.util.Set; + + +/** + * LinkedDataHub package implementation. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class PackageImpl extends ResourceImpl implements Package +{ + + /** + * Constructs instance from node and graph. + * + * @param n node + * @param g graph + */ + public PackageImpl(Node n, EnhGraph g) + { + super(n, g); + } + + @Override + public Resource getOntology() + { + return getPropertyResourceValue(LDT.ontology); + } + + @Override + public Resource getStylesheet() + { + return getPropertyResourceValue(AC.stylesheet); + } + + @Override + public Set<Resource> getImportedPackages() + { + Set<Resource> packages = new HashSet<>(); + StmtIterator it = listProperties(LDH.importPackage); + + try + { + while (it.hasNext()) + { + Statement stmt = it.next(); + if (stmt.getObject().isResource()) + packages.add(stmt.getResource()); + } + } + finally + { + it.close(); + } + + return packages; + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImplementation.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImplementation.java new file mode 100644 index 000000000..09ebb5e9d --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImplementation.java @@ -0,0 +1,56 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.apps.model.impl; + +import com.atomgraph.linkeddatahub.vocabulary.LAPP; +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.EnhNode; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; +import org.apache.jena.ontology.ConversionException; +import org.apache.jena.vocabulary.RDF; + +/** + * Jena's implementation factory for Package. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class PackageImplementation extends Implementation +{ + + @Override + public EnhNode wrap(Node node, EnhGraph enhGraph) + { + if (canWrap(node, enhGraph)) + { + return new PackageImpl(node, enhGraph); + } + else + { + throw new ConversionException("Cannot convert node " + node.toString() + " to Package: it does not have rdf:type lapp:Package"); + } + } + + @Override + public boolean canWrap(Node node, EnhGraph eg) + { + if (eg == null) throw new IllegalArgumentException("EnhGraph cannot be null"); + + return eg.asGraph().contains(node, RDF.type.asNode(), LAPP.Package.asNode()); + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/client/LinkedDataClient.java b/src/main/java/com/atomgraph/linkeddatahub/client/GraphStoreClient.java similarity index 62% rename from src/main/java/com/atomgraph/linkeddatahub/client/LinkedDataClient.java rename to src/main/java/com/atomgraph/linkeddatahub/client/GraphStoreClient.java index 21b6668d3..61694c57d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/client/LinkedDataClient.java +++ b/src/main/java/com/atomgraph/linkeddatahub/client/GraphStoreClient.java @@ -23,30 +23,32 @@ import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.security.IDTokenSecurityContext; import com.atomgraph.linkeddatahub.server.security.WebIDSecurityContext; +import static jakarta.ws.rs.HttpMethod.PATCH; import java.net.URI; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.Entity; -import static jakarta.ws.rs.client.Entity.entity; +import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.Response; -import org.apache.jena.rdf.model.Model; +import java.util.List; +import java.util.Map; +import org.apache.jena.update.UpdateRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Linked Data client that supports WebID and OIDC delegation. + * Graph Store client that supports WebID and OIDC delegation. * Sends <code>User-Agent</code> header to impersonate a web browser. * Respects <code>Retry-After</code> response headers. * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class LinkedDataClient extends com.atomgraph.core.client.LinkedDataClient +public class GraphStoreClient extends com.atomgraph.core.client.GraphStoreClient { - private static final Logger log = LoggerFactory.getLogger(LinkedDataClient.class); + private static final Logger log = LoggerFactory.getLogger(GraphStoreClient.class); /** * <samp>User-Agent</samp> request header value used by this HTTP client. @@ -57,29 +59,42 @@ public class LinkedDataClient extends com.atomgraph.core.client.LinkedDataClient private AgentContext agentContext; private long defaultDelayMillis; private final int maxRetryCount; + + /** + * Constructs Graph Store Protocol client. + * + * @param client HTTP client + * @param mediaTypes registry of supported readable/writable media types + */ + protected GraphStoreClient(Client client, MediaTypes mediaTypes) + { + this(client, mediaTypes, null); + } /** - * Constructs Linked Data client from HTTP client and media types. + * Constructs Graph Store Protocol client. * * @param client HTTP client * @param mediaTypes registry of supported readable/writable media types + * @param endpoint endpoint URL (optional) */ - protected LinkedDataClient(Client client, MediaTypes mediaTypes) + protected GraphStoreClient(Client client, MediaTypes mediaTypes, URI endpoint) { - this(client, mediaTypes, 5000L, 3); + this(client, mediaTypes, endpoint, 5000L, 3); } /** - * Constructs Linked Data client from HTTP client and media types. + * Constructs Graph Store Protocol client. * * @param client HTTP client * @param mediaTypes registry of supported readable/writable media types + * @param endpoint endpoint URL (optional) * @param defaultDelayMillis default period the client waits before retrying the request * @param maxRetryCount maximum number of request retries */ - protected LinkedDataClient(Client client, MediaTypes mediaTypes, long defaultDelayMillis, int maxRetryCount) + protected GraphStoreClient(Client client, MediaTypes mediaTypes, URI endpoint, long defaultDelayMillis, int maxRetryCount) { - super(client, mediaTypes); + super(client, mediaTypes, endpoint); this.defaultDelayMillis = defaultDelayMillis; this.maxRetryCount = maxRetryCount; } @@ -89,13 +104,14 @@ protected LinkedDataClient(Client client, MediaTypes mediaTypes, long defaultDel * * @param client HTTP client * @param mediaTypes registry of supported readable/writable media types + * @param endpoint endpoint URL (optional) * @param defaultDelayMillis default period the client waits before retrying the request * @param maxRetryCount max request retry count - * @return Linked Data client instance + * @return Graph Store client instance */ - public static LinkedDataClient create(Client client, MediaTypes mediaTypes, long defaultDelayMillis, int maxRetryCount) + public static GraphStoreClient create(Client client, MediaTypes mediaTypes, URI endpoint, long defaultDelayMillis, int maxRetryCount) { - return new LinkedDataClient(client, mediaTypes, defaultDelayMillis, maxRetryCount); + return new GraphStoreClient(client, mediaTypes, endpoint, defaultDelayMillis, maxRetryCount); } /** @@ -103,11 +119,24 @@ public static LinkedDataClient create(Client client, MediaTypes mediaTypes, long * * @param client HTTP client * @param mediaTypes registry of supported readable/writable media types - * @return Linked Data client instance + * @param endpoint endpoint URL (optional) + * @return Graph Store client instance */ - public static LinkedDataClient create(Client client, MediaTypes mediaTypes) + public static GraphStoreClient create(Client client, MediaTypes mediaTypes, URI endpoint) { - return new LinkedDataClient(client, mediaTypes); + return new GraphStoreClient(client, mediaTypes, endpoint); + } + + /** + * Factory method that accepts HTTP client and media types. + * + * @param client HTTP client + * @param mediaTypes registry of supported readable/writable media types + * @return Graph Store client instance + */ + public static GraphStoreClient create(Client client, MediaTypes mediaTypes) + { + return new GraphStoreClient(client, mediaTypes); } /** @@ -118,7 +147,7 @@ public static LinkedDataClient create(Client client, MediaTypes mediaTypes) * @param agentContext agent's auth context * @return client instance */ - public LinkedDataClient delegation(URI baseURI, AgentContext agentContext) + public GraphStoreClient delegation(URI baseURI, AgentContext agentContext) { this.baseURI = baseURI; this.agentContext = agentContext; @@ -157,59 +186,65 @@ protected WebTarget getWebTarget(URI uri) } @Override - public Response get(URI uri, jakarta.ws.rs.core.MediaType[] acceptedTypes) + protected Invocation.Builder applyHeaders(Invocation.Builder builder, MultivaluedMap<String, Object> headers) + { + if (headers != null) + for (Map.Entry<String, List<Object>> entry : headers.entrySet()) + for (Object value : entry.getValue()) + builder = builder.header(entry.getKey(), value); + + return builder.header(HttpHeaders.USER_AGENT, getUserAgentHeaderValue()); + } + + @Override + public Response get(URI uri, jakarta.ws.rs.core.MediaType[] acceptedTypes, MultivaluedMap<String, Object> headers) { - WebTarget webTarget = getWebTarget(uri); return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() -> - webTarget.request(acceptedTypes) - .header(HttpHeaders.USER_AGENT, getUserAgentHeaderValue()) - .get()); + applyHeaders(getWebTarget(uri).request(acceptedTypes), headers).get()); } @Override - public Response post(URI uri, MediaType[] acceptedTypes, Entity entity) + public Response post(URI uri, Entity entity, jakarta.ws.rs.core.MediaType[] acceptedTypes, MultivaluedMap<String, Object> headers) { - WebTarget webTarget = getWebTarget(uri); return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() -> - webTarget.request(acceptedTypes).post(entity)); + applyHeaders(getWebTarget(uri).request(acceptedTypes), headers).post(entity)); } @Override - public Response put(URI uri, MediaType[] acceptedTypes, Entity entity) + public Response put(URI uri, Entity entity, jakarta.ws.rs.core.MediaType[] acceptedTypes, MultivaluedMap<String, Object> headers) { - WebTarget webTarget = getWebTarget(uri); return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() -> - webTarget.request(acceptedTypes).put(entity)); + applyHeaders(getWebTarget(uri).request(acceptedTypes), headers).put(entity)); } - /** - * Sends a PUT request with RDF model data to the specified URI. - * - * @param uri the target URI - * @param model the RDF model to send - * @param headers additional HTTP headers - * @return the HTTP response - */ - public Response put(URI uri, Model model, MultivaluedMap<String, Object> headers) + @Override + public Response delete(URI uri, jakarta.ws.rs.core.MediaType[] acceptedTypes, MultivaluedMap<String, String> params, MultivaluedMap<String, Object> headers) { - WebTarget webTarget = getWebTarget(uri); return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() -> - webTarget.request(getReadableMediaTypes(Model.class)). - headers(headers). - put(Entity.entity(model, getDefaultMediaType()))); + applyHeaders(getWebTarget(uri).request(acceptedTypes), headers).delete()); } - - @Override - public Response delete(URI uri) + + /** + * Sends a PATCH request with SPARQL UPDATE to the specified graph URI. + * + * @param uri the target graph URI + * @param updateRequest the SPARQL UPDATE request + * @return the HTTP response + */ + public Response patch(URI uri, UpdateRequest updateRequest) { + if (updateRequest == null) throw new IllegalArgumentException("UpdateRequest cannot be null"); + WebTarget webTarget = getWebTarget(uri); + String updateString = updateRequest.toString(); + return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() -> - webTarget.request().delete()); + webTarget.request().method(PATCH, Entity.entity(updateString, com.atomgraph.linkeddatahub.MediaType.APPLICATION_SPARQL_UPDATE_TYPE))); } - + /** * Returns the application's base URI. - * + * * @return base URI */ public URI getBaseURI() diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/ImportExecutor.java b/src/main/java/com/atomgraph/linkeddatahub/imports/ImportExecutor.java index 7dfac9e35..2c2b2ad10 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/ImportExecutor.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/ImportExecutor.java @@ -19,7 +19,7 @@ import com.atomgraph.client.MediaTypes; import com.atomgraph.client.vocabulary.LDT; import com.atomgraph.core.model.DatasetAccessor; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.imports.stream.RDFGraphStoreOutput; import com.atomgraph.linkeddatahub.imports.stream.csv.CSVGraphStoreOutput; import com.atomgraph.linkeddatahub.imports.stream.csv.CSVGraphStoreOutputWriter; @@ -100,10 +100,10 @@ public ImportExecutor(ExecutorService execService) * @param service application's SPARQL service * @param adminService admin application's SPARQL service * @param appBaseURI application's base URI - * @param ldc Linked Data client + * @param gsc Graph Store client * @param csvImport CSV import resource */ - public void start(Service service, Service adminService, String appBaseURI, LinkedDataClient ldc, CSVImport csvImport) + public void start(Service service, Service adminService, String appBaseURI, GraphStoreClient gsc, CSVImport csvImport) { if (csvImport == null) throw new IllegalArgumentException("CSVImport cannot be null"); if (log.isDebugEnabled()) log.debug("Submitting new import to thread pool: {}", csvImport.toString()); @@ -112,15 +112,15 @@ public void start(Service service, Service adminService, String appBaseURI, Link addProperty(PROV.startedAtTime, csvImport.getModel().createTypedLiteral(Calendar.getInstance())); String queryBaseURI = csvImport.getFile().getURI(); // file URI becomes the query base URI - QueryLoader queryLoader = new QueryLoader(URI.create(csvImport.getQuery().getURI()), queryBaseURI, Syntax.syntaxARQ, ldc); + QueryLoader queryLoader = new QueryLoader(URI.create(csvImport.getQuery().getURI()), queryBaseURI, Syntax.syntaxARQ, gsc); ParameterizedSparqlString pss = new ParameterizedSparqlString(queryLoader.get().toString(), queryBaseURI); pss.setIri(LDT.base.getLocalName(), appBaseURI); // app's base URI becomes $base final Query query = pss.asQuery(); - Supplier<Response> fileSupplier = new ClientResponseSupplier(ldc, CSV_MEDIA_TYPES, URI.create(csvImport.getFile().getURI())); + Supplier<Response> fileSupplier = new ClientResponseSupplier(gsc, CSV_MEDIA_TYPES, URI.create(csvImport.getFile().getURI())); // skip validation because it will be done during final POST anyway CompletableFuture.supplyAsync(fileSupplier, getExecutorService()).thenApplyAsync(getStreamRDFOutputWriter(service, adminService, - ldc, queryBaseURI, query, csvImport), getExecutorService()). + gsc, queryBaseURI, query, csvImport), getExecutorService()). thenAcceptAsync(success(service, csvImport, provImport), getExecutorService()). exceptionally(failure(service, csvImport, provImport)); } @@ -131,11 +131,11 @@ public void start(Service service, Service adminService, String appBaseURI, Link * @param service application's SPARQL service * @param adminService admin application's SPARQL service * @param appBaseURI application's base URI - * @param ldc Linked Data client + * @param gsc Graph Store client * @param rdfImport RDF import resource */ - public void start(Service service, Service adminService, String appBaseURI, LinkedDataClient ldc, RDFImport rdfImport) + public void start(Service service, Service adminService, String appBaseURI, GraphStoreClient gsc, RDFImport rdfImport) { if (rdfImport == null) throw new IllegalArgumentException("RDFImport cannot be null"); if (log.isDebugEnabled()) log.debug("Submitting new import to thread pool: {}", rdfImport.toString()); @@ -147,7 +147,7 @@ public void start(Service service, Service adminService, String appBaseURI, Link final Query query; if (rdfImport.getQuery() != null) // query is optional on RDFImport { - QueryLoader queryLoader = new QueryLoader(URI.create(rdfImport.getQuery().getURI()), queryBaseURI, Syntax.syntaxARQ, ldc); + QueryLoader queryLoader = new QueryLoader(URI.create(rdfImport.getQuery().getURI()), queryBaseURI, Syntax.syntaxARQ, gsc); ParameterizedSparqlString pss = new ParameterizedSparqlString(queryLoader.get().toString(), queryBaseURI); pss.setIri(LDT.base.getLocalName(), appBaseURI); // app's base URI becomes $base query = pss.asQuery(); @@ -155,10 +155,10 @@ public void start(Service service, Service adminService, String appBaseURI, Link else query = null; - Supplier<Response> fileSupplier = new ClientResponseSupplier(ldc, RDF_MEDIA_TYPES, URI.create(rdfImport.getFile().getURI())); + Supplier<Response> fileSupplier = new ClientResponseSupplier(gsc, RDF_MEDIA_TYPES, URI.create(rdfImport.getFile().getURI())); // skip validation because it will be done during final POST anyway CompletableFuture.supplyAsync(fileSupplier, getExecutorService()).thenApplyAsync(getStreamRDFOutputWriter(service, adminService, - ldc, queryBaseURI, query, rdfImport), getExecutorService()). + gsc, queryBaseURI, query, rdfImport), getExecutorService()). thenAcceptAsync(success(service, rdfImport, provImport), getExecutorService()). exceptionally(failure(service, rdfImport, provImport)); } @@ -273,15 +273,15 @@ protected void appendProvGraph(Resource provImport, DatasetAccessor accessor) * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param baseURI base URI * @param query transformation query * @param imp import resource * @return function */ - protected Function<Response, CSVGraphStoreOutput> getStreamRDFOutputWriter(Service service, Service adminService, LinkedDataClient ldc, String baseURI, Query query, CSVImport imp) + protected Function<Response, CSVGraphStoreOutput> getStreamRDFOutputWriter(Service service, Service adminService, GraphStoreClient gsc, String baseURI, Query query, CSVImport imp) { - return new CSVGraphStoreOutputWriter(service, adminService, ldc, baseURI, query, imp.getDelimiter()); + return new CSVGraphStoreOutputWriter(service, adminService, gsc, baseURI, query, imp.getDelimiter()); } /** @@ -289,15 +289,15 @@ protected Function<Response, CSVGraphStoreOutput> getStreamRDFOutputWriter(Servi * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param baseURI base URI * @param query transformation query * @param imp import resource * @return function */ - protected Function<Response, RDFGraphStoreOutput> getStreamRDFOutputWriter(Service service, Service adminService, LinkedDataClient ldc, String baseURI, Query query, RDFImport imp) + protected Function<Response, RDFGraphStoreOutput> getStreamRDFOutputWriter(Service service, Service adminService, GraphStoreClient gsc, String baseURI, Query query, RDFImport imp) { - return new StreamRDFOutputWriter(service, adminService, ldc, baseURI, query, imp.getGraphName() != null ? imp.getGraphName().getURI() : null); + return new StreamRDFOutputWriter(service, adminService, gsc, baseURI, query, imp.getGraphName() != null ? imp.getGraphName().getURI() : null); } diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/QueryLoader.java b/src/main/java/com/atomgraph/linkeddatahub/imports/QueryLoader.java index 1de325866..7e5d0f4d8 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/QueryLoader.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/QueryLoader.java @@ -16,7 +16,7 @@ */ package com.atomgraph.linkeddatahub.imports; -import com.atomgraph.core.client.LinkedDataClient; +import com.atomgraph.core.client.GraphStoreClient; import com.atomgraph.spinrdf.vocabulary.SP; import java.net.URI; import java.util.function.Supplier; @@ -39,18 +39,18 @@ public class QueryLoader implements Supplier<Query> private final URI uri; private final String baseURI; private final Syntax syntax; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; /** * Constructs loader from query URI. * * @param uri query URI * @param baseURI base URI - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public QueryLoader(URI uri, String baseURI, LinkedDataClient ldc) + public QueryLoader(URI uri, String baseURI, GraphStoreClient gsc) { - this(uri, baseURI, Syntax.syntaxSPARQL_11, ldc); + this(uri, baseURI, Syntax.syntaxSPARQL_11, gsc); } /** @@ -59,20 +59,20 @@ public QueryLoader(URI uri, String baseURI, LinkedDataClient ldc) * @param uri query URI * @param baseURI base URI * @param syntax query syntax - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public QueryLoader(URI uri, String baseURI, Syntax syntax, LinkedDataClient ldc) + public QueryLoader(URI uri, String baseURI, Syntax syntax, GraphStoreClient gsc) { this.uri = uri; this.baseURI = baseURI; this.syntax = syntax; - this.ldc = ldc; + this.gsc = gsc; } @Override public Query get() { - try (Response cr = getLinkedDataClient().get(getURI())) + try (Response cr = getGraphStoreClient().get(getURI())) { Resource queryRes = cr.readEntity(Model.class).getResource(getURI().toString()); return QueryFactory.create(queryRes.getRequiredProperty(SP.text).getString(), getBaseURI(), getSyntax()); @@ -110,13 +110,13 @@ public Syntax getSyntax() } /** - * Returns Linked Data client. + * Returns Graph Store client. * - * @return Linked Data client + * @return Graph Store client */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } } diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/RDFGraphStoreOutput.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/RDFGraphStoreOutput.java index cb7d86c04..f18e3891c 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/RDFGraphStoreOutput.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/RDFGraphStoreOutput.java @@ -16,11 +16,12 @@ */ package com.atomgraph.linkeddatahub.imports.stream; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.exception.ImportException; import java.io.InputStream; import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; @@ -51,7 +52,7 @@ public class RDFGraphStoreOutput private static final Logger log = LoggerFactory.getLogger(RDFGraphStoreOutput.class); private final Service service, adminService; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final String base; private final InputStream is; private final Query query; @@ -63,18 +64,18 @@ public class RDFGraphStoreOutput * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client for RDF results + * @param gsc Graph Store client for RDF results * @param is RDF input stream * @param base base URI * @param query <code>CONSTRUCT</code> transformation query or null * @param lang RDF language * @param graphURI named graph URI */ - public RDFGraphStoreOutput(Service service, Service adminService, LinkedDataClient ldc, InputStream is, String base, Query query, Lang lang, String graphURI) + public RDFGraphStoreOutput(Service service, Service adminService, GraphStoreClient gsc, InputStream is, String base, Query query, Lang lang, String graphURI) { this.service = service; this.adminService = adminService; - this.ldc = ldc; + this.gsc = gsc; this.is = is; this.base = base; this.query = query; @@ -111,11 +112,11 @@ public void write() MultivaluedMap<String, Object> headers = new MultivaluedHashMap(); headers.putSingle(HttpHeaders.IF_NONE_MATCH, "*"); - try (Response putResponse = getLinkedDataClient().put(URI.create(graphUri), namedModel, headers)) + try (Response putResponse = getGraphStoreClient().put(URI.create(graphUri), Entity.entity(namedModel, getGraphStoreClient().getDefaultMediaType()), new jakarta.ws.rs.core.MediaType[]{}, headers)) { if (putResponse.getStatusInfo().equals(Response.Status.PRECONDITION_FAILED)) { - try (Response postResponse = getLinkedDataClient().post(URI.create(graphUri), namedModel)) + try (Response postResponse = getGraphStoreClient().post(URI.create(graphUri), namedModel)) { if (!postResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) { @@ -133,10 +134,22 @@ public void write() } } } - + // purge cache entries that include the graph URI - if (getService().getBackendProxy() != null) ban(getService().getClient(), getService().getBackendProxy(), graphUri).close(); - if (getAdminService() != null && getAdminService().getBackendProxy() != null) ban(getAdminService().getClient(), getAdminService().getBackendProxy(), graphUri).close(); + if (getService().getBackendProxy() != null) + { + try (Response response = ban(getService().getClient(), getService().getBackendProxy(), graphUri)) + { + // Response automatically closed by try-with-resources + } + } + if (getAdminService() != null && getAdminService().getBackendProxy() != null) + { + try (Response response = ban(getAdminService().getClient(), getAdminService().getBackendProxy(), graphUri)) + { + // Response automatically closed by try-with-resources + } + } } } ); @@ -152,11 +165,11 @@ public void write() MultivaluedMap<String, Object> headers = new MultivaluedHashMap(); headers.putSingle(HttpHeaders.IF_NONE_MATCH, "*"); - try (Response putResponse = getLinkedDataClient().put(URI.create(getGraphURI()), model, headers)) + try (Response putResponse = getGraphStoreClient().put(URI.create(getGraphURI()), Entity.entity(model, getGraphStoreClient().getDefaultMediaType()), new jakarta.ws.rs.core.MediaType[]{}, headers)) { if (putResponse.getStatusInfo().equals(Response.Status.PRECONDITION_FAILED)) { - try (Response postResponse = getLinkedDataClient().post(URI.create(getGraphURI()), model)) + try (Response postResponse = getGraphStoreClient().post(URI.create(getGraphURI()), model)) { if (!postResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) { @@ -174,10 +187,22 @@ public void write() } } } - + // purge cache entries that include the graph URI - if (getService().getBackendProxy() != null) ban(getService().getClient(), getService().getBackendProxy(), getGraphURI()).close(); - if (getAdminService() != null && getAdminService().getBackendProxy() != null) ban(getAdminService().getClient(), getAdminService().getBackendProxy(), getGraphURI()).close(); + if (getService().getBackendProxy() != null) + { + try (Response response = ban(getService().getClient(), getService().getBackendProxy(), getGraphURI())) + { + // Response automatically closed by try-with-resources + } + } + if (getAdminService() != null && getAdminService().getBackendProxy() != null) + { + try (Response response = ban(getAdminService().getClient(), getAdminService().getBackendProxy(), getGraphURI())) + { + // Response automatically closed by try-with-resources + } + } } } @@ -222,13 +247,13 @@ public Service getAdminService() } /** - * Returns Linked Data client. + * Returns Graph Store client. * * @return client object */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/StreamRDFOutputWriter.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/StreamRDFOutputWriter.java index 2ebe0a38d..422e2da06 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/StreamRDFOutputWriter.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/StreamRDFOutputWriter.java @@ -17,7 +17,7 @@ package com.atomgraph.linkeddatahub.imports.stream; import com.atomgraph.core.MediaType; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import java.io.File; import java.io.FileInputStream; @@ -48,7 +48,7 @@ public class StreamRDFOutputWriter implements Function<Response, RDFGraphStoreOu private static final Logger log = LoggerFactory.getLogger(StreamRDFOutputWriter.class); private final Service service, adminService; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final String baseURI, graphURI; private final Query query; @@ -57,16 +57,16 @@ public class StreamRDFOutputWriter implements Function<Response, RDFGraphStoreOu * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc GSP client + * @param gsc GSP client * @param baseURI base URI * @param query transformation query or null * @param graphURI target graph URI */ - public StreamRDFOutputWriter(Service service, Service adminService, LinkedDataClient ldc, String baseURI, Query query, String graphURI) + public StreamRDFOutputWriter(Service service, Service adminService, GraphStoreClient gsc, String baseURI, Query query, String graphURI) { this.service = service; this.adminService = adminService; - this.ldc = ldc; + this.gsc = gsc; this.baseURI = baseURI; this.query = query; this.graphURI = graphURI; @@ -92,7 +92,7 @@ public RDFGraphStoreOutput apply(Response rdfInput) Lang lang = RDFLanguages.contentTypeToLang(mediaType.toString()); // convert media type to RDF language if (lang == null) throw new BadRequestException("Content type '" + mediaType + "' is not an RDF media type"); - RDFGraphStoreOutput output = new RDFGraphStoreOutput(getService(), getAdminService(), getLinkedDataClient(), fis, getBaseURI(), getQuery(), lang, getGraphURI()); + RDFGraphStoreOutput output = new RDFGraphStoreOutput(getService(), getAdminService(), getGraphStoreClient(), fis, getBaseURI(), getQuery(), lang, getGraphURI()); output.write(); return output; } @@ -129,13 +129,13 @@ public Service getAdminService() } /** - * Returns the Linked Data client. + * Returns the Graph Store client. * * @return client object */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutput.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutput.java index 71b4ad324..c4dd531ba 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutput.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutput.java @@ -16,7 +16,7 @@ */ package com.atomgraph.linkeddatahub.imports.stream.csv; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import com.univocity.parsers.csv.CsvParser; import com.univocity.parsers.csv.CsvParserSettings; @@ -46,21 +46,21 @@ public class CSVGraphStoreOutput // extends com.atomgraph.etl.csv.stream.CSVStre * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param base base URI * @param reader CSV reader * @param query <code>CONSTRUCT</code> transformation query * @param delimiter CSV delimiter * @param maxCharsPerColumn max number of characters per column */ - public CSVGraphStoreOutput(Service service, Service adminService, LinkedDataClient ldc, String base, Reader reader, Query query, char delimiter, Integer maxCharsPerColumn) + public CSVGraphStoreOutput(Service service, Service adminService, GraphStoreClient gsc, String base, Reader reader, Query query, char delimiter, Integer maxCharsPerColumn) { this.base = base; this.reader = reader; this.query = query; this.delimiter = delimiter; this.maxCharsPerColumn = maxCharsPerColumn; - this.processor = new CSVGraphStoreRowProcessor(service, adminService, ldc, base, query); + this.processor = new CSVGraphStoreRowProcessor(service, adminService, gsc, base, query); CsvParserSettings parserSettings = new CsvParserSettings(); parserSettings.setLineSeparatorDetectionEnabled(true); diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutputWriter.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutputWriter.java index 55458fed9..5ab88cd53 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutputWriter.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreOutputWriter.java @@ -16,7 +16,7 @@ */ package com.atomgraph.linkeddatahub.imports.stream.csv; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import java.io.File; import java.io.FileInputStream; @@ -48,7 +48,7 @@ public class CSVGraphStoreOutputWriter implements Function<Response, CSVGraphSto private static final Logger log = LoggerFactory.getLogger(CSVGraphStoreOutputWriter.class); private final Service service, adminService; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final String baseURI; private final Query query; private final char delimiter; @@ -58,16 +58,16 @@ public class CSVGraphStoreOutputWriter implements Function<Response, CSVGraphSto * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param baseURI base URI * @param query transformation query * @param delimiter CSV delimiter */ - public CSVGraphStoreOutputWriter(Service service, Service adminService, LinkedDataClient ldc, String baseURI, Query query, char delimiter) + public CSVGraphStoreOutputWriter(Service service, Service adminService, GraphStoreClient gsc, String baseURI, Query query, char delimiter) { this.service = service; this.adminService = adminService; - this.ldc = ldc; + this.gsc = gsc; this.baseURI = baseURI; this.query = query; this.delimiter = delimiter; @@ -89,7 +89,7 @@ public CSVGraphStoreOutput apply(Response csvInput) try (InputStream fis = new FileInputStream(tempFile); Reader reader = new InputStreamReader(fis, StandardCharsets.UTF_8)) { - CSVGraphStoreOutput output = new CSVGraphStoreOutput(getService(), getAdminService(), getLinkedDataClient(), getBaseURI(), reader, getQuery(), getDelimiter(), null); + CSVGraphStoreOutput output = new CSVGraphStoreOutput(getService(), getAdminService(), getGraphStoreClient(), getBaseURI(), reader, getQuery(), getDelimiter(), null); output.write(); return output; } @@ -126,13 +126,13 @@ public Service getAdminService() } /** - * Returns the Linked Data client. + * Returns the Graph Store client. * * @return client object */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreRowProcessor.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreRowProcessor.java index 5f56198e6..b07862894 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreRowProcessor.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/CSVGraphStoreRowProcessor.java @@ -16,12 +16,13 @@ */ package com.atomgraph.linkeddatahub.imports.stream.csv; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.exception.ImportException; import com.univocity.parsers.common.ParsingContext; import com.univocity.parsers.common.processor.RowProcessor; import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MultivaluedHashMap; import jakarta.ws.rs.core.MultivaluedMap; @@ -51,7 +52,7 @@ public class CSVGraphStoreRowProcessor implements RowProcessor // extends com.at private static final Logger log = LoggerFactory.getLogger(CSVGraphStoreRowProcessor.class); private final Service service, adminService; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final String base; private final Query query; private int subjectCount, tripleCount; @@ -61,15 +62,15 @@ public class CSVGraphStoreRowProcessor implements RowProcessor // extends com.at * * @param service SPARQL service of the application * @param adminService SPARQL service of the admin application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param base base URI * @param query transformation query */ - public CSVGraphStoreRowProcessor(Service service, Service adminService, LinkedDataClient ldc, String base, Query query) + public CSVGraphStoreRowProcessor(Service service, Service adminService, GraphStoreClient gsc, String base, Query query) { this.service = service; this.adminService = adminService; - this.ldc = ldc; + this.gsc = gsc; this.base = base; this.query = query; } @@ -96,8 +97,20 @@ public void rowProcessed(String[] row, ParsingContext context) try { // purge cache entries that include the graph URI - if (getService().getBackendProxy() != null) ban(getService().getClient(), getService().getBackendProxy(), graphUri).close(); - if (getAdminService() != null && getAdminService().getBackendProxy() != null) ban(getAdminService().getClient(), getAdminService().getBackendProxy(), graphUri).close(); + if (getService().getBackendProxy() != null) + { + try (Response response = ban(getService().getClient(), getService().getBackendProxy(), graphUri)) + { + // Response automatically closed by try-with-resources + } + } + if (getAdminService() != null && getAdminService().getBackendProxy() != null) + { + try (Response response = ban(getAdminService().getClient(), getAdminService().getBackendProxy(), graphUri)) + { + // Response automatically closed by try-with-resources + } + } } catch (Exception e) { @@ -121,11 +134,11 @@ protected void add(Model namedModel, String graphURI) MultivaluedMap<String, Object> headers = new MultivaluedHashMap(); headers.putSingle(HttpHeaders.IF_NONE_MATCH, "*"); - try (Response putResponse = getLinkedDataClient().put(URI.create(graphURI), namedModel, headers)) + try (Response putResponse = getGraphStoreClient().put(URI.create(graphURI), Entity.entity(namedModel, getGraphStoreClient().getDefaultMediaType()), new jakarta.ws.rs.core.MediaType[]{}, headers)) { if (putResponse.getStatusInfo().equals(Response.Status.PRECONDITION_FAILED)) { - try (Response postResponse = getLinkedDataClient().post(URI.create(graphURI), namedModel)) + try (Response postResponse = getGraphStoreClient().post(URI.create(graphURI), namedModel)) { if (!postResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) { @@ -264,13 +277,13 @@ public int getTripleCount() } /** - * Returns the HTTP client. + * Returns the Graph Store client. * * @return client object */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } } diff --git a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/ClientResponseSupplier.java b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/ClientResponseSupplier.java index da45b4546..078ff30c1 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/ClientResponseSupplier.java +++ b/src/main/java/com/atomgraph/linkeddatahub/imports/stream/csv/ClientResponseSupplier.java @@ -16,7 +16,7 @@ */ package com.atomgraph.linkeddatahub.imports.stream.csv; -import com.atomgraph.core.client.LinkedDataClient; +import com.atomgraph.core.client.GraphStoreClient; import java.net.URI; import java.util.function.Supplier; import jakarta.ws.rs.core.Response; @@ -35,7 +35,7 @@ public class ClientResponseSupplier implements Supplier<Response> private static final Logger log = LoggerFactory.getLogger(ClientResponseSupplier.class); - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final jakarta.ws.rs.core.MediaType[] mediaTypes; private final URI uri; @@ -44,11 +44,11 @@ public class ClientResponseSupplier implements Supplier<Response> * * @param uri request URI * @param mediaTypes registry of media types - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public ClientResponseSupplier(LinkedDataClient ldc, jakarta.ws.rs.core.MediaType[] mediaTypes, URI uri) + public ClientResponseSupplier(GraphStoreClient gsc, jakarta.ws.rs.core.MediaType[] mediaTypes, URI uri) { - this.ldc = ldc; + this.gsc = gsc; this.mediaTypes = mediaTypes; this.uri = uri; } @@ -57,19 +57,19 @@ public ClientResponseSupplier(LinkedDataClient ldc, jakarta.ws.rs.core.MediaType * Constructs supplier from request URI. * * @param uri request URI - * @param ldc Linked Data client + * @param gsc Graph Store client */ - public ClientResponseSupplier(LinkedDataClient ldc, URI uri) + public ClientResponseSupplier(GraphStoreClient gsc, URI uri) { - this(ldc, null, uri); + this(gsc, null, uri); } @Override public Response get() { - if (getMediaTypes() != null) return getLinkedDataClient().get(getURI(), getMediaTypes()); + if (getMediaTypes() != null) return getGraphStoreClient().get(getURI(), getMediaTypes()); - return getLinkedDataClient().get(getURI()); + return getGraphStoreClient().get(getURI()); } /** @@ -93,13 +93,13 @@ public jakarta.ws.rs.core.MediaType[] getMediaTypes() } /** - * Returns Linked Data client. + * Returns Graph Store client. * * @return manager instance */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } } diff --git a/src/main/java/com/atomgraph/linkeddatahub/model/impl/ServiceImpl.java b/src/main/java/com/atomgraph/linkeddatahub/model/impl/ServiceImpl.java index c6c03f80e..e754b91e5 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/model/impl/ServiceImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/model/impl/ServiceImpl.java @@ -158,18 +158,18 @@ public EndpointAccessor getEndpointAccessor() @Override public GraphStoreClient getGraphStoreClient() { - return getGraphStoreClient(getClient().target(getProxiedURI(URI.create(getGraphStore().getURI())))); + return getGraphStoreClient(getProxiedURI(URI.create(getGraphStore().getURI()))); } /** - * Creates Graph Store Protocol client for the specified URI web target. + * Creates Graph Store Protocol client for the specified endpoint URI. * - * @param webTarget URI web target + * @param endpoint endpoint * @return GSP client */ - public GraphStoreClient getGraphStoreClient(WebTarget webTarget) + public GraphStoreClient getGraphStoreClient(URI endpoint) { - GraphStoreClient graphStoreClient = GraphStoreClient.create(webTarget); + GraphStoreClient graphStoreClient = GraphStoreClient.create(getClient(), getMediaTypes(), endpoint); if (getAuthUser() != null && getAuthPwd() != null) { @@ -177,7 +177,7 @@ public GraphStoreClient getGraphStoreClient(WebTarget webTarget) credentials(getAuthUser(), getAuthPwd()). build(); - graphStoreClient.getEndpoint().register(authFeature); + graphStoreClient.register(authFeature); } return graphStoreClient; diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java index e4e45a97a..64c2a4494 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java @@ -18,7 +18,7 @@ import com.atomgraph.core.MediaTypes; import com.atomgraph.core.vocabulary.SD; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; @@ -115,8 +115,8 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") Resource graph = arg.getPropertyResourceValue(SD.name); if (graph == null || !graph.isURIResource()) throw new BadRequestException("Graph URI (sd:name) not provided"); - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getMediaTypes()); // TO-DO: inject - Model importModel = ldc.getModel(source.getURI()); + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getMediaTypes()); // TO-DO: inject + Model importModel = gsc.getModel(source.getURI()); // forward the stream to the named graph document -- do not directly append triples to graph because the agent might not have access to it return forwardPost(Entity.entity(importModel, com.atomgraph.client.MediaType.APPLICATION_NTRIPLES_TYPE), graph.getURI()); } @@ -215,10 +215,10 @@ public Response postFileBodyPart(Model model, Map<String, FormDataBodyPart> file */ protected Response forwardPost(Entity entity, String graphURI) { - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); // forward the stream to the named graph document. Buffer the entity first so that the server response is not returned before the client response completes - try (Response response = ldc.post(URI.create(graphURI), ldc.getReadableMediaTypes(Model.class), entity)) + try (Response response = gsc.post(URI.create(graphURI), entity, gsc.getReadableMediaTypes(Model.class))) { return Response.status(response.getStatus()). entity(response.readEntity(Model.class)). diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java index a296dbbb0..f4a1ccea9 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java @@ -18,7 +18,7 @@ import com.atomgraph.client.util.DataManager; import com.atomgraph.core.MediaTypes; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.imports.QueryLoader; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter; @@ -122,9 +122,9 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") Resource queryRes = part.getPropertyResourceValue(SPIN.query); if (queryRes == null) throw new BadRequestException("Container query string (spin:query) not provided"); - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); - QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, ldc); + QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, gsc); Query query = queryLoader.get(); if (!query.isSelectType()) throw new BadRequestException("Container query is not of SELECT type"); diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java index 939d2f241..cdbff42ef 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java @@ -21,11 +21,12 @@ import com.atomgraph.core.MediaTypes; import com.atomgraph.core.model.EndpointAccessor; import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.CSVImport; import com.atomgraph.linkeddatahub.model.RDFImport; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; +import com.atomgraph.linkeddatahub.server.model.Patchable; import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.PatchUpdateVisitor; @@ -119,7 +120,7 @@ * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class Graph extends GraphStoreImpl +public class Graph extends GraphStoreImpl implements Patchable { private static final Logger log = LoggerFactory.getLogger(Graph.class); @@ -731,7 +732,7 @@ public void submitImports(Model model) try { Service adminService = getApplication().canAs(EndUserApplication.class) ? getApplication().as(EndUserApplication.class).getAdminApplication().getService() : null; - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getImportClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getImportClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); while (it.hasNext()) @@ -740,9 +741,9 @@ public void submitImports(Model model) // start the import asynchroniously if (_import.canAs(CSVImport.class)) - getSystem().submitImport(_import.as(CSVImport.class), getApplication(), getApplication().getService(), adminService, getUriInfo().getBaseUri().toString(), ldc); + getSystem().submitImport(_import.as(CSVImport.class), getApplication(), getApplication().getService(), adminService, getUriInfo().getBaseUri().toString(), gsc); if (_import.canAs(RDFImport.class)) - getSystem().submitImport(_import.as(RDFImport.class), getApplication(), getApplication().getService(), adminService, getUriInfo().getBaseUri().toString(), ldc); + getSystem().submitImport(_import.as(RDFImport.class), getApplication(), getApplication().getService(), adminService, getUriInfo().getBaseUri().toString(), gsc); } } finally diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java index b49f85d87..cc449de4f 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java @@ -19,7 +19,7 @@ import com.atomgraph.client.util.DataManager; import com.atomgraph.core.MediaTypes; import com.atomgraph.core.vocabulary.SD; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.imports.QueryLoader; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; @@ -120,13 +120,13 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") validateNotInternalURL(URI.create(queryRes.getURI())); validateNotInternalURL(URI.create(source.getURI())); - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); - QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, ldc); + QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, gsc); Query query = queryLoader.get(); if (!query.isConstructType()) throw new BadRequestException("Transformation query is not of CONSTRUCT type"); - Model importModel = ldc.getModel(source.getURI()); + Model importModel = gsc.getModel(source.getURI()); try (QueryExecution qex = QueryExecution.create(query, importModel)) { Model transformModel = qex.execConstruct(); @@ -211,9 +211,9 @@ public Response postFileBodyPart(Model model, Map<String, FormDataBodyPart> file // LNK-002: Validate query URI to prevent SSRF attacks validateNotInternalURL(URI.create(queryRes.getURI())); - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); - QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, ldc); + QueryLoader queryLoader = new QueryLoader(URI.create(queryRes.getURI()), getApplication().getBase().getURI(), Syntax.syntaxARQ, gsc); Query query = queryLoader.get(); if (!query.isConstructType()) throw new BadRequestException("Transformation query is not of CONSTRUCT type"); @@ -240,10 +240,10 @@ public Response postFileBodyPart(Model model, Map<String, FormDataBodyPart> file */ protected Response forwardPost(Entity entity, String graphURI) { - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); // forward the stream to the named graph document. Buffer the entity first so that the server response is not returned before the client response completes - try (Response response = ldc.post(URI.create(graphURI), ldc.getReadableMediaTypes(Model.class), entity)) + try (Response response = gsc.post(URI.create(graphURI), entity, gsc.getReadableMediaTypes(Model.class))) { return Response.status(response.getStatus()). entity(response.readEntity(Model.class)). diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java similarity index 72% rename from src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java rename to src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java index 67c25cd0f..b064bc6bf 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/Clear.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/ClearOntology.java @@ -47,10 +47,10 @@ * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} * @see com.atomgraph.linkeddatahub.server.filter.request.OntologyFilter */ -public class Clear +public class ClearOntology { - private static final Logger log = LoggerFactory.getLogger(Clear.class); + private static final Logger log = LoggerFactory.getLogger(ClearOntology.class); private final com.atomgraph.linkeddatahub.apps.model.Application application; private final com.atomgraph.linkeddatahub.Application system; @@ -62,7 +62,7 @@ public class Clear * @param system system application */ @Inject - public Clear(com.atomgraph.linkeddatahub.apps.model.Application application, com.atomgraph.linkeddatahub.Application system) + public ClearOntology(com.atomgraph.linkeddatahub.apps.model.Application application, com.atomgraph.linkeddatahub.Application system) { this.application = application; this.system = system; @@ -81,33 +81,40 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer { if (ontologyURI == null) throw new BadRequestException("Ontology URI not specified"); - EndUserApplication app = getApplication().as(AdminApplication.class).getEndUserApplication(); // we're assuming the current app is admin - OntModelSpec ontModelSpec = new OntModelSpec(getSystem().getOntModelSpec(app)); + EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); // we're assuming the current app is admin + OntModelSpec ontModelSpec = new OntModelSpec(getSystem().getOntModelSpec(endUserApp)); if (ontModelSpec.getDocumentManager().getFileManager().hasCachedModel(ontologyURI)) { if (log.isDebugEnabled()) log.debug("Clearing ontology with URI '{}' from memory", ontologyURI); ontModelSpec.getDocumentManager().getFileManager().removeCacheModel(ontologyURI); + + URI ontologyDocURI = UriBuilder.fromUri(ontologyURI).fragment(null).build(); // skip fragment from the ontology URI to get its graph URI + // purge from admin cache if (getApplication().getFrontendProxy() != null) { - URI ontologyDocURI = UriBuilder.fromUri(ontologyURI).fragment(null).build(); // skip fragment from the ontology URI to get its graph URI if (log.isDebugEnabled()) log.debug("Purge ontology document with URI '{}' from frontend proxy cache", ontologyDocURI); - try (Response response = purge(getApplication().getFrontendProxy(), ontologyDocURI.toString())) - { - // Response automatically closed by try-with-resources - } + ban(getApplication().getFrontendProxy(), ontologyDocURI.toString(), false); } if (getApplication().getService().getBackendProxy() != null) { if (log.isDebugEnabled()) log.debug("Ban ontology with URI '{}' from backend proxy cache", ontologyURI); - try (Response response = ban(getApplication().getService().getBackendProxy(), ontologyURI)) - { - // Response automatically closed by try-with-resources - } + ban(getApplication().getService().getBackendProxy(), ontologyURI); + } + // purge from end-user cache + if (endUserApp.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purge ontology document with URI '{}' from frontend proxy cache", ontologyDocURI); + ban(endUserApp.getFrontendProxy(), ontologyDocURI.toString(), false); + } + if (endUserApp.getService().getBackendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Ban ontology with URI '{}' from backend proxy cache", ontologyURI); + ban(endUserApp.getService().getBackendProxy(), ontologyURI); } // !!! we need to reload the ontology model before returning a response, to make sure the next request already gets the new version !!! // same logic as in OntologyFilter. TO-DO: encapsulate? - OntologyModelGetter modelGetter = new OntologyModelGetter(app, ontModelSpec, getSystem().getOntologyQuery()); + OntologyModelGetter modelGetter = new OntologyModelGetter(endUserApp, ontModelSpec, getSystem().getOntologyQuery()); ontModelSpec.setImportModelGetter(modelGetter); if (log.isDebugEnabled()) log.debug("Started loading ontology with URI '{}' from the admin dataset", ontologyURI); Model baseModel = modelGetter.getModel(ontologyURI); @@ -125,36 +132,36 @@ public Response post(@FormParam("uri") String ontologyURI, @HeaderParam("Referer else return Response.ok().build(); } + public void ban(Resource proxy, String url) + { + ban(proxy, url, true); + } + /** * Bans URL from the backend proxy cache. * * @param proxy proxy server URL * @param url banned URL - * @return proxy server response - */ - public Response ban(Resource proxy, String url) - { - if (url == null) throw new IllegalArgumentException("Resource cannot be null"); - - return getSystem().getClient().target(proxy.getURI()).request(). - header(CacheInvalidationFilter.HEADER_NAME, UriComponent.encode(url, UriComponent.Type.UNRESERVED)). // the value has to be URL-encoded in order to match request URLs in Varnish - method("BAN", Response.class); - } - - /** - * Purges URL from proxy cache. - * - * @param proxy proxy resource - * @param url URL to be banned - * @return response from proxy + * @param urlEncode if true, the banned URL value will be URL-encoded */ - public Response purge(Resource proxy, String url) + public void ban(Resource proxy, String url, boolean urlEncode) { if (url == null) throw new IllegalArgumentException("Resource cannot be null"); - // create new Client instance, otherwise ApacheHttpClient reuses connection and Varnish ignores BAN request - return getSystem().getClient().target(proxy.getURI()).request(). - method("PURGE", Response.class); + // Extract path from URL - Varnish req.url only contains the path, not the full URL + URI uri = URI.create(url); + String path = uri.getPath(); + if (uri.getQuery() != null) path += "?" + uri.getQuery(); + + final String urlValue = urlEncode ? UriComponent.encode(path, UriComponent.Type.UNRESERVED) : path; + + try (Response cr = getSystem().getClient().target(proxy.getURI()). + request(). + header(CacheInvalidationFilter.HEADER_NAME, urlValue). + method("BAN", Response.class)) + { + // Response automatically closed by try-with-resources + } } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java new file mode 100644 index 000000000..1cca2ff2c --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -0,0 +1,470 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.resource.admin.pkg; + +import com.atomgraph.client.util.DataManager; +import com.atomgraph.linkeddatahub.apps.model.AdminApplication; +import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; +import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; +import com.atomgraph.linkeddatahub.server.security.AgentContext; +import com.atomgraph.linkeddatahub.server.util.UriPath; +import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; +import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; +import jakarta.inject.Inject; +import jakarta.servlet.ServletContext; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.container.ResourceContext; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriBuilder; +import org.apache.commons.codec.binary.Hex; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import org.apache.jena.ontology.ConversionException; +import org.apache.jena.update.UpdateFactory; +import org.apache.jena.update.UpdateRequest; +import org.apache.jena.util.FileManager; + +/** + * JAX-RS resource that installs a LinkedDataHub package. + * Package installation involves: + * 1. Fetching package metadata + * 2. Downloading package ontology and PUTting as new document under model/ontologies/{hash}/ + * 3. Adding owl:imports of package ontology to namespace ontology + * 4. Downloading package stylesheet (layout.xsl) and saving to /static/{package-path}/ + * 5. Regenerating application master stylesheet + * 6. Adding ldh:import triple to application (TODO) + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class InstallPackage +{ + private static final Logger log = LoggerFactory.getLogger(InstallPackage.class); + + private final com.atomgraph.linkeddatahub.apps.model.Application application; + private final com.atomgraph.linkeddatahub.Application system; + private final DataManager dataManager; + private final Optional<AgentContext> agentContext; + + @Context ServletContext servletContext; + @Context ResourceContext resourceContext; + + /** + * Constructs endpoint. + * + * @param application matched application (admin app) + * @param system system application + * @param dataManager data manager + * @param agentContext authenticated agent context + */ + @Inject + public InstallPackage(com.atomgraph.linkeddatahub.apps.model.Application application, + com.atomgraph.linkeddatahub.Application system, + DataManager dataManager, + Optional<AgentContext> agentContext) + { + this.application = application; + this.system = system; + this.dataManager = dataManager; + this.agentContext = agentContext; + } + + /** + * Installs a package into the current dataspace. + * + * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) + * @param referer the referring URL + * @return JAX-RS response + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response post(@FormParam("package-uri") String packageURI, @HeaderParam("Referer") URI referer) + { + if (packageURI == null) + { + if (log.isErrorEnabled()) log.error("Package URI not specified"); + throw new BadRequestException("Package URI not specified"); + } + + EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); + + if (log.isInfoEnabled()) log.info("Installing package: {}", packageURI); + + // 1. Fetch package + com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); + if (pkg == null) + { + if (log.isErrorEnabled()) log.error("Loading package failed: {}", packageURI); + throw new WebApplicationException("Loading package failed", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity + } + + Resource ontology = pkg.getOntology(); + Resource stylesheet = pkg.getStylesheet(); + + // either ontology or stylesheet need to be specified, or both + if (ontology == null && stylesheet == null) + { + if (log.isErrorEnabled()) log.error("Package ontology and stylesheet are both unspecified for package: {}", packageURI); + throw new WebApplicationException("Package ontology and stylesheet are both unspecified", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity + } + + try + { + String packagePath = UriPath.convert(packageURI); + + // 2. Download and install ontology if present + if (ontology != null) + { + if (log.isDebugEnabled()) log.debug("Downloading package ontology from: {}", ontology.getURI()); + Model ontologyModel = downloadOntology(ontology.getURI()); + installOntology(endUserApp, ontologyModel, ontology.getURI()); + } + + // 3. Download and install stylesheet if present + if (stylesheet != null) + { + URI stylesheetURI = URI.create(stylesheet.getURI()); + + if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); + String stylesheetContent = downloadStylesheet(stylesheetURI); + installStylesheet(packagePath, stylesheetContent); + + // 4. Regenerate master stylesheet + regenerateMasterStylesheet(endUserApp, packagePath); + } + + // 5. Add ldh:import triple to application (in system.trig) + //addImportToApplication(endUserApp, packageURI); + + if (log.isInfoEnabled()) log.info("Successfully installed package: {}", packageURI); + + // Redirect back to referer or application base + URI redirectURI = (referer != null) ? referer : endUserApp.getBaseURI(); + return Response.seeOther(redirectURI).build(); + } + catch (IOException e) + { + log.error("Failed to install package: {}", packageURI, e); + throw new WebApplicationException("Package installation failed", e); + } + } + + /** + * Loads package metadata from its URI using GraphStoreClient. + * Package metadata is expected to be available as Linked Data. + * + * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) + * @return Package instance + * @throws NotFoundException if package cannot be found (404) + */ + private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String packageURI) + { + if (log.isDebugEnabled()) log.debug("Loading package from: {}", packageURI); + + final Model model; + + // check if we have the model in the cache first and if yes, return it from there instead making an HTTP request + if (((FileManager)getDataManager()).hasCachedModel(packageURI) || + (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file + { + if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI)); + if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI)); + model = getDataManager().loadModel(packageURI); + } + else + { + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + model = gsc.getModel(packageURI); + } + + try + { + return model.getResource(packageURI).as(com.atomgraph.linkeddatahub.apps.model.Package.class); + } + catch (ConversionException ex) + { + return null; + } + } + + /** + * Downloads RDF from a URI using GraphStoreClient. + */ + private Model downloadOntology(String uri) + { + if (log.isDebugEnabled()) log.debug("Downloading ontology from: {}", uri); + + // check if we have the model in the cache first and if yes, return it from there instead making an HTTP request + if (((FileManager)getDataManager()).hasCachedModel(uri) || + (getDataManager().isResolvingMapped() && getDataManager().isMapped(uri))) // read mapped URIs (such as system ontologies) from a file + { + if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", uri, ((FileManager)getDataManager()).hasCachedModel(uri)); + if (log.isDebugEnabled()) log.debug("isMapped({}): {}", uri, getDataManager().isMapped(uri)); + return getDataManager().loadModel(uri); + } + else + { + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + return gsc.getModel(uri); + } + } + + /** + * Downloads XSLT stylesheet content from a URI using Jersey Client. + * Prioritizes text/xsl, falls back to text/*. + */ + private String downloadStylesheet(URI uri) throws IOException + { + if (log.isDebugEnabled()) log.debug("Downloading XSLT stylesheet from: {}", uri); + + WebTarget target = getClient().target(uri); + // Prioritize text/xsl (q=1.0), then any text/* (q=0.8) + try (Response response = target.request("text/xsl", "text/*;q=0.8").get()) + { + if (!response.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to download XSLT from {}: {}", uri, response.getStatus()); + throw new IOException("Failed to download XSLT from " + uri + ": " + response.getStatus()); + } + + return response.readEntity(String.class); + } + } + + /** + * Installs ontology by PUTting as a new document and adding owl:imports to namespace ontology. + * + * @param app the end-user application + * @param ontologyModel the package ontology model + * @param packageOntologyURI the package ontology URI + * @throws IOException if installation fails + */ + private void installOntology(EndUserApplication app, Model ontologyModel, String packageOntologyURI) throws IOException + { + AdminApplication adminApp = app.getAdminApplication(); + + // 1. Create hash of package URI to use as document slug + String hash; + try + { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + md.update(packageOntologyURI.getBytes(StandardCharsets.UTF_8)); + hash = Hex.encodeHexString(md.digest()); + if (log.isDebugEnabled()) log.debug("Package ontology URI '{}' hashed to '{}'", packageOntologyURI, hash); + } + catch (NoSuchAlgorithmException e) + { + if (log.isErrorEnabled()) log.error("Failed to hash package ontology URI: {}", packageOntologyURI, e); + throw new IOException("Failed to hash package ontology URI", e); + } + + // 2. PUT package ontology as a document under model/ontologies/{hash}/ (overwrites if exists) + URI ontologyDocumentURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/{hash}/").build(hash); + if (log.isDebugEnabled()) log.debug("PUTting package ontology to document: {}", ontologyDocumentURI); + + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + + // Delegate agent credentials if authenticated + if (getAgentContext().isPresent()) + { + if (log.isDebugEnabled()) log.debug("Delegating agent credentials for PUT request"); + gsc = gsc.delegation(adminApp.getBaseURI(), getAgentContext().get()); + } + + try (Response putResponse = gsc.put(ontologyDocumentURI, ontologyModel)) + { + if (!putResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to PUT package ontology to {}: {}", ontologyDocumentURI, putResponse.getStatus()); + throw new IOException("Failed to PUT package ontology to " + ontologyDocumentURI + ": " + putResponse.getStatus()); + } + if (log.isDebugEnabled()) log.debug("Package ontology PUT response status: {}", putResponse.getStatus()); + } + + // 3. Add owl:imports triple to namespace ontology in namespace graph + String namespaceOntologyURI = app.getOntology().getURI(); + URI namespaceGraphURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/namespace/").build(); + + if (log.isDebugEnabled()) log.debug("Adding owl:imports from namespace ontology '{}' to package ontology '{}'", namespaceOntologyURI, packageOntologyURI); + + String updateString = String.format( + "PREFIX owl: <http://www.w3.org/2002/07/owl#> " + + "INSERT { <%s> owl:imports <%s> } WHERE { }", + namespaceOntologyURI, packageOntologyURI + ); + UpdateRequest updateRequest = UpdateFactory.create(updateString); + + try (Response patchResponse = gsc.patch(namespaceGraphURI, updateRequest)) + { + if (!patchResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to PATCH namespace graph {}: {}", namespaceGraphURI, patchResponse.getStatus()); + throw new IOException("Failed to PATCH namespace graph " + namespaceGraphURI + ": " + patchResponse.getStatus()); + } + if (log.isDebugEnabled()) log.debug("Namespace graph PATCH response status: {}", patchResponse.getStatus()); + } + + // 4. Clear and reload namespace ontology from cache + if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); + getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); + } + + /** + * Installs stylesheet to /static/<package-path>/layout.xsl + */ + private void installStylesheet(String packagePath, String stylesheetContent) throws IOException + { + Path staticDir = Paths.get(getServletContext().getRealPath("/static")); + Path packageDir = staticDir.resolve(packagePath); + Files.createDirectories(packageDir); + + Path stylesheetFile = packageDir.resolve("layout.xsl"); + Files.writeString(stylesheetFile, stylesheetContent); + + if (log.isDebugEnabled()) log.debug("Installed package stylesheet at: {}", stylesheetFile); + } + + /** + * Regenerates master stylesheet for the application. + */ + private void regenerateMasterStylesheet(EndUserApplication app, String newPackagePath) throws IOException + { + // Get all currently installed packages + Set<Resource> packages = app.getImportedPackages(); + List<String> packagePaths = new ArrayList<>(); + + for (Resource pkg : packages) + packagePaths.add(UriPath.convert(pkg.getURI())); + + // Add the new package + if (!packagePaths.contains(newPackagePath)) + packagePaths.add(newPackagePath); + + // Regenerate master stylesheet + XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); + updater.regenerateMasterStylesheet(packagePaths); + } + + /** + * Adds ldh:import triple to the end-user application resource. + */ +// private void addImportToApplication(EndUserApplication app, String packageURI) +// { +// // This would need to modify system.trig via SPARQL UPDATE +// // For now, log a warning that this needs manual configuration +// if (log.isWarnEnabled()) +// { +// log.warn("TODO: Add ldh:import triple to application. Manual edit required:"); +// log.warn(" <{}> ldh:import <{}> .", app.getURI(), packageURI); +// } +// } + + /** + * Returns the current application. + * + * @return application resource + */ + public com.atomgraph.linkeddatahub.apps.model.Application getApplication() + { + return application; + } + + /** + * Returns the system application. + * + * @return system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns Jersey HTTP client. + * + * @return HTTP client + */ + public Client getClient() + { + return getSystem().getClient(); + } + + /** + * Returns servlet context. + * + * @return servlet context + */ + public ServletContext getServletContext() + { + return servletContext; + } + + /** + * Returns RDF data manager. + * + * @return RDF data manager + */ + public DataManager getDataManager() + { + return dataManager; + } + + /** + * Returns JAX-RS resource context. + * + * @return resource context + */ + public ResourceContext getResourceContext() + { + return resourceContext; + } + + /** + * Returns the authenticated agent context. + * + * @return agent context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java new file mode 100644 index 000000000..f4ada8c98 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -0,0 +1,413 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.resource.admin.pkg; + +import com.atomgraph.client.util.DataManager; +import com.atomgraph.linkeddatahub.apps.model.AdminApplication; +import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; +import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; +import com.atomgraph.linkeddatahub.server.security.AgentContext; +import com.atomgraph.linkeddatahub.server.util.UriPath; +import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; +import jakarta.inject.Inject; +import jakarta.servlet.ServletContext; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.WebApplicationException; +import jakarta.ws.rs.container.ResourceContext; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriBuilder; +import org.apache.commons.codec.binary.Hex; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.update.UpdateFactory; +import org.apache.jena.update.UpdateRequest; +import org.apache.jena.util.FileManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + * JAX-RS resource that uninstalls a LinkedDataHub package. + * Package uninstallation involves: + * 1. DELETEing package ontology document from ontologies/{hash}/ + * 2. Removing owl:imports triple from namespace graph + * 3. Clearing and reloading namespace ontology from cache + * 4. Deleting package stylesheet from /static/{package-path}/ + * 5. Regenerating application master stylesheet + * 6. Removing ldh:import triple from application (TODO) + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class UninstallPackage +{ + private static final Logger log = LoggerFactory.getLogger(UninstallPackage.class); + + private final com.atomgraph.linkeddatahub.apps.model.Application application; + private final com.atomgraph.linkeddatahub.Application system; + private final DataManager dataManager; + private final Optional<AgentContext> agentContext; + + @Context ServletContext servletContext; + @Context ResourceContext resourceContext; + + /** + * Constructs endpoint. + * + * @param application matched application (admin app) + * @param system system application + * @param dataManager data manager + * @param agentContext authenticated agent context + */ + @Inject + public UninstallPackage(com.atomgraph.linkeddatahub.apps.model.Application application, + com.atomgraph.linkeddatahub.Application system, + DataManager dataManager, + Optional<AgentContext> agentContext) + { + this.application = application; + this.system = system; + this.dataManager = dataManager; + this.agentContext = agentContext; + } + + /** + * Uninstalls a package from the current dataspace. + * + * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) + * @param referer the referring URL + * @return JAX-RS response + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response post(@FormParam("package-uri") String packageURI, @HeaderParam("Referer") URI referer) + { + if (packageURI == null) + { + if (log.isErrorEnabled()) log.error("Package URI not specified"); + throw new BadRequestException("Package URI not specified"); + } + + try + { + EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); + + if (log.isInfoEnabled()) log.info("Uninstalling package: {}", packageURI); + + String packagePath = UriPath.convert(packageURI); + + // 1. Remove package ontology and owl:imports from namespace graph + uninstallOntology(endUserApp, packageURI); + + // 2. Delete stylesheet from /static/<package-path>/ + uninstallStylesheet(packagePath); + + // 3. Regenerate master stylesheet + regenerateMasterStylesheet(endUserApp, packagePath); + + // 4. Remove ldh:import triple from application + //removeImportFromApplication(endUserApp, packageURI); + + if (log.isInfoEnabled()) log.info("Successfully uninstalled package: {}", packageURI); + + // Redirect back to referer or application base + URI redirectURI = (referer != null) ? referer : endUserApp.getBaseURI(); + return Response.seeOther(redirectURI).build(); + } + catch (IOException e) + { + if (log.isErrorEnabled()) log.error("Failed to uninstall package: {}", packageURI, e); + throw new WebApplicationException("Package uninstallation failed", e); + } + } + + /** + * Uninstalls ontology by deleting the package ontology document and removing owl:imports from namespace graph. + * + * @param app the end-user application + * @param packageURI the package URI + * @throws IOException if uninstallation fails + */ + private void uninstallOntology(EndUserApplication app, String packageURI) throws IOException + { + AdminApplication adminApp = app.getAdminApplication(); + + // 1. Fetch package to get ontology URI + com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); + if (pkg == null) + { + if (log.isWarnEnabled()) log.warn("Package not found, skipping ontology uninstallation: {}", packageURI); + return; + } + + Resource ontology = pkg.getOntology(); + if (ontology == null) + { + if (log.isWarnEnabled()) log.warn("Package ontology not specified, skipping ontology uninstallation"); + return; + } + + String packageOntologyURI = ontology.getURI(); + + // 2. Calculate hash of package ontology URI + String hash; + try + { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + md.update(packageOntologyURI.getBytes(StandardCharsets.UTF_8)); + hash = Hex.encodeHexString(md.digest()); + if (log.isDebugEnabled()) log.debug("Package ontology URI '{}' hashed to '{}'", packageOntologyURI, hash); + } + catch (NoSuchAlgorithmException e) + { + if (log.isErrorEnabled()) log.error("Failed to hash package ontology URI: {}", packageOntologyURI, e); + throw new IOException("Failed to hash package ontology URI", e); + } + + // 3. DELETE package ontology document at ontologies/{hash}/ + URI ontologyDocumentURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/{hash}/").build(hash); + if (log.isDebugEnabled()) log.debug("DELETEing package ontology document: {}", ontologyDocumentURI); + + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + + // Delegate agent credentials if authenticated + if (getAgentContext().isPresent()) + { + if (log.isDebugEnabled()) log.debug("Delegating agent credentials for DELETE request"); + gsc = gsc.delegation(adminApp.getBaseURI(), getAgentContext().get()); + } + + try (Response deleteResponse = gsc.delete(ontologyDocumentURI)) + { + if (!deleteResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to DELETE package ontology document {}: {}", ontologyDocumentURI, deleteResponse.getStatus()); + throw new IOException("Failed to DELETE package ontology document " + ontologyDocumentURI + ": " + deleteResponse.getStatus()); + } + if (log.isDebugEnabled()) log.debug("Package ontology DELETE response status: {}", deleteResponse.getStatus()); + } + + // 4. Remove owl:imports triple from namespace ontology in namespace graph + String namespaceOntologyURI = app.getOntology().getURI(); + URI namespaceGraphURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/namespace/").build(); + + if (log.isDebugEnabled()) log.debug("Removing owl:imports from namespace ontology '{}' to package ontology '{}'", namespaceOntologyURI, packageOntologyURI); + + String updateString = String.format( + "PREFIX owl: <http://www.w3.org/2002/07/owl#> " + + "DELETE WHERE { <%s> owl:imports <%s> }", + namespaceOntologyURI, packageOntologyURI + ); + UpdateRequest updateRequest = UpdateFactory.create(updateString); + + try (Response patchResponse = gsc.patch(namespaceGraphURI, updateRequest)) + { + if (!patchResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to PATCH namespace graph {}: {}", namespaceGraphURI, patchResponse.getStatus()); + throw new IOException("Failed to PATCH namespace graph " + namespaceGraphURI + ": " + patchResponse.getStatus()); + } + if (log.isDebugEnabled()) log.debug("Namespace graph PATCH response status: {}", patchResponse.getStatus()); + } + + // 5. Clear and reload namespace ontology from cache + if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); + getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); + } + + /** + * Deletes stylesheet from /static/<package-path>/ + */ + private void uninstallStylesheet(String packagePath) throws IOException + { + Path staticDir = Paths.get(getServletContext().getRealPath("/static")); + Path packageDir = staticDir.resolve(packagePath); + + if (Files.exists(packageDir)) + { + // Delete layout.xsl + Path stylesheetFile = packageDir.resolve("layout.xsl"); + if (Files.exists(stylesheetFile)) + { + Files.delete(stylesheetFile); + if (log.isDebugEnabled()) log.debug("Deleted package stylesheet: {}", stylesheetFile); + } + + // Delete directory if empty + if (Files.list(packageDir).count() == 0) + { + Files.delete(packageDir); + if (log.isDebugEnabled()) log.debug("Deleted package directory: {}", packageDir); + } + } + } + + /** + * Regenerates master stylesheet for the application without the uninstalled package. + */ + private void regenerateMasterStylesheet(EndUserApplication app, String removedPackagePath) throws IOException + { + // Get all currently installed packages + Set<Resource> packages = app.getImportedPackages(); + List<String> packagePaths = new ArrayList<>(); + + for (Resource pkg : packages) + { + String pkgPath = UriPath.convert(pkg.getURI()); + // Exclude the package being removed + if (!pkgPath.equals(removedPackagePath)) + { + packagePaths.add(pkgPath); + } + } + + // Regenerate master stylesheet + XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); + updater.regenerateMasterStylesheet(packagePaths); + } + + /** + * Removes ldh:import triple from the end-user application resource. + */ +// private void removeImportFromApplication(EndUserApplication app, String packageURI) +// { +// // This would need to modify system.trig via SPARQL UPDATE +// // For now, log a warning that this needs manual configuration +// if (log.isWarnEnabled()) +// { +// log.warn("TODO: Remove ldh:import triple from application. Manual edit required:"); +// log.warn(" DELETE DATA {{ <{}> ldh:import <{}> }}", app.getURI(), packageURI); +// } +// } + + /** + * Returns the current application. + * + * @return application resource + */ + public com.atomgraph.linkeddatahub.apps.model.Application getApplication() + { + return application; + } + + /** + * Returns servlet context. + * + * @return servlet context + */ + public ServletContext getServletContext() + { + return servletContext; + } + + /** + * Loads package metadata from its URI using GraphStoreClient. + * Package metadata is expected to be available as Linked Data. + * + * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) + * @return Package instance, or null if package cannot be loaded + */ + private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String packageURI) + { + if (log.isDebugEnabled()) log.debug("Loading package from: {}", packageURI); + + try + { + final Model model; + + // check if we have the model in the cache first and if yes, return it from there instead making an HTTP request + if (((FileManager)getDataManager()).hasCachedModel(packageURI) || + (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file + { + if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI)); + if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI)); + model = getDataManager().loadModel(packageURI); + } + else + { + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + model = gsc.getModel(packageURI); + } + + return model.getResource(packageURI).as(com.atomgraph.linkeddatahub.apps.model.Package.class); + } + catch (Exception e) + { + if (log.isWarnEnabled()) log.warn("Failed to load package: {}", packageURI, e); + return null; + } + } + + /** + * Returns the system application. + * + * @return system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns RDF data manager. + * + * @return RDF data manager + */ + public DataManager getDataManager() + { + return dataManager; + } + + /** + * Returns JAX-RS resource context. + * + * @return resource context + */ + public ResourceContext getResourceContext() + { + return resourceContext; + } + + /** + * Returns the authenticated agent context. + * + * @return agent context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java b/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java index babd44aa6..7353e0297 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/event/AuthorizationCreated.java @@ -18,7 +18,7 @@ import com.atomgraph.core.util.jena.DataManager; import com.atomgraph.linkeddatahub.apps.model.Application; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import org.apache.jena.rdf.model.Resource; /** @@ -30,20 +30,20 @@ public class AuthorizationCreated { private final Application app; - private final LinkedDataClient ldc; + private final GraphStoreClient gsc; private final Resource authorization; /** * Constructs the event from application and authorization. * * @param app associated application - * @param ldc Linked Data client + * @param gsc Graph Store client * @param authorization associated authorization */ - public AuthorizationCreated(Application app, LinkedDataClient ldc, Resource authorization) + public AuthorizationCreated(Application app, GraphStoreClient gsc, Resource authorization) { this.app = app; - this.ldc = ldc; + this.gsc = gsc; this.authorization = authorization; } @@ -58,13 +58,13 @@ public Application getApplication() } /** - * Returns Linked Data client. + * Returns Graph Store client. * * @return client */ - public LinkedDataClient getLinkedDataClient() + public GraphStoreClient getGraphStoreClient() { - return ldc; + return gsc; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/response/CacheInvalidationFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/response/CacheInvalidationFilter.java index 25f5789b9..b3e7e1874 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/response/CacheInvalidationFilter.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/response/CacheInvalidationFilter.java @@ -35,6 +35,8 @@ import java.util.Set; import org.apache.jena.rdf.model.Resource; import org.glassfish.jersey.uri.UriComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Attempts to make backend (triplestore) proxy cache layer transparent by invalidating cache entries that potentially become stale after a write/update request. @@ -45,12 +47,14 @@ @Priority(Priorities.USER + 400) public class CacheInvalidationFilter implements ContainerResponseFilter { - + + private static final Logger log = LoggerFactory.getLogger(CacheInvalidationFilter.class); + /** * Name of the HTTP request header that is used to pass values of URLs for invalidation. */ public static final String HEADER_NAME = "X-Escaped-Request-URI"; - + @Inject com.atomgraph.linkeddatahub.Application system; @Inject jakarta.inject.Provider<Optional<com.atomgraph.linkeddatahub.apps.model.Application>> app; @@ -137,7 +141,17 @@ public void filter(ContainerRequestContext req, ContainerResponseContext resp) t public void banIfNotNull(Resource proxy, String url) { if (proxy != null) - ban(proxy, url).close(); + { + try (Response response = ban(proxy, url)) + { + // Response is automatically closed by try-with-resources, ensuring connection is released + } + catch (Exception ex) + { + // Log and swallow exception to prevent cache invalidation errors from failing user requests + if (log.isErrorEnabled()) log.error("Cache invalidation failed for URL: " + url, ex); + } + } } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java b/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java index db5ac8908..206228401 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/io/ValidatingModelProvider.java @@ -18,7 +18,7 @@ import com.atomgraph.linkeddatahub.apps.model.AdminApplication; import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.auth.Agent; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.vocabulary.ACL; @@ -245,10 +245,10 @@ public Resource processRead(Resource resource) // this logic really belongs in a if (getApplication().isPresent() && resource.hasProperty(RDF.type, ACL.Authorization)) { - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContextProvider().get().orElse(null)); getSystem().getEventBus().post(new com.atomgraph.linkeddatahub.server.event.AuthorizationCreated(getEndUserApplication(), - ldc, resource)); + gsc, resource)); } return resource; diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java index 91667c801..430427a60 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java @@ -22,7 +22,9 @@ import com.atomgraph.linkeddatahub.resource.Generate; import com.atomgraph.linkeddatahub.resource.Namespace; import com.atomgraph.linkeddatahub.resource.Transform; -import com.atomgraph.linkeddatahub.resource.admin.Clear; +import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; +import com.atomgraph.linkeddatahub.resource.admin.pkg.InstallPackage; +import com.atomgraph.linkeddatahub.resource.admin.pkg.UninstallPackage; import com.atomgraph.linkeddatahub.resource.admin.SignUp; import com.atomgraph.linkeddatahub.resource.Graph; import com.atomgraph.linkeddatahub.resource.acl.Access; @@ -216,13 +218,35 @@ public Class getGenerateEndpoint() /** * Returns the endpoint that allows clearing ontologies from cache by URI. - * + * * @return endpoint resource */ @Path("clear") public Class getClearEndpoint() { - return getProxyClass().orElse(Clear.class); + return getProxyClass().orElse(ClearOntology.class); + } + + /** + * Returns the endpoint for installing LinkedDataHub packages. + * + * @return endpoint resource + */ + @Path("packages/install") + public Class getInstallPackageEndpoint() + { + return getProxyClass().orElse(InstallPackage.class); + } + + /** + * Returns the endpoint for uninstalling LinkedDataHub packages. + * + * @return endpoint resource + */ + @Path("packages/uninstall") + public Class getUninstallPackageEndpoint() + { + return getProxyClass().orElse(UninstallPackage.class); } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java index 6dc3c2f10..1c25cd2a2 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java @@ -18,7 +18,6 @@ import com.atomgraph.core.MediaTypes; import com.atomgraph.core.riot.lang.RDFPostReader; -import static com.atomgraph.linkeddatahub.apps.model.Application.UPLOADS_PATH; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.security.AgentContext; import java.net.URI; @@ -57,6 +56,11 @@ public abstract class GraphStoreImpl extends com.atomgraph.core.model.impl.Graph { private static final Logger log = LoggerFactory.getLogger(GraphStoreImpl.class); + + /** + * The relative path of the content-addressed file container. + */ + public static final String UPLOADS_PATH = "uploads"; private final UriInfo uriInfo; private final com.atomgraph.linkeddatahub.apps.model.Application application; diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java index a1cc2f4dd..5665a8e72 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java @@ -24,7 +24,7 @@ import com.atomgraph.core.util.ModelUtils; import com.atomgraph.core.util.ResultSetUtils; import com.atomgraph.linkeddatahub.apps.model.Dataset; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.client.filter.auth.IDTokenDelegationFilter; import com.atomgraph.linkeddatahub.client.filter.auth.WebIDDelegationFilter; import com.atomgraph.linkeddatahub.model.Service; @@ -566,7 +566,7 @@ public com.atomgraph.linkeddatahub.Application getSystem() */ public String getUserAgentHeaderValue() { - return LinkedDataClient.USER_AGENT; + return GraphStoreClient.USER_AGENT; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java new file mode 100644 index 000000000..aa59c9273 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java @@ -0,0 +1,76 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.server.util; + +import java.net.URI; + +/** + * Utility for converting URIs to filesystem paths. + * Reverses hostname components following Java package naming conventions. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class UriPath +{ + + /** + * Converts a URI to a filesystem path by reversing hostname components. + * Example: https://packages.linkeddatahub.com/skos/#this -> com/linkeddatahub/packages/skos + * + * @param uri the URI string + * @return filesystem path relative to static directory + * @throws IllegalArgumentException if URI is invalid + */ + public static String convert(String uri) + { + if (uri == null) + throw new IllegalArgumentException("URI cannot be null"); + + try + { + URI uriObj = URI.create(uri); + String host = uriObj.getHost(); + String path = uriObj.getPath(); + + if (host == null) + throw new IllegalArgumentException("URI must have a host: " + uri); + + // Reverse hostname components: packages.linkeddatahub.com -> com/linkeddatahub/packages + String[] hostParts = host.split("\\."); + StringBuilder reversedHost = new StringBuilder(); + for (int i = hostParts.length - 1; i >= 0; i--) + { + reversedHost.append(hostParts[i]); + if (i > 0) reversedHost.append("/"); + } + + // Append path without leading/trailing slashes and fragment + if (path != null && !path.isEmpty() && !path.equals("/")) + { + String cleanPath = path.replaceAll("^/+|/+$", ""); // Remove leading/trailing slashes + return reversedHost + "/" + cleanPath; + } + + return reversedHost.toString(); + } + catch (IllegalArgumentException e) + { + throw new IllegalArgumentException("Invalid URI: " + uri, e); + } + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java new file mode 100644 index 000000000..72a043b57 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java @@ -0,0 +1,165 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.server.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import jakarta.servlet.ServletContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import org.w3c.dom.DOMException; + +/** + * Updates master XSLT stylesheets with package import chains. + * Writes master stylesheets to the webapp's /static/ directory. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class XSLTMasterUpdater +{ + private static final Logger log = LoggerFactory.getLogger(XSLTMasterUpdater.class); + + private static final String XSL_NS = "http://www.w3.org/1999/XSL/Transform"; + private static final String SYSTEM_STYLESHEET_HREF = "../com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl"; + + private final ServletContext servletContext; + + /** + * Constructs updater with servlet context. + * + * @param servletContext the servlet context + */ + public XSLTMasterUpdater(ServletContext servletContext) + { + this.servletContext = servletContext; + } + + /** + * Regenerates the master stylesheet for the application. + * Creates a fresh stylesheet with system import followed by package imports. + * + * @param packagePaths list of package paths to import (e.g., ["com/linkeddatahub/packages/skos"]) + * @throws IOException if file operations fail + */ + public void regenerateMasterStylesheet(List<String> packagePaths) throws IOException + { + try + { + Path staticDir = getStaticPath(); + Path xslDir = staticDir.resolve("xsl"); + Path masterFile = xslDir.resolve("layout.xsl"); + + // Create fresh XML document + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.newDocument(); + + // Create stylesheet root element + Element stylesheet = doc.createElementNS(XSL_NS, "xsl:stylesheet"); + stylesheet.setAttribute("version", "3.0"); + stylesheet.setAttribute("xmlns:xsl", XSL_NS); + stylesheet.setAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema"); + stylesheet.setAttribute("exclude-result-prefixes", "xs"); + doc.appendChild(stylesheet); + + // Add system stylesheet import (lowest priority) + stylesheet.appendChild(doc.createTextNode("\n\n ")); + stylesheet.appendChild(doc.createComment("System stylesheet (lowest priority) ")); + stylesheet.appendChild(doc.createTextNode("\n ")); + Element systemImport = doc.createElementNS(XSL_NS, "xsl:import"); + systemImport.setAttribute("href", SYSTEM_STYLESHEET_HREF); + stylesheet.appendChild(systemImport); + + // Add package stylesheet imports + if (packagePaths != null && !packagePaths.isEmpty()) + { + stylesheet.appendChild(doc.createTextNode("\n\n ")); + stylesheet.appendChild(doc.createComment(" Package stylesheets ")); + + for (String packagePath : packagePaths) + { + stylesheet.appendChild(doc.createTextNode("\n ")); + Element importElement = doc.createElementNS(XSL_NS, "xsl:import"); + importElement.setAttribute("href", "../" + packagePath + "/layout.xsl"); + stylesheet.appendChild(importElement); + + if (log.isDebugEnabled()) log.debug("Added xsl:import for package: {}", packagePath); + } + } + + stylesheet.appendChild(doc.createTextNode("\n\n")); + + // Write to file + Files.createDirectories(xslDir); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(masterFile.toFile()); + transformer.transform(source, result); + + if (log.isDebugEnabled()) log.debug("Regenerated master stylesheet at: {}", masterFile); + } + catch (ParserConfigurationException | TransformerException | DOMException e) + { + throw new IOException("Failed to regenerate master stylesheet", e); + } + } + + /** + * Gets the path to the webapp's /static/ directory. + * + * @return path to static directory + */ + private Path getStaticPath() + { + String realPath = getServletContext().getRealPath("/static"); + if (realPath == null) + throw new IllegalStateException("Could not resolve real path for /static directory"); + return Paths.get(realPath); + } + + /** + * Returns servlet context. + * + * @return servlet context + */ + public ServletContext getServletContext() + { + return servletContext; + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java index fe51bdd86..3161938c9 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java +++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LAPP.java @@ -63,7 +63,10 @@ public static String getURI() /** End-user application class */ public static final OntClass EndUserApplication = m_model.createClass( NS + "EndUserApplication" ); - + + /** Package class */ + public static final OntClass Package = m_model.createClass( NS + "Package" ); + /** Admin application class */ public static final ObjectProperty adminApplication = m_model.createObjectProperty( NS + "adminApplication" ); diff --git a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java index 555ffdce5..17414f681 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java +++ b/src/main/java/com/atomgraph/linkeddatahub/vocabulary/LDH.java @@ -106,7 +106,7 @@ public static String getURI() public static final ObjectProperty forShape = m_model.createObjectProperty( NS + "forShape" ); /** - * Graph URI property */ - //public static final ObjectProperty graph = m_model.createObjectProperty( NS + "graph" ); + * Import property - used to import packages into an application */ + public static final ObjectProperty importPackage = m_model.createObjectProperty( NS + "import" ); } diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java index f242f421a..a9774fd63 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java +++ b/src/main/java/com/atomgraph/linkeddatahub/writer/factory/DataManagerFactory.java @@ -22,7 +22,7 @@ import com.atomgraph.client.util.DataManager; import com.atomgraph.linkeddatahub.apps.model.Application; import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; -import com.atomgraph.linkeddatahub.client.LinkedDataClient; +import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.vocabulary.LAPP; import com.atomgraph.linkeddatahub.writer.impl.DataManagerImpl; @@ -84,12 +84,12 @@ public DataManager getDataManager(Optional<Application> appOpt) else baseManager = getSystem().getDataManager(); - LinkedDataClient ldc = LinkedDataClient.create(getSystem().getClient(), getSystem().getMediaTypes()). + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext()); // copy cached models over from the app's FileManager return new DataManagerImpl(LocationMapper.get(), new HashMap<>(baseManager.getModelCache()), - ldc, true, getSystem().isPreemptiveAuth(), getSystem().isResolvingUncached(), + gsc, true, getSystem().isPreemptiveAuth(), getSystem().isResolvingUncached(), getSystem().getBaseURI(), getAgentContext()); } diff --git a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java index 46208c1b4..b62cfefad 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/writer/impl/DataManagerImpl.java @@ -18,7 +18,7 @@ import org.apache.jena.util.LocationMapper; import java.net.URI; -import com.atomgraph.core.client.LinkedDataClient; +import com.atomgraph.core.client.GraphStoreClient; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.google.common.net.InternetDomainName; import java.util.Map; @@ -44,7 +44,7 @@ public class DataManagerImpl extends com.atomgraph.client.util.DataManagerImpl * * @param mapper location mapper * @param modelCache model cache - * @param ldc Linked Data client + * @param gsc Graph Store client * @param cacheModelLoads true if loaded RDF models are cached * @param preemptiveAuth true if HTTP basic auth is sent preemptively * @param resolvingUncached true if uncached URLs are resolved @@ -52,12 +52,12 @@ public class DataManagerImpl extends com.atomgraph.client.util.DataManagerImpl * @param agentContext agent context */ public DataManagerImpl(LocationMapper mapper, Map<String, Model> modelCache, - LinkedDataClient ldc, + GraphStoreClient gsc, boolean cacheModelLoads, boolean preemptiveAuth, boolean resolvingUncached, URI rootContextURI, AgentContext agentContext) { - super(mapper, modelCache, ldc, cacheModelLoads, preemptiveAuth, resolvingUncached); + super(mapper, modelCache, gsc, cacheModelLoads, preemptiveAuth, resolvingUncached); this.rootContextURI = rootContextURI; this.agentContext = agentContext; } diff --git a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl index 77c6c15fe..819120f9b 100644 --- a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl +++ b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl @@ -163,6 +163,13 @@ rdfs:label "Admin application constructor" ; rdfs:isDefinedBy : . +# package + +:Package a rdfs:Class, owl:Class ; + rdfs:label "Package" ; + rdfs:comment "A reusable package containing RDF ontology and optional XSLT stylesheet for vocabulary support" ; + rdfs:isDefinedBy : . + # CONSTRAINTS :StartsWithHTTPS a sp:Construct ; diff --git a/src/main/resources/com/atomgraph/linkeddatahub/vivo.owl b/src/main/resources/com/atomgraph/linkeddatahub/vivo.owl deleted file mode 100644 index fc6c0c457..000000000 --- a/src/main/resources/com/atomgraph/linkeddatahub/vivo.owl +++ /dev/null @@ -1,12563 +0,0 @@ -<?xml version="1.0"?> -<rdf:RDF xmlns="http://vivoweb.org/ontology/core#" - xml:base="http://vivoweb.org/ontology/core" - xmlns:study_protocol="http://purl.org/net/OCRe/study_protocol.owl#" - xmlns:ns="http://www.w3.org/2003/06/sw-vocab-status/ns#" - xmlns:owl="http://www.w3.org/2002/07/owl#" - xmlns:xsd="http://www.w3.org/2001/XMLSchema#" - xmlns:skos="http://www.w3.org/2004/02/skos/core#" - xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" - xmlns:geopolitical="http://aims.fao.org/aos/geopolitical.owl#" - xmlns:vitro="http://vitro.mannlib.cornell.edu/ns/vitro/0.7#" - xmlns:skos2="http://www.w3.org/2008/05/skos#" - xmlns:core="http://vivoweb.org/ontology/core#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:terms="http://purl.org/dc/terms/" - xmlns:obo="http://purl.obolibrary.org/obo/" - xmlns:statistics="http://purl.org/net/OCRe/statistics.owl#"> - - <owl:Ontology rdf:about="http://vivoweb.org/ontology/core"> - <rdfs:label xml:lang="en-US">VIVO Core Ontology</rdfs:label> - </owl:Ontology> - - <!-- - /////////////////////////////////////////////////////////////////////////////////////// - // - // Annotation properties - // - /////////////////////////////////////////////////////////////////////////////////////// - --> - - - <!-- http://aims.fao.org/aos/geopolitical.owl#sourceCreator --> - - <owl:AnnotationProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#sourceCreator"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#sourceIdentifier --> - - <owl:AnnotationProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#sourceIdentifier"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#sourceModified --> - - <owl:AnnotationProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#sourceModified"/> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000033 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/ARG_0000033"/> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000179 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000179"/> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000180 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000180"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000111 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000111"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000112 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000112"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000114 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000114"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000115 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000115"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000116 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000116"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000117 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000117"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000118 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000118"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000119 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000119"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000231 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000231"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000232 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000232"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000412 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000412"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000600 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000600"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000601 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000601"/> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000602 --> - - <owl:AnnotationProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000602"/> - - - - <!-- http://purl.org/dc/terms/description --> - - <owl:AnnotationProperty rdf:about="http://purl.org/dc/terms/description"/> - - - - <!-- http://purl.org/dc/terms/source --> - - <owl:AnnotationProperty rdf:about="http://purl.org/dc/terms/source"/> - - - - <!-- http://purl.org/net/OCRe/statistics.owl#curator --> - - <owl:AnnotationProperty rdf:about="http://purl.org/net/OCRe/statistics.owl#curator"/> - - - - <!-- http://purl.org/net/OCRe/study_protocol.owl#develop_comment --> - - <owl:AnnotationProperty rdf:about="http://purl.org/net/OCRe/study_protocol.owl#develop_comment"/> - - - - <!-- http://vitro.mannlib.cornell.edu/ns/vitro/0.7#descriptionAnnot --> - - <owl:AnnotationProperty rdf:about="http://vitro.mannlib.cornell.edu/ns/vitro/0.7#descriptionAnnot"/> - - - - <!-- http://vitro.mannlib.cornell.edu/ns/vitro/0.7#exampleAnnot --> - - <owl:AnnotationProperty rdf:about="http://vitro.mannlib.cornell.edu/ns/vitro/0.7#exampleAnnot"/> - - - - <!-- http://vitro.mannlib.cornell.edu/ns/vitro/0.7#stubObjectPropertyAnnot --> - - <owl:AnnotationProperty rdf:about="http://vitro.mannlib.cornell.edu/ns/vitro/0.7#stubObjectPropertyAnnot"/> - - - <!-- http://www.w3.org/2000/01/rdf-schema#comment --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2000/01/rdf-schema#comment"/> - - - - <!-- http://www.w3.org/2000/01/rdf-schema#isDefinedBy --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2000/01/rdf-schema#isDefinedBy"/> - - - - <!-- http://www.w3.org/2000/01/rdf-schema#label --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2000/01/rdf-schema#label"/> - - - - <!-- http://www.w3.org/2002/07/owl#minCardinality --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2002/07/owl#minCardinality"/> - - - - <!-- http://www.w3.org/2003/06/sw-vocab-status/ns#term_status --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2003/06/sw-vocab-status/ns#term_status"/> - - - - <!-- http://www.w3.org/2004/02/skos/core#scopeNote --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2004/02/skos/core#scopeNote"/> - - - - <!-- http://www.w3.org/2008/05/skos#editorialNote --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2008/05/skos#editorialNote"/> - - - - <!-- http://www.w3.org/2008/05/skos#scopeNote --> - - <owl:AnnotationProperty rdf:about="http://www.w3.org/2008/05/skos#scopeNote"/> - - - - <!-- - /////////////////////////////////////////////////////////////////////////////////////// - // - // Datatypes - // - /////////////////////////////////////////////////////////////////////////////////////// - --> - - - - - <!-- http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral --> - - <rdfs:Datatype rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral"/> - - - - <!-- http://www.w3.org/2000/01/rdf-schema#Literal --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2000/01/rdf-schema#Literal"/> - - - - <!-- http://www.w3.org/2001/XMLSchema#anyURI --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2001/XMLSchema#anyURI"/> - - - - <!-- http://www.w3.org/2001/XMLSchema#boolean --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2001/XMLSchema#boolean"/> - - - - <!-- http://www.w3.org/2001/XMLSchema#date --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2001/XMLSchema#date"/> - - - - <!-- http://www.w3.org/2001/XMLSchema#int --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2001/XMLSchema#int"/> - - - - <!-- http://www.w3.org/2001/XMLSchema#string --> - - <rdfs:Datatype rdf:about="http://www.w3.org/2001/XMLSchema#string"/> - - - - <!-- - /////////////////////////////////////////////////////////////////////////////////////// - // - // Object Properties - // - /////////////////////////////////////////////////////////////////////////////////////// - --> - - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasBorderWith --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasBorderWith"> - <rdfs:label xml:lang="en">has border with</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-05-01</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations cartographic maps</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations cartographic maps http://www.un.org/Depts/Cartographic/map/profile/world00.pdf</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.un.org/Depts/Cartographic/map/profile/world00.pdf</geopolitical:sourceIdentifier> - </owl:ObjectProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasMember --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasMember"> - <rdfs:label xml:lang="en">has member country or territory</rdfs:label> - <rdfs:domain rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - <owl:inverseOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#isInGroup"/> - <rdfs:range rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - </owl:ObjectProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#isAdministeredBy --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#isAdministeredBy"> - <rdfs:label xml:lang="en">is administered by</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-05-01</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations cartographic maps</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations cartographic maps http://www.un.org/Depts/Cartographic/map/profile/world00.pdf</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://www.un.org/Depts/Cartographic/map/profile/world00.pdf</geopolitical:sourceIdentifier> - </owl:ObjectProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#isInGroup --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#isInGroup"> - <rdfs:label xml:lang="en">in geographic grouping</rdfs:label> - <rdfs:range rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - <rdfs:domain rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - </owl:ObjectProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#isPredecessorOf --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#isPredecessorOf"> - <rdfs:label xml:lang="en">is predecessor of</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-04-15</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division http://unstats.un.org/unsd/methods/m49/m49chang.htm</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://unstats.un.org/unsd/methods/m49/m49chang.htm</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://unstats.un.org/unsd/methods/m49/m49chgef.htm</geopolitical:sourceIdentifier> - <rdfs:range rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - <rdfs:domain rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - <owl:inverseOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#isSuccessorOf"/> - </owl:ObjectProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#isSuccessorOf --> - - <owl:ObjectProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#isSuccessorOf"> - <rdfs:label xml:lang="en">is successor of</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-04-15</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division http://unstats.un.org/unsd/methods/m49/m49chang.htm</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://unstats.un.org/unsd/methods/m49/m49chang.htm</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://unstats.un.org/unsd/methods/m49/m49chgef.htm</geopolitical:sourceIdentifier> - <rdfs:range rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - <rdfs:domain rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - </owl:ObjectProperty> - - - - <!-- http://isf/deprecated_op --> - - <owl:ObjectProperty rdf:about="http://isf/deprecated_op"/> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000028 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000028"> - <rdfs:label xml:lang="en">has contact info</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000029"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ARG_2000379"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000029 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000029"> - <rdfs:label xml:lang="en">contact info for</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ARG_2000379"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000390 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000390"> - <rdfs:label xml:lang="en">context for</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000391"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000391 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000391"> - <rdfs:label xml:lang="en">has context</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000399 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000399"> - <rdfs:label xml:lang="en">has contact agent</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000050 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000050"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/> - <rdfs:label xml:lang="en">part of</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000051 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000051"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/> - <rdfs:label xml:lang="en">has part</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000054 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000054"> - <rdfs:label xml:lang="en">realized in</rdfs:label> - <obo:BFO_0000180>realizedIn</obo:BFO_0000180> - <obo:BFO_0000179>realized-in</obo:BFO_0000179> - <obo:IAO_0000600>[copied from inverse property 'realizes'] to say that b realizes c at t is to assert that there is some material entity d & b is a process which has participant d at t & c is a disposition or role of which d is bearer_of at t& the type instantiated by b is correlated with the type instantiated by c. (axiom label in BFO2 Reference: [059-003])</obo:IAO_0000600> - <obo:IAO_0000602>(forall (x y z t) (if (and (RealizableEntity x) (Process y) (realizesAt y x t) (bearerOfAt z x t)) (hasParticipantAt y z t))) // axiom label in BFO2 CLIF: [106-002] </obo:IAO_0000602> - <obo:IAO_0000601 xml:lang="en">if a realizable entity b is realized in a process p, then p stands in the has_participant relation to the bearer of b. (axiom label in BFO2 Reference: [106-002])</obo:IAO_0000601> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000017"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000055"/> - <rdfs:isDefinedBy rdf:resource="http://purl.obolibrary.org/obo/bfo.owl"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000055 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/BFO_0000055"> - <rdfs:label xml:lang="en">realizes</rdfs:label> - <obo:IAO_0000602>(forall (x y t) (if (realizesAt x y t) (and (Process x) (or (Disposition y) (Role y)) (exists (z) (and (MaterialEntity z) (hasParticipantAt x z t) (bearerOfAt z y t)))))) // axiom label in BFO2 CLIF: [059-003] </obo:IAO_0000602> - <obo:BFO_0000180>realizes</obo:BFO_0000180> - <obo:BFO_0000179>realizes</obo:BFO_0000179> - <obo:IAO_0000600 xml:lang="en">to say that b realizes c at t is to assert that there is some material entity d & b is a process which has participant d at t & c is a disposition or role of which d is bearer_of at t& the type instantiated by b is correlated with the type instantiated by c. (axiom label in BFO2 Reference: [059-003])</obo:IAO_0000600> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000017"/> - <rdfs:isDefinedBy rdf:resource="http://purl.obolibrary.org/obo/bfo.owl"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000029 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000029"> - <rdfs:label xml:lang="en">provides access to</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An access service that provides access to a flow cytometer.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Instruments, reagents, organisms, or software for which the service provides access.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">change the domain tye to access service</rdfs:comment> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/scientific-research#accessProvidedBy"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000031 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000031"> - <rdfs:label xml:lang="en">uses</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Here there are things to be fixed (for instance a service can use a technique...)</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Microsoft powerpoint is commonly used in research laboratories to prepare presentations.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Software or protocol used by the laboratory.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">uses</obo:IAO_0000111> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000070"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/OBI_0000272"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000033 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000033"> - <rdfs:label xml:lang="en">has expertise in technique</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Brian Druker has expertise in cancer research.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Technique in which the person is proficient. </obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has expertise</obo:IAO_0000111> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000007"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000034 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000034"> - <rdfs:label xml:lang="en">manufacturer</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Organization or person that created the resource.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Santa Cruz Biotechnology is the manufacturer of many antibodies.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has manufacturer</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/OBI_0000835"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000037 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000037"> - <rdfs:label xml:lang="en">contact or provider for service</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A core lab providing cell sorting to individual labs.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Service offered by the organization.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">provides services</obo:IAO_0000111> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000390"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Organization"/> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000038 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000038"> - <rdfs:label xml:lang="en">specifies the use of</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A protocol can specify the use of a flow cytometer.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Instruments, techniques, reagents, organisms, or software that are referenced in a protocol.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">specifies the use of</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/OBI_0000272"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000007"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000070 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000070"> - <rdfs:label xml:lang="en">used by</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A laboratory uses Microsoft Word.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Laboratory that uses the protocol or software.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">used by</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/OBI_0000272"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000390 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000390"> - <rdfs:label xml:lang="en">service provided by</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A core laboratory provides a service.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Organization or laboratory performing the service.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">service provided by</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Organization"/> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000397 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000397"> - <rdfs:label xml:lang="en">performs technique</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A cancer researcher performs apoptosis assays.</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Technique carried out by the person or laboratory.</obo:IAO_0000115> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000007"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000398"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Laboratory"/> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000398 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000398"> - <rdfs:label xml:lang="en">is performed by</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Confocal microscopy is performed by a confocal core laboratory.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Person or laboratory that performs the service or technique.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">is performed by</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000007"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Laboratory"/> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000460 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000460"> - <rdfs:label xml:lang="en">has documentation</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An antibody has documentation describing attributes of the antibody.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Document that contains relevant resource information.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has documentation</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/scientific-research#documentationFor"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000014"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000020"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/OBI_0000272"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000481 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000481"> - <rdfs:label xml:lang="en">realizes protocol</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A sequencing protocol used for next generation sequencing.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Protocol used to perform the service.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">placeholder: need to be modeled for the proper kind of service (production services)</rdfs:comment> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">realizes protocol</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/OBI_0000272"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/scientific-research#protocolRealizedBy"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000014"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000482 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000482"> - <rdfs:label xml:lang="en">uses software</rdfs:label> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Placeholder needs to be redesign</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Sequence analysis software.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Software used to perform the service.</obo:IAO_0000115> - <owl:deprecated rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean">true</owl:deprecated> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">uses software</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000071"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:subPropertyOf rdf:resource="http://www.w3.org/2002/07/owl#DeprecatedProperty"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000543 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000543"> - <rdfs:label xml:lang="en">related technique</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Flow cytometry is a related technique for a flow cytometer instrument.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Method in which the resource can be used.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">related technique</obo:IAO_0000111> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000007"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000572 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000572"> - <rdfs:label xml:lang="en">used to study</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A study of hibernation in bears.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Biological process studied in the organism.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">used to study</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000775 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000775"> - <rdfs:label xml:lang="en">has residency requirement</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A research opportunity requires applicants to be US citizens.</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">US residency status of applicants that may apply for the student research opportunity.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has residency requirement</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000595"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000776"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000918 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000918"> - <rdfs:label xml:lang="en">related research project</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A research project studying breast cancer.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Research project during which the biological specimen was collected.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">related research project</obo:IAO_0000111> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000014"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000020"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000919"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000919 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000919"> - <rdfs:label xml:lang="en">related biological specimen</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A breast cancer specimen.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Biological specimen collected as part of the research project.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">related biological specimen</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000014"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000020"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001518 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0001518"> - <rdfs:label xml:lang="en">has phase</rdfs:label> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 1 clinical trial.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase of a clinical trial to evaluate risk and to clinically evaluate the efficacy of drugs or biologicals.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has phase</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001520 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0001520"> - <rdfs:label xml:lang="en">performs human study</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Human study performed by the organization.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The Jackson Heart Institute performs human studies on heart disease.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">performs human study</obo:IAO_0000111> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000015"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001521"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001521 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0001521"> - <rdfs:label xml:lang="en">performed by organization</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Jackson State University performs human studies on heart disease.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Organization that performs the human study.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">human study performed by</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000015"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:subPropertyOf rdf:resource="http://www.obofoundry.org/ro/ro.owl#has_agent"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000039 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000039"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">has measurement unit label</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/IAO_0000003"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000136 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000136"> - <rdfs:label xml:lang="en">is about</rdfs:label> - <obo:IAO_0000116 xml:lang="en">7/6/2009 Alan Ruttenberg. Following discussion with Jonathan Rees, and introduction of "mentions" relation. Weaken the is_about relationship to be primitive. - -We will try to build it back up by elaborating the various subproperties that are more precisely defined. - -Some currently missing phenomena that should be considered "about" are predications - "The only person who knows the answer is sitting beside me" , Allegory, Satire, and other literary forms that can be topical without explicitly mentioning the topic.</obo:IAO_0000116> - <obo:IAO_0000119 xml:lang="en">Smith, Ceusters, Ruttenberg, 2000 years of philosophy</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">This document is about information artifacts and their representations</obo:IAO_0000112> - <obo:IAO_0000115 xml:lang="en">is_about is a (currently) primitive relation that relates an information artifact to an entity.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">person:Alan Ruttenberg</obo:IAO_0000117> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000125"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000142 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000142"> - <rdfs:label xml:lang="en">mentions</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000136"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000221 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000221"> - <rdfs:label xml:lang="en">is quality measurement of</rdfs:label> - <obo:IAO_0000116 xml:lang="en">8/6/2009 Alan Ruttenberg: The strategy is to be rather specific with this relationship. There are other kinds of measurements that are not of qualities, such as those that measure time. We will add these as separate properties for the moment and see about generalizing later</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000116 xml:lang="en">From the second IAO workshop [Alan Ruttenberg 8/6/2009: not completely current, though bringing in comparison is probably important] - -This one is the one we are struggling with at the moment. The issue is what a measurement measures. On the one hand saying that it measures the quality would include it "measuring" the bearer = referring to the bearer in the measurement. However this makes comparisons of two different things not possible. On the other hand not having it inhere in the bearer, on the face of it, breaks the audit trail. - -Werner suggests a solution based on "Magnitudes" a proposal for which we are awaiting details. --- -From the second IAO workshop, various comments, [commented on by Alan Ruttenberg 8/6/2009] - -unit of measure is a quality, e.g. the length of a ruler. - -[We decided to hedge on what units of measure are, instead talking about measurement unit labels, which are the information content entities that are about whatever measurement units are. For IAO we need that information entity in any case. See the term measurement unit label] - -[Some struggling with the various subflavors of is_about. We subsequently removed the relation represents, and describes until and only when we have a better theory] - -a represents b means either a denotes b or a describes - -describe: -a describes b means a is about b and a allows an inference of at least one quality of b - -We have had a long discussion about denotes versus describes.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">From the second IAO workshop: An attempt at tieing the quality to the measurement datum more carefully. - -a is a magnitude means a is a determinate quality particular inhering in some bearer b existing at a time t that can be represented/denoted by an information content entity e that has parts denoting a unit of measure, a number, and b. The unit of measure is an instance of the determinable quality.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">From the second meeting on IAO: - -An attempt at defining assay using Barry's "reliability" wording - -assay: -process and has_input some material entity -and has_output some information content entity -and which is such that instances of this process type reliably generate -outputs that describes the input.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">This one is the one we are struggling with at the moment. The issue is what a measurement measures. On the one hand saying that it measures the quality would include it "measuring" the bearer = referring to the bearer in the measurement. However this makes comparisons of two different things not possible. On the other hand not having it inhere in the bearer, on the face of it, breaks the audit trail. - -Werner suggests a solution based on "Magnitudes" a proposal for which we are awaiting details.</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">m is a quality measurement of q at t when -q is a quality -there is a measurement process p that has specified output m, a measurement datum, that is about q</obo:IAO_0000115> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000019"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000109"/> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000136"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000417"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000417 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/IAO_0000417"> - <rdfs:label xml:lang="en">is quality measured as</rdfs:label> - <obo:IAO_0000116 xml:lang="en">2009/10/19 Alan Ruttenberg. Named 'junk' relation useful in restrictions, but not a real instance relationship</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">Person:Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">inverse of the relation of is quality measurement of</obo:IAO_0000115> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000293 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000293"> - <rdfs:label xml:lang="en">has specified input</rdfs:label> - <obo:IAO_0000116 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">8/17/09: specified inputs of one process are not necessarily specified inputs of a larger process that it is part of. This is in contrast to how 'has participant' works.</obo:IAO_0000116> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Larry Hunter</obo:IAO_0000117> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melanie Coutot</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has_specified_input</obo:IAO_0000111> - <obo:IAO_0000115 xml:lang="en">A relation between a planned process and a continuant participating in that process that is not created during the process. The presence of the continuant during the process is explicitly specified in the plan specification which the process realizes the concretization of.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000112 xml:lang="en">see is_input_of example_of_usage</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0002233"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000299 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000299"> - <rdfs:label xml:lang="en">has specified output</rdfs:label> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Larry Hunter</obo:IAO_0000117> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melanie Courtot</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has_specified_output</obo:IAO_0000111> - <obo:IAO_0000115 xml:lang="en">A relation between a planned process and a continuant participating in that process. The presence of the continuant at the end of the process is explicitly specified in the objective specification which the process realizes the concretization of.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000312"/> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0002234"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000304 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000304"> - <rdfs:label xml:lang="en">manufactured by</rdfs:label> - <obo:IAO_0000117 xml:lang="en">Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">Liju Fan</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">c is_manufactured_by o means that there was a process p in which c was built in which a person, or set of people or machines did the work(bore the "Manufacturer Role", and those people/and or machines were members or of directed by the organization to do this.</obo:IAO_0000115> - <obo:IAO_0000118 xml:lang="en">has_make</obo:IAO_0000118> - <obo:IAO_0000118 xml:lang="en">has_manufacturer</obo:IAO_0000118> - <obo:IAO_0000112 xml:lang="en">http://www.affymetrix.com/products/arrays/specific/hgu133.affx is_manufactered_by http://www.affymetrix.com/ (if we decide to use these URIs for the actual entities)</obo:IAO_0000112> - <obo:IAO_0000111 xml:lang="en">is_manufactured_by</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000312 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000312"> - <rdfs:label xml:lang="en">is specified output of</rdfs:label> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON:Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">is_specified_output_of</obo:IAO_0000111> - <obo:IAO_0000115 xml:lang="en">A relation between a planned process and a continuant participating in that process. The presence of the continuant at the end of the process is explicitly specified in the objective specification which the process realizes the concretization of.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">Alan Ruttenberg</obo:IAO_0000117> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0002353"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000417 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000417"> - <rdfs:label xml:lang="en">achieves planned objective</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A cell sorting process achieves the objective specification 'material separation objective'</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">BP, AR, PPPB branch</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PPPB branch derived</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This relation obtains between a planned process and a objective specification when the criteria specified in the objective specification are met at the end of the planned process.</obo:IAO_0000115> - <obo:IAO_0000232 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">modified according to email thread from 1/23/09 in accordince with DT and PPPB branch</obo:IAO_0000232> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/IAO_0000005"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000833"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000643 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000643"> - <rdfs:label xml:lang="en">has grain</rdfs:label> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PAPER: Granularity, scale and collectivity: When size does and does not matter, Alan Rector, Jeremy Rogers, Thomas Bittner, Journal of Biomedical Informatics 39 (2006) 333-349</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has grain</obo:IAO_0000111> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">the relation of the cells in the finger of the skin to the finger, in which an indeterminate number of grains are parts of the whole by virtue of being grains in a collective that is part of the whole, and in which removing one granular part does not nec- essarily damage or diminish the whole. Ontological Whether there is a fixed, or nearly fixed number of parts - e.g. fingers of the hand, chambers of the heart, or wheels of a car - such that there can be a notion of a single one being missing, or whether, by contrast, the number of parts is indeterminate - e.g., cells in the skin of the hand, red cells in blood, or rubber molecules in the tread of the tire of the wheel of the car.</obo:IAO_0000115> - <obo:IAO_0000116 xml:lang="en">Discussion in Karslruhe with, among others, Alan Rector, Stefan Schulz, Marijke Keet, Melanie Courtot, and Alan Ruttenberg. Definition take from the definition of granular parthood in the cited paper. Needs work to put into standard form</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi_webservice.owl"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000833 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/OBI_0000833"> - <rdfs:label xml:lang="en">objective achieved by</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This relation obtains between a a objective specification and a planned process when the criteria specified in the objective specification are met at the end of the planned process.</obo:IAO_0000115> - <obo:IAO_0000116 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">definition needs clean up to indicate directionality</obo:IAO_0000116> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000005"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0000052 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0000052"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">inheres in</rdfs:label> - <obo:IAO_0000116 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This clarifies that only specifically dependent continuants inhere in (specifically) one independent continuant over all time. For GDCs, there in implicitly inherence to all the independent continuants in which the concretizations inhere. Should add a 'cardinality 1' restriction to the definition of specifically dependent continuant.</obo:IAO_0000116> - <obo:IAO_0000116 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This relation belongs in BFO/RO, and will be in BFO 2</obo:IAO_0000116> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000004"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000020"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0000053"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0000053 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0000053"> - <rdfs:label xml:lang="en">bearer of</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000004"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000020"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0000056 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0000056"> - <rdfs:label xml:lang="en">participates in</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000002"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000003"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0000057"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0000057 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0000057"> - <rdfs:label xml:lang="en">has participant</rdfs:label> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000002"/> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000003"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0001000 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0001000"> - <rdfs:label xml:lang="en">derives from</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0001015 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0001015"> - <rdfs:label xml:lang="en">location of</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0001025"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0001018 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0001018"> - <rdfs:label xml:lang="en">contained in</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0001019"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0001019 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0001019"> - <rdfs:label xml:lang="en">contains</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0001025 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0001025"> - <rdfs:label xml:lang="en">located in</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002220 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002220"> - <rdfs:label xml:lang="en">adjacent to</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002233 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002233"> - <rdfs:label xml:lang="en">has input</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0000057"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002234 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002234"> - <rdfs:label xml:lang="en">has output</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0000057"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0002353"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002350 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002350"> - <rdfs:label xml:lang="en">member of</rdfs:label> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0002351"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002351 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002351"> - <rdfs:label xml:lang="en">has member</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0002353 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0002353"> - <rdfs:label xml:lang="en">output of</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/RO_0000056"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0003000 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0003000"> - <rdfs:label xml:lang="en">produces</rdfs:label> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">a produces b if some process that occurs_in a has_output b, where a and b are material entities. Examples: hybridoma cell line produces monoclonal antibody reagent; chondroblast produces avascular GAG-rich matrix.</obo:IAO_0000115> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <owl:inverseOf rdf:resource="http://purl.obolibrary.org/obo/RO_0003001"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/ro.owl"/> - </owl:ObjectProperty> - - - - <!-- http://purl.obolibrary.org/obo/RO_0003001 --> - - <owl:ObjectProperty rdf:about="http://purl.obolibrary.org/obo/RO_0003001"> - <rdfs:label xml:lang="en">produced by</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/dc/terms/contributor --> - - <owl:ObjectProperty rdf:about="http://purl.org/dc/terms/contributor"> - <rdfs:label xml:lang="en">contributor</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/affirmedBy --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/affirmedBy"> - <rdfs:label xml:lang="en">affirmed by</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The public description was taken from here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A legal decision that affirms a ruling.</rdfs:comment> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/annotates --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/annotates"> - <rdfs:label xml:lang="en">annotates</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The public description source is: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">Critical or explanatory note for a Document.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/citedBy --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/citedBy"> - <rdfs:label xml:lang="en">cited by</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - <owl:inverseOf rdf:resource="http://purl.org/ontology/bibo/cites"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/cites --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/cites"> - <rdfs:label xml:lang="en">cites</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/court --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/court"> - <rdfs:label xml:lang="en">Court</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description take from: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html. Bibo considers this property "unstable".</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A court associated with a legal document; for example, that which issues a decision.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/degree --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/degree"> - <rdfs:label xml:lang="en">related degree</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The source of the public description and this info is found here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html. Bibo considers this term "unstable". The bibo editorial note is: "We are not defining, using an enumeration, the range of the bibo:degree to the defined list of bibo:ThesisDegree. We won't do it because we want people to be able to define new degress if needed by some special usecases. Creating such an enumeration would restrict this to happen."</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">The thesis degree.</rdfs:comment> - <skos2:editorialNote xml:lang="en">We are not defining, using an enumeration, the range of the bibo:degree to the defined list of bibo:ThesisDegree. We won't do it because we want people to be able to define new degress if needed by some special usecases. Creating such an enumeration would restrict this to happen.</skos2:editorialNote> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/ThesisDegree"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/director --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/director"> - <rdfs:label xml:lang="en">director</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from this site: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html .</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A Film director.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/distributor --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/distributor"> - <rdfs:label xml:lang="en">distributor</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Description for bibo:distributor taken from here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html .</vitro:descriptionAnnot> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#distributes"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/interviewee --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/interviewee"> - <rdfs:label xml:lang="en">interviewee</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">An agent that is interviewed by another agent.</rdfs:comment> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/interviewer --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/interviewer"> - <rdfs:label xml:lang="en">interviewer</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An agent that interview another agent.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/issuer --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/issuer"> - <rdfs:label xml:lang="en">issuer</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An entity responsible for issuing often informally published documents such as press releases, reports, etc. This term is classified as unstable by bibo.</vitro:descriptionAnnot> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment>An entity responsible for issuing often informally published documents such as press releases, reports, etc.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/performer --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/performer"> - <rdfs:label xml:lang="en">performer</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/contributor"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/presentedAt --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/presentedAt"> - <rdfs:label xml:lang="en">presented at event</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Description from source: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html . Bibo considers the bibo:presents and the bibo:presentedAt unstable terms. It also indicates that bibo:presents is a sub-property of event:product.</vitro:descriptionAnnot> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">Relates a document to an event; for example, a paper to a conference.</rdfs:comment> - <rdfs:range rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <owl:inverseOf rdf:resource="http://purl.org/ontology/bibo/presents"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/presents --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/presents"> - <rdfs:label xml:lang="en">related documents</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Description from source: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html . Bibo considers the bibo:presents and the bibo:presentedAt unstable terms. It also indicates that bibo:presents is a sub-property of event:product.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">Relates an event to associated documents; for example, conference to a paper.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/recipient --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/recipient"> - <rdfs:label xml:lang="en">recipient</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An agent that receives a communication document.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/reproducedIn --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/reproducedIn"> - <rdfs:label xml:lang="en">reproduced in</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000050"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#reproduces"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/reversedBy --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/reversedBy"> - <rdfs:label xml:lang="en">reversed by</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The first sentence of the public description was taken from here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A legal decision that reverses a ruling.</rdfs:comment> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/reviewOf --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/reviewOf"> - <rdfs:label xml:lang="en">review of</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The bibo:reviewOf public description was found here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html . As of 26 May 2010, bibo:reviewOf is used with the class Review, but core:reviewIn doesn't seem to be being used.</obo:IAO_0000112> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#reviewedIn"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/status --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/status"> - <rdfs:label xml:lang="en">status</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">paraphrased editorial note from the bibo ontology: We are not defining, using an enumeration, the range of the bibo:status to be a defined list of bibo:DocumentStatus. This is because we want people to be able to define new statuses if needed; and creating such an enumeration would prevent this.</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/DocumentStatus"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/subsequentLegalDecision --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/subsequentLegalDecision"> - <rdfs:label xml:lang="en">subsequent legal decision</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description is from comments of this object property in bibo ontology located here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A legal decision on appeal that takes action on a case (affirming it, reversing it, etc.).</rdfs:comment> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/transcriptOf --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/transcriptOf"> - <rdfs:label xml:lang="en">transcript of</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The bibo:transcriptOf public description was found here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html . Bibo considers this term unstable.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">Relates a document to some transcribed original.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/translationOf --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/translationOf"> - <rdfs:label xml:lang="en">translation of</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Examples shows a book has French language version. Public description source: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html .</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Relates a translated document to the original document.</rdfs:comment> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasTranslation"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/ontology/bibo/translator --> - - <owl:ObjectProperty rdf:about="http://purl.org/ontology/bibo/translator"> - <rdfs:label xml:lang="en">translator</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/contributor"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#translatorOf"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.org/ontology/bibo/Collection"/> - <rdf:Description rdf:about="http://purl.org/ontology/bibo/Document"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://purl.org/spar/c4o/hasGlobalCitationFrequency --> - - <owl:ObjectProperty rdf:about="http://purl.org/spar/c4o/hasGlobalCitationFrequency"> - <rdfs:label xml:lang="en">has global citation frequency</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A property linking a publication entity to an instance of c40:GlobalCitationCount that specifies how many times a work has been cited by others, according to a particular information source on a particular date.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A property linking a publication entity to the property c40:GlobalCitationCount that specify how many times a work has been cited by others, according to a particular information source on a particular date.</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://purl.org/spar/c4o/GlobalCitationCount"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/spar/c4o/hasGlobalCountSource --> - - <owl:ObjectProperty rdf:about="http://purl.org/spar/c4o/hasGlobalCountSource"> - <rdfs:label xml:lang="en">has global count source</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A property linking an instance of c40:GlobalCitationCount to the bibliographic information source providing the global citation count information for a particular publication on a particular date.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A property linking the property c40:GlobalCitationCount to the bibliographic information source providing the global citation count information for a particular publication on a particular date.</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://purl.org/spar/c4o/BibliographicInformationSource"/> - <rdfs:domain rdf:resource="http://purl.org/spar/c4o/GlobalCitationCount"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/spar/cito/citesAsDataSource --> - - <owl:ObjectProperty rdf:about="http://purl.org/spar/cito/citesAsDataSource"> - <rdfs:label xml:lang="en">cites as data source</rdfs:label> - <rdfs:comment xml:lang="en">The citing entity cites the cited entity as source of data.</rdfs:comment> - <owl:inverseOf rdf:resource="http://purl.org/spar/cito/isCitedAsDataSourceBy"/> - </owl:ObjectProperty> - - - - <!-- http://purl.org/spar/cito/isCitedAsDataSourceBy --> - - <owl:ObjectProperty rdf:about="http://purl.org/spar/cito/isCitedAsDataSourceBy"> - <rdfs:label xml:lang="en">is cited as data source by</rdfs:label> - <rdfs:comment xml:lang="en">The cited entity is cited as a data source by the citing entity.</rdfs:comment> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#affiliatedOrganization --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#affiliatedOrganization"> - <rdfs:label xml:lang="en">has affiliated organization</rdfs:label> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#assignedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#assignedBy"> - <rdfs:label xml:lang="en">assigned by</rdfs:label> - <obo:IAO_0000115 xml:lang="en">Relates a Relationship (as a predicate or n-ary relation over one or more Thing) to an Agent that defined or instantiated the predicate instance. </obo:IAO_0000115> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#assigns"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#assignee --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#assignee"> - <rdfs:label xml:lang="en">assignee</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Patent"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#assigneeFor"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#assigneeFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#assigneeFor"> - <rdfs:label xml:lang="en">assignee for patent</rdfs:label> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Patent"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#assigns --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#assigns"> - <rdfs:label xml:lang="en">assigns</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#conceptAssociatedWith --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#conceptAssociatedWith"> - <rdfs:label xml:lang="en">concept for</rdfs:label> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasAssociatedConcept"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#confirmedOrcidId --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#confirmedOrcidId"> - <rdfs:label xml:lang="en-us">Orcid ID confirmation</rdfs:label> - <rdfs:comment>Indicates that the Orcid ID has been confirmed by this Person</rdfs:comment> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#contributingRole --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#contributingRole"> - <rdfs:label xml:lang="en">contributor</rdfs:label> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#roleContributesTo"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateFiled --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#dateFiled"> - <rdfs:label xml:lang="en">date filed</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Patent"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateIssued --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#dateIssued"> - <rdfs:label xml:lang="en">date issued</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateTimeInterval --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#dateTimeInterval"> - <rdfs:label xml:lang="en">date/time interval</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateTimePrecision --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#dateTimePrecision"> - <rdfs:label xml:lang="en">date/time precision</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValuePrecision"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateTimeValue --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#dateTimeValue"> - <rdfs:label xml:lang="en">date/time value</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#degreeCandidacy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#degreeCandidacy"> - <rdfs:label xml:lang="en">degree candidacy</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#AcademicDegree"/> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#AdvisingRelationship"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#distributes --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#distributes"> - <rdfs:label xml:lang="en">distributes</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Description for bibo:distributor taken from here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html .</vitro:descriptionAnnot> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#distributesFundingFrom --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#distributesFundingFrom"> - <rdfs:label xml:lang="en">distributes funding from</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">For example, National Science Foundation providesFundingThrough Graduate Research Fellowship Program; National Institutes of Health providesFundingThrough National Center for Research Resources. </vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#FundingOrganization"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#FundingOrganization"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#providesFundingThrough"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#eligibleFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#eligibleFor"> - <rdfs:label xml:lang="en">credential eligibility attained</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Credential"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#end --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#end"> - <rdfs:label xml:lang="en">end</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#equipmentFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#equipmentFor"> - <rdfs:label xml:lang="en-us">equipment for</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://isf/deprecated_op"/> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Equipment"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasEquipment"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#expirationDate --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#expirationDate"> - <rdfs:label xml:lang="en">expiration date</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#facilityFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#facilityFor"> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasFacility"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#featuredIn --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#featuredIn"> - <rdfs:label xml:lang="en">featured in</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This is done through a restriction on the foaf:Person class.</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#features"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#features --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#features"> - <rdfs:label xml:lang="en">features</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This is done through a restriction on the foaf:Person class.</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#fundingVehicleFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#fundingVehicleFor"> - <rdfs:label xml:lang="en">provides funding for</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Grant"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasFundingVehicle"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#supports"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#geographicFocus --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#geographicFocus"> - <rdfs:label xml:lang="en">geographic focus</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#geographicFocusOf"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#geographicFocusOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#geographicFocusOf"> - <rdfs:label xml:lang="en">geographic focus of</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#governingAuthorityFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#governingAuthorityFor"> - <rdfs:label xml:lang="en">governing authority for</rdfs:label> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasGoverningAuthority"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#grantSubcontractedThrough --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#grantSubcontractedThrough"> - <rdfs:label xml:lang="en">subcontracted through</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Grant"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#subcontractsGrant"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasAssociatedConcept --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasAssociatedConcept"> - <rdfs:label xml:lang="en">associated concept</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasCollaborator --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasCollaborator"> - <rdfs:label xml:lang="en">has collaborator</rdfs:label> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasEquipment --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasEquipment"> - <rdfs:label xml:lang="en">has equipment</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Equipment"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasFacility --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasFacility"> - <rdfs:label xml:lang="en">has facility</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasFundingVehicle --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasFundingVehicle"> - <rdfs:label xml:lang="en">funding provided via</rdfs:label> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Contract"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Grant"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasGoverningAuthority --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasGoverningAuthority"> - <rdfs:label xml:lang="en">governing authority</rdfs:label> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasPredecessorOrganization --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasPredecessorOrganization"> - <rdfs:label xml:lang="en">predecessor organization</rdfs:label> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#hasSuccessorOrganization"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasPrerequisite --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasPrerequisite"> - <rdfs:label xml:lang="en">has prerequisite</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Course"/> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Course"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#prerequisiteFor"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasProceedings --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasProceedings"> - <rdfs:label xml:lang="en">proceedings</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A possible working example: The conference proceeding of the SPIE was generated from the conference - International Society for Optical Engineering.</vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Conference"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Proceedings"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#proceedingsOf"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasPublicationVenue --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasPublicationVenue"> - <rdfs:label xml:lang="en">published in</rdfs:label> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#publicationVenueFor"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasResearchArea --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasResearchArea"> - <rdfs:label xml:lang="en">research areas</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#hasAssociatedConcept"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#researchAreaOf"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasSubjectArea --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasSubjectArea"> - <rdfs:label xml:lang="en">has subject area</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#hasAssociatedConcept"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#subjectAreaOf"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasSuccessorOrganization --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasSuccessorOrganization"> - <rdfs:label xml:lang="en">successor organization</rdfs:label> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasTranslation --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#hasTranslation"> - <rdfs:label xml:lang="en">has translation</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Examples shows a book has French language version. Public description source: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html .</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#informationResourceSupportedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#informationResourceSupportedBy"> - <rdfs:label xml:lang="en">supported by</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">an information resource (typically a publication) supported by (typically via funding) an agreement (such as a grant)</vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#supportedBy"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#supportedInformationResource"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#offeredBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#offeredBy"> - <rdfs:label xml:lang="en">offered by</rdfs:label> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#offers"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#offers --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#offers"> - <rdfs:label xml:lang="en">offers</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#orcidId --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#orcidId"> - <rdfs:label xml:lang="en">ORCID iD</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This is now an object property where the object value is a resource of the form <http://orcid.org/NNNN-NNNN-NNNN-NNNN>. This is to support connecting VIVO and ORCID in the linked data web. Note: a person can have multiple ORCID iDs.</obo:IAO_0000112> - <vitro:stubObjectPropertyAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean">true</vitro:stubObjectPropertyAnnot> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#prerequisiteFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#prerequisiteFor"> - <rdfs:label xml:lang="en">prerequisite for</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Course"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Course"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#proceedingsOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#proceedingsOf"> - <rdfs:label xml:lang="en">proceedings of</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A possible working example: The conference proceeding of the SPIE was generated from the conference - International Society for Optical Engineering.</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Conference"/> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Proceedings"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#providesFundingThrough --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#providesFundingThrough"> - <rdfs:label xml:lang="en">provides funding through</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">For example, National Science Foundation providesFundingThrough Graduate Research Fellowship Program; National Institutes of Health providesFundingThrough National Center for Research Resources. </obo:IAO_0000112> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#FundingOrganization"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#FundingOrganization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#publicationVenueFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#publicationVenueFor"> - <rdfs:label xml:lang="en">publication venue for</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#publisher --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#publisher"> - <rdfs:label xml:lang="en">publisher</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Definition source (http://www.answers.com/topic/publisher).</obo:IAO_0000112> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#publisherOf"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#publisherOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#publisherOf"> - <rdfs:label xml:lang="en">publisher of</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public Definition source (http://www.answers.com/topic/publisher).</obo:IAO_0000112> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#relatedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#relatedBy"> - <rdfs:label xml:lang="en">related by</rdfs:label> - <obo:IAO_0000115 xml:lang="en">Relates a Thing to a Relationship as a Thing that is somehow related to other Thing in the same Relationship instance. A Relationship instnace is a predicate over Thing and is created by an Agent.</obo:IAO_0000115> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#relates"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#relates --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#relates"> - <rdfs:label xml:lang="en">relates</rdfs:label> - <obo:IAO_0000115 xml:lang="en">Relates a Relationship instance to the one or more Thing of the Relationship. There is a separate property (assigned by) to relate to the Agent that defines the Relationship.</obo:IAO_0000115> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#reproduces --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#reproduces"> - <rdfs:label xml:lang="en">reproduces</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://purl.org/ontology/bibo/Document"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#researchAreaOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#researchAreaOf"> - <rdfs:label xml:lang="en">research area of</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#conceptAssociatedWith"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#reviewedIn --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#reviewedIn"> - <rdfs:label xml:lang="en">reviewed in</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The bibo:reviewOf public description was found here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html . As of 26 May 2010, bibo:reviewOf is used with the class Review, but core:reviewIn doesn't seem to be being used.</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Review"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#roleContributesTo --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#roleContributesTo"> - <rdfs:label xml:lang="en">contributes to</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#sponsoredBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#sponsoredBy"> - <rdfs:label xml:lang="en">award sponsored by</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Award"/> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#sponsors"/> - <rdfs:range rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#sponsors --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#sponsors"> - <rdfs:label xml:lang="en">sponsors award or honor</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Award"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#start --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#start"> - <rdfs:label xml:lang="en">start</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#subcontractsGrant --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#subcontractsGrant"> - <rdfs:label xml:lang="en">subcontracts grant</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#Grant"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#subjectAreaOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#subjectAreaOf"> - <rdfs:label xml:lang="en">subject area of</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#conceptAssociatedWith"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#supportedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#supportedBy"> - <rdfs:label xml:lang="en">supported by</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">general relationship of support</vitro:descriptionAnnot> - <owl:inverseOf rdf:resource="http://vivoweb.org/ontology/core#supports"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#supportedInformationResource --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#supportedInformationResource"> - <rdfs:label xml:lang="en">supported publications or other works</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">an information resource (typically a publication) supported by (typically via funding) an agreement (such as a grant)</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#supports"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#supports --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#supports"> - <rdfs:label xml:lang="en">supports</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">general relationship of support</vitro:descriptionAnnot> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#translatorOf --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#translatorOf"> - <rdfs:label xml:lang="en">translator of</rdfs:label> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.org/ontology/bibo/Collection"/> - <rdf:Description rdf:about="http://purl.org/ontology/bibo/Document"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/core#validIn --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/core#validIn"> - <rdfs:label xml:lang="en">valid in</rdfs:label> - <rdfs:range rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#accessProvidedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/scientific-research#accessProvidedBy"> - <rdfs:label xml:lang="en">access provided by</rdfs:label> - <rdfs:range rdf:resource="http://purl.obolibrary.org/obo/ERO_0000391"/> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#documentationFor --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/scientific-research#documentationFor"> - <rdfs:label xml:lang="en">documentation for project or resource</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000014"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000020"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#protocolRealizedBy --> - - <owl:ObjectProperty rdf:about="http://vivoweb.org/ontology/scientific-research#protocolRealizedBy"> - <rdfs:label xml:lang="en">protocol realized by</rdfs:label> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/OBI_0000272"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000014"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://www.ebi.ac.uk/efo/swo/SWO_0000740 --> - - <owl:ObjectProperty rdf:about="http://www.ebi.ac.uk/efo/swo/SWO_0000740"> - <rdfs:label xml:lang="en">implements</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://www.ebi.ac.uk/efo/swo/SWO_0000741 --> - - <owl:ObjectProperty rdf:about="http://www.ebi.ac.uk/efo/swo/SWO_0000741"> - <rdfs:label xml:lang="en">is encoded in</rdfs:label> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:ObjectProperty> - - - - <!-- http://www.obofoundry.org/ro/ro.owl#has_agent --> - - <owl:ObjectProperty rdf:about="http://www.obofoundry.org/ro/ro.owl#has_agent"> - <rdfs:label xml:lang="en">has agent</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2002/07/owl#DeprecatedProperty --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2002/07/owl#DeprecatedProperty"> - <rdfs:label xml:lang="en">deprecated property</rdfs:label> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2002/07/owl#sameAs --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2002/07/owl#sameAs"> - <rdfs:label xml:lang="en">same as</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - <rdfs:domain rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - <rdfs:subPropertyOf rdf:resource="http://www.w3.org/2002/07/owl#topObjectProperty"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2002/07/owl#topObjectProperty --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2002/07/owl#topObjectProperty"/> - - - - <!-- http://www.w3.org/2004/02/skos/core#broader --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2004/02/skos/core#broader"> - <rdfs:label xml:lang="en">broader concept</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description modified from the information on this page: http://www.w3.org/TR/2005/WD-swbp-skos-core-guide-20050510/#sechierarchy .</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description modified from the information on this page: http://www.w3.org/TR/2005/WD-swbp-skos-core-guide-20050510/#sechierarchy .</vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <rdfs:range rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <owl:inverseOf rdf:resource="http://www.w3.org/2004/02/skos/core#narrower"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2004/02/skos/core#narrower --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2004/02/skos/core#narrower"> - <rdfs:label xml:lang="en">narrower concept</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description modified from the information on this page: http://www.w3.org/TR/2005/WD-swbp-skos-core-guide-20050510/#sechierarchy .</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Public description modified from the information on this page: http://www.w3.org/TR/2005/WD-swbp-skos-core-guide-20050510/#sechierarchy .</vitro:descriptionAnnot> - <rdfs:range rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <rdfs:domain rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2004/02/skos/core#related --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2004/02/skos/core#related"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#SymmetricProperty"/> - <rdfs:label xml:lang="en">related concept</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <rdfs:domain rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasAddress --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasAddress"> - <rdfs:label xml:lang="en">has address</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasCalendarLink --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasCalendarLink"> - <rdfs:label xml:lang="en">has calendar link</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarLink"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasCalendarRequest --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasCalendarRequest"> - <rdfs:label xml:lang="en">has calendar request</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarRequest"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasCalenderBusy --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasCalenderBusy"> - <rdfs:label xml:lang="en">has calendar busy</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarBusy"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasCategory --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasCategory"> - <rdfs:label xml:lang="en">has category</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Category"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasEmail --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasEmail"> - <rdfs:label xml:lang="en">has email</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Email"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasFormattedName --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasFormattedName"> - <rdfs:label xml:lang="en">has formatted name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#FormattedName"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasGeo --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasGeo"> - <rdfs:label xml:lang="en">has geo</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Geo"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasInstantMessage --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasInstantMessage"> - <rdfs:label xml:lang="en">has messaging</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#InstantMessage"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasKey --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasKey"> - <rdfs:label xml:lang="en">has key</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Key"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasLanguage --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasLanguage"> - <rdfs:label xml:lang="en">has language</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Language"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasLogo --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasLogo"> - <rdfs:label xml:lang="en">has logo</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Logo"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasMember --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasMember"> - <rdfs:label xml:lang="en">member</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To include a member in the group this vCard represents</rdfs:comment> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Group"/> - <rdfs:range> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://www.w3.org/2006/vcard/ns#Individual"/> - <rdf:Description rdf:about="http://www.w3.org/2006/vcard/ns#Location"/> - <rdf:Description rdf:about="http://www.w3.org/2006/vcard/ns#Organization"/> - </owl:unionOf> - </owl:Class> - </rdfs:range> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasName --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasName"> - <rdfs:label xml:lang="en">has name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasNickname --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasNickname"> - <rdfs:label xml:lang="en">has nickname</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Nickname"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasNote --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasNote"> - <rdfs:label xml:lang="en">has note</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Note"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasOrganizationName --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasOrganizationName"> - <rdfs:label xml:lang="en">has organization name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#OrganizationName"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasOrganizationalUnitName --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasOrganizationalUnitName"> - <rdfs:label xml:lang="en">has organizational unit name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#OrganizationUnitName"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasPhoto --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasPhoto"> - <rdfs:label xml:lang="en">has photo</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Photo"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasRelated --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasRelated"> - <rdfs:label xml:lang="en">has related</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Related"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasSound --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasSound"> - <rdfs:label xml:lang="en">has sound</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Sound"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasTelephone --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasTelephone"> - <rdfs:label xml:lang="en">has telephone</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Telephone"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasTimeZone --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasTimeZone"> - <rdfs:label xml:lang="en">has time zone</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#TimeZone"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasTitle --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasTitle"> - <rdfs:label xml:lang="en">has title</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#Title"/> - </owl:ObjectProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#hasURL --> - - <owl:ObjectProperty rdf:about="http://www.w3.org/2006/vcard/ns#hasURL"> - <rdfs:label xml:lang="en">has URL</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2006/vcard/ns#URL"/> - </owl:ObjectProperty> - - - - <!-- - /////////////////////////////////////////////////////////////////////////////////////// - // - // Data properties - // - /////////////////////////////////////////////////////////////////////////////////////// - --> - - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#GDP --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#GDP"> - <rdfs:label xml:lang="en">GDP</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-12-16</geopolitical:sourceModified> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">GDP at purchaser's prices is the sum of gross value added by all resident producers in the economy plus any product taxes and minus any subsidies not included in the value of the products. It is calculated without making deductions for depreciation of fabricated assets or for depletion and degradation of natural resources. Data are in current U.S. dollars. Dollar figures for GDP are converted from domestic currencies using single year official exchange rates. For a few countries where the official exchange rate does not reflect the rate effectively applied to actual foreign exchange transactions, an alternative conversion factor is used. Source: World Bank national accounts data, and OECD National Accounts data files. http://data.worldbank.org/indicator/NY.GDP.MKTP.CD</terms:description> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">World Bank</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">World Bank http://data.worldbank.org/indicator/NY.GDP.MKTP.CD</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://data.worldbank.org/indicator/NY.GDP.MKTP.CD</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://data.albankaldawli.org/indicator/NY.GDP.MKTP.CD</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://data.worldbank.org/indicator/NY.GDP.MKTP.CD</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://datos.bancomundial.org/indicador/NY.GDP.MKTP.CD</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://donnees.banquemondiale.org/indicateur/NY.GDP.MKTP.CD</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#GDPNotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#GDPNotes"> - <rdfs:label xml:lang="en">GDP notes</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#GDPTotalInCurrentPrices --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#GDPTotalInCurrentPrices"> - <rdfs:label xml:lang="en">GDP total in current prices</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#GDPUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#GDPUnit"> - <rdfs:label xml:lang="en">GDP unit</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#GDPYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#GDPYear"> - <rdfs:label xml:lang="en">GDPYear</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#HDI --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#HDI"> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> composite index measuring average achievement in three basic dimensions of human development-a long and healthy life, knowledge and a decent standard of living. Source: Calculated based on data from UNDESA (2009d), Barro and Lee (2010), UNESCO Institute for Statistics (2010b), World Bank (2010b) and IMF(2010a) . http://hdrstats.undp.org/en/indicators/49806.html</terms:description> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> composite index measuring average achievement in three basic dimensions of human development—a long and healthy life, knowledge and a decent standard of living. Source: Calculated based on data from UNDESA (2009d), Barro and Lee (2010), UNESCO Institute for Statistics (2010b), World Bank (2010b) and IMF(2010a) . http://hdrstats.undp.org/en/indicators/49806.html</terms:description> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-11-04</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">UNDP - HDRO</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">UNDP - HDRO http://hdrstats.undp.org/en/indicators/49806.html</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://hdrstats.undp.org/en/indicators/49806.html</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://hdrstats.undp.org/en/indicators/49806.html</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://hdrstats.undp.org/es/indicadores/49806.html</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://hdrstats.undp.org/fr/indicateurs/49806.html</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#HDINotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#HDINotes"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#HDITotal --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#HDITotal"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#HDIUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#HDIUnit"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#HDIYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#HDIYear"/> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#agriculturalArea --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#agriculturalArea"> - <rdfs:label xml:lang="en">agricultural area</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-07-21</geopolitical:sourceModified> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Agricultural area, this category is the sum of areas under a) arable land - land under temporary agricultural crops (multiple-cropped areas are counted only once), temporary meadows for mowing or pasture, land under market and kitchen gardens and land temporarily fallow (less than five years). The abandoned land resulting from shifting cultivation is not included in this category. Data for “Arable land” are not meant to indicate the amount of land that is potentially cultivable; (b) permanent crops - land cultivated with long-term crops which do not have to be replanted for several years (such as cocoa and coffee); land under trees and shrubs producing flowers, such as roses and jasmine; and nurseries (except those for forest trees, which should be classified under "forest"); and (c) permanent meadows and pastures - land used permanently (five years or more) to grow herbaceous forage crops, either cultivated or growing wild (wild prairie or grazing land). Data are expressed in 1000 hectares. http://faostat.fao.org/site/375/default.aspx </terms:description> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=es#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=fr#ancor</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaNotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaNotes"> - <rdfs:label xml:lang="en">agricultural area notes</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaTotal --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaTotal"> - <rdfs:label xml:lang="en">agriculturalAreaTotal</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaUnit"> - <rdfs:label xml:lang="en">agricultural area unit</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaYear"> - <rdfs:label xml:lang="en">agriculturalAreaYear</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeAGROVOC --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeAGROVOC"> - <rdfs:label xml:lang="en">codeAGROVOC</rdfs:label> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">AGROVOC</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">AGROVOC http://aims.fao.org/website/Search-AGROVOC/sub</terms:source> - <geopolitical:sourceIdentifier xml:lang="ar">http://aims.fao.org/ar/website/Search-AGROVOC/sub</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://aims.fao.org/website/Search-AGROVOC/sub</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://aims.fao.org/es/website/Search-AGROVOC/sub</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://aims.fao.org/fr/website/Search-AGROVOC/sub</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://aims.fao.org/zh-hans/website/Search-AGROVOC/sub</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeCurrency --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeCurrency"> - <rdfs:label xml:lang="en">codeCurrency</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeDBPediaID --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeDBPediaID"> - <rdfs:label xml:lang="en">codeDBPediaID</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-04-28</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DBpedia</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">DBpedia http://dbpedia.org/About</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://dbpedia.org/About</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeFAOSTAT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeFAOSTAT"> - <rdfs:label xml:lang="en">codeFAOSTAT</rdfs:label> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT http://faostat.fao.org</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://faostat.fao.org</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://faostat.fao.org/default.aspx?lang=es</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://faostat.fao.org/default.aspx?lang=fr</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeFAOTERM --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeFAOTERM"> - <rdfs:label xml:lang="en">codeFAOTERM</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeGAUL --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeGAUL"> - <rdfs:label xml:lang="en">codeGAUL</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2008-12-10</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Global Administrative Unit Layers</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Global Administrative Unit Layers http://www.fao.org/geonetwork/srv/en/metadata.show?id=12691</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/geonetwork/srv/en/metadata.show?id=12691</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeISO2 --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeISO2"> - <rdfs:label xml:lang="en">codeISO2</rdfs:label> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ISO 3166-1</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ISO 3166-1 http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.iso.org/iso/country_codes/iso_3166_code_lists.htm</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeISO3 --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeISO3"> - <rdfs:label xml:lang="en">codeISO3</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-04-01</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division http://unstats.un.org/unsd/methods/m49/m49alpha.htm</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://unstats.un.org/unsd/methods/m49/m49alpha.htm</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://unstats.un.org/unsd/methods/m49/m49alphaf.htm</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeUN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeUN"> - <rdfs:label xml:lang="en">codeUN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-04-01</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Statistics Division http://unstats.un.org/unsd/methods/m49/m49alpha.htm</terms:source> - <geopolitical:sourceIdentifier xml:lang="en">http://unstats.un.org/unsd/methods/m49/m49alpha.htm</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://unstats.un.org/unsd/methods/m49/m49alphaf.htm</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#codeUNDP --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#codeUNDP"> - <rdfs:label xml:lang="en">codeUNDP</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#countryArea --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#countryArea"> - <rdfs:label xml:lang="en">countryArea</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2011-07-21</geopolitical:sourceModified> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Country area, area of the country including area under inland water bodies, but excluding offshore territorial waters. Possible variations in the data may be due to updating and revisions of the country data and not necessarily to any change of area. Data are expressed in 1000 hectares. http://faostat.fao.org/site/375/default.aspx </terms:description> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=es#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=fr#ancor</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#countryAreaNotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#countryAreaNotes"> - <rdfs:label xml:lang="en">country area notes</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#countryAreaTotal --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#countryAreaTotal"> - <rdfs:label xml:lang="en">total country area</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#countryAreaUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#countryAreaUnit"> - <rdfs:label xml:lang="en">country area unit</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#countryAreaYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#countryAreaYear"> - <rdfs:label xml:lang="en">countryAreaYear</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasCode --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasCode"> - <rdfs:label xml:lang="en">has code</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasCoordinate --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasCoordinate"> - <rdfs:label xml:lang="en">has coordinate</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasCurrency --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasCurrency"> - <rdfs:label xml:lang="en">has currency</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasListName --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasListName"> - <rdfs:label xml:lang="en">has list name</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasMaxLatitude --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasMaxLatitude"> - <rdfs:label xml:lang="en">has maximum latitude</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasMaxLongitude --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasMaxLongitude"> - <rdfs:label xml:lang="en">has maximum longitude</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasMinLatitude --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasMinLatitude"> - <rdfs:label xml:lang="en">has minimum latitude</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasMinLongitude --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasMinLongitude"> - <rdfs:label xml:lang="en">has minimum longitude</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasNationality --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasNationality"> - <rdfs:label xml:lang="en">has nationality</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasOfficialName --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasOfficialName"> - <rdfs:label xml:lang="en">has official name</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasShortName --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasShortName"> - <rdfs:label xml:lang="en">has short name</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#hasStatistics --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#hasStatistics"> - <rdfs:label xml:lang="en">has statistics</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#landArea --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#landArea"> - <rdfs:label xml:lang="en">land area</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2011-07-21</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</terms:source> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Land area is the total area of the country excluding area under inland water bodies. Possible variations in the data may be due to updating and revisions of the country data and not necessarily to any change of area. Data are expressed in 1 000 hectares. http://faostat.fao.org/site/375/default.aspx </terms:description> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=es#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://faostat.fao.org/DesktopDefault.aspx?PageID=377&lang=fr#ancor</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#landAreaNotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#landAreaNotes"> - <rdfs:label xml:lang="en">land area notes</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#landAreaTotal --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#landAreaTotal"> - <rdfs:label xml:lang="en">total land area</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#landAreaUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#landAreaUnit"> - <rdfs:label xml:lang="en">land area unit</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#landAreaYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#landAreaYear"> - <rdfs:label xml:lang="en">landAreaYear</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyAR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyAR"> - <rdfs:label xml:lang="en">nameCurrencyAR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyEN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyEN"> - <rdfs:label xml:lang="en">nameCurrencyEN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyES --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyES"> - <rdfs:label xml:lang="en">nameCurrencyES</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyFR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyFR"> - <rdfs:label xml:lang="en">nameCurrencyFR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyIT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyIT"> - <rdfs:label xml:lang="en">nameCurrencyIT</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyRU --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyRU"> - <rdfs:label xml:lang="en">nameCurrencyRU</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameCurrencyZH --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyZH"> - <rdfs:label xml:lang="en">nameCurrencyZH</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListAR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListAR"> - <rdfs:label xml:lang="en">nameListAR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListEN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListEN"> - <rdfs:label xml:lang="en">nameListEN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListES --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListES"> - <rdfs:label xml:lang="en">nameListES</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListFR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListFR"> - <rdfs:label xml:lang="en">nameListFR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListIT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListIT"> - <rdfs:label xml:lang="en">nameListIT</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListRU --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListRU"> - <rdfs:label xml:lang="en">nameListRU</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameListZH --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameListZH"> - <rdfs:label xml:lang="en">nameListZH</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialAR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialAR"> - <rdfs:label xml:lang="en">nameOfficialAR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialEN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialEN"> - <rdfs:label xml:lang="en">nameOfficialEN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialES --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialES"> - <rdfs:label xml:lang="en">nameOfficialES</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialFR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialFR"> - <rdfs:label xml:lang="en">nameOfficialFR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialIT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialIT"> - <rdfs:label xml:lang="en">nameOfficialIT</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialRU --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialRU"> - <rdfs:label xml:lang="en">nameOfficialRU</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameOfficialZH --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameOfficialZH"> - <rdfs:label xml:lang="en">nameOfficialZH</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortAR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortAR"> - <rdfs:label xml:lang="en">nameShortAR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortEN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortEN"> - <rdfs:label xml:lang="en">nameShortEN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortES --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortES"> - <rdfs:label xml:lang="en">nameShortES</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortFR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortFR"> - <rdfs:label xml:lang="en">nameShortFR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortIT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortIT"> - <rdfs:label xml:lang="en">nameShortIT</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortRU --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortRU"> - <rdfs:label xml:lang="en">nameShortRU</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nameShortZH --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nameShortZH"> - <rdfs:label xml:lang="en">nameShortZH</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityAR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityAR"> - <rdfs:label xml:lang="en">nationalityAR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityEN --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityEN"> - <rdfs:label xml:lang="en">nationalityEN</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityES --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityES"> - <rdfs:label xml:lang="en">nationalityES</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityFR --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityFR"> - <rdfs:label xml:lang="en">nationalityFR</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityIT --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityIT"> - <rdfs:label xml:lang="en">nationalityIT</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityRU --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityRU"> - <rdfs:label xml:lang="en">nationalityRU</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#nationalityZH --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#nationalityZH"> - <rdfs:label xml:lang="en">nationalityZH</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010-06-24</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAO terminology http://www.fao.org/termportal/en/</terms:source> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.fao.org/termportal/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="ar">http://www.fao.org/termportal/contr/ar/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://www.fao.org/termportal/contr/en/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://www.fao.org/termportal/contr/es/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://www.fao.org/termportal/contr/fr/</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="zh">http://www.fao.org/termportal/contr/zh/</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#population --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#population"> - <rdfs:label xml:lang="en">population</rdfs:label> - <geopolitical:sourceModified rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2009-09-21</geopolitical:sourceModified> - <geopolitical:sourceCreator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT</geopolitical:sourceCreator> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">FAOSTAT http://faostat.fao.org/site/550/default.aspx</terms:source> - <terms:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The total population usually refers to the present-in-area (de facto) population which includes all persons physically present within the present geographical boundaries of countries at the mid-point of the reference period. http://faostat.fao.org/site/375/default.aspx</terms:description> - <geopolitical:sourceIdentifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://faostat.fao.org/DesktopDefault.aspx?PageID=550&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="en">http://faostat.fao.org/DesktopDefault.aspx?PageID=550&lang=en#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="es">http://faostat.fao.org/DesktopDefault.aspx?PageID=550&lang=es#ancor</geopolitical:sourceIdentifier> - <geopolitical:sourceIdentifier xml:lang="fr">http://faostat.fao.org/DesktopDefault.aspx?PageID=550&lang=fr#ancor</geopolitical:sourceIdentifier> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#populationNotes --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#populationNotes"> - <rdfs:label xml:lang="en">population notes</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#populationTotal --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#populationTotal"> - <rdfs:label xml:lang="en">total population</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#populationUnit --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#populationUnit"> - <rdfs:label xml:lang="en">population unit</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#populationYear --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#populationYear"> - <rdfs:label xml:lang="en">populationYear</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#validSince --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#validSince"> - <rdfs:label xml:lang="en">valid since</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The value of the datatype property *validSince* associated to a particular area (territory or group) indicates the area's first year of validity. The geopolitical ontology traces back historic changes only until 1985, therefore, if an area has a validSince = 1985, this indicates that the area is/was valid since 1985 or before. </rdfs:comment> - </owl:DatatypeProperty> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#validUntil --> - - <owl:DatatypeProperty rdf:about="http://aims.fao.org/aos/geopolitical.owl#validUntil"> - <rdfs:label xml:lang="en">valid until</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The value of the datatype property *validUntil* associated to a particular area (territory or group) indicates the area's last year of validity. In case the area is currently valid, this value is set by default to 9999. - </rdfs:comment> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000001 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ARG_0000001"> - <rdfs:label xml:lang="en">is template</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The document can be used as a template for the creation of other documents. </obo:IAO_0000115> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000015 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ARG_0000015"> - <rdfs:label xml:lang="en">user-defined tag</rdfs:label> - <obo:IAO_0000115>A free text field for recording topics which relate to the resource. </obo:IAO_0000115> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ARG_0000008"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000172 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ARG_0000172"> - <rdfs:label xml:lang="en">patient ID</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000197 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ARG_0000197"> - <rdfs:label xml:lang="en">health care provider ID</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000012 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ARG_2000012"> - <rdfs:label xml:lang="en">Measurement Label</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000044 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000044"> - <rdfs:label xml:lang="en">inventory number</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An example inventory number can be in the form: 12345</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Inventory identifier for the resource.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has inventory number</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000020"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/OBI_0100026"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000045 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000045"> - <rdfs:label xml:lang="en">has restriction</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A restriction on service availability, such as university or consortium affiliation, geographical location, professional certification, or other factors.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Resource is only available to researchers in the department.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has restriction</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000015"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000020"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000595"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/OBI_0100026"/> - <rdf:Description rdf:about="http://purl.org/ontology/bibo/Document"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000046 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000046"> - <rdfs:label xml:lang="en">has geographic restriction</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Any service limitation tied to geographically-defined areas such as metro areas, counties, states, or regions. </obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Resource is only available to researchers in Boston area.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has geographic restriction</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <rdfs:subPropertyOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000045"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000050 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000050"> - <rdfs:label xml:lang="en">model number</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ABI 9000</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Instrument model number, which may be a name, number, or both.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">model number</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000004"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000054 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000054"> - <rdfs:label xml:lang="en">lab data format</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Current method or software used to inventory a lab's resources. Examples include Excel, index cards, FileMaker, 3-ring binder, etc.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Excel spreadsheet</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">lab data format</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Center"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Laboratory"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000072 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000072"> - <rdfs:label xml:lang="en">version</rdfs:label> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Software edition, typically a numeral followed by a decimal and another numeral, such as 2.1.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">v 1.0</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"/> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000424 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000424"> - <rdfs:label xml:lang="en">has study population</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">African american study population.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Characteristics of the human population being studied. May include number, demographic or geographic information, inclusion or exclusion criteria, or other descriptive information.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">study population</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000015"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000774 --> - - <owl:DatatypeProperty rdf:about="http://purl.obolibrary.org/obo/ERO_0000774"> - <rdfs:label xml:lang="en">has eligibility requirement</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A grade point average above 3.5 is an eligibility requirement.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Requirements for research opportunity eligibility. Requirements include: coursework, minimum gradepoint average, state residency, under-represented group status, field of study, or matriculation status.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">has eligibility requirement</obo:IAO_0000111> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/ERO_0000595"/> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/abstract --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/abstract"> - <rdfs:label xml:lang="en">abstract</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/dc/terms/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment>A summary of the resource.</rdfs:comment> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/asin --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/asin"> - <rdfs:label xml:lang="en">Amazon Standard Identification Number (ASIN)</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">020530902X</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Amazon standard identification number. Source: http://en.wikipedia.org/wiki/Amazon_Standard_Identification_Number.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">Amazon Standard Identification Number</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/chapter --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/chapter"> - <rdfs:label xml:lang="en">chapter number</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An chapter number</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/BookSection"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/coden --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/coden"> - <rdfs:label xml:lang="en">coden</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">CODEN became particularly common in the scientific community as a citation system for periodicals cited in technical- as well in chemistry-related publications and as a search tool in many bibliographic catalogues. -Definition and description came from Wikipedia here: http://en.wikipedia.org/wiki/CODEN </obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An identifier of serials, still in use by libraries, but replaced by ISSN for any new work</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/doi --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/doi"> - <rdfs:label xml:lang="en">Digital Object Identifier (DOI)</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Digital Object Identifier</rdfs:comment> - <rdfs:domain rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/eanucc13 --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/eanucc13"> - <rdfs:label xml:lang="en">EAN International-Uniform Code Council (EAN-UCC) 13</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition source: http://en.wikipedia.org/wiki/European_Article_Numbering-Uniform_Code_Council. -The Uniform Code Council (UCC) was the Numbering Organization in the USA to administer and manage the EAN.UCC System. In 2005 the UCC changed its name to GS1 US.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">European Article Number/Uniform Commercier Code 13</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/edition --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/edition"> - <rdfs:label xml:lang="en">edition</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">The name defining a special edition of a document. Normally its a literal value composed of a version number and words.</rdfs:comment> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/eissn --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/eissn"> - <rdfs:label xml:lang="en">Electronic International Standard Serial Number (EISSN)</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">eissn stands for Electronic International Standard Serial Number. source: http://www.definition-of.com/EISSN</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">The electronic ISSN number of a periodical.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/gtin14 --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/gtin14"> - <rdfs:label xml:lang="en">Global Trade Item Number (GTIN-14)</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Global_Trade_Item_Number.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Global Trade Item Number 14</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/identifier --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/identifier"> - <rdfs:label xml:lang="en">identifier</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/isbn10 --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/isbn10"> - <rdfs:label xml:lang="en">International Standard Book Number (ISBN) 10</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Isbn.</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Book"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/isbn13 --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/isbn13"> - <rdfs:label xml:lang="en">International Standard Book Number (ISBN) 13</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">source: http://en.wikipedia.org/wiki/Isbn.</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Book"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/issn --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/issn"> - <rdfs:label xml:lang="en">International Standard Serial Number (ISSN)</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">source: http://en.wikipedia.org/wiki/Issn</obo:IAO_0000112> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">International Standard Serial Number</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/issue --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/issue"> - <rdfs:label xml:lang="en">issue</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Bibo has the domain of bibo:issue as the class Issue, but an example on their site uses it with Article, referring to the issue number "4"</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/lccn --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/lccn"> - <rdfs:label xml:lang="en">Library of Congress Control Number (LCCN)</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Source: http://en.wikipedia.org/wiki/Library_of_Congress_Control_Number.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Library of Congress Control Number</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/locator --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/locator"> - <rdfs:label xml:lang="en">locator</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">definition from: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A description (often numeric) that locates an item within a containing document or collection.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/numPages --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/numPages"> - <rdfs:label xml:lang="en">number of pages</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/number --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/number"> - <rdfs:label xml:lang="en">number</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition from here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/oclcnum --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/oclcnum"> - <rdfs:label xml:lang="en">Online Computer Library Center (OCLC) number</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:oclcnum/. - - -bibo has the domain of this property set to the union of Collection and Document.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">OCLC Identifier</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/pageEnd --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/pageEnd"> - <rdfs:label xml:lang="en">end page</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Ending page number within a continuous page range.</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/pageStart --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/pageStart"> - <rdfs:label xml:lang="en">start page</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Starting page number within a continuous page range.</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/pmid --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/pmid"> - <rdfs:label xml:lang="en">PubMed ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The PubMed ID (PMID) identifies a citation record (rather than full-text) in the PubMed database. It is not evidence of compliance with the NIH Public Access Policy, because it does not identify a full-text submission of any kind.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">PubMed Identifier</rdfs:comment> - <ns:term_status>stable</ns:term_status> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/prefixName --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/prefixName"> - <rdfs:label xml:lang="en">name prefix</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Mr; Ms; Mrs</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://dictionary.reference.com/browse/prefix</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">The prefix of a name</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/section --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/section"> - <rdfs:label xml:lang="en">section</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An section number</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - <obo:IAO_0000112 xml:lang="en">Di Rado, Alicia. 1995. Trekking through college: Classes explore -modern society using the world of Star trek. Los Angeles Times, March -15, sec. A, p. 3.</obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/shortDescription --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/shortDescription"> - <rdfs:label xml:lang="en">short description</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment>A short description of the resource.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - <skos:scopeNote xml:lang="en">The idea here is that while dcterms:description may involve length descriptions, this for short (two or three word) descriptions that could go in a bibliographic entry.</skos:scopeNote> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/sici --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/sici"> - <rdfs:label xml:lang="en">Serial Item and Contribution Identifier (SICI)</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A sub property of identifier (http://en.wikipedia.org/wiki/SICI).</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Serial Item and Contribution Identifier</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/upc --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/upc"> - <rdfs:label xml:lang="en">Universal Product Code (UPC)</rdfs:label> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">source for public description: http://en.wikipedia.org/wiki/Universal_Product_Code.</obo:IAO_0000112> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Universal Product Code</rdfs:comment> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/uri --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/uri"> - <rdfs:label xml:lang="en">URI</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition from: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/ontology/bibo/volume --> - - <owl:DatatypeProperty rdf:about="http://purl.org/ontology/bibo/volume"> - <rdfs:label xml:lang="en">volume</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/locator"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/spar/c4o/hasGlobalCountDate --> - - <owl:DatatypeProperty rdf:about="http://purl.org/spar/c4o/hasGlobalCountDate"> - <rdfs:label xml:lang="en">has global count date</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The date on which the global citation count of the cited entity was recorded from a named bibliographic information source.</obo:IAO_0000115> - <rdfs:domain rdf:resource="http://purl.org/spar/c4o/GlobalCitationCount"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#date"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/spar/c4o/hasGlobalCountValue --> - - <owl:DatatypeProperty rdf:about="http://purl.org/spar/c4o/hasGlobalCountValue"> - <rdfs:label xml:lang="en">has global count value</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An integer defining the value of the global citation count of a cited entity recorded from a named bibliographic information source on a particular date.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An integer defining the value of the global citation count of a cited entity recorded from a named bibliographic information source on a particular date.</vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://purl.org/spar/c4o/GlobalCitationCount"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/> - </owl:DatatypeProperty> - - - - <!-- http://purl.org/vocab/vann/preferredNamespaceUri --> - - <owl:DatatypeProperty rdf:about="http://purl.org/vocab/vann/preferredNamespaceUri"> - <rdfs:label xml:lang="en">preferred namespace URI</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#abbreviation --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#abbreviation"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">abbreviation</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A short form for an longer title or name.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">B.A.</obo:IAO_0000112> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#cclCode --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#cclCode"> - <rdfs:label xml:lang="en">published US Classification Class/subclass (CCL) code</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Patent"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#contactInformation --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#contactInformation"> - <rdfs:label xml:lang="en">contact information</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#courseCredits --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#courseCredits"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">credits</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#dateTime --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#dateTime"> - <rdfs:label xml:lang="en">date/time</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#departmentOrSchool --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#departmentOrSchool"> - <rdfs:label xml:lang="en">department or school name within institution</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Not intended to be an institution name.</vitro:descriptionAnnot> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#EducationalProcess"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#description --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#description"> - <rdfs:label xml:lang="en">description</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#eRACommonsId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#eRACommonsId"> - <rdfs:label xml:lang="en">eRA Commons ID</rdfs:label> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#entryTerm --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#entryTerm"> - <rdfs:label xml:lang="en">entry term</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#freetextKeyword --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#freetextKeyword"> - <rdfs:label xml:lang="en">keywords</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">conservation - -use one freetextKeyword assertion for each keyword or phrase.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">one keyword or phrase per freetextKeyword assertion</obo:IAO_0000112> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#grantDirectCosts --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#grantDirectCosts"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">direct costs</rdfs:label> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Contract"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Grant"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasMonetaryAmount --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#hasMonetaryAmount"> - <rdfs:label xml:lang="en">has monetary amount</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#hasValue --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#hasValue"> - <rdfs:label xml:lang="en">has value</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#hideFromDisplay --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#hideFromDisplay"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">hide from display</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#hrJobTitle --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#hrJobTitle"> - <rdfs:label xml:lang="en">HR job title</rdfs:label> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition http://en.wikipedia.org/wiki/Job_title#Job_title.</vitro:descriptionAnnot> - <vitro:exampleAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">administrative secretary</vitro:exampleAnnot> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Position"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#iclCode --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#iclCode"> - <rdfs:label xml:lang="en">International Classification (ICL) code</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The International classification(s) to which the published application has been assigned. -</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Patent"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#identifier --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#identifier"> - <rdfs:label xml:lang="en">identifier</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#isCorrespondingAuthor --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#isCorrespondingAuthor"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">Is this person a corresponding author?</rdfs:label> - <vitro:exampleAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">True; False</vitro:exampleAnnot> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Authorship"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#licenseNumber --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#licenseNumber"> - <rdfs:label xml:lang="en">license number</rdfs:label> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Licensure"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#localAwardId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#localAwardId"> - <rdfs:label xml:lang="en">local award ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">core:localAwardId has a domain of core:Grant, and should be public since that's its public identifier for local use by OSP, accounting, department admins, and the PI </obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Contract"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Grant"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#majorField --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#majorField"> - <rdfs:label xml:lang="en">major field of degree</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Information Science; Computer Science; Anthropology</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#EducationalProcess"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#middleName --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#middleName"> - <rdfs:label xml:lang="en">middle name or initial</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#nihmsid --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#nihmsid"> - <rdfs:label xml:lang="en">NIH Manuscript Submission System ID</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#outreachOverview --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#outreachOverview"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">outreach overview</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">My extension program consists of developing and reporting disease management strategies that are both economically and environmentally sound for fresh market vegetable production. We hope that some of this testing will result in practices adaptable for organic production.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used for a single narrative summary of outreach, typically covering a wide range of activities and time periods; use Outreach Provider Role for information on individual activities</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#overview --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#overview"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">overview</rdfs:label> - <obo:IAO_0000112 xml:lang="en">My research focuses on diseases of pine crops in the southeastern United States.</obo:IAO_0000112> - <obo:IAO_0000115 xml:lang="en">Short text for presentation describing the agent's purpose, activities, and/or accomplishments.</obo:IAO_0000115> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#patentNumber --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#patentNumber"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">patent number</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">source of definition: http://www.uspto.gov/main/glossary/#p . The following site has patent number formats: http://www.uspto.gov/patents/ebc/kindcodesum.jsp .</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Patent"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#placeOfPublication --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#placeOfPublication"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">place of publication</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#pmcid --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#pmcid"> - <rdfs:label xml:lang="en">PubMed Central ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> A PMCID is a unique PubMed Central reference number, which is assigned to each full-text record made available A PMCID is a unique PubMed Central reference number, which is assigned to each full-text record made available in PubMed Central. The PMCID is issued shortly after the PI or author approves the PubMed Central formatted web version of the submission. </obo:IAO_0000112> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#preferredDisplayOrder --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#preferredDisplayOrder"> - <rdfs:label xml:lang="en">preferred display order</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#rank --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#rank"> - <rdfs:label xml:lang="en">rank</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">this number indicates a position in a list</obo:IAO_0000112> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#reportId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#reportId"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">report identifier</rdfs:label> - <rdfs:domain rdf:resource="http://purl.org/ontology/bibo/Report"/> - <rdfs:subPropertyOf rdf:resource="http://purl.org/ontology/bibo/identifier"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#researchOverview --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#researchOverview"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">research overview</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used for a single narrative summary of research, typically covering a wide range of activities and time periods; use Researcher Role for information on individual activities</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#researcherId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#researcherId"> - <rdfs:label xml:lang="en">ISI Researcher ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">RearcherID is a Thomson Reuters project where researchers have a place to manage and share their professional information. It will allow them to solve author identity issues while simultaneously adding dynamic citation metrics and collaboration networks to your personal profile. -Definition source: http://isiwebofknowledge.com/researcherid/</obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#scopusId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#scopusId"> - <rdfs:label xml:lang="en">Scopus ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Home page for Scopus: http://www.scopus.com/home.url</obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#seatingCapacity --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#seatingCapacity"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">seating capacity</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">55</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">definition modified from: source (http://en.wikipedia.org/wiki/Seating_capacity).</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://vivoweb.org/ontology/core#Room"/> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#sponsorAwardId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#sponsorAwardId"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">sponsor award ID</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Has a domain of Grant. There is not a strong reason have this be publically visible, since most users would care more about the name of the sponsoring agency than its identifier, but it does no harm to be public. - - -See also core:localAwardId. -</obo:IAO_0000112> - <rdfs:subPropertyOf rdf:resource="http://vivoweb.org/ontology/core#identifier"/> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Contract"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Grant"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#supplementalInformation --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#supplementalInformation"> - <rdfs:label xml:lang="en">supplemental information</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#teachingOverview --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#teachingOverview"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">teaching overview</rdfs:label> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used for a single narrative summary of teaching, typically covering a wide range of courses including for credit and non-credit teaching over multiple semesters; the "teaches" property links a person directly with an instance of a Semester Class, typically from an institutional database of record; then use Teacher Role for information about a person's role in non-credit teaching or their specific contribution to individual courses</obo:IAO_0000112> - <rdfs:domain rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#termLabel --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#termLabel"> - <rdfs:label xml:lang="en">term label</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#termType --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#termType"> - <rdfs:label xml:lang="en">term type</rdfs:label> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/core#totalAwardAmount --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/core#totalAwardAmount"> - <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/> - <rdfs:label xml:lang="en">total award amount</rdfs:label> - <rdfs:domain> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Contract"/> - <rdf:Description rdf:about="http://vivoweb.org/ontology/core#Grant"/> - </owl:unionOf> - </owl:Class> - </rdfs:domain> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#irbNumber --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/scientific-research#irbNumber"> - <rdfs:label xml:lang="en">Institutional Review Board (IRB) number</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Every clinical trial in the United States must be approved and monitored by an Institutional Review Board (IRB). An IRB is an independent committee of physicians, statisticians, community advocates and others whose objective is to ensure that a clinical trial is ethical and the rights of study participants are protected. </obo:IAO_0000115> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#nctId --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/scientific-research#nctId"> - <rdfs:label xml:lang="en">National Clinical Trials (NCT) number</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">ClinicalTrials.gov is an ICMJE-acceptable public registry, offering up-to-date information for locating clinical trials for a wide range of diseases and conditions. The U.S. National Institutes of Health (NIH), through its National Library of Medicine (NLM), developed this site in collaboration with the Food and Drug Administration (FDA), as a result of the FDA Modernization Act, which was passed into law in November 1997. This property should be publically visible since it is one of the principal identifiers in a national registry of clinical trials </obo:IAO_0000115> - <vitro:exampleAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">NCT00000419</vitro:exampleAnnot> - </owl:DatatypeProperty> - - - - <!-- http://vivoweb.org/ontology/scientific-research#studyPopulationCount --> - - <owl:DatatypeProperty rdf:about="http://vivoweb.org/ontology/scientific-research#studyPopulationCount"> - <rdfs:label xml:lang="en">study population count</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">number of human participants in the study (trial).</obo:IAO_0000115> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#additionalName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#additionalName"> - <rdfs:label xml:lang="en">additional name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#anniversary --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#anniversary"> - <rdfs:label xml:lang="en">anniversary</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The date of marriage, or equivalent, of the object the vCard represents</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Individual"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#birthdate --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#birthdate"> - <rdfs:label xml:lang="en">birthdate</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the birth date of the object the vCard represents</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Individual"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#calendarBusy --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#calendarBusy"> - <rdfs:label xml:lang="en">calendar busy</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarBusy"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#calendarLink --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#calendarLink"> - <rdfs:label xml:lang="en">calendar link</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarLink"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#calendarRequest --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#calendarRequest"> - <rdfs:label xml:lang="en">calendar request</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#CalendarRequest"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#category --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#category"> - <rdfs:label xml:lang="en">category</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Category"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#country --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#country"> - <rdfs:label xml:lang="en">country</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#email --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#email"> - <rdfs:label xml:lang="en">email</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Email"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#familyName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#familyName"> - <rdfs:label xml:lang="en">has last name</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Called Family Name in vCard</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#formattedName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#formattedName"> - <rdfs:label xml:lang="en">has formatted name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#FormattedName"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#gender --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#gender"> - <rdfs:label xml:lang="en">gender</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the components of the sex and gender identity of the object the vCard represents. -To enable other Gender/Sex codes to be used, this dataproperty has range URI. The vCard gender code classes are defined under Code/Gender</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Individual"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#geo --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#geo"> - <rdfs:label xml:lang="en">geo</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Must use the geo URI scheme RFC5870</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Geo"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#givenName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#givenName"> - <rdfs:label xml:lang="en">first name</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">called Given Name invCard</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#honorificPrefix --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#honorificPrefix"> - <rdfs:label xml:lang="en">honorific prefix</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Called Honorific Prefix in vCard</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#honorificSuffix --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#honorificSuffix"> - <rdfs:label xml:lang="en">honorific suffix</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#instantMessage --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#instantMessage"> - <rdfs:label xml:lang="en">instant message</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#InstantMessage"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#key --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#key"> - <rdfs:label xml:lang="en">key</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Key"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#language --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#language"> - <rdfs:label xml:lang="en">has language</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use 2 char language code from RFC5646</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#locality --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#locality"> - <rdfs:label xml:lang="en">locality</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#logo --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#logo"> - <rdfs:label xml:lang="en">logo</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Logo"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#nickName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#nickName"> - <rdfs:label xml:lang="en">nickname</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Nickname"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#note --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#note"> - <rdfs:label xml:lang="en">note</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Note"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#organizationName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#organizationName"> - <rdfs:label xml:lang="en">organization name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#OrganizationName"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#organizationalUnitName --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#organizationalUnitName"> - <rdfs:label xml:lang="en">organizational unit name</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#OrganizationUnitName"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#photo --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#photo"> - <rdfs:label xml:lang="en">photo</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Photo"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#postalCode --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#postalCode"> - <rdfs:label xml:lang="en">postal code</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#productId --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#productId"> - <rdfs:label xml:lang="en">product ID</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#region --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#region"> - <rdfs:label xml:lang="en">region</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#related --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#related"> - <rdfs:label xml:lang="en">related</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Related"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#revision --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#revision"> - <rdfs:label xml:lang="en">revision</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#role --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#role"> - <rdfs:label xml:lang="en">role</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Role"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#sortAs --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#sortAs"> - <rdfs:label xml:lang="en">sort as</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#sound --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#sound"> - <rdfs:label xml:lang="en">sound</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Sound"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#source --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#source"> - <rdfs:label xml:lang="en">source</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#streetAddress --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#streetAddress"> - <rdfs:label xml:lang="en">street address</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#telephone --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#telephone"> - <rdfs:label xml:lang="en">Telephone</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#timeZone --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#timeZone"> - <rdfs:label xml:lang="en">timezone</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#TimeZone"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#title --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#title"> - <rdfs:label xml:lang="en">title</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - <rdfs:domain rdf:resource="http://www.w3.org/2006/vcard/ns#Title"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#uid --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#uid"> - <rdfs:label xml:lang="en">uid</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify a value that represents a globally unique identifier corresponding to the entity associated with the vCard</rdfs:comment> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:DatatypeProperty> - - - - <!-- http://www.w3.org/2006/vcard/ns#url --> - - <owl:DatatypeProperty rdf:about="http://www.w3.org/2006/vcard/ns#url"> - <rdfs:label xml:lang="en">URL</rdfs:label> - <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:DatatypeProperty> - - - - <!-- - /////////////////////////////////////////////////////////////////////////////////////// - // - // Classes - // - /////////////////////////////////////////////////////////////////////////////////////// - --> - - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#area --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#area"> - <rdfs:label xml:lang="en">Area</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialEN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListRU"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialRU"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#validSince"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialES"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeDBPediaID"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortFR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListAR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListIT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialFR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListES"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortEN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeISO3"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeUN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeGAUL"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListEN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeFAOSTAT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortZH"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListZH"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortAR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeISO2"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeFAOTERM"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialIT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#validUntil"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialAR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeAGROVOC"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortES"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameListFR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeUNDP"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortRU"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameOfficialZH"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameShortIT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#disputed --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#disputed"> - <rdfs:label xml:lang="en">Disputed</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#economic_region --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#economic_region"> - <rdfs:label xml:lang="en">Economic Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#geographical_region --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#geographical_region"> - <rdfs:label xml:lang="en">Transnational Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations statistics department http://unstats.un.org/unsd/methods/m49/m49regin.htm</terms:source> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#group --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#group"> - <rdfs:label xml:lang="en">Group</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#non_self_governing --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#non_self_governing"> - <rdfs:label xml:lang="en">Non Self Governing</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#isAdministeredBy"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#isAdministeredBy"/> - <owl:allValuesFrom rdf:resource="http://aims.fao.org/aos/geopolitical.owl#self_governing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#isAdministeredBy"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">UN Cartographic Section, Department of Field Support http://www.un.org/Depts/Cartographic/map/profile/world00.pdf</terms:source> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#organization --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#organization"> - <rdfs:label xml:lang="en">Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#other --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#other"> - <rdfs:label xml:lang="en">Other</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#self_governing --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#self_governing"> - <rdfs:label xml:lang="en">Self Governing</rdfs:label> - <owl:equivalentClass rdf:resource="http://vivoweb.org/ontology/core#Country"/> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#territory"/> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <terms:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United Nations Map Library http://www.un.org/depts/dhl/maplib/countinfo.htm</terms:source> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#special_group --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#special_group"> - <rdfs:label xml:lang="en">Special Group</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#group"/> - </owl:Class> - - - - <!-- http://aims.fao.org/aos/geopolitical.owl#territory --> - - <owl:Class rdf:about="http://aims.fao.org/aos/geopolitical.owl#territory"> - <rdfs:label xml:lang="en">Territory</rdfs:label> - <rdfs:subClassOf rdf:resource="http://aims.fao.org/aos/geopolitical.owl#area"/> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityFR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#GDPTotalInCurrentPrices"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#countryAreaUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#populationYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyZH"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityAR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#landAreaNotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#populationNotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityZH"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#hasMinLongitude"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#landAreaYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#landAreaUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#HDIUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityES"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#GDPNotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#countryAreaYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyIT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyRU"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#populationTotal"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#countryAreaNotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#GDPYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#hasMaxLongitude"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyEN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaTotal"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaNotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#landAreaTotal"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#codeCurrency"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyES"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#HDINotes"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#GDPUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityEN"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nameCurrencyFR"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityIT"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#agriculturalAreaYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#hasMaxLatitude"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#countryAreaTotal"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#HDIYear"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#HDITotal"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#hasMinLatitude"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#populationUnit"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://aims.fao.org/aos/geopolitical.owl#nationalityRU"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </rdfs:subClassOf> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_0000008 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_0000008"/> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000008 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000008"> - <rdfs:label xml:lang="en">Topic Weight Measurement</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000032"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000009 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000009"> - <rdfs:label xml:lang="en">Expertise Measurement</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000008"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000010 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000010"> - <rdfs:label xml:lang="en">Topic Weight Measurement Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000011 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000011"> - <rdfs:label xml:lang="en">Expertise Measurement Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000010"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000021 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000021"> - <rdfs:label xml:lang="en">Experience</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000019"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000022 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000022"> - <rdfs:label xml:lang="en">specialty</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000019"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000376 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000376"> - <rdfs:label xml:lang="en">Contact Qualifier</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000377 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000377"> - <rdfs:label xml:lang="en">FOAF Profile</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000379"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ARG_2000379 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ARG_2000379"> - <rdfs:label xml:lang="en">Contact</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000001 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000001"> - <rdfs:label xml:lang="en">Entity</rdfs:label> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000002 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000002"> - <rdfs:label xml:lang="en">Continuant</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000001"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000003 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000003"> - <rdfs:label xml:lang="en">Occurrent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000001"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000004 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000004"> - <rdfs:label xml:lang="en">Independent Continuant</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000002"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000006 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000006"> - <rdfs:label xml:lang="en">Spatial Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000141"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000008 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000008"> - <rdfs:label xml:lang="en">Temporal Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000003"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000015 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000015"> - <rdfs:label xml:lang="en">Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000003"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000016 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000016"> - <rdfs:label xml:lang="en">Disposition</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000017"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000017 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000017"> - <rdfs:label xml:lang="en">Realizable Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000020"/> - <owl:disjointWith rdf:resource="http://purl.obolibrary.org/obo/BFO_0000019"/> - <obo:IAO_0000602>(forall (x) (if (RealizableEntity x) (and (SpecificallyDependentContinuant x) (exists (y) (and (IndependentContinuant y) (not (SpatialRegion y)) (inheresIn x y)))))) // axiom label in BFO2 CLIF: [058-002] </obo:IAO_0000602> - <obo:IAO_0000602>(forall (x t) (if (RealizableEntity x) (exists (y) (and (IndependentContinuant y) (not (SpatialRegion y)) (bearerOfAt y x t))))) // axiom label in BFO2 CLIF: [060-002] </obo:IAO_0000602> - <obo:IAO_0000601 xml:lang="en">All realizable dependent continuants have independent continuants that are not spatial regions as their bearers. (axiom label in BFO2 Reference: [060-002])</obo:IAO_0000601> - <obo:BFO_0000180>RealizableEntity</obo:BFO_0000180> - <obo:IAO_0000600 xml:lang="en">To say that b is a realizable entity is to say that b is a specifically dependent continuant that inheres in some independent continuant which is not a spatial region and is of a type instances of which are realized in processes of a correlated type. (axiom label in BFO2 Reference: [058-002])</obo:IAO_0000600> - <obo:BFO_0000179>realizable</obo:BFO_0000179> - <obo:IAO_0000112 xml:lang="en">the disposition of this piece of metal to conduct electricity.</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">the disposition of your blood to coagulate</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">the function of your reproductive organs</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">the role of being a doctor</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">the role of this boundary to delineate where Utah and Colorado meet</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:resource="http://purl.obolibrary.org/obo/bfo.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000019 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000019"> - <rdfs:label xml:lang="en">Quality</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000020"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000020 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000020"> - <rdfs:label xml:lang="en">Specifically Dependent Continuant</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000002"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000023 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000023"> - <rdfs:label xml:lang="en">Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000017"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hideFromDisplay"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person's, group's or organization's role in an endeavor</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Only use if no specific subclasses of core:Role describe the role.</obo:IAO_0000112> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Only use this broad role class if no subclasses of role describe the item being classified.</vitro:descriptionAnnot> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000029 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000029"> - <rdfs:label xml:lang="en">Site</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000141"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000031 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000031"> - <rdfs:label xml:lang="en">Generically Dependent Continuant</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000002"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000034 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000034"> - <rdfs:label xml:lang="en">Function</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000016"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000038 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000038"> - <rdfs:label xml:lang="en">One-Dimensional Temporal Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000008"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000040 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000040"> - <rdfs:label xml:lang="en">Material Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000004"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000141 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000141"> - <rdfs:label xml:lang="en">Immaterial Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000004"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/BFO_0000148 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000148"> - <rdfs:label xml:lang="en">Zero-Dimensional Temporal Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000008"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000004 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000004"> - <rdfs:label xml:lang="en">Instrument</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/ERO_0000543"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/ERO_0000007"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/OBI_0000312"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0000094"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A flow cytometer.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Material entity that is designed to have a function and play a role in scientific investigation.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">See OBI listserv discussion for considerations in defining instrument. http://sourceforge.net/tracker/index.php?func=detail&aid=2894801&group_id=177891&atid=886178</rdfs:comment> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Scientific_instrument</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">instrument</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000005 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000005"> - <rdfs:label xml:lang="en">Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A DNA sequencing service performed by a core lab.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An information content entity that describes a service performed by a person or organization with the objective of performing a technique, providing training, providing storage of data or material entities, or providing access to resources for another person or organization</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF. NIF ID: nlx_res_20090105</rdfs:comment> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">service</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000006 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000006"> - <rdfs:label xml:lang="en">Reagent</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.obolibrary.org/obo/BFO_0000040"/> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/OBI_0000312"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0000094"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0000053"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0000086"/> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A plasmid can be used as a reagent.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Placeholder for class to be imported from the Reagent Ontology (ReO).</rdfs:comment> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Processed material that is used in a chemical reaction or other experimental process to detect, measure, examine, or produce other substances.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.yourdictionary.com/reagent</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">reagent</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000007 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000007"> - <rdfs:label xml:lang="en">Technique</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A technique is a planned process used to accomplish a specific activity or task.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Flow cytometry is a technique.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Protocol is added to eagle-i temporarily until a relationship between the informatio entity "protocol" and these planned processes is created. This class refers to the axtual process not the document</rdfs:comment> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Technique</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000012 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000012"> - <rdfs:label xml:lang="en">Service Provider Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role inhering in a person or organization that is realized when the bearer participates in providing a service to meet the need of another person or thing.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A technician in a core laboratory.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An role of an individual within his or her profession or institution; use outreach provider role for community service or other activities outside the profession.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Member of the International Conference on Complex Systems Organizing Committee</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000014 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000014"> - <rdfs:label xml:lang="en">Research Project</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Project"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0000066"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A funded collection of investigations as described in a research proposal.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A project to study the role of a specific protein in cell signaling.</obo:IAO_0000112> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Maybe SameAs "Investigation" but is the subject of funding</rdfs:comment> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000015 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000015"> - <rdfs:label xml:lang="en">Human Study</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000014"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A clinical trial.</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">OCRe</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Research project that uses or collects measurements or assessments about humans.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This should be imported from OCRE- but they currently have no generic human study type. Def is modified.</rdfs:comment> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">human study</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000016 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000016"> - <rdfs:label xml:lang="en">Clinical Trial</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://purl.org/net/OCRe/research.owl#Interventional_study"/> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/ERO_0001518"/> - <owl:someValuesFrom rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/research.owl#Interventional_study"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A clinical trial to evaluate the efficacy of a new drug.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An interventional study that contains a set of procedures in medical research and drug development that are conducted to allow safety (or more specifically, information about adverse drug reactions and adverse effects of other treatments) and efficacy data to be collected for health interventions (e.g., drugs, diagnostics, devices, therapy protocols) that is performed over phases.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Clinical_trial</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000020 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000020"> - <rdfs:label xml:lang="en">Biological Specimen</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0001000"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0100026"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Heart tissue obtained from an organism.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Material entity that is a portion or quantity of a biological material for use in testing, examination, or study. A biological specimen can be an individual animal, a population of organisms, or is a part of or derived from an animal, plant, part of a plant, or microorganism. When a taxon is described, it is typically based on a single specimen and is referred to as the holotype.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Should have relationship to Organism</rdfs:comment> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">biological specimen</obo:IAO_0000111> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">biospecimen</obo:IAO_0000118> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Specimen</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000071 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000071"> - <rdfs:label xml:lang="en">Software</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A general term primarily used for digitally stored data such as computer programs and other kinds of information read and written by computers.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">IAO is a planned specification, in SWO is an Information artifact. In eagle-i, we have a need to collect material instances and is it thus currently classified as a material entity.</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Microsoft Word is commonly used word processing software.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Computer_software</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">software</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000224 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000224"> - <rdfs:label xml:lang="en">Funding Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role inhering in a person or organization that is realized when the bearer participates in providing funding to a person or an organization for academic or business purposes.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The NIH is a funding agency.</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000225 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000225"> - <rdfs:label xml:lang="en">Educator Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role inhering in a person or organization that is realized when the bearer participates in providing education to a student or group of students.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A teacher.</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000391 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000391"> - <rdfs:label xml:lang="en">Access Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the consumer receives the right to use a resource (instrument, database, software, etc) that is owned or managed by a service provider. Ownership of the accessed resource remains with the service provider during and after provision of service.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Allowing access to a microscope in a core lab.</obo:IAO_0000112> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000392 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000392"> - <rdfs:label xml:lang="en">Storage Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A computer server.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the consumer provides some material or data as input which a service provider stores and returns as output.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">coordinate with NIF. NIF ID:nlx_res_20090419</rdfs:comment> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000393 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000393"> - <rdfs:label xml:lang="en">Training Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the provider offers educational materials or events, such as courses, workshops or graduate programs, to the service consumer </obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF. NIF ID: nlx_res_20090444</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Training a researcher to use a microscope.</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000394 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000394"> - <rdfs:label xml:lang="en">Material Processing Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the provider makes physical changes to a specified input material entity with the objective of producing a new material entity form input materials, or modifying the input material entity, and returning this as output to the service consumer</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Biopsy service.</obo:IAO_0000112> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF: NIF ID: nlx_res_20090416</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://neurolex.org/wiki/Category:Production_service_resource</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000395 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000395"> - <rdfs:label xml:lang="en">Material Analysis Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001261"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An analysis service offering that describes a service in which the consumer provides some input material and a service provider performs some analysis of this material to generate data that is returned to the service consumer.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF: NIF ID: nlx_res_20090420</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Flow cytometry analysis of T cells.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://neurolex.org/wiki/Category:Analysis_service_resource</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000396 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000396"> - <rdfs:label xml:lang="en">Material Production Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000394"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A material processing service offering that describes a service in which the provider makes physical changes to a specified input material that produce a new entity as specified output that is returned the service consumer. The specified output of a material production service can be contained within, derived from, or synthesized from specified input materials, but it represents a material entity that is of a distinct type from any of the specified input materials.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Coordinate with NIF. NIF ID: nlx_res_20090418</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Production of monoclonal antibodies from a hybridoma.</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://neurolex.org/wiki/Category:Material_service_resource</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000565 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000565"> - <rdfs:label xml:lang="en">Technology Transfer Office</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization that provides services for commercialization and licensing of technologies at an institution.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Technology Transfer Office</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000595 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000595"> - <rdfs:label xml:lang="en">Research Opportunity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000017"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasFundingVehicle"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Grant"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#contactInformation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A planned process carried out by a person or organization with the objective of performing research.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An offering through an ongoing program or single request of research support: internships, positions, financial awards or other forms of tangible or intangible support</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Training grant to perform post-doctoral research.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">student research opportunity</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000776 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000776"> - <rdfs:label xml:lang="en">US Resident Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role that inheres in a person who maintains residency in the United states. </obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000777 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000777"> - <rdfs:label xml:lang="en">US Citizen Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000776"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A US resident role that inheres in an individual that is a legally recognized as a member of a state, with associated rights and obligations.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wiktionary.org/wiki/citizen</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000778 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000778"> - <rdfs:label xml:lang="en">Non-US Citizen</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000776"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A US resident role that inheres in an individual who is not a legally recognized subject or national of the United States.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">https://www.google.com/search?q=residency+status&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a#hl=en&client=firefox-a&hs=Bcx&rls=org.mozilla:en-US:official&q=citizen&tbs=dfn:1&tbo=u&sa=X&ei=micXT_DwMIjUiAK15tDUDw&ved=0CCgQkQ4&bav=on.2,or.r_gc.r_pw.,cf.osb&fp=7b67128a22f602af&biw=1609&bih=794</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000779 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000779"> - <rdfs:label xml:lang="en">Permanent Resident Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000778"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An role that inheres in an individual who is not a citizen but who legally resides in another nation on a permanent or extended basis.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://connection.ebscohost.com/us/immigration-restrictions/overview-legal-and-illegal-immigration</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000780 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000780"> - <rdfs:label xml:lang="en">Non-Permanent Resident Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000778"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A non-US citizen role that inheres in an individual who is residing in a country, but is neither a citizen nor a permanent resident. </obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.irs.gov/taxtopics/tc851.html</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000783 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000783"> - <rdfs:label xml:lang="en">Student Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A college student.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role inhering in a person that is realized when the bearer participates a course of study, as in a school, college, university, etc.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.thefreedictionary.com/student</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000784 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000784"> - <rdfs:label xml:lang="en">Undergraduate Student Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000783"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A college student.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student role inhering in a person that is realized when the bearer participates in a course of study at a college, university, etc. in pursuit of an associate or bachelor degree.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.thefreedictionary.com/student</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000785 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000785"> - <rdfs:label xml:lang="en">Graduate Student Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000783"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A PhD student at a university.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student role inhering in a person that is realized when the bearer participates a course of study at a university or institution in pursuit of an graduate or professional degree.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.thefreedictionary.com/student</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000786 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000786"> - <rdfs:label xml:lang="en">High School Student Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000783"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A freshman in high school.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student role inhering in a person that is realized when the bearer participates in a course of study at a secondary learning institution.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://www.thefreedictionary.com/student</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000787 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000787"> - <rdfs:label xml:lang="en">Employee Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role inhering in a person that is realized when the bearer participates in an occupation by which a person earns a living or spends their time.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An employee at a university.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://dictionary.reference.com/browse/employment</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000788 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000788"> - <rdfs:label xml:lang="en">Faculty Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000787"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A professor at a university.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An employee role inhering in a person that is realized when the bearer participates in the teaching and/or administrative force of a university, college, or school.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://dictionary.reference.com/browse/faculty</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000789 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000789"> - <rdfs:label xml:lang="en">Staff Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000787"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A research technician in a lab.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An employee role inhering in a person that is realized when the bearer is employed by an employer.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000790 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000790"> - <rdfs:label xml:lang="en">Post-Baccalaureate Trainee</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000783"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student role inhering in a person that is realized when the bearer participates in a post-baccalaureate training program in pursuit of an additional bachelor degree or new or additional training in a particular field.</obo:IAO_0000115> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0000914 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0000914"> - <rdfs:label xml:lang="en">Post-Graduate Student Trainee Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000783"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A post-doctoral fellow.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student role inhering in a person that is realized when the bearer participates in a post-graduate training program in pursuit of new or additional training in a particular field, such as a post-doctoral fellowship.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001245 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001245"> - <rdfs:label xml:lang="en">Licensing</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/OBI_0000011"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A technique that authorizes a use (such as copying software or using a (patented) invention) to a licensee, sparing the licensee from a claim of infringement brought by the licensor.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Licensing of a new technology.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Nicole Vasilevsky</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/License</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001254 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001254"> - <rdfs:label xml:lang="en">Transport Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the provider facilitates the transport of some material entity to a specified destination for the service consumer.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Transport of a patient within a hospital.</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001255 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001255"> - <rdfs:label xml:lang="en">Support Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the provider assists the consumer in activities directly or indirectly associated with the production and analysis or experimental research data.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Technical support.</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001256 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001256"> - <rdfs:label xml:lang="en">Material Storage Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000392"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A storage service offering that describes a service in which the consumer provides some material as input which a service provider stores and returns as output</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Cryopreservation service.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001257 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001257"> - <rdfs:label xml:lang="en">Data Storage Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000392"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A storage service offering that describes a service in which the consumer provides data as input, which a service provider stores and returns as output in its original form.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Storing data on a server.</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001258 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001258"> - <rdfs:label xml:lang="en">Maintenance Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the provider actively maintains a material or data resource (e.g. a model organism colony or database) for the service consumer. This may involved making physical alterations to the material or data with the goal of maintaining its integrity or features.</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001259 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001259"> - <rdfs:label xml:lang="en">Material Maintenance Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001258"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A maintenance service offering that describes a service in which the provider actively maintains a material resource (e.g. a model organism colony) for the service consumer. A material maintenance service may or may not include storage of the material input.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Maintaining an animal coloy.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001260 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001260"> - <rdfs:label xml:lang="en">Data Maintenance Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001258"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A maintenance service offering that describes a service in which the provider actively manages or maintains data or a database for the service consumer. Maintenance of the data is performed to maintain its integrity or enhance its quality or utility for the consumer, but new data is not generated as a result of the maintenance.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Maintaining a database.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001261 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001261"> - <rdfs:label xml:lang="en">Analysis Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000005"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A service offering that describes a service in which the consumer provides some input material or data and a service provider returns data about the input material or data.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Flow cytometry analysis service.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001262 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001262"> - <rdfs:label xml:lang="en">Data Analysis Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001261"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An analysis service offering that describes a service in which the consumer provides some input data and a service provider transforms, models, or interprets the input data and returns this generated data as output</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Sequence data analysis.</obo:IAO_0000112> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">data processing service</obo:IAO_0000118> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">data transformation service</obo:IAO_0000118> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001263 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001263"> - <rdfs:label xml:lang="en">Material Modification Service</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000394"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A material processing service offering that describes a service in which the provider makes physical modifications to a specified input material, such that at least one of the specified outputs of this process is a modified version of a specified input material.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Histology service.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matt Brush</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Matthew Brush</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/ERO_0001716 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/ERO_0001716"> - <rdfs:label xml:lang="en">Database</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A database is an organized collection of data, today typically in digital form.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Just a place horder. It will probably be replaced by NIF term: http://ontology.neuinfo.org/NIF/DigitalEntities/NIF-Resource.owl#nlx_res_20090405</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Carlo Torniai</obo:IAO_0000117> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">http://en.wikipedia.org/wiki/Database</obo:IAO_0000119> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000003 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000003"> - <rdfs:label xml:lang="en">Measurement Unit Label</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000009"/> - <obo:IAO_0000116 xml:lang="en">2009-03-16: provenance: a term measurement unit was -proposed for OBI (OBI_0000176) , edited by Chris Stoeckert and -Cristian Cocos, and subsequently moved to IAO where the objective for -which the original term was defined was satisfied with the definition -of this, different, term.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">2009-03-16: review of this term done during during the OBI workshop winter 2009 and the current definition was considered acceptable for use in OBI. If there is a need to modify this definition please notify OBI.</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">A measurement unit label is as a label that is part of a scalar measurement datum and denotes a unit of measure.</obo:IAO_0000115> - <obo:IAO_0000112 xml:lang="en">Examples of measurement unit labels are liters, inches, weight per volume.</obo:IAO_0000112> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Melanie Courtot</obo:IAO_0000117> - <obo:IAO_0000111 xml:lang="en">measurement unit label</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000125"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000005 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000005"> - <rdfs:label xml:lang="en">Objective Specification</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000033"/> - <obo:IAO_0000116 xml:lang="en">Answers the question, why did you do this experiment?</obo:IAO_0000116> - <obo:IAO_0000119 xml:lang="en">OBI Plan and Planned Process/Roles Branch</obo:IAO_0000119> - <obo:IAO_0000119 xml:lang="en">OBI_0000217</obo:IAO_0000119> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Barry Smith</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Jennifer Fostel</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">a directive information entity that describes an intended process endpoint. When part of a plan specification the concretization is realized in a planned process in which the bearer tries to effect the world so that the process endpoint is achieved.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">objective specification</obo:IAO_0000111> - <obo:IAO_0000112 xml:lang="en">purpose of a study; support of hypothesis, discovery of new information</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000125"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000007 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000007"> - <rdfs:label xml:lang="en">Action Specification</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000033"/> - <obo:IAO_0000117 xml:lang="en">Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000119 xml:lang="en">OBI Plan and Planned Process branch</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">Pour the contents of flask 1 into flask 2</obo:IAO_0000112> - <obo:IAO_0000115 xml:lang="en">a directive information entity that describes an action the bearer will take</obo:IAO_0000115> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000009 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000009"> - <rdfs:label xml:lang="en">Datum Label</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000115 xml:lang="en">A label is a symbol that is part of some other datum and is used to either partially define the denotation of that datum or to provide a means for identifying the datum as a member of the set of data with the same label</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">GROUP: IAO</obo:IAO_0000117> - <obo:IAO_0000111 xml:lang="en">datum label</obo:IAO_0000111> - <obo:IAO_0000116 xml:lang="en">http://www.golovchenko.org/cgi-bin/wnsearch?q=label#4n</obo:IAO_0000116> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000013 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000013"> - <rdfs:label xml:lang="en">Journal Article</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/AcademicArticle"/> - <obo:IAO_0000112 xml:lang="en">Examples are articles published in the journals, Nature and Science. The content can often be cited by reference to a paper based encoding, e.g. Authors, Title of article, Journal name, date or year of publication, volume and page number.</obo:IAO_0000112> - <obo:IAO_0000119 xml:lang="en">OBI_0000159</obo:IAO_0000119> - <obo:IAO_0000115 xml:lang="en">a report that is published in a journal</obo:IAO_0000115> - <obo:IAO_0000119 xml:lang="en">group:OBI</obo:IAO_0000119> - <obo:IAO_0000111 xml:lang="en">journal article</obo:IAO_0000111> - <obo:IAO_0000117 xml:lang="en">person:Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">person:Chris Stoeckert</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000027 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000027"> - <rdfs:label xml:lang="en">Data Item</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000116 xml:lang="en">2/2/2009 Alan and Bjoern discussing FACS run output data. This is a data item because it is about the cell population. Each element records an event and is typically further composed a set of measurment data items that record the fluorescent intensity stimulated by one of the lasers.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">2009-03-16: data item deliberatly ambiguous: we merged data set and datum to be one entity, not knowing how to define singular versus plural. So data item is more general than datum.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">2009-03-16: removed datum as alternative term as datum specifically refers to singular form, and is thus not an exact synonym.</obo:IAO_0000116> - <obo:IAO_0000112 xml:lang="en">Data items include counts of things, analyte concentrations, and statistical summaries.</obo:IAO_0000112> - <obo:IAO_0000116 xml:lang="en">JAR: datum -- well, this will be very tricky to define, but maybe some -information-like stuff that might be put into a computer and that is -meant, by someone, to denote and/or to be interpreted by some -process... I would include lists, tables, sentences... I think I might -defer to Barry, or to Brian Cantwell Smith - -JAR: A data item is an approximately justified approximately true approximate belief</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Chris Stoeckert</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Jonathan Rees</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">a data item is an information content entity that is intended to be a truthful statement about something (modulo, e.g., measurement precision or other systematic errors) and is constructed/acquired by a method which reliably tends to produce (approximately) truthful statements.</obo:IAO_0000115> - <obo:IAO_0000118 xml:lang="en">data</obo:IAO_0000118> - <obo:IAO_0000111 xml:lang="en">data item</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000125"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000030 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000030"> - <rdfs:label xml:lang="en">Information Content Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000031"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#freetextKeyword"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relatedBy"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/IAO_0000136"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BFO_0000001"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0002353"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#geographicFocus"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#freetextKeyword"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The most general classification of an information resource</obo:IAO_0000115> - <obo:IAO_0000112 xml:lang="en">Examples of information content entites include journal articles, data, graphical layouts, and graphs.</obo:IAO_0000112> - <obo:IAO_0000119 xml:lang="en">OBI_0000142</obo:IAO_0000119> - <obo:IAO_0000117 xml:lang="en">PERSON: Chris Stoeckert</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">an information content entity is an entity that is generically dependent on some artifact and stands in relation of aboutness to some entity</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">information content entity</obo:IAO_0000111> - <obo:IAO_0000116 xml:lang="en">information_content_entity 'is_encoded_in' some digital_entity in obi before split (040907). information_content_entity 'is_encoded_in' some physical_document in obi before split (040907). - -Previous. An information content entity is a non-realizable information entity that 'is encoded in' some digital or physical entity.</obo:IAO_0000116> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000125"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000032 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000032"> - <rdfs:label xml:lang="en">Scalar Measurement Datum</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000109"/> - <obo:IAO_0000112 xml:lang="en">10 feet. 3 ml.</obo:IAO_0000112> - <obo:IAO_0000116 xml:lang="en">2009-03-16: we decided to keep datum singular in scalar measurement datum, as in -this case we explicitly refer to the singular form</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Melanie Courtot</obo:IAO_0000117> - <obo:IAO_0000116 xml:lang="en">Would write this as: has_part some 'measurement unit label' and has_part some numeral and has_part exactly 2, except for the fact that this won't let us take advantage of OWL reasoning over the numbers. Instead use has measurment value property to represent the same. Use has measurement unit label (subproperty of has_part) so we can easily say that there is only one of them.</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">a scalar measurement datum is a measurement datum that is composed of two parts, numerals and a unit label.</obo:IAO_0000115> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000033 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000033"> - <rdfs:label xml:lang="en">Directive Information Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000116 xml:lang="en">8/6/2009 Alan Ruttenberg: Changed label from "information entity about a realizable" after discussions at ICBO</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">An information content entity whose concretizations indicate to their bearer how to realize them in a process.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">PERSON: Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000117 xml:lang="en">PERSON: Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000116 xml:lang="en">Werner pushed back on calling it realizable information entity as it isn't realizable. However this name isn't right either. An example would be a recipe. The realizable entity would be a plan, but the information entity isn't about the plan, it, once concretized, *is* the plan. -Alan</obo:IAO_0000116> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000123"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000102 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000102"> - <rdfs:label xml:lang="en">Data about an Ontology Part</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000027"/> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Person:Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">data about an ontology part is a data item about a part of an ontology, for example a term</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000104 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000104"> - <rdfs:label xml:lang="en">Plan Specification</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000033"/> - <obo:IAO_0000116 xml:lang="en">2009-03-16: provenance: a term a plan was proposed for OBI (OBI_0000344) , edited by the PlanAndPlannedProcess branch. Original definition was " a plan is a specification of a process that is realized by an actor to achieve the objective specified as part of the plan". It has been subsequently moved to IAO where the objective for which the original term was defined was satisfied with the definitionof this, different, term.</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000116 xml:lang="en">Alternative previous definition: a plan is a set of instructions that specify how an objective should be achieved</obo:IAO_0000116> - <obo:IAO_0000119 xml:lang="en">OBI Plan and Planned Process branch</obo:IAO_0000119> - <obo:IAO_0000119 xml:lang="en">OBI_0000344</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">PMID: 18323827.Nat Med. 2008 Mar;14(3):226.New plan proposed to help resolve conflicting medical advice.</obo:IAO_0000112> - <obo:IAO_0000115 xml:lang="en">a directive information entity that when concretized it is realized in a process in which the bearer tries to achieve the objectives, in part by taking the actions specified. Plan specifications includes parts such as objective specification, action specifications and conditional specifications.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">plan specification</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000109 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000109"> - <rdfs:label xml:lang="en">Measurement Datum</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000027"/> - <obo:IAO_0000116 xml:lang="en">2/2/2009 is_specified_output of some assay?</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">A measurement datum is an information content entity that is a recording of the output of a measurement such as produced by a device.</obo:IAO_0000115> - <obo:IAO_0000112 xml:lang="en">Examples of measurement data are the recoding of the weight of a mouse as {40,mass,"grams"}, the recording of an observation of the behavior of the mouse {,process,"agitated"}, the recording of the expression level of a gene as measured through the process of microarray experiment {3.4,luminosity,}.</obo:IAO_0000112> - <obo:IAO_0000119 xml:lang="en">OBI_0000305</obo:IAO_0000119> - <obo:IAO_0000119 xml:lang="en">group:OBI</obo:IAO_0000119> - <obo:IAO_0000111 xml:lang="en">measurement datum</obo:IAO_0000111> - <obo:IAO_0000117 xml:lang="en">person:Chris Stoeckert</obo:IAO_0000117> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000144 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000144"> - <rdfs:label xml:lang="en">Conclusion Textual Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000116 xml:lang="en">2009/09/28 Alan Ruttenberg. Fucoidan-use-case</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">2009/10/23 Alan Ruttenberg: We need to work on the definition still</obo:IAO_0000116> - <obo:IAO_0000115 xml:lang="en">A textual entity that expresses the results of reasoning about a problem, for instance as typically found towards the end of scientific papers.</obo:IAO_0000115> - <obo:IAO_0000117 xml:lang="en">Person:Alan Ruttenberg</obo:IAO_0000117> - <obo:IAO_0000111 xml:lang="en">conclusion textual entity</obo:IAO_0000111> - <obo:IAO_0000112 xml:lang="en">that fucoidan has a small statistically significant effect on AT3 level but no useful clinical effect as in-vivo anticoagulant, a paraphrase of part of the last paragraph of the discussion section of the paper 'Pilot clinical study to evaluate the anticoagulant activity of fucoidan', by Lowenthal et. al.PMID:19696660</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/IAO_0000300 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/IAO_0000300"> - <rdfs:label xml:lang="en">Textual Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <obo:IAO_0000115 xml:lang="en">A textual entity is a part of a manifestation (FRBR sense), a generically dependent continuant whose concretizations are patterns of glyphs intended to be interpreted as words, formulas, etc.</obo:IAO_0000115> - <obo:IAO_0000116 xml:lang="en">AR, (IAO call 2009-09-01): a document as a whole is not typically a textual entity, because it has pictures in it - rather there are parts of it that are textual entities. Examples: The title, paragraph 2 sentence 7, etc.</obo:IAO_0000116> - <obo:IAO_0000116 xml:lang="en">MC, 2009-09-14 (following IAO call 2009-09-01): textual entities live at the FRBR (http://en.wikipedia.org/wiki/Functional_Requirements_for_Bibliographic_Records) manifestation level. Everything is significant: line break, pdf and html versions of same document are different textual entities.</obo:IAO_0000116> - <obo:IAO_0000117 xml:lang="en">PERSON: Lawrence Hunter</obo:IAO_0000117> - <obo:IAO_0000112 xml:lang="en">Words, sentences, paragraphs, and the written (non-figure) parts of publications are all textual entities</obo:IAO_0000112> - <obo:IAO_0000118 xml:lang="en">text</obo:IAO_0000118> - <obo:IAO_0000111 xml:lang="en">textual entity</obo:IAO_0000111> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000011 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000011"> - <rdfs:label xml:lang="en">Planned Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <obo:IAO_0000116 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">'Plan' includes a future direction sense. That can be problematic if plans are changed during their execution. There are however implicit contingencies for protocols that an agent has in his mind that can be considered part of the plan, even if the agent didn't have them in mind before. Therefore, a planned process can diverge from what the agent would have said the plan was before executing it, by adjusting to problems encountered during execution (e.g. choosing another reagent with equivalent properties, if the originally planned one has run out.)</obo:IAO_0000116> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Bjoern Peters</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Injecting mice with a vaccine in order to test its efficacy</obo:IAO_0000112> - <obo:IAO_0000119 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">branch derived</obo:IAO_0000119> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">planned process</obo:IAO_0000111> - <obo:IAO_0000115 xml:lang="en">A processual entity that realizes a plan which is the concretization of a plan specification.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">planned process</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000122"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000017 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000017"> - <rdfs:label xml:lang="en">Regulatory Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000117 xml:lang="en">GROUP: Role branch</obo:IAO_0000117> - <obo:IAO_0000119 xml:lang="en">OBI, CDISC</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">Regulatory agency, Ethics committee, Approval letter; example: Browse these EPA Regulatory Role subtopics http://www.epa.gov/ebtpages/enviregulatoryrole.html Feb 29, 2008</obo:IAO_0000112> - <obo:IAO_0000115 xml:lang="en">a role which inheres in material entities and is realized in the processes of making, enforcing or being defined by legislation or orders issued by a governmental body.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">regulatory role</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000066 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000066"/> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000086 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000086"/> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000094 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000094"/> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000272 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000272"> - <rdfs:label xml:lang="en">Protocol</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000119 xml:lang="en">OBI branch derived + wikipedia (http://en.wikipedia.org/wiki/Protocol_%28natural_sciences%29)</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">PMID: 18388943.Nat Protoc. 2008;3(4):612-8.Protocol for the induction of arthritis in C57BL/6 mice.</obo:IAO_0000112> - <obo:IAO_0000117 xml:lang="en">PlanAndPlannedProcess Branch</obo:IAO_0000117> - <obo:IAO_0000111 xml:lang="en">Protocol</obo:IAO_0000111> - <obo:IAO_0000115 xml:lang="en">a protocol is a plan specification which has sufficient level of detail and quantitative information to communicate it between domain experts, so that different domain experts will reliably be able to independently reproduce the process.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">protocol</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000122"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000571 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000571"/> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0000835 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0000835"> - <rdfs:label xml:lang="en">Manufacturer</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Organization"/> - <rdf:Description rdf:about="http://xmlns.com/foaf/0.1/Person"/> - </owl:unionOf> - </owl:Class> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0000053"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/OBI_0000571"/> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person or organization that has a manufacturer role</obo:IAO_0000115> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000124"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0001554 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0001554"> - <rdfs:label xml:lang="en">Rate Measurement Datum</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000032"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0100026 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0100026"> - <rdfs:label xml:lang="en">Organism</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">GROUP: OBI Biomaterial Branch</obo:IAO_0000117> - <obo:IAO_0000115 xml:lang="en">A material entity that is an individual living system, such as animal, plant, bacteria or virus, that is capable of replicating or reproducing, growth and maintenance in the right environment. An organism may be unicellular or made up, like humans, of many billions of cells divided into specialized tissues and organs.</obo:IAO_0000115> - <obo:IAO_0000119 xml:lang="en">WEB: http://en.wikipedia.org/wiki/Organism</obo:IAO_0000119> - <obo:IAO_0000112 xml:lang="en">animal</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">fungus</obo:IAO_0000112> - <obo:IAO_0000111 xml:lang="en">organism</obo:IAO_0000111> - <obo:IAO_0000112 xml:lang="en">plant</obo:IAO_0000112> - <obo:IAO_0000112 xml:lang="en">virus</obo:IAO_0000112> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000121"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/OBI_0500000 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/OBI_0500000"> - <rdfs:label xml:lang="en">Study Design</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000104"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A study design is a plan specification comprised of protocols (which may specify how and what kinds of data will be gathered) that are executed as part of an investigation and is realized during a study design execution.</obo:IAO_0000115> - <obo:IAO_0000111 xml:lang="en">study design</obo:IAO_0000111> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/obi.owl"/> - </owl:Class> - - - - <!-- http://purl.obolibrary.org/obo/UO_0000280 --> - - <owl:Class rdf:about="http://purl.obolibrary.org/obo/UO_0000280"> - <rdfs:label xml:lang="en">Rate Unit</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000003"/> - </owl:Class> - - - - <!-- http://purl.org/NET/c4dm/event.owl#Event --> - - <owl:Class rdf:about="http://purl.org/NET/c4dm/event.owl#Event"> - <rdfs:label xml:lang="en">Event</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/presents"/> - <owl:allValuesFrom rdf:resource="http://purl.org/ontology/bibo/Document"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0001025"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#contactInformation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#geographicFocus"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Only use if no specific subclasses of event:Event are appropriate.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something that happens at a given place and time.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This class will also display instances of subclasses under Event, e.g. Philosophy Department Discussion Club; 2009 Racker Lecture; screening of a documentary. In addition to a location in space and time, an event may have any or all the following qualities: actively participating agents, passive factors, work products. Also, it may be in a virtual space or part of a series such as a lecture series. - -The previous short definition was: "An arbitrary classification of a space/time region, by a cognitive agent."</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/research.owl#Interventional_study --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/research.owl#Interventional_study"/> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#OCRE100038 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#OCRE100038"> - <rdfs:label xml:lang="en">Phase</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase describes the level of a trial required of drugs before (and after) they are routinely used in clinical practice: -- Phase I trials assess toxic effects on humans (not many people participate in them, and usually without controls); -- Phase ll trials assess therapeutic benefit (usually involving a few hundred people, usually with controls, but not always); -- Phase III trials compare the new treatment against standard (or placebo) treatment (usually a full randomised controlled trial). At this point, a drug can be approved for community use. -- Phase IV monitors a new treatment in the community, often to evaluate longterm safety and effectiveness. [Glossary of Terms in The Cochrane Collaboration] - -A trial can be of a combination phase (e.g., I/II). -The concept of phase is not applicable to trials studying certain interventions (e.g., device, procedure, behavioral)</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</obo:IAO_0000117> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Phase_0 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Phase_0"> - <rdfs:label xml:lang="en">Phase 0</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Phase 0 trial is an exploratory trial involving very limited human exposure, with no therapeutic or diagnostic intent (e.g., screening study, microdose study). [http://prsinfo.clinicaltrials.gov/definitions.html]</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Phase_1 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Phase_1"> - <rdfs:label xml:lang="en">Phase 1</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Phase I trial assesses toxic effects on humans (not many people participate, and usually without controls) [Glossary of Terms in The Cochrane Collaboration]</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Phase_2 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Phase_2"> - <rdfs:label xml:lang="en">Phase 2</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Phase ll trial assesses therapeutic benefit (usually involving a few hundred people, usually with controls, but not always) [Glossary of Terms in The Cochrane Collaboration]</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Phase_3 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Phase_3"> - <rdfs:label xml:lang="en">Phase 3</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Phase III trial compares the new treatment against standard (or placebo) treatment (usually a full -randomised controlled trial). At this point, a drug can be approved for community use. [Glossary of Terms in The Cochrane Collaboration]</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Phase_4 --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Phase_4"> - <rdfs:label xml:lang="en">Phase 4</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/study_design.owl#OCRE100038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Phase IV study monitors a new treatment in the community, often to evaluate longterm safety and effectiveness. [Glossary of Terms in The Cochrane Collaboration]</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - </owl:Class> - - - - <!-- http://purl.org/net/OCRe/study_design.owl#Single_group_study --> - - <owl:Class rdf:about="http://purl.org/net/OCRe/study_design.owl#Single_group_study"> - <rdfs:label xml:lang="en">Single Group Study</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/net/OCRe/research.owl#Interventional_study"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A single group study is an interventional study that has only a single allocation group and no contemporaneuos comparison group. -A study in which an individual acts has his/her own comparison does not fall into this category, since an individual is not a group.</obo:IAO_0000115> - <statistics:curator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona</statistics:curator> - <study_protocol:develop_comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Simona: to be reviewed</study_protocol:develop_comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/AcademicArticle --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/AcademicArticle"> - <rdfs:label xml:lang="en">Academic Article</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasPublicationVenue"/> - <owl:allValuesFrom rdf:resource="http://purl.org/ontology/bibo/Journal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/eanucc13"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A specific academic journal article</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Written by scholars for other scholars, typically published in an academic journal with an abstract and bibliography</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A scholarly academic article, typically published in a journal.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Article --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Article"> - <rdfs:label xml:lang="en">Article</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/pageEnd"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/doi"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/pageStart"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A specific journal article</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A written composition in prose, usually nonfiction, on a specific topic, forming an independent part of a periodical or book</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition modified from the bibo ontology.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A written composition in prose, usually nonfiction, on a specific topic, forming an independent part of a book or other publication, as a newspaper or magazine.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/AudioDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/AudioDocument"> - <rdfs:label xml:lang="en">Audio Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/distributor"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Recorded audio in any format</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">phonograph record; tape; CD; DVD; DAT</obo:IAO_0000112> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">An audio document; aka record.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/AudioVisualDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/AudioVisualDocument"> - <rdfs:label xml:lang="en">Audio-Visual Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/distributor"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Audiovisual recording in any format</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">film; video; Blu-ray</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An audio-visual document; film, video, and so forth.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Bill --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Bill"> - <rdfs:label xml:lang="en">Bill</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Legislation"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Draft legislation presented for discussion to a legal body</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">Draft legislation presented for discussion to a legal body.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Book --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Book"> - <rdfs:label xml:lang="en">Book</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/edition"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/lccn"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A written or printed work of fiction or nonfiction, usually on sheets of paper fastened or bound together within covers</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition copied from bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A written or printed work of fiction or nonfiction, usually on sheets of paper fastened or bound together within covers.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/BookSection --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/BookSection"> - <rdfs:label xml:lang="en">Book Section</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/DocumentPart"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/pageStart"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/pageEnd"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/edition"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A section of a book</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology </obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A section of a book.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Brief --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Brief"> - <rdfs:label xml:lang="en">Brief</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/LegalCaseDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document stating the facts and points of law of a client's case</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A written argument submitted to a court.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Chapter --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Chapter"> - <rdfs:label xml:lang="en">Chapter</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/BookSection"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A main division of a book</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A chapter of a book.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Code --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Code"> - <rdfs:label xml:lang="en">Code</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A work consisting of texts of rules and regulations related to statutes issued by executive or administrative agencies</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Code of Federal Regulations</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from OCLC Input Standards, EntW</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A collection of statutes.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/CollectedDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/CollectedDocument"> - <rdfs:label xml:lang="en">Collected Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition is the Medical Subject Heading (MeSH) definition</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Work consisting of collections of previously published works</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A document that simultaneously contains other documents.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Collection --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Collection"> - <rdfs:label xml:lang="en">Collection</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/oclcnum"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Collection of information resources that have a unified identity</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Collection of information resources that have a unified identity. Archives, museums and libraries often acquire collections on specific subjects and from distinguished authors or researchers. Also includes collections of resources bundled into a license.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Hill Ornithology Collection; Wiley Interscience Online Books Biochemisty Collection</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A collection of Documents or Collections</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Conference --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Conference"> - <rdfs:label xml:lang="en">Conference</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">2010 International Congress on Autoimmunity; American Libraries Association 2009</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A meeting for consultation or discussion.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">core:Seminar and bibo:Conference are very similar.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A meeting for consultation or discussion.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/CourtReporter --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/CourtReporter"> - <rdfs:label xml:lang="en">Court Reporter</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Collection of legal cases</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Supreme Court Reporter</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A collection of legal cases.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Document --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Document"> - <rdfs:label xml:lang="en">Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/spar/cito/citesAsDataSource"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Dataset"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/spar/c4o/hasGlobalCitationFrequency"/> - <owl:allValuesFrom rdf:resource="http://purl.org/spar/c4o/GlobalCitationCount"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#features"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/numPages"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/oclcnum"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/abstract"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A bounded physical representation of a body of information designed with the capacity (and usually intent) to communicate</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000115 xml:lang="en">A collection of information content entities intended to be understood together as a whole</obo:IAO_0000115> - <rdfs:comment xml:lang="en">A document (noun) is a bounded physical representation of body of information designed with the capacity (and usually intent) to communicate. A document may manifest symbolic, diagrammatic or sensory-representational information.</rdfs:comment> - <obo:IAO_0000112 xml:lang="en">A journal article, patent application, laboratory notebook, or a book</obo:IAO_0000112> - <obo:IAO_0000117 xml:lang="en">PERSON: Lawrence Hunter</obo:IAO_0000117> - <obo:IAO_0000111 xml:lang="en">document</obo:IAO_0000111> - <obo:IAO_0000114 rdf:resource="http://purl.obolibrary.org/obo/IAO_0000120"/> - <obo:IAO_0000412 rdf:resource="http://purl.obolibrary.org/obo/iao.owl"/> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/DocumentPart --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/DocumentPart"> - <rdfs:label xml:lang="en">Document Part</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A distinct part of a larger document or collected document</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology </obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">a distinct part of a larger document or collected document.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/DocumentStatus --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/DocumentStatus"> - <rdfs:label xml:lang="en">Document Status</rdfs:label> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The status of a document with respect to its publication.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The status of a document with respect to its publication. The statuses are represented as individuals of this class. Use the "show all individuals of this class" button on the class control panel to see the currently defined statuses.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">submitted; accepted; in-press; published; invited; refereed.</obo:IAO_0000112> - <rdfs:comment xml:lang="en">The status of the publication of a document.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/EditedBook --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/EditedBook"> - <rdfs:label xml:lang="en">Edited Book</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/CollectedDocument"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/edition"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An edited collection of stand-alone articles published as a book</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Best American Science Writing 2009</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An edited book.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Excerpt --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Excerpt"> - <rdfs:label xml:lang="en">Excerpt</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/DocumentPart"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A passage selected from a larger work</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A passage selected from a larger work.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Film --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Film"> - <rdfs:label xml:lang="en">Film</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/AudioVisualDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Audiovisual recording in film format</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">aka movie.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Hearing --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Hearing"> - <rdfs:label xml:lang="en">Hearing</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An instance or a session in which testimony and arguments are presented, esp. before an official, as a judge in a lawsuit.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definiton from Bibo here: http://bibotools.googlecode.com/svn/bibo-ontology/trunk/doc/index.html</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An instance or a session in which testimony and arguments are presented, esp. before an official, as a judge in a lawsuit.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Image --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Image"> - <rdfs:label xml:lang="en">Image</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> -</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A visual representation such as a photograph or graph</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">photograph; diagram</obo:IAO_0000112> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A document that presents visual or diagrammatic information.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Interview --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Interview"> - <rdfs:label xml:lang="en">Interview</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A conversation between two or more people where questions are asked by the interviewer to obtain information from the interviewee.</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">radio or newspaper interview</obo:IAO_0000112> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A formalized discussion between two or more people.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Issue --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Issue"> - <rdfs:label xml:lang="en">Issue</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/CollectedDocument"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">something that is printed or published and distributed, esp. a given number of a periodical</obo:IAO_0000115> - <rdfs:comment xml:lang="en">something that is printed or published and distributed, esp. a given number of a periodical</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Journal --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Journal"> - <rdfs:label xml:lang="en">Journal</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Articles usually contain abstracts and bibliographies. Includes peer-reviewed, non-peer-reviewed, and open access journals. Journals are usually indexed in the major academic databases such as PubMed and Web of Science.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains original scholarly research or review articles by experts in the field</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Journal of Information Science; IEEE Intelligent System; Scientometrics</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A periodical of scholarly journal Articles.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/LegalCaseDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/LegalCaseDocument"> - <rdfs:label xml:lang="en">Legal Case Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/LegalDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Official court papers for a case</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A document accompanying a legal case.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/LegalDecision --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/LegalDecision"> - <rdfs:label xml:lang="en">Decision</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/LegalCaseDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The written determination of a case, motion or claim by a court or tribunal</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A document containing an authoritative determination (as a decree or judgment) made after consideration of facts or law.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/LegalDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/LegalDocument"> - <rdfs:label xml:lang="en">Legal Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">a document that states some contractual relationship or grants some right</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A legal document; for example, a court decision, a brief, and so forth.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Legislation --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Legislation"> - <rdfs:label xml:lang="en">Legislation</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/LegalDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Enactments of legislative bodies, published in either statute or code form</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">From OCLC Input Standards, EntW</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A legal document proposing or enacting a law or a group of laws.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Letter --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Letter"> - <rdfs:label xml:lang="en">Letter</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/PersonalCommunicationDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A written or printed communication addressed to a person or organization and usually transmitted by mail</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A written or printed communication addressed to a person or organization and usually transmitted by mail</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Magazine --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Magazine"> - <rdfs:label xml:lang="en">Magazine</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Abstracts and bibliographies are usually not included in magazines. </obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains articles of current events or general interest, geared to the reading public as being informative or recreational</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">New Yorker</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A periodical of magazine Articles. A magazine is a publication that is issued periodically, usually bound in a paper cover, and typically contains essays, stories, poems, etc., by many writers, and often photographs and drawings, frequently specializing in a particular subject or area, as hobbies, news, or sports.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Manual --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Manual"> - <rdfs:label xml:lang="en">Manual</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A book of instructions or guide to a specific topic</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">SDB User Manual</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A small reference book, especially one giving instructions.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Manuscript --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Manuscript"> - <rdfs:label xml:lang="en">manuscript</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition is the Medical Subject Heading (MeSH) definition</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Works prepared by hand including handwritten or typescript drafts of pre-publication papers or works not otherwise reproduced in multiple copies</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An unpublished Document, which may also be submitted to a publisher for publication.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Map --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Map"> - <rdfs:label xml:lang="en">Map</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Image"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A graphical depiction of geographic features, scientific discipline, scientific data analytical results</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The Short Definition is how the bibo ontology defines Map. It has been extended to include more broader concept of map which includes science maps, social network maps.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A graphical depiction of geographic features.</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Newspaper --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Newspaper"> - <rdfs:label xml:lang="en">Newspaper</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains news articles, opinions, features, advertising, and is usually issued daily or weekly</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">USA Today</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A periodical of documents, usually issued daily or weekly, containing current news, editorials, feature articles, and usually advertising.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Note --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Note"> - <rdfs:label xml:lang="en">Note</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Notes or annotations about a resource</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">Notes or annotations about a resource.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Patent --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Patent"> - <rdfs:label xml:lang="en">Patent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateIssued"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">(from BIBO) A document describing the exclusive right granted by a government to an inventor to manufacture, use, or sell an invention for a certain number of years</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A patent is an exclusive right granted for an invention, which is a product or a process that provides, in general, a new way of doing something, or offers a new technical solution to a problem. In order to be patentable, the invention must fulfill certain conditions. (http://www.wipo.int/patentscope/en/)</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A document describing the exclusive right granted by a government to an inventor to manufacture, use, or sell an invention for a certain number of years.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Performance --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Performance"> - <rdfs:label xml:lang="en">Performance</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something carried out, acted or rendered.</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A public performance.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Periodical --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Periodical"> - <rdfs:label xml:lang="en">Periodical</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Collection"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/issn"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/eissn"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A group of related documents issued at regular intervals.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/PersonalCommunicationDocument --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/PersonalCommunicationDocument"> - <rdfs:label xml:lang="en">Personal Communication Document</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A personal communication manifested in some document.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A personal communication manifested in some document.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Proceedings --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Proceedings"> - <rdfs:label xml:lang="en">Proceedings</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Book"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A compilation of documents published from an event, such as a conference</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition copied from bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A compilation of documents published from an event, such as a conference.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Quote --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Quote"> - <rdfs:label xml:lang="en">Quote</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Excerpt"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An excerpted collection of words</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">An excerpted collection of words.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/ReferenceSource --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/ReferenceSource"> - <rdfs:label xml:lang="en">Reference Source</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document that presents authoritative reference information, such as a dictionary or encylopedia</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A document that presents authoritative reference information, such as a dictionary or encylopedia .</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Report --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Report"> - <rdfs:label xml:lang="en">Report</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/distributor"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document describing an account or statement describing in detail an event, situation, or the like, usually as the result of observation, inquiry, etc.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Medical Subject Heading (MeSH) definition of Technical Report: Work consisting of a formal report giving details of the investigation and results of a medical or other scientific problem. When issued by a government agency or comparable official body, its contents may be classified, unclassified, or declassified with regard to security clearance. This publication type may also cover a scientific paper or article that records the current state or current position of scientific research and development. If so labeled by the editor or publisher, this publication type may be properly used for journal articles.</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A document describing an account or statement describing in detail an event, situation, or the like, usually as the result of observation, inquiry, etc..</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Series --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Series"> - <rdfs:label xml:lang="en">Series</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Collection"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/issn"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/eissn"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A thematic collection of documents, usually books, issued at regular or irregular intervals</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Methods in Molecular Biology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A loose, thematic, collection of Documents, often Books.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Slide --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Slide"> - <rdfs:label xml:lang="en">Slide</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/DocumentPart"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A slide in a slideshow</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A slide in a slideshow</rdfs:comment> - <ns:term_status>unstable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Slideshow --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Slideshow"> - <rdfs:label xml:lang="en">Slideshow</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A presentation of a series of slides, usually presented in front of an audience with written text and images</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from the bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A presentation of a series of slides, usually presented in front of an audience with written text and images.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Standard --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Standard"> - <rdfs:label xml:lang="en">Standard</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A specification giving a precise statement of a process or a service requirement, often sanctioned by a nation or industry</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from OCLC Input Standards, EntW</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">A document describing a standard</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Statute --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Statute"> - <rdfs:label xml:lang="en">Statute</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Legislation"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A bill enacted into law</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from bibo ontology</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A bill enacted into law.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Thesis --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Thesis"> - <rdfs:label xml:lang="en">Thesis</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition from OCLC Input Standards, EntW</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Works created to satisfy the requirements for an academic certification or degree; also called dissertation</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A document created to summarize research findings associated with the completion of an academic degree.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/ThesisDegree --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/ThesisDegree"> - <rdfs:label xml:lang="en">Thesis Degree</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#AcademicDegree"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Different from general academic degree, thesis degree is achieved through one's completed thesis. Thesis is a document submitted in support of candidature for a degree or professional qualification presenting the author's research and findings(http://en.wikipedia.org/wiki/Thesis_or_dissertation).</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Doctor of Philosophy (Ph.D.)</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The academic degree of a Thesis.</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>stable</ns:term_status> - <rdfs:comment xml:lang="en">The academic degree of a Thesis</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Webpage --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Webpage"> - <rdfs:label xml:lang="en">Webpage</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">One section of a website that appears at a unique address within the parent site's address or URL on the World Wide Web </obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A web page is an online document available (at least initially) on the world wide web. A web page is written first and foremost to appear on the web, as distinct from other online resources such as books, manuscripts or audio documents which use the web primarily as a distribution mechanism alongside other more traditional methods such as print.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Website --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Website"> - <rdfs:label xml:lang="en">Website</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Collection"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of webpages available within a specific parent address or URL on the World Wide Web</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Facebook; VIVOweb.org; Flickr</obo:IAO_0000112> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <ns:term_status>unstable</ns:term_status> - <rdfs:comment xml:lang="en">A group of Webpages accessible on the Web.</rdfs:comment> - </owl:Class> - - - - <!-- http://purl.org/ontology/bibo/Workshop --> - - <owl:Class rdf:about="http://purl.org/ontology/bibo/Workshop"> - <rdfs:label xml:lang="en">Workshop</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Bibo Definition: A seminar, discussion group, or the like, that emphasizes exchange of ideas and the demonstration and application of techniques, skills, etc.</obo:IAO_0000115> - <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI">http://purl.org/ontology/bibo/</rdfs:isDefinedBy> - <rdfs:comment xml:lang="en">A seminar, discussion group, or the like, that emphasizes zxchange of ideas and the demonstration and application of techniques, skills, etc.</rdfs:comment> - <ns:term_status>stable</ns:term_status> - </owl:Class> - - - - <!-- http://purl.org/spar/c4o/BibliographicInformationSource --> - - <owl:Class rdf:about="http://purl.org/spar/c4o/BibliographicInformationSource"> - <rdfs:label xml:lang="en">Bibliographic Information Source</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0001716"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A source of information about bibliographic citations, such as Google Scholar, Web of Science or Scopus.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A source of information about bibliographic citations, such as Google Scholar, Web of Science or Scopus.</vitro:descriptionAnnot> - </owl:Class> - - - - <!-- http://purl.org/spar/c4o/GlobalCitationCount --> - - <owl:Class rdf:about="http://purl.org/spar/c4o/GlobalCitationCount"> - <rdfs:label xml:lang="en">Global Citation Count</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000032"/> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The number of times a work has been cited globally, as determined from a particular bibliographic information source on a particular date.</vitro:descriptionAnnot> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The number of times a work has been cited globally, as determined from a particular bibliographic information source on a particular date.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://purl.org/spar/fabio/ClinicalGuideline --> - - <owl:Class rdf:about="http://purl.org/spar/fabio/ClinicalGuideline"> - <rdfs:label xml:lang="en">Clinical Guideline</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A recommendation on the appropriate treatment and care of people with a specific disease or condition, based on the best available evidence, designed to help healthcare professionals in their work.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://purl.org/spar/fabio/Comment --> - - <owl:Class rdf:about="http://purl.org/spar/fabio/Comment"> - <rdfs:label xml:lang="en">Comment</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A verbal or written remark concerning some entity. In written form, a comment is often appended to that entity and termed an annotation. Within computer programs or ontologies, comments are added to enhance human understanding, and are usually prefaced by</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A verbal or written remark concerning some entity. In written form, a comment is often appended to that entity and termed an annotation. Within computer programs or ontologies, comments are added to enhance human understanding, and are usually prefaced by a special syntactic symbol that ensures they are ignored during execution of the program. - -has super-classes</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://purl.org/spar/fabio/Erratum --> - - <owl:Class rdf:about="http://purl.org/spar/fabio/Erratum"> - <rdfs:label xml:lang="en">Erratum</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A formal correction to an error introduced by the publisher into a previously published document.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Abstract --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Abstract"> - <rdfs:label xml:lang="en">Abstract</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An abstract that is published as a standalone document or in a journal of abstracts</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AcademicDegree --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AcademicDegree"> - <rdfs:label xml:lang="en">Academic Degree</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:minQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minQualifiedCardinality> - <owl:onDataRange rdf:resource="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An academic degree at any level, both as reported by individuals for employment and as offered by academic degree programs.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">B.A. Bachelor of Arts</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This list may have multiple abbreviations for some degrees.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AcademicDepartment --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AcademicDepartment"> - <rdfs:label xml:lang="en">Academic Department</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Department"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A distinct, usually specialized educational unit within an educational organization.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Endodontics (department within a College of Dentistry); English (department within a College of Liberal Arts)</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AcademicTerm --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AcademicTerm"> - <rdfs:label xml:lang="en">Academic Term</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An explicit individual academic term, quarter, or semester rather than the generic fall, spring or summer semester.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AcademicYear --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AcademicYear"> - <rdfs:label xml:lang="en">Academic Year</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An explicit individual period considered by an academic institution to be its primary academic cycle.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AdministratorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AdministratorRole"> - <rdfs:label xml:lang="en">Administrator Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AdviseeRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AdviseeRole"> - <rdfs:label xml:lang="en">Advisee Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AdvisingProcess --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AdvisingProcess"> - <rdfs:label xml:lang="en">Advising Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AdvisingRelationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AdvisingRelationship"> - <rdfs:label xml:lang="en">Advising Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#AdvisorRole"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#AdviseeRole"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A dual relationship of one person being advised or mentored by another person, typically including start and end dates</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AdvisorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AdvisorRole"> - <rdfs:label xml:lang="en">Advisor Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Association --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Association"> - <rdfs:label xml:lang="en">Association</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A formal organization of people or groups of people around a subject or practice.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of persons or organizations organized for a common purpose.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Special Libraries Association; Association for Computing Machinery(ACM); American Medical Informatics Association(AMIA)</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AttendeeRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AttendeeRole"> - <rdfs:label xml:lang="en">Attendee Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of attending an Event or EventSeries</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AttendingProcess --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AttendingProcess"> - <rdfs:label xml:lang="en">Attending Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Authorship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Authorship"> - <rdfs:label xml:lang="en">Authorship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hideFromDisplay"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"></rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Authorship of journal articles, books and other original works is a means by which academics communicate the results of their scholarly work, establish priority for their discoveries, and build their reputation among their peers. -This class allows for linking an author to a publication while indicating information about that author's authorship.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains the authors name, their rank in the publication, and whether or not they are a corresponding author on the publication.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Currently any abstract name is given to members of this class. This could change in the future.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Award --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Award"> - <rdfs:label xml:lang="en">Award or Honor</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An Award or Honor</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An Award or Honor</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Wiley Prize in Biomedical Sciences</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AwardReceipt --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AwardReceipt"> - <rdfs:label xml:lang="en">Award or Honor Receipt</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeValue"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Award"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#assignedBy"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The award bestowed may be represented with the Award class.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The bestowal of an award, honor, or distinction to a person or person's at a particular time. </obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#AwardedDegree --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#AwardedDegree"> - <rdfs:label xml:lang="en">Awarded Degree</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#AcademicDegree"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115>The awarding of a degree by an agent to another agent. It is mostly for academic degrees.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Blog --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Blog"> - <rdfs:label xml:lang="en">Blog</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Website"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Blog is short for weblog. </obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Library of Congress Blog</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Regularly updated online journal or newsletter by one or more writers, called bloggers, containing articles and commentary of interest to the blogger</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#BlogPosting --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#BlogPosting"> - <rdfs:label xml:lang="en">Blog Posting</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasPublicationVenue"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Blog"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A specific blog posting</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An online article or commentary appearing on a blog</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Building --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Building"> - <rdfs:label xml:lang="en">Building</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000050"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Room"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Building that provides a particular service or is used for a particular activity.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Enter building name. If the building's name is a number (as in many governmental organizations such as national laboratories and military bases), then enter it. Do not confuse with the number that appears in a postal address.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Martha Van Rensselaer Hall (VR); Caldwell Hall (CD); University Auditorium</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Campus --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Campus"> - <rdfs:label xml:lang="en">Campus</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Cornell Ithaca; Cornell Geneva; Cornell New York City; Cornell Qatar</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition taken from dictionary.com (http://dictionary.reference.com/browse/campus).</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The grounds of a school, college, university, or hospital. Or, a large, usually suburban, landscaped business or industrial site.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#CaseStudy --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#CaseStudy"> - <rdfs:label xml:lang="en">Case Study</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A form of qualitative descriptive research that is used to study individuals, a small group of participants, or a group as a whole. Medical usage (from MeSH): clinical presentations that may be followed by evaluative studies that eventually lead to a diagnosis. </obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A qualitative descriptive research study of individuals or a group</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Catalog --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Catalog"> - <rdfs:label xml:lang="en">Catalog</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A list of items in a collection; an ordered compilation of item descriptions and sufficient information to afford access to them</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">NLM Catalog</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition is the Medical Subject Heading (MeSH) definition </obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Center --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Center"> - <rdfs:label xml:lang="en">Center</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A place where a particular activity or service is concentrated.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Alchohol Education Center; Center for Arts and Public Policy; Hearing Research Center</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization where a specified activity is concentrated.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition take from http://www.thefreedictionary.com/center.</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Certificate --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Certificate"> - <rdfs:label xml:lang="en">Certificate</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Credential"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document confirming certain characteristics of a person or organization, usually provided by some form of external review, education, or assessment.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document confirming certain characteristics of a person or organization, usually provided by some form of external review, education, or assessment.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Certification --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Certification"> - <rdfs:label xml:lang="en">Certification</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#IssuedCredential"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An issued certificate</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">see also core:Certificate</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ClinicalOrganization --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ClinicalOrganization"> - <rdfs:label xml:lang="en">Clinical Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Any organization that offers significant health services or routinely provides medical care to patients.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Any organization with a significant clinical function as a matter of course and not just through occasional clinical roles</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">In the future we may be able to make this a defined class that would not need to be directly asserted, but the consensus seems to be that some organizations "are" clinical and some "are" research organizations and that the distinction is important enough to warrant the additional class and class assertions</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ClinicalRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ClinicalRole"> - <rdfs:label xml:lang="en">Clinical Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of observing or treating patients</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#CoPrincipalInvestigatorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#CoPrincipalInvestigatorRole"> - <rdfs:label xml:lang="en">Co-Principal Investigator Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#InvestigatorRole"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Role of co-principal investigator of an Agreement (for example, a grant), who devotes a specified percentage of time and is considered key personnel.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#College --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#College"> - <rdfs:label xml:lang="en">College</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A primary academic unit within a University or a free-standing higher education organization without graduate degree programs</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A primary academic unit within a University or a free-standing higher education organization without graduate degree programs.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">College of Arts & Sciences; Ivy Tech Community College</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Committee --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Committee"> - <rdfs:label xml:lang="en">Committee</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Group"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of people organized for a specific purpose (e.g., a reporting or advisory role), often with a charge and for a specific duration</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of people organized for a specific purpose, whose members are often selected from a larger group to serve for designated periods of time.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Curriculum Steering Committee; PhD Advisory Committee</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">There could be many subclasses such as thesis committee or tenure committee, but these may typically be differentiated via the moniker unless distinct properties become important.</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Company --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Company"> - <rdfs:label xml:lang="en">Company</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A legally-recognized business organization</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A legally-recognized business organization.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">from Wikipedia: "A company is a form of business organization. It is an association or collection of individual real persons and/or other companies ... This collection, group or association of persons can be made to exist in law and then a company is itself considered a "legal person". The name company arose because, at least originally, it represented or was owned by more than one real or legal person."</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Competition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Competition"> - <rdfs:label xml:lang="en">Competition</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An occasion on which a winner is selected from among two or more contestants.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Intel Talent Search; poetry contest</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Not the same as an award or distinction.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ConferencePaper --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ConferencePaper"> - <rdfs:label xml:lang="en">Conference Paper</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Article"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/presentedAt"/> - <owl:allValuesFrom rdf:resource="http://purl.org/ontology/bibo/Conference"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A paper presented at a conference; optionally collected into a Proceedings or a special Journal issue</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ConferencePoster --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ConferencePoster"> - <rdfs:label xml:lang="en">Conference Poster</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The digital file (or physical equivalent), if available after the conference, vs. the act of attending/presenting: use ConferencePresentation for information about date/time/location/name of the event where the poster was presented</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ConferenceSeries --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ConferenceSeries"> - <rdfs:label xml:lang="en">Conference Series</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EventSeries"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organized series of a meeting for consultation or discussion.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">For individual, separate conferences, use conference instead. core:ConferenceSeries and core:SeminarSeries are very similar.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Consortium --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Consortium"> - <rdfs:label xml:lang="en">Consortium</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of independent organizations working together toward a common goal, under an expressed agreement.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Committee on Institutional Cooperation (CIC); The Five Colleges of Ohio</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Continent --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Continent"> - <rdfs:label xml:lang="en">Continent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A large contiguous landmass that is at least partially surrounded by water, together with any islands on its continental shelf.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition take from http://en.wiktionary.org/wiki/continent.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The seven commonly recognized continents are Africa; Antarctica; Asia; Australia; Europe; North America; South America</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Contract --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Contract"> - <rdfs:label xml:lang="en">Contract</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/abstract"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#supportedInformationResource"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#assignedBy"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An agreement involving specific deliverables and payment</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#CoreLaboratory --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#CoreLaboratory"> - <rdfs:label xml:lang="en">Core Laboratory</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#ServiceProvidingLaboratory"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A lab providing services such as training, protocols, or access to instruments or software</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Country --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Country"> - <rdfs:label xml:lang="en">Country</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Afghanistan; Antigua and Barbuda; Cameroon; Iceland; Jamaica; Nigeria; United States of America</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An area of land distinguished by its political autonomy. Politically independent territories.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Source of the Short Definition: http://www.thefreedictionary.com/country. This is also the same as geopolitical.owl:self_governing.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#County --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#County"> - <rdfs:label xml:lang="en">County</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Alachua; Baker; Bradford; Kenora; Ottawa; Waterloo</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition modified from the one found here: http://www.thefreedictionary.com/county.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The largest administrative division of most states or provinces.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Course --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Course"> - <rdfs:label xml:lang="en">Course</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#courseCredits"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A course as taught in one time period (such as a semester; although note that a course could consist of only one meeting (teaching session)) by one or more instructors, normally but not always for credit. Does not represent either each meeting of the course or the course offering such as Biology 101 taught every semester from 1980 to 2010</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A course as taught in one time period by one or more instructors, normally but not always for credit. Does not represent either each meeting of the course or the course offering such as Biology 101 taught every semester from 1980 to 2010</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Credential --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Credential"> - <rdfs:label xml:lang="en">Credential</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasGoverningAuthority"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#validIn"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An attestation of qualification, competence, or authority issued to an individual by a third party with a relevant or de facto authority or assumed competence to do so.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An attestation of qualification, competence, or authority issued to an individual by a third party with a relevant or de facto authority or assumed competence to do so.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Database --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Database"> - <rdfs:label xml:lang="en">Database</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/CollectedDocument"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#publisher"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A structured file of information or a set of logically related data stored and retrieved using computer-based means</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PubMed</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short Definition is the Medical Subject Heading (MeSH) definition</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Dataset --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Dataset"> - <rdfs:label xml:lang="en">Dataset</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/spar/cito/isCitedAsDataSourceBy"/> - <owl:allValuesFrom rdf:resource="http://purl.org/ontology/bibo/Document"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A named collection of data, usually containing only one type of data</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">US Patent Data; US Job Data</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#DateTimeInterval --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#DateTimeInterval"> - <rdfs:label xml:lang="en">Date/Time Interval</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000038"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">a specific period or duration, defined by (optional) start and end date/times.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#DateTimeValue --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#DateTimeValue"> - <rdfs:label xml:lang="en">Date/Time Value</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000148"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A date and/or time</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#DateTimeValuePrecision --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#DateTimeValuePrecision"> - <rdfs:label xml:lang="en">Date/Time Value Precision</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Indicates the precision of the value of a DateTimeValue instance.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Department --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Department"> - <rdfs:label xml:lang="en">Department</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A unit within a larger organization that addresses a specific subject or area of activity.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition modified from the definition here: http://dictionary.reference.com/browse/department. It is difficult to tell the difference between and department and a division.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Legal (department within a company); Use for any non-academic department</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Division --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Division"> - <rdfs:label xml:lang="en">Division</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A major unit or section within a larger organization.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Cardiovascular Medicine (division within medicine)</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition modified from http://www.thefreedictionary.com/division. It is difficult to tell the difference between a division and a department.</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EditorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EditorRole"> - <rdfs:label xml:lang="en">Editor Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An ongoing editorial responsibility for a bibo:Collection, such as a Journal or Series</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An ongoing editorial responsibility for a bibo:Collection, such as a Journal or Series</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EditorialArticle --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EditorialArticle"> - <rdfs:label xml:lang="en">Editorial Article</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Article"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An article of opinion, typically published in a newspaper. For academics, most commonly Op Ed pieces</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Editorship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Editorship"> - <rdfs:label xml:lang="en">Editorship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115>A relationship that represents the recognition of an agent as an editor.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EducationalProcess --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EducationalProcess"> - <rdfs:label xml:lang="en">Educational Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#supplementalInformation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Currently any abstract name is given to individuals of this class. This could change in the future.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Represents educational training that has been received.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This connects person to their academic degree through this educational training, but can also be used when the training does not result in a degree.</vitro:descriptionAnnot> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EmeritusFaculty --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EmeritusFaculty"> - <rdfs:label xml:lang="en">Faculty Member Emeritus</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A retired faculty member who has retained their rank, title and privileges.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EmeritusLibrarian --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EmeritusLibrarian"> - <rdfs:label xml:lang="en">Librarian Emeritus</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A retired librarian who has retained their rank, title and privileges.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EmeritusProfessor --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EmeritusProfessor"> - <rdfs:label xml:lang="en">Professor Emeritus</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EmeritusFaculty"/> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A retired professor who has retained their rank, title and privileges.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Equipment --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Equipment"> - <rdfs:label xml:lang="en">Equipment</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000040"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#freetextKeyword"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A network server is one example. Medical schools and research laboratories can list professional equipment, such as microscopes.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A physical object provided for specific purpose, task or occupation. </obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">server; Bruker Vector-33 FT-IR</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#EventSeries --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#EventSeries"> - <rdfs:label xml:lang="en">Event Series</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#contactInformation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A generic class which may include a conference series, a course section, a seminar series, or a workshop series. When possible, use one of these more specific classes.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Only use if no specific subclasses of core:EventSeries desribe the activity.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Two or more events that occur at different times and are connected to each other.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Exhibit --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Exhibit"> - <rdfs:label xml:lang="en">Exhibit</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The showing of an object or a collection of objects, in an organized manner.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ExtensionUnit --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ExtensionUnit"> - <rdfs:label xml:lang="en">Extension Unit</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A unit devoted primarily to extension activities, whether for outreach or research</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A unit devoted primarily to extension activities, whether for outreach or research.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Alachua County Extension Office</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#F1000Link --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#F1000Link"> - <rdfs:label xml:lang="en">F1000 Link</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#URL"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">F1000 is a place where faculty go to critique papers published in PubMed. Any given record in F1000 might have anywhere from one to dozens of reviews.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Facility --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Facility"> - <rdfs:label xml:lang="en">Facility</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000029"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000050"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BFO_0000029"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Distinct from the organization that runs it; e.g., a laboratory may be an organization but may be run by another organization and only consist of facilities housing equipment or services. Can be a building or place that provides a particular service or is used for a particular activity. Use the specific Building or Room whenever possible. Short definition from http://dictionary.reference.com/browse/facility.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Something designed, built, installed, etc., to serve a specific function or activity affording a convenience or service.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use subclasses of core:Facility subclasses instead of this class if possible</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#FacultyAdministrativePosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#FacultyAdministrativePosition"> - <rdfs:label xml:lang="en">Faculty Administrative Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An academic administrative position (associate dean, etc.) as distinct from a professional administrative position (non-academic)</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Associate Dean</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">That is a position held by an academic faculty member who works for administration.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#FacultyMember --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#FacultyMember"> - <rdfs:label xml:lang="en">Faculty Member</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person with at least one academic appointment to a specific faculty of a university or institution of higher learning.</obo:IAO_0000115> - <vitro:descriptionAnnot rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition from here: http://research.carleton.ca/htr/defs.php.</vitro:descriptionAnnot> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#FacultyMentoringRelationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#FacultyMentoringRelationship"> - <rdfs:label xml:lang="en">Faculty Mentoring Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#AdvisingRelationship"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An advisory relationship in which one faculty member mentors another faculty member.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#FacultyPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#FacultyPosition"> - <rdfs:label xml:lang="en">Faculty Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Academic position in a university or institution</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Professor, associate professor and assistant professor are common positions for academic faculty.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Professor; Associate Professor; Assistant Professor</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Foundation --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Foundation"> - <rdfs:label xml:lang="en">Foundation</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An institution founded with an endowment to support educational, research, artistic or other charitable activities.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from: http://dictionary.reference.com/browse/foundation.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The Ford Foundation</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#FundingOrganization --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#FundingOrganization"> - <rdfs:label xml:lang="en">Funding Organization</rdfs:label> - <owl:equivalentClass> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#assigns"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Grant"/> - </owl:Restriction> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A defined class of organizations that fund Grants</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization that provides financial support to individuals or organizations to carry out specified activities.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">National Institute of Health (NIH)</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GeographicLocation --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GeographicLocation"> - <rdfs:label xml:lang="en">Geographic Location</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Location"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000050"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A location having coordinates in geographic space.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Removed the word "stable" because disputed territories from geopolitical.owl are included. This could imply that the geographic coordinates could change. I've also copied this definition to core:Geographic Location. I think core:Geographic Location and core:Geographic Region are both the same and only one is needed. There is also geopolitical.owl:geographical_region which further causes confusion.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use subclasses of core:Geographic Location subclasses instead of this class if possible.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GeographicRegion --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GeographicRegion"> - <rdfs:label xml:lang="en">Geographic Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A location having coordinates in geographic space.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Removed the word "stable" because disputed territories from geopolitical.owl are included. This could imply that the geographic coordinates could change. This definition was originally in core:Geographic Location. I simply copied the definition from there. I think core:Geographic Location and core:Geographic Region are both the same and only one is needed. There is also geopolitical.owl:geographical_region which further causes confusion.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use subclasses of core:Geographic Region subclasses instead of this class if possible.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GeopoliticalEntity --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GeopoliticalEntity"> - <rdfs:label xml:lang="en">Geopolitical Entity</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A geographical area which is associated with some sort of political structure.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short definition obtained here: http://en.wiktionary.org/wiki/geopolitical_entity.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use subclasses of core:GeopoliticalEntity subclasses instead of this class if possible.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GovernmentAgency --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GovernmentAgency"> - <rdfs:label xml:lang="en">Government Agency</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A unit of government responsible for oversight and regulation of certain activities or the administration and provision of specific services.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from: http://en.wikipedia.org/wiki/Government_agency.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">United States Library of Congress</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GraduateAdvisingRelationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GraduateAdvisingRelationship"> - <rdfs:label xml:lang="en">Graduate Advising Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#AdvisingRelationship"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An advisory relationship in which a professor advises a graduate student.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#GraduateStudent --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#GraduateStudent"> - <rdfs:label xml:lang="en">Graduate Student</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Student"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person who has already received a bachelor's degree and is working toward a Master's or Doctoral degree.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Grant --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Grant"> - <rdfs:label xml:lang="en">Grant</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.org/ontology/bibo/abstract"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#supportedInformationResource"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#assignedBy"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An intramural or extramural award to support scholarly work, such as UF09179 (VIVO)</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Financial assistance mechanism providing money, property, or both to an eligible entity to carry out an approved project or activity</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short definition is from the Glossary of NIH Terms.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Hospital --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Hospital"> - <rdfs:label xml:lang="en">Hospital</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An institution that provides medical, surgical, psychiatric or nursing care.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from: http://dictionary.reference.com/browse/hospital.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Shands at the University of Florida</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Institute --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Institute"> - <rdfs:label xml:lang="en">Institute</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An Institute normally has a research focus but may also fulfill instructional or outreach roles</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization founded to pursue or promote certain research, educational or public policy interests or activities.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Institute for Fundamental Theory</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Internship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Internship"> - <rdfs:label xml:lang="en">Internship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EducationalProcess"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Typically a student or a recent graduate undergoing supervised practical training.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#InvestigatorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#InvestigatorRole"> - <rdfs:label xml:lang="en">Investigator Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#ResearcherRole"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role in an Agreement (for example, a grant) as a named investigator or key personnel.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#InvitedTalk --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#InvitedTalk"> - <rdfs:label xml:lang="en">Invited Talk</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Presentation"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#IssuedCredential --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#IssuedCredential"> - <rdfs:label xml:lang="en">Issued Credential</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#validIn"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Credential"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasSubjectArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateIssued"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#expirationDate"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeValue"/> - </owl:Restriction> - </rdfs:subClassOf> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Laboratory --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Laboratory"> - <rdfs:label xml:lang="en">Laboratory</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization unit that facilitates or conduits observation, testing, experimentation, or research in a field of study or practice.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organizational unit (as opposed to the physical facility) that performs research, provides services, or processes materials</obo:IAO_0000115> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#LeaderRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#LeaderRole"> - <rdfs:label xml:lang="en">Leader Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A broad-ranging leader concept, from leading a small temporary committee to head of a large international organization.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A leadership role</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Librarian --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Librarian"> - <rdfs:label xml:lang="en">Librarian</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person working in a position of librarian or information professional, or academic or technical expert in support of providing information services or materials.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#LibrarianPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#LibrarianPosition"> - <rdfs:label xml:lang="en">Librarian Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A position held by library and information science professionals, or academic or technical experts, in support of providing information services or materials</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">It is the common position in libraries.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Librarian; Library Systems Analyst; Music Bibliographer</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Library --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Library"> - <rdfs:label xml:lang="en">Library</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization maintaining one or more collections of physical and/or electronic information resources for access or lending.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Marston Science Library</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used information from this definition: http://dictionary.reference.com/browse/library.</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#License --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#License"> - <rdfs:label xml:lang="en">License</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Credential"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Licenses are usually issued in order to regulate some activity that is deemed to be dangerous or a threat to the person or the public or which involves a high level of specialized skill. See also core:Licensure.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Official or legal permission to do something</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Licensure --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Licensure"> - <rdfs:label xml:lang="en">Licensure</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#IssuedCredential"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A granted license, which gives a 'permission to practice.'</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A granted license, which gives a 'permission to practice.' Such licenses are usually issued in order to regulate some activity that is deemed to be dangerous or a threat to the person or the public or which involves a high level of specialized skill. See also core:License.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Location --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Location"> - <rdfs:label xml:lang="en">Location</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000006"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">It's anticipated that the subclasses will be used when classifying items. And, all locations can be viewable via this class.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Top level of all location classes.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use subclasses of core:Location when classsifying items.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#MedicalResidency --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#MedicalResidency"> - <rdfs:label xml:lang="en">Medical Residency</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EducationalProcess"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Residency is a stage of graduate medical training. </obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Meeting --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Meeting"> - <rdfs:label xml:lang="en">Meeting</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A gathering of people for a defined purpose, not necessarily public or announced</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#MemberRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#MemberRole"> - <rdfs:label xml:lang="en">Member Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of being a member in a Process or an Organization</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Museum --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Museum"> - <rdfs:label xml:lang="en">Museum</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization devoted to the acquisition, conservation, study, exhibition, and educational interpretation of objects having scientific, historical, cultural or artistic value.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition was take from here: http://dictionary.reference.com/browse/museum</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The Getty Museum</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#NewsRelease --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#NewsRelease"> - <rdfs:label xml:lang="en">News Release</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A short written piece focused on an event or announcement of note, having a defined publication time and of less enduring interest than a news feature.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Newsletter --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Newsletter"> - <rdfs:label xml:lang="en">Newsletter</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Periodical"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The Ornithological Newsletter</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Usually issued periodically, prepared by or for a group or institution to present information to a specific audience, often also made available to the press and public</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#NonAcademic --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#NonAcademic"> - <rdfs:label xml:lang="en">Non-Academic</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person holding a position that is not considered to be an academic appointment.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#NonAcademicPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#NonAcademicPosition"> - <rdfs:label xml:lang="en">Non-Academic Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A position classified as professional, staff, support, or any other non-academic role</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Accounting & Research Services Assistant; Director of Information Technology</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Staff, support, and other non-academic positions.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#NonFacultyAcademic --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#NonFacultyAcademic"> - <rdfs:label xml:lang="en">Non-Faculty Academic</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person not considered a faculty member but holding an academic appointment.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#NonFacultyAcademicPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#NonFacultyAcademicPosition"> - <rdfs:label xml:lang="en">Non-Faculty Academic Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A position involving academic work but without faculty status</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Researcher; Academic Extension Associate; Postdoctoral Associate</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Those positions are held by people who do academic work but do not have faculty positions in universities or institutes.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#OrganizerRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#OrganizerRole"> - <rdfs:label xml:lang="en">Organizer Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of organizing</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#OrganizingProcess --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#OrganizingProcess"> - <rdfs:label xml:lang="en">Organizing Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#OutreachProviderRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#OutreachProviderRole"> - <rdfs:label xml:lang="en">Outreach Provider Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An outreach or community service role directed outside a person's primary profession and institution</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Communicating Astronomy to the Public</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The example is one outreach role required by US space agency NASA, which is related with one project in NASA. Name of the outreach role should be put here.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PeerReviewerRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PeerReviewerRole"> - <rdfs:label xml:lang="en">Peer Reviewer Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#ReviewerRole"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of peer reviewing</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">is a generic term for a process of self-regulation by a profession or a process of evaluation involving qualified individuals within the relevant field. Peer review methods are employed to maintain standards, improve performance and provide credibility. In academia the term is often used to denote a prepublication review of academic papers; reviewing an academic paper is often called refereeing. -Contents -[hide]</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PopulatedPlace --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PopulatedPlace"> - <rdfs:label xml:lang="en">Populated Place</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Either city or town - a thickly populated area having fixed boundaries and certain local powers of government.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Position --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Position"> - <rdfs:label xml:lang="en">Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#rank"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#int"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relates"/> - <owl:someValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An employment activity, whether compensated or not. Short definition comes from http://en.wikipedia.org/wiki/Position, and has been modified.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Director of Admissions and Placement; Associate University Librarian</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Particular position in an organization, commonly identified by job title, and normally associated with a job description that details the tasks and responsibilities that go with the position.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Postdoc --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Postdoc"> - <rdfs:label xml:lang="en">Postdoc</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#NonFacultyAcademic"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Person holding an academic employment appointment focused on research rather than teaching; temporary (or for some defined term)</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PostdocOrFellowAdvisingRelationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PostdocOrFellowAdvisingRelationship"> - <rdfs:label xml:lang="en">Postdoc or Fellow Advising Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#AdvisingRelationship"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An advisory relationship in which the advisee is a Postdoc or Fellow.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PostdocPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PostdocPosition"> - <rdfs:label xml:lang="en">Postdoctoral Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#NonFacultyAcademicPosition"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A postdoctoral training appointment (job)</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PostdoctoralTraining --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PostdoctoralTraining"> - <rdfs:label xml:lang="en">Postdoctoral Training</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EducationalProcess"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Postdoctoral research is academic or scholarly research conducted by a person who has completed his or her doctoral studies, normally within the following five years. It is intended to further deepen expertise in a specialist subject.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Presentation --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Presentation"> - <rdfs:label xml:lang="en">Presentation</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/NET/c4dm/event.owl#Event"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Encompasses talk, speech, lecture, slide lecture, conference presentation</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PresenterRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PresenterRole"> - <rdfs:label xml:lang="en">Presenter Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of presenting information</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Are we assuming that a PresenterRole is in a Presentation? Or could you have a PresenterRole in, say, a committee?</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PresentingProcess --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PresentingProcess"> - <rdfs:label xml:lang="en">Presenting Process</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PrimaryPosition --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PrimaryPosition"> - <rdfs:label xml:lang="en">Primary Position</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Position"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A position designated as primary by the organization or group where it is held. This designation may be applied to zero or more of an agent's positions and may be asserted in conjunction with other subclasses of position.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A position designated as primary by the organization where it is held.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PrincipalInvestigatorRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PrincipalInvestigatorRole"> - <rdfs:label xml:lang="en">Principal Investigator Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#InvestigatorRole"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Role of a person to direct a project or activity being supported by an Agreement (for example, a grant), and who is accountable to the grantee for the proper conduct of the project or activity. Also known as Program Director or Project Director.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#PrivateCompany --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#PrivateCompany"> - <rdfs:label xml:lang="en">Private Company</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Company"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A private company is one that is privately-owned, and thus, is not publicly-traded in the stock market. Members of the general public cannot purchase stock in a private company unless that company chooses to go public and become a public company.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition obtained here: http://answers.ask.com/Business/Finance/what_is_a_private_company. Examples of private companies found here: http://www.forbes.com/2008/11/03/largest-private-companies-biz-privates08-cx_sr_1103private_land.html</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Publix Super Markets; Ernst & Young; PricewaterhouseCoopers</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Program --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Program"> - <rdfs:label xml:lang="en">Program</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A Cornell graduate field (http://vivo.cornell.edu/index.jsp?home=65535&collection=820)</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An ongoing academic initiative not formalized with department or division status.</obo:IAO_0000115> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Project --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Project"> - <rdfs:label xml:lang="en">Project</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000015"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#geographicFocus"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#description"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An endeavor, frequently collaborative, that occurs over a finite period of time and is intended to achieve a particular aim.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An endeavor, frequently collaborative, that occurs over a finite period of time and is intended to achieve a particular aim. -</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Publisher --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Publisher"> - <rdfs:label xml:lang="en">Publisher</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person or company whose business is the publishing of books, periodicals, engravings, computer software, etc.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition found here: http://dictionary.reference.com/browse/publisher</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Elsevier; Harper & Row; Indiana University Press</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Relationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Relationship"> - <rdfs:label xml:lang="en">Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000020"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">a reified relationship</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">functions as an n-ary predicate</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ResearchOrganization --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ResearchOrganization"> - <rdfs:label xml:lang="en">Research Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Any organization (likely also asserted as another class of Organization) with a primary, ongoing research function, not just through occasional roles</obo:IAO_0000115> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ResearchProposal --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ResearchProposal"> - <rdfs:label xml:lang="en">Research Proposal</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A proposal for a research grant that has been submitted but not approved; does not represent an existing activity</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ResearcherRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ResearcherRole"> - <rdfs:label xml:lang="en">Researcher Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of conducting funded or unfunded research, sometimes linked to an Agreement.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Examples of research can be seen at: http://www.ufl.edu/research/products/index.html. Note these may have been funded, but the research doesn't have to be funded. Also, the research may be linked to an Agreement (for example, a Grant), but does not need to be.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Review --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Review"> - <rdfs:label xml:lang="en">Review</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Article"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An article reviewing one or more other information resources (a book, one or more other articles, movies, etc)</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ReviewerRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ReviewerRole"> - <rdfs:label xml:lang="en">Reviewer Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role that encompasses both ongoing reviewer responsibility for a bibo:Collection, such as a Journal or Series, and also a review performed for a bibo:Document, such as a book, academic article or conference paper.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role that encompasses both ongoing reviewer responsibility for a bibo:Collection, such as a Journal or Series, and also a review performed for a bibo:Document, such as a book, academic article or conference paper.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Room --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Room"> - <rdfs:label xml:lang="en">Room</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000050"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Facility"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">100 Caldwell Hall; 114 Martha Van Rensselaer (Rushmore Conference Room)</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Enter room number of name.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Room that provides a particular service or is used for a particular activity.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#School --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#School"> - <rdfs:label xml:lang="en">School</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An institution for instruction in a particular skill or field.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from here: http://dictionary.reference.com/browse/school.</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">School of Architecture; School of Music</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Score --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Score"> - <rdfs:label xml:lang="en">Score</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Written musical composition for voice or instruments or both</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Screenplay --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Screenplay"> - <rdfs:label xml:lang="en">Screenplay</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Written script for a film production, including dialogue and descriptions of gestures, actions, shooting directions</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#SeminarSeries --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#SeminarSeries"> - <rdfs:label xml:lang="en">Seminar Series</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EventSeries"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organized series of a meeting for an exchange of ideas, typically put on by a department or center.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Applied Microeconomics Seminars; Future of Rural New York Seminar Series</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">For individual seminars, use seminar instead. core:ConferenceSeries and core:SeminarSeries are very similar.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#ServiceProvidingLaboratory --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#ServiceProvidingLaboratory"> - <rdfs:label xml:lang="en">Service Providing Lab</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Laboratory"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A laboratory that provides services</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Ideally a defined class -- a Laboratory the provides some Service via the property</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Speech --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Speech"> - <rdfs:label xml:lang="en">Speech</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Text of a speech written in preparation for delivery of the speech.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#StateOrProvince --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#StateOrProvince"> - <rdfs:label xml:lang="en">State or Province</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeopoliticalEntity"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Minnesota; Michigan; Indiana; New York; Quebec; Manitoba; Ontario</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">One of a number of areas or communities having their own governments and forming a federation under a sovereign government, as in the US.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Source of the Short Definition: http://www.thefreedictionary.com/state.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Student --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Student"> - <rdfs:label xml:lang="en">Student</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person who is enrolled in an educational institution.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use only if no specific subclasses of core:Student describe the person.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#StudentOrganization --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#StudentOrganization"> - <rdfs:label xml:lang="en">Student Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A student organization is an organization, operated by students at a university, whose membership normally consists only of students.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Dancin' Gators</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition take from here: http://en.wikipedia.org/wiki/Student_society</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#SubnationalRegion --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#SubnationalRegion"> - <rdfs:label xml:lang="en">Subnational Region</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Boroughs; townships; districts; the Midwest</obo:IAO_0000112> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">For example, the Midwest, northeast U.S.</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Short definition was partially taken from http://en.wikipedia.org/wiki/Subnational_entity.</obo:IAO_0000112> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Smaller administrative division into which a country may be divided.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#TeacherRole --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#TeacherRole"> - <rdfs:label xml:lang="en">Teacher Role</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A role of serving as an educator</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Team --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Team"> - <rdfs:label xml:lang="en">Team</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Group"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group of people working together.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An informal organization brought together for the purposes of a project or event</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">VIVO Outreach Team; VIVO Ontology Team</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Translation --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Translation"> - <rdfs:label xml:lang="en">Translation</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The result of rendering a work from one language to another</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#UndergraduateAdvisingRelationship --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#UndergraduateAdvisingRelationship"> - <rdfs:label xml:lang="en">Undergraduate Advising Relationship</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#AdvisingRelationship"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An advisory relationship in which a professor advises an undergraduate student.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#UndergraduateStudent --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#UndergraduateStudent"> - <rdfs:label xml:lang="en">Undergraduate Student</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#Student"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person registered in an undergraduate program leading to a bachelor's degree or an undergraduate diploma or certificate.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#University --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#University"> - <rdfs:label xml:lang="en">University</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An institution of higher education and research, which grants academic degrees in a variety of subjects, and provides both undergraduate education and postgraduate education.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Definition taken from: http://en.wikipedia.org/wiki/University</obo:IAO_0000112> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">University of Florida; Washington University in St. Louis</obo:IAO_0000112> - <obo:IAO_0000412 rdf:resource="http://vivoweb.org/ontology/core"/> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#Video --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#Video"> - <rdfs:label xml:lang="en">Video</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/AudioVisualDocument"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Audiovisual recording in video format</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#WorkingPaper --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#WorkingPaper"> - <rdfs:label xml:lang="en">Working Paper</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.org/ontology/bibo/Document"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#placeOfPublication"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A document created as a basis for discussion or a very early draft of a formal paper</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/core#WorkshopSeries --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/core#WorkshopSeries"> - <rdfs:label xml:lang="en">Workshop Series</rdfs:label> - <rdfs:subClassOf rdf:resource="http://vivoweb.org/ontology/core#EventSeries"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organized series of workshop events, whether repetitions of the same workshop or multiple different workshops.</obo:IAO_0000115> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Use workshop for individual events.</obo:IAO_0000112> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/scientific-research#Phase0ClinicalTrial --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/scientific-research#Phase0ClinicalTrial"> - <rdfs:label xml:lang="en">Phase 0 Clinical Trial</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 0 Clinical Trial</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 0 is a recent designation for exploratory, first-in-human trials conducted in accordance with the United States Food and Drug Administration's (FDA) 2006 Guidance on Exploratory Investigational New Drug (IND) Studies. Phase 0 trials are also known as human microdosing studies and are designed to speed up the development of promising drugs or imaging agents by establishing very early on whether the drug or agent behaves in human subjects as was expected from preclinical studies.</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/scientific-research#Phase1ClinicalTrial --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/scientific-research#Phase1ClinicalTrial"> - <rdfs:label xml:lang="en">Phase 1 Clinical Trial</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">In Phase I trials, researchers test an experimental drug or treatment in a small group of people (20-80) for the first time to evaluate its safety, determine a safe dosage range, and identify side effects</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 1 Clinical Trial</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/scientific-research#Phase2ClinicalTrial --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/scientific-research#Phase2ClinicalTrial"> - <rdfs:label xml:lang="en">Phase 2 Clinical Trial</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">In Phase 2 trials, an experimental study drug or treatment is given to a larger group of people (100-300) to see if it is effective and to further evaluate its safety.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 2 Clinical Trial</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/scientific-research#Phase3ClinicalTrial --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/scientific-research#Phase3ClinicalTrial"> - <rdfs:label xml:lang="en">Phase 3 Clinical Trial</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">In Phase 3 trials, an experimental study drug or treatment is given to large groups of people (1,000-3,000) to confirm its effectiveness, monitor side effects, compare it to commonly used treatments, and collect information that will allow the experimental drug or treatment to be used safely. -</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 3 Clinical Trial</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://vivoweb.org/ontology/scientific-research#Phase4ClinicalTrial --> - - <owl:Class rdf:about="http://vivoweb.org/ontology/scientific-research#Phase4ClinicalTrial"> - <rdfs:label xml:lang="en">Phase 4 Clinical Trial</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ERO_0000016"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">In Phase 4 trials, post marketing studies delineate additional information including the drug's or treatment's risks, benefits, and optimal use.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Phase 4 Clinical Trial</obo:IAO_0000115> - </owl:Class> - - - - <!-- http://www.geneontology.org/formats/oboInOwl#DbXref --> - - <owl:Class rdf:about="http://www.geneontology.org/formats/oboInOwl#DbXref"> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000102"/> - </owl:Class> - - - - <!-- http://www.geneontology.org/formats/oboInOwl#Definition --> - - <owl:Class rdf:about="http://www.geneontology.org/formats/oboInOwl#Definition"> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000102"/> - </owl:Class> - - - - <!-- http://www.geneontology.org/formats/oboInOwl#Synonym --> - - <owl:Class rdf:about="http://www.geneontology.org/formats/oboInOwl#Synonym"> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000102"/> - </owl:Class> - - - - <!-- http://www.geneontology.org/formats/oboInOwl#SynonymType --> - - <owl:Class rdf:about="http://www.geneontology.org/formats/oboInOwl#SynonymType"> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/IAO_0000102"/> - </owl:Class> - - - - <!-- http://www.w3.org/2004/02/skos/core#Concept --> - - <owl:Class rdf:about="http://www.w3.org/2004/02/skos/core#Concept"> - <rdfs:label xml:lang="en">Concept</rdfs:label> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Acquaintance --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Acquaintance"> - <rdfs:label xml:lang="en">Acquaintance</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Address --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Address"> - <rdfs:label xml:lang="en">Address</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#country"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#country"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#locality"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#locality"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#postalCode"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#postalCode"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#region"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#region"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#streetAddress"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#streetAddress"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Addressing"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the components of the delivery address for the vCard object</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Addressing --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Addressing"> - <rdfs:label xml:lang="en">Addressing</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:unionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These types are concerned with information related to the delivery addressing or label for the vCard object</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Agent --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Agent"> - <rdfs:label xml:lang="en">Agent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Calendar --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Calendar"> - <rdfs:label xml:lang="en">Calendar</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#CalendarBusy --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#CalendarBusy"> - <rdfs:label xml:lang="en">Calendar Busy</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarBusy"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarBusy"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Calendar"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the URI for the busy time associated with the object that the vCard represents. -Was called FBURI in vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#CalendarLink --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#CalendarLink"> - <rdfs:label xml:lang="en">Calendar Link</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarLink"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarLink"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Calendar"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the URI for a calendar associated with the object represented by the vCard. -Was called CALURI in vCard.</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#CalendarRequest --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#CalendarRequest"> - <rdfs:label xml:lang="en">Calendar Request</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarRequest"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#calendarRequest"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Calendar"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the calendar user address [RFC5545] to which a scheduling request [RFC5546] should be sent for the object represented by the vCard. -Was called CALADRURI in vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Category --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Category"> - <rdfs:label xml:lang="en">Category</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#category"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#category"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Explanatory"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify application category information about the vCard, also known as tags. This was called CATEGORIES in vCard.</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Cell --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Cell"> - <rdfs:label xml:lang="en">Cell</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Also called mobile telephone</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Child --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Child"> - <rdfs:label xml:lang="en">Child</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Code --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Code"> - <rdfs:label xml:lang="en">Code</rdfs:label> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains all the Code related Classes that are used to indicate vCard Types</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Colleague --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Colleague"> - <rdfs:label xml:lang="en">Colleague</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Communication --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Communication"> - <rdfs:label xml:lang="en">Communication</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:unionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These properties describe information about how to communicate with the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Contact --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Contact"> - <rdfs:label xml:lang="en">Contact</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Coresident --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Coresident"> - <rdfs:label xml:lang="en">Coresident</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Coworker --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Coworker"> - <rdfs:label xml:lang="en">Coworker</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Crush --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Crush"> - <rdfs:label xml:lang="en">Crush</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Date --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Date"> - <rdfs:label xml:lang="en">Date</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Email --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Email"> - <rdfs:label xml:lang="en">Email</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#email"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#email"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Communication"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the electronic mail address for communication with the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Emergency --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Emergency"> - <rdfs:label xml:lang="en">Emergency</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Explanatory --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Explanatory"> - <rdfs:label xml:lang="en">Explanatory</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:unionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These properties are concerned with additional explanations, such as that related to informational notes or revisions specific to the vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Fax --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Fax"> - <rdfs:label xml:lang="en">Fax</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Female --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Female"> - <rdfs:label xml:lang="en">Female</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Gender"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#FormattedName --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#FormattedName"> - <rdfs:label xml:lang="en">Formatted Name</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#formattedName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#formattedName"/> - <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Identification"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Specifies the formatted text corresponding to the name of the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Friend --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Friend"> - <rdfs:label xml:lang="en">Friend</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Gender --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Gender"> - <rdfs:label xml:lang="en">Gender</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Code"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Geo --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Geo"> - <rdfs:label xml:lang="en">Geo</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Geographical"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used to indicate global positioning information that is specific to an address</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Geographical --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Geographical"> - <rdfs:label xml:lang="en">Geographical</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These properties are concerned with information associated with geographical positions or regions associated with the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Group --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Group"> - <rdfs:label xml:lang="en">Group</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasMember"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Kind"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasMember"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Kind"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Defines all the properties required to be a Group of Individuals or Organizations</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Home --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Home"> - <rdfs:label xml:lang="en">Home</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Type"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This implies that the property is related to an individual's personal life</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Identification --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Identification"> - <rdfs:label xml:lang="en">Identification</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:unionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:unionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These types are used to capture information associated with the identification and naming of the entity associated with the vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Individual --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Individual"> - <rdfs:label xml:lang="en">Individual</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Name"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasName"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#anniversary"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#anniversary"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#birthdate"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#birthdate"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#gender"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#gender"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Kind"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Defines all the properties required to be an Individual</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#InstantMessage --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#InstantMessage"> - <rdfs:label xml:lang="en">Messaging</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#instantMessage"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#instantMessage"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Communication"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the URI for instant messaging and presence protocol communications with the object the vCard represents. -Was called IMPP in vCard.</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Key --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Key"> - <rdfs:label xml:lang="en">Key</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#key"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#key"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Security"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Kin --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Kin"> - <rdfs:label xml:lang="en">Kin</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Kind --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Kind"> - <rdfs:label xml:lang="en">VCard Kind</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasAddress"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Address"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasAddress"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasEmail"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Email"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasEmail"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasFormattedName"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#FormattedName"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasFormattedName"/> - <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasNickname"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Nickname"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasNickname"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasTelephone"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Telephone"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasTelephone"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasTitle"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Title"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasTitle"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasURL"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#URL"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#hasURL"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/ARG_2000379"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The parent class for all vCard Objects</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Language --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Language"> - <rdfs:label xml:lang="en">Language</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:cardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:cardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Communication"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the language(s) that may be used for contacting the entity associated with the vCard.</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Location --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Location"> - <rdfs:label xml:lang="en">Location</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Kind"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Defines all the properties required to be a Location</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Logo --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Logo"> - <rdfs:label xml:lang="en">Logo</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#logo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#logo"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Organizational"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify a graphic image of a logo associated with the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Male --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Male"> - <rdfs:label xml:lang="en">Male</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Gender"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Me --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Me"> - <rdfs:label xml:lang="en">Me</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Met --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Met"> - <rdfs:label xml:lang="en">Met</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Muse --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Muse"> - <rdfs:label xml:lang="en">Muse</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Name --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Name"> - <rdfs:label xml:lang="en">Name</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#additionalName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#additionalName"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#familyName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#familyName"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#givenName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#givenName"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#honorificPrefix"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#honorificPrefix"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#honorificSuffix"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#honorificSuffix"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Identification"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Specifies the components of the name of the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Neighbor --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Neighbor"> - <rdfs:label xml:lang="en">Neighbor</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Nickname --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Nickname"> - <rdfs:label xml:lang="en">Nickname</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#nickName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#nickName"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Identification"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Specifies the text corresponding to the nickname of the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#None --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#None"> - <rdfs:label xml:lang="en">None</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Gender"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Note --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Note"> - <rdfs:label xml:lang="en">Note</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#note"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#note"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Explanatory"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify supplemental information or a comment that is associated with the vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Organization --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Organization"> - <rdfs:label xml:lang="en">Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Kind"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Defines all the properties required to be an Organization</rdfs:comment> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the organizational name associated with the vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#OrganizationName --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#OrganizationName"> - <rdfs:label xml:lang="en">Organization Name</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#organizationName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#organizationName"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Organizational"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#OrganizationUnitName --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#OrganizationUnitName"> - <rdfs:label xml:lang="en">Organizational Unit Name</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#organizationalUnitName"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#organizationalUnitName"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#OrganizationName"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Organizational --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Organizational"> - <rdfs:label xml:lang="en">Organizational</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#language"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">These properties are concerned with information associated with characteristics of the organization or organizational units of the object that the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Other --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Other"> - <rdfs:label xml:lang="en">Other</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Gender"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Pager --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Pager"> - <rdfs:label xml:lang="en">Pager</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Parent --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Parent"> - <rdfs:label xml:lang="en">Parent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Photo --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Photo"> - <rdfs:label xml:lang="en">Photo</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#photo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#photo"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Identification"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Specifies an image or photograph information that annotates some aspect of the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Related --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Related"> - <rdfs:label xml:lang="en">Related</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#related"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#related"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Organizational"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify a relationship between another entity and the entity represented by this vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#RelatedType --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#RelatedType"> - <rdfs:label xml:lang="en">Relation Type</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Code"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Role --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Role"/> - - - - <!-- http://www.w3.org/2006/vcard/ns#Security --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Security"> - <rdfs:label xml:lang="en">Security</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#geo"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sortAs"/> - <owl:maxCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Contains all the Security related Classes</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Sibling --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Sibling"> - <rdfs:label xml:lang="en">Sibling</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Sound --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Sound"> - <rdfs:label xml:lang="en">Sound</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sound"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#sound"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Explanatory"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify a digital sound content information that annotates some aspect of the vCard. This property is often used to specify the proper pronunciation of the name property value of the vCard</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Spouse --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Spouse"> - <rdfs:label xml:lang="en">Spouse</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Sweetheart --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Sweetheart"> - <rdfs:label xml:lang="en">Sweetheart</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#RelatedType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Telephone --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Telephone"> - <rdfs:label xml:lang="en">Telephone</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#telephone"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#telephone"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Communication"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#TelephoneType --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#TelephoneType"> - <rdfs:label xml:lang="en">Telephone Type</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Code"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Text --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Text"> - <rdfs:label xml:lang="en">Text</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Also called sms telephone</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#TextPhone --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#TextPhone"> - <rdfs:label xml:lang="en">Text Phone</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#TimeZone --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#TimeZone"> - <rdfs:label xml:lang="en">Time Zone</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#timeZone"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Geographical"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Used to indicate time zone information that is specific to a location or address</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Title --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Title"> - <rdfs:label xml:lang="en">Title</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#title"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#title"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Organizational"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify the position or job of the object the vCard represents</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Type --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Type"> - <rdfs:label xml:lang="en">Type</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Code"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This is called TYPE in vCard but renamed here to Context for less confusion (with types/class)</rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#URL --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#URL"> - <rdfs:label xml:lang="en">URL</rdfs:label> - <owl:equivalentClass> - <owl:Class> - <owl:intersectionOf rdf:parseType="Collection"> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#url"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#anyURI"/> - </owl:Restriction> - <owl:Restriction> - <owl:onProperty rdf:resource="http://www.w3.org/2006/vcard/ns#url"/> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </owl:Restriction> - </owl:intersectionOf> - </owl:Class> - </owl:equivalentClass> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Explanatory"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">To specify a uniform resource locator associated with the object to which the vCard refers. Examples for individuals include personal web sites, blogs, and social networking site identifiers. </rdfs:comment> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Unknown --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Unknown"> - <rdfs:label xml:lang="en">Unknown</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Gender"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Video --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Video"> - <rdfs:label xml:lang="en">Video</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Voice --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Voice"> - <rdfs:label xml:lang="en">Voice</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#TelephoneType"/> - </owl:Class> - - - - <!-- http://www.w3.org/2006/vcard/ns#Work --> - - <owl:Class rdf:about="http://www.w3.org/2006/vcard/ns#Work"> - <rdfs:label xml:lang="en">Work</rdfs:label> - <rdfs:subClassOf rdf:resource="http://www.w3.org/2006/vcard/ns#Type"/> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This implies that the property is related to an individual's work place</rdfs:comment> - </owl:Class> - - - - <!-- http://xmlns.com/foaf/0.1/Agent --> - - <owl:Class rdf:about="http://xmlns.com/foaf/0.1/Agent"> - <rdfs:label xml:lang="en">Agent</rdfs:label> - <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000004"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#featuredIn"/> - <owl:allValuesFrom rdf:resource="http://purl.obolibrary.org/obo/IAO_0000030"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#freetextKeyword"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#relatedBy"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Relationship"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"></obo:IAO_0000118> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Agents are things that do stuff</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An agent</rdfs:comment> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Scott Hoffmann</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Things that do stuff.</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">agent</obo:IAO_0000111> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">see: http://xmlns.com/foaf/spec/#term_Agent</obo:IAO_0000112> - <skos:scopeNote xml:lang="en">Used to describe any "agent" related to bibliographic items. Such agents can be persons, organizations or groups of any kind.</skos:scopeNote> - </owl:Class> - - - - <!-- http://xmlns.com/foaf/0.1/Group --> - - <owl:Class rdf:about="http://xmlns.com/foaf/0.1/Group"> - <rdfs:label xml:lang="en">Group</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"> A collection of individual agents (and may itself play the role of a Agent, ie. something that can perform actions). </obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A collection of individual agents.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A group can also be an organization but need not be; typically used for looser associations of people or organizations acting together in some fashion, not necessarily through formal agreement or on a long-term basis. Added to the VIVO ontology to be able to support informal and perhaps even private groups of people around an idea, funding opportunity, or event. - -see: http://xmlns.com/foaf/spec/#term_Group</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Scott Hoffmann</obo:IAO_0000117> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">group</obo:IAO_0000111> - </owl:Class> - - - - <!-- http://xmlns.com/foaf/0.1/Organization --> - - <owl:Class rdf:about="http://xmlns.com/foaf/0.1/Organization"> - <rdfs:label xml:lang="en">Organization</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0001025"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicLocation"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#abbreviation"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/ARG_2000028"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/> - <owl:allValuesFrom rdf:resource="http://xmlns.com/foaf/0.1/Organization"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#dateTimeInterval"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#DateTimeInterval"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"></obo:IAO_0000118> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A generic class encompassing several types of organizations.</obo:IAO_0000115> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A kind of Agent corresponding to social instititutions such as companies, societies etc.</obo:IAO_0000115> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An organization</rdfs:comment> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">Only use if no specific subclasses of foaf:organization desribe the organization.</obo:IAO_0000112> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Scott Hoffmann</obo:IAO_0000117> - <obo:IAO_0000112 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">This class will display all the instances in the subclasses below it, as well as any organizations that were added as part of this generic class because there wasn't a specific class available.</obo:IAO_0000112> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">organization</obo:IAO_0000111> - <skos:scopeNote xml:lang="en">Ued to describe an organization related to bibliographic items such as a publishing company, etc.</skos:scopeNote> - </owl:Class> - - - - <!-- http://xmlns.com/foaf/0.1/Person --> - - <owl:Class rdf:about="http://xmlns.com/foaf/0.1/Person"> - <rdfs:label xml:lang="en">Person</rdfs:label> - <rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Agent"/> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/ARG_2000028"/> - <owl:someValuesFrom rdf:resource="http://www.w3.org/2006/vcard/ns#Individual"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#freetextKeyword"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2001/XMLSchema#string"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#eligibleFor"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#Credential"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#hasResearchArea"/> - <owl:allValuesFrom rdf:resource="http://www.w3.org/2002/07/owl#Thing"/> - </owl:Restriction> - </rdfs:subClassOf> - <rdfs:subClassOf> - <owl:Restriction> - <owl:onProperty rdf:resource="http://vivoweb.org/ontology/core#geographicFocus"/> - <owl:allValuesFrom rdf:resource="http://vivoweb.org/ontology/core#GeographicRegion"/> - </owl:Restriction> - </rdfs:subClassOf> - <obo:IAO_0000118 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"></obo:IAO_0000118> - <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string">A person</rdfs:comment> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">An instance of a human being (Homo sapiens)</obo:IAO_0000115> - <obo:IAO_0000117 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">PERSON: Melissa Haendel</obo:IAO_0000117> - <obo:IAO_0000115 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">The most general classification of a person</obo:IAO_0000115> - <obo:IAO_0000111 rdf:datatype="http://www.w3.org/2001/XMLSchema#string">person</obo:IAO_0000111> - </owl:Class> - - - - <rdf:Description> - <owl:minCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minCardinality> - </rdf:Description> - -</rdf:RDF> - - - -<!-- Generated by the OWL API (version 3.4.3) http://owlapi.sourceforge.net --> - diff --git a/src/main/resources/com/linkeddatahub/packages/skos/layout.xsl b/src/main/resources/com/linkeddatahub/packages/skos/layout.xsl new file mode 100644 index 000000000..bea9ee244 --- /dev/null +++ b/src/main/resources/com/linkeddatahub/packages/skos/layout.xsl @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE xsl:stylesheet [ + <!ENTITY ldh "https://w3id.org/atomgraph/linkeddatahub#"> + <!ENTITY ac "https://w3id.org/atomgraph/client#"> + <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#"> + <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#"> + <!ENTITY skos "http://www.w3.org/2004/02/skos/core#"> + <!ENTITY srx "http://www.w3.org/2005/sparql-results#"> + <!ENTITY foaf "http://xmlns.com/foaf/0.1/"> +]> +<xsl:stylesheet version="2.0" +xmlns="http://www.w3.org/1999/xhtml" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +xmlns:xhtml="http://www.w3.org/1999/xhtml" +xmlns:xs="http://www.w3.org/2001/XMLSchema" +xmlns:ldh="&ldh;" +xmlns:ac="∾" +xmlns:rdf="&rdf;" +xmlns:rdfs="&rdfs;" +xmlns:xsd="&xsd;" +xmlns:skos="&skos;" +xmlns:srx="&srx;" +xmlns:foaf="&foaf;" +xmlns:bs2="http://graphity.org/xsl/bootstrap/2.3.2" +exclude-result-prefixes="#all"> + + <xsl:param name="ldh:base" as="xs:anyURI" static="yes"/> + + <xsl:import _href="{resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl', $ldh:base)}"/> + + <xsl:param name="foaf:Agent" as="document-node()?"/> + + <xsl:template match="rdf:RDF | srx:sparql" mode="xhtml:Style"> + <xsl:param name="load-wymeditor" select="exists($foaf:Agent//@rdf:about)" as="xs:boolean"/> + <xsl:param name="load-yasqe" select="true()" as="xs:boolean"/> + + <xsl:apply-imports/> + + <!-- inject custom Bootstrap theme that overrides the default one --> + <link href="{resolve-uri('static/com/linkeddatahub/demo/skos/css/bootstrap.css', $ac:contextUri)}" rel="stylesheet" type="text/css"/> + <!-- re-apply LinkedDataHub's Bootstrap customizations --> + <link href="{resolve-uri('static/com/atomgraph/linkeddatahub/css/bootstrap.css', $ac:contextUri)}" rel="stylesheet" type="text/css"/> + + <xsl:if test="$load-wymeditor"> + <link href="{resolve-uri('static/com/atomgraph/linkeddatahub/js/wymeditor/skins/default/skin.css', $ac:contextUri)}" rel="stylesheet" type="text/css"/> + </xsl:if> + <xsl:if test="$load-yasqe"> + <link href="{resolve-uri('static/css/yasqe.css', $ac:contextUri)}" rel="stylesheet" type="text/css"/> + </xsl:if> + </xsl:template> + + <xsl:template match="rdf:RDF" mode="xhtml:Style"> + <xsl:next-match/> + + <link href="{resolve-uri('static/com/linkeddatahub/demo/skos/css/bootstrap.css', $ac:contextUri)}" rel="stylesheet" type="text/css"/> + </xsl:template> + + <xsl:template match="skos:narrower | skos:broader | skos:related | skos:member" mode="bs2:PropertyList"/> + +</xsl:stylesheet> \ No newline at end of file diff --git a/src/main/resources/com/linkeddatahub/packages/skos/ns.ttl b/src/main/resources/com/linkeddatahub/packages/skos/ns.ttl new file mode 100644 index 000000000..e97dbd5b3 --- /dev/null +++ b/src/main/resources/com/linkeddatahub/packages/skos/ns.ttl @@ -0,0 +1,186 @@ +@prefix : <#> . +@prefix ldh: <https://w3id.org/atomgraph/linkeddatahub#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix sp: <http://spinrdf.org/sp#> . +@prefix spin: <http://spinrdf.org/spin#> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix skos: <http://www.w3.org/2004/02/skos/core#> . + +: a owl:Ontology ; + owl:imports <http://www.w3.org/2004/02/skos/core> ; + rdfs:label "SKOS package ontology". + +# Concept + +skos:Concept spin:constructor :ConceptConstructor ; + spin:constraint :MissingPrefLabel ; + ldh:template :NarrowerConcepts . + +:ConceptConstructor a ldh:Constructor ; + rdfs:label "Concept constructor" ; + sp:text """ + PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> + + CONSTRUCT { + $this skos:prefLabel [ a xsd:string ] ; + skos:altLabel [ a xsd:string ] ; + skos:definition [ a xsd:string ] ; + skos:broader [ a skos:Concept ] ; + skos:narrower [ a skos:Concept ] ; + skos:related [ a skos:Concept ] ; + skos:inScheme [ a skos:ConceptScheme ] . + } + WHERE {}""" ; + rdfs:isDefinedBy : . + +# narrower + +:NarrowerConcepts a ldh:View ; + dct:title "Narrower concepts" ; + spin:query :SelectNarrowerConcepts ; + rdfs:isDefinedBy : . + +:SelectNarrowerConcepts a sp:Select ; + rdfs:label "Select narrower concepts" ; + sp:text """ +PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + +SELECT DISTINCT ?narrower +WHERE + { GRAPH ?graph + { $about skos:narrower ?narrower . + GRAPH ?narrowerGraph + { + ?narrower skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy : . + +# broader + +skos:Concept ldh:template :BroaderConcepts. + +:BroaderConcepts a ldh:View ; + dct:title "Broader concepts" ; + spin:query :SelectBroaderConcepts ; + rdfs:isDefinedBy : . + +:SelectBroaderConcepts a sp:Select ; + rdfs:label "Select broader concepts" ; + sp:text """ +PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + +SELECT DISTINCT ?broader +WHERE + { GRAPH ?graph + { $about skos:broader ?broader . + GRAPH ?broaderGraph + { + ?broader skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy : . + +# Collection + +skos:Collection spin:constructor :CollectionConstructor ; + spin:constraint :MissingPrefLabel ; + ldh:template :CollectionMembers. + +:CollectionConstructor a ldh:Constructor ; + rdfs:label "Collection constructor" ; + sp:text """ + PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> + + CONSTRUCT { + $this skos:prefLabel [ a xsd:string ] ; + skos:definition [ a xsd:string ] ; + skos:member [ a skos:Concept ] . + } + WHERE {}""" ; + rdfs:isDefinedBy : . + +:CollectionMembers a ldh:View ; + dct:title "Collection members" ; + spin:query :SelectCollectionMembers ; + rdfs:isDefinedBy : . + +:SelectCollectionMembers a sp:Select ; + rdfs:label "Select collection members" ; + sp:text """ +PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + +SELECT DISTINCT ?member +WHERE + { GRAPH ?graph + { $about skos:member ?member . + GRAPH ?memberGraph + { + ?member skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy : . + +# ConceptScheme + +skos:ConceptScheme spin:constructor :ConceptSchemeConstructor ; + ldh:template :ConceptsInScheme. + +:ConceptSchemeConstructor a ldh:Constructor ; + rdfs:label "Concept scheme constructor" ; + sp:text """ + PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> + PREFIX dct: <http://purl.org/dc/terms/> + + CONSTRUCT { + $this dct:title [ a xsd:string ] ; + dct:description [ a xsd:string ] ; + skos:hasTopConcept [ a skos:Concept ] . + } + WHERE {}""" ; + rdfs:isDefinedBy : . + +:ConceptsInScheme a ldh:View ; + dct:title "Concepts in scheme" ; + spin:query :SelectConceptsInScheme ; + rdfs:isDefinedBy : . + +:SelectConceptsInScheme a sp:Select ; + rdfs:label "Select concepts in scheme" ; + sp:text """ +PREFIX skos: <http://www.w3.org/2004/02/skos/core#> + +SELECT DISTINCT ?concept +WHERE + { GRAPH ?graph + { ?concept skos:inScheme $about ; + skos:prefLabel ?prefLabel . + FILTER (langMatches(lang(?prefLabel), "en")) + } + } +ORDER BY ?prefLabel +""" ; + rdfs:isDefinedBy : . + +# Constraints + +:MissingPrefLabel a ldh:MissingPropertyValue ; + rdfs:label "Missing skos:prefLabel" ; + sp:arg1 skos:prefLabel ; + rdfs:isDefinedBy : . diff --git a/src/main/resources/com/linkeddatahub/packages/skos/package.ttl b/src/main/resources/com/linkeddatahub/packages/skos/package.ttl new file mode 100644 index 000000000..b906f9619 --- /dev/null +++ b/src/main/resources/com/linkeddatahub/packages/skos/package.ttl @@ -0,0 +1,20 @@ +@base <https://packages.linkeddatahub.com/skos/> . +@prefix : <#> . +@prefix lapp: <https://w3id.org/atomgraph/linkeddatahub/apps#> . +@prefix ldt: <https://www.w3.org/ns/ldt#> . +@prefix ac: <https://w3id.org/atomgraph/client#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . + +<https://packages.linkeddatahub.com/skos/#this> a lapp:Package ; + rdfs:label "SKOS Package" ; + dct:title "SKOS Package for LinkedDataHub" ; + dct:description "Provides SKOS (Simple Knowledge Organization System) vocabulary support with custom templates for concept hierarchies, schemes, and collections." ; + dct:creator <https://atomgraph.com/#company> ; + ldt:ontology <https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#> ; + ac:stylesheet <https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/layout.xsl> . + +<https://atomgraph.com/#company> a foaf:Organization ; + foaf:name "AtomGraph" ; + foaf:homepage <https://atomgraph.com> . diff --git a/src/main/resources/location-mapping.ttl b/src/main/resources/location-mapping.ttl index 6db880201..91856575c 100644 --- a/src/main/resources/location-mapping.ttl +++ b/src/main/resources/location-mapping.ttl @@ -16,5 +16,7 @@ [ lm:name "http://spinrdf.org/spin#" ; lm:altName "etc/spin.ttl" ] , [ lm:name "http://spinrdf.org/spin" ; lm:altName "etc/spin.ttl" ] , [ lm:name "http://spinrdf.org/spl#" ; lm:altName "etc/spl.spin.ttl" ] , - [ lm:name "http://spinrdf.org/spl" ; lm:altName "etc/spl.spin.ttl" ] + [ lm:name "http://spinrdf.org/spl" ; lm:altName "etc/spl.spin.ttl" ] , + [ lm:name "https://packages.linkeddatahub.com/skos/" ; lm:altName "com/linkeddatahub/packages/skos/package.ttl" ] , + [ lm:name "https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl" ; lm:altName "com/linkeddatahub/packages/skos/ns.ttl" ] . \ No newline at end of file diff --git a/src/main/resources/prefix-mapping.ttl b/src/main/resources/prefix-mapping.ttl index d82a1f554..872c5b932 100644 --- a/src/main/resources/prefix-mapping.ttl +++ b/src/main/resources/prefix-mapping.ttl @@ -17,7 +17,6 @@ [ lm:name "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#" ; lm:altName "com/atomgraph/linkeddatahub/nie.rdf" ] , [ lm:name "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#" ; lm:altName "com/atomgraph/linkeddatahub/nfo.rdf" ] , [ lm:name "http://purl.org/dc/dcmitype/" ; lm:altName "com/atomgraph/linkeddatahub/dcmitype.rdf" ] , - [ lm:name "http://vivoweb.org/ontology/core#" ; lm:altName "com/atomgraph/linkeddatahub/vivo.owl" ] , [ lm:name "https://www.w3.org/ns/ldt#" ; lm:altName "com/atomgraph/linkeddatahub/ldt.ttl" ] , [ lm:name "https://www.w3.org/ns/ldt/document-hierarchy#" ; lm:altName "com/atomgraph/linkeddatahub/dh.ttl" ] , [ lm:name "http://www.w3.org/2011/http#" ; lm:altName "com/atomgraph/linkeddatahub/http.owl" ] , @@ -53,7 +52,6 @@ [ lm:prefix "http://www.semanticdesktop.org/ontologies/2007/01/19/nie" ; lm:altName "com/atomgraph/linkeddatahub/nie.rdf" ] , [ lm:prefix "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo" ; lm:altName "com/atomgraph/linkeddatahub/nfo.rdf" ] , [ lm:prefix "http://purl.org/dc/dcmitype/" ; lm:altName "com/atomgraph/linkeddatahub/dcmitype.rdf" ] , - [ lm:prefix "http://vivoweb.org/ontology/core" ; lm:altName "com/atomgraph/linkeddatahub/vivo.owl" ] , [ lm:prefix "https://www.w3.org/ns/ldt" ; lm:altName "com/atomgraph/linkeddatahub/ldt.ttl" ] , [ lm:prefix "https://www.w3.org/ns/ldt/core/domain" ; lm:altName "com/atomgraph/linkeddatahub/c.ttl" ] , [ lm:prefix "https://www.w3.org/ns/ldt/document-hierarchy" ; lm:altName "com/atomgraph/linkeddatahub/dh.ttl" ] , @@ -73,5 +71,7 @@ [ lm:prefix "http://purl.org/goodrelations/v1" ; lm:altName "com/atomgraph/client/goodrelations.owl" ] , [ lm:prefix "http://spinrdf.org/sp" ; lm:altName "etc/sp.ttl" ] , [ lm:prefix "http://spinrdf.org/spin" ; lm:altName "etc/spin.ttl" ] , - [ lm:prefix "http://spinrdf.org/spl" ; lm:altName "etc/spl.spin.ttl" ] + [ lm:prefix "http://spinrdf.org/spl" ; lm:altName "etc/spl.spin.ttl" ] , + [ lm:prefix "https://packages.linkeddatahub.com/skos/" ; lm:altName "com/linkeddatahub/packages/skos/package.ttl" ] , + [ lm:prefix "https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl" ; lm:altName "com/linkeddatahub/packages/skos/ns.ttl" ] . \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index a31768cc5..aed16f1f7 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -143,7 +143,7 @@ WHERE } } # only namespace, signup, OAuth2 login and WebID profiles can be public in admin app, nothing else - FILTER ( $this IN (uri(concat(str($base), "ns")), uri(concat(str($base), "sign%20up")), uri(concat(str($base), "transform"))) || strstarts(str($this), concat(str($base), "acl/agents/")) || strstarts(str($this), concat(str($base), "acl/public-keys/"))) + FILTER ( $this IN (uri(concat(str($base), "ns")), uri(concat(str($base), "sign%20up"))) || strstarts(str($this), concat(str($base), "acl/agents/")) || strstarts(str($this), concat(str($base), "acl/public-keys/"))) } } diff --git a/src/main/webapp/static/xsl/admin/layout.xsl b/src/main/webapp/static/xsl/admin/layout.xsl new file mode 100644 index 000000000..2527026ad --- /dev/null +++ b/src/main/webapp/static/xsl/admin/layout.xsl @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="3.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + exclude-result-prefixes="xs"> + + <!-- System admin stylesheet (lowest priority) --> + <xsl:import href="../../com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl"/> + + <!-- Package stylesheets will be added here by InstallPackage endpoint --> + +</xsl:stylesheet> diff --git a/src/main/webapp/static/xsl/layout.xsl b/src/main/webapp/static/xsl/layout.xsl new file mode 100644 index 000000000..ceb6d2b13 --- /dev/null +++ b/src/main/webapp/static/xsl/layout.xsl @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="3.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + exclude-result-prefixes="xs"> + + <!-- System stylesheet (lowest priority) --> + <xsl:import href="../com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl"/> + + <!-- Package stylesheets will be added here by InstallPackage endpoint --> + +</xsl:stylesheet> From d0bb33b69f35262d673f14edded8b096896f9566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 14:28:26 +0100 Subject: [PATCH 13/64] Remove volumes in the GH action --- .github/workflows/http-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/http-tests.yml b/.github/workflows/http-tests.yml index c79fa6804..22e9740bd 100644 --- a/.github/workflows/http-tests.yml +++ b/.github/workflows/http-tests.yml @@ -49,7 +49,7 @@ jobs: run: ./run.sh "$PWD/ssl/owner/cert.pem" "${{ secrets.HTTP_TEST_OWNER_CERT_PASSWORD }}" "$PWD/ssl/secretary/cert.pem" "${{ secrets.HTTP_TEST_SECRETARY_CERT_PASSWORD }}" shell: bash working-directory: http-tests - - name: Stop Docker containers - run: docker compose --env-file ./http-tests/.env down + - name: Stop Docker containers and remove volumes + run: docker compose --env-file ./http-tests/.env down -v - name: Remove Docker containers run: docker compose --env-file ./http-tests/.env rm -f From 6cb0532635ee3c50655ccfec736ac9f0e28854cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 17:11:35 +0100 Subject: [PATCH 14/64] Test changes --- .../admin/packages/install-package-stylesheet.sh | 2 +- .../packages/install-uninstall-package-stylesheet.sh | 10 +++++----- .../admin/packages/uninstall-package-stylesheet.sh | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index d79a3401c..be38f5a31 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -21,7 +21,7 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ - "$END_USER_BASE_URL"static/com/linkeddatahub/packages/skos/layout.xsl + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" # verify master stylesheet was regenerated and includes package import curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index be547bdc2..f0066071f 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -16,7 +16,7 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "$ADMIN_BASE_URL"packages/install \ + "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" # verify package stylesheet was installed (should return 200) @@ -33,16 +33,16 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "$ADMIN_BASE_URL"packages/uninstall \ + "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# verify package stylesheet was deleted (should return 404) +# verify package stylesheet was deleted (should return 403) curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ -| grep -q "$STATUS_NOT_FOUND" +| grep -q "$STATUS_FORBIDDEN" # verify master stylesheet no longer includes package -master_xsl=$(curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl) +master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then exit 1 fi diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh index 67ced2c8a..523b63cf8 100755 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -32,13 +32,13 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# verify package stylesheet was deleted (should return 404) +# verify package stylesheet was deleted (should return 403) curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ -| grep -q "$STATUS_NOT_FOUND" +| grep -q "$STATUS_FORBIDDEN" # verify master stylesheet was regenerated without package import -master_xsl=$(curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl) +master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then exit 1 fi From 978e174f239ab75d177d44b81c39dc3179dd0cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 18:52:57 +0100 Subject: [PATCH 15/64] Banning stylesheet URLs when uninstalling package Test fixes --- .../install-uninstall-package-stylesheet.sh | 10 +++- .../packages/uninstall-package-stylesheet.sh | 10 +++- .../resource/admin/pkg/UninstallPackage.java | 56 ++++++++++++++++++- .../server/util/XSLTMasterUpdater.java | 8 ++- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index f0066071f..768dcfd70 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -36,10 +36,16 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# verify package stylesheet was deleted (should return 403) +# Wait for Tomcat's static resource cache to expire +# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) +# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes +default_ttl=5 +sleep $default_ttl + +# verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ -| grep -q "$STATUS_FORBIDDEN" +| grep -q "$STATUS_NOT_FOUND" # verify master stylesheet no longer includes package master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh index 523b63cf8..048b7017c 100755 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -32,10 +32,16 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# verify package stylesheet was deleted (should return 403) +# Wait for Tomcat's static resource cache to expire +# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) +# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes +default_ttl=5 +sleep $default_ttl + +# verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ -| grep -q "$STATUS_FORBIDDEN" +| grep -q "$STATUS_NOT_FOUND" # verify master stylesheet was regenerated without package import master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index f4ada8c98..c0a32f4f5 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -21,6 +21,7 @@ import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; +import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.UriPath; import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; @@ -43,6 +44,7 @@ import org.apache.jena.update.UpdateFactory; import org.apache.jena.update.UpdateRequest; import org.apache.jena.util.FileManager; +import org.glassfish.jersey.uri.UriComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -248,10 +250,11 @@ private void uninstallOntology(EndUserApplication app, String packageURI) throws } /** - * Deletes stylesheet from /static/<package-path>/ + * Deletes stylesheet from <samp>/static/<package-path>/</samp> */ private void uninstallStylesheet(String packagePath) throws IOException { + EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); Path staticDir = Paths.get(getServletContext().getRealPath("/static")); Path packageDir = staticDir.resolve(packagePath); @@ -263,6 +266,14 @@ private void uninstallStylesheet(String packagePath) throws IOException { Files.delete(stylesheetFile); if (log.isDebugEnabled()) log.debug("Deleted package stylesheet: {}", stylesheetFile); + + // Purge stylesheet from frontend proxy cache + String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; + if (endUserApp.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); + ban(endUserApp.getFrontendProxy(), stylesheetURL, false); + } } // Delete directory if empty @@ -296,10 +307,18 @@ private void regenerateMasterStylesheet(EndUserApplication app, String removedPa // Regenerate master stylesheet XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); updater.regenerateMasterStylesheet(packagePaths); + + // Purge master stylesheet from cache + if (app.getFrontendProxy() != null) + { + String masterStylesheetURL = "/static/xsl/layout.xsl"; + if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", masterStylesheetURL); + ban(app.getFrontendProxy(), masterStylesheetURL, false); + } } /** - * Removes ldh:import triple from the end-user application resource. + * Removes <samp>ldh:import</samp> triple from the end-user application resource. */ // private void removeImportFromApplication(EndUserApplication app, String packageURI) // { @@ -370,6 +389,39 @@ private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String package } } + + public void ban(Resource proxy, String url) + { + ban(proxy, url, true); + } + + /** + * Bans URL from the backend proxy cache. + * + * @param proxy proxy server URL + * @param url banned URL + * @param urlEncode if true, the banned URL value will be URL-encoded + */ + public void ban(Resource proxy, String url, boolean urlEncode) + { + if (url == null) throw new IllegalArgumentException("Resource cannot be null"); + + // Extract path from URL - Varnish req.url only contains the path, not the full URL + URI uri = URI.create(url); + String path = uri.getPath(); + if (uri.getQuery() != null) path += "?" + uri.getQuery(); + + final String urlValue = urlEncode ? UriComponent.encode(path, UriComponent.Type.UNRESERVED) : path; + + try (Response cr = getSystem().getClient().target(proxy.getURI()). + request(). + header(CacheInvalidationFilter.HEADER_NAME, urlValue). + method("BAN", Response.class)) + { + // Response automatically closed by try-with-resources + } + } + /** * Returns the system application. * diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java index 72a043b57..6ba4ffcf4 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java @@ -39,7 +39,7 @@ /** * Updates master XSLT stylesheets with package import chains. - * Writes master stylesheets to the webapp's /static/ directory. + * Writes master stylesheets to the webapp's <samp>/static/</samp> directory. * * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ @@ -70,10 +70,14 @@ public XSLTMasterUpdater(ServletContext servletContext) * @throws IOException if file operations fail */ public void regenerateMasterStylesheet(List<String> packagePaths) throws IOException + { + regenerateMasterStylesheet(getStaticPath(), packagePaths); + } + + public void regenerateMasterStylesheet(Path staticDir, List<String> packagePaths) throws IOException { try { - Path staticDir = getStaticPath(); Path xslDir = staticDir.resolve("xsl"); Path masterFile = xslDir.resolve("layout.xsl"); From 0081255069c00a7a58a613804b4a1c6201aefd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 19:14:33 +0100 Subject: [PATCH 16/64] Test fix --- .../admin/packages/install-uninstall-package-ontology.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/http-tests/admin/packages/install-uninstall-package-ontology.sh b/http-tests/admin/packages/install-uninstall-package-ontology.sh index 47d1e2b19..30a3edfb5 100755 --- a/http-tests/admin/packages/install-uninstall-package-ontology.sh +++ b/http-tests/admin/packages/install-uninstall-package-ontology.sh @@ -29,8 +29,10 @@ curl -k -s \ # verify package ontology document exists package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) -curl -k -f -s -o /dev/null \ - "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" \ +| grep -qE "^($STATUS_OK|$STATUS_NOT_MODIFIED)$" # uninstall package curl -k -w "%{http_code}\n" -o /dev/null -f -s \ @@ -49,5 +51,6 @@ fi # verify package ontology document was deleted curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" \ | grep -q "$STATUS_FORBIDDEN" From 4b8feb7fb8af0d3d13d2e996c1b81f881e6699d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 20:03:53 +0100 Subject: [PATCH 17/64] Refactored install/uninstall endpoints --- .../resource/admin/pkg/InstallPackage.java | 14 +- .../resource/admin/pkg/UninstallPackage.java | 149 ++++++++---------- 2 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 1cca2ff2c..3d1e3c292 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -16,6 +16,7 @@ */ package com.atomgraph.linkeddatahub.resource.admin.pkg; +import static com.atomgraph.client.MediaType.TEXT_XSL; import com.atomgraph.client.util.DataManager; import com.atomgraph.linkeddatahub.apps.model.AdminApplication; import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; @@ -127,8 +128,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); if (log.isInfoEnabled()) log.info("Installing package: {}", packageURI); - - // 1. Fetch package com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); if (pkg == null) { @@ -139,7 +138,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" Resource ontology = pkg.getOntology(); Resource stylesheet = pkg.getStylesheet(); - // either ontology or stylesheet need to be specified, or both if (ontology == null && stylesheet == null) { if (log.isErrorEnabled()) log.error("Package ontology and stylesheet are both unspecified for package: {}", packageURI); @@ -150,7 +148,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" { String packagePath = UriPath.convert(packageURI); - // 2. Download and install ontology if present if (ontology != null) { if (log.isDebugEnabled()) log.debug("Downloading package ontology from: {}", ontology.getURI()); @@ -158,20 +155,18 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" installOntology(endUserApp, ontologyModel, ontology.getURI()); } - // 3. Download and install stylesheet if present if (stylesheet != null) { URI stylesheetURI = URI.create(stylesheet.getURI()); if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); String stylesheetContent = downloadStylesheet(stylesheetURI); - installStylesheet(packagePath, stylesheetContent); + installStylesheet(Paths.get(getServletContext().getRealPath("/static")), packagePath, stylesheetContent); // 4. Regenerate master stylesheet regenerateMasterStylesheet(endUserApp, packagePath); } - // 5. Add ldh:import triple to application (in system.trig) //addImportToApplication(endUserApp, packageURI); if (log.isInfoEnabled()) log.info("Successfully installed package: {}", packageURI); @@ -257,7 +252,7 @@ private String downloadStylesheet(URI uri) throws IOException WebTarget target = getClient().target(uri); // Prioritize text/xsl (q=1.0), then any text/* (q=0.8) - try (Response response = target.request("text/xsl", "text/*;q=0.8").get()) + try (Response response = target.request(TEXT_XSL, "text/*;q=0.8").get()) { if (!response.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) { @@ -350,9 +345,8 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String /** * Installs stylesheet to /static/<package-path>/layout.xsl */ - private void installStylesheet(String packagePath, String stylesheetContent) throws IOException + private void installStylesheet(Path staticDir, String packagePath, String stylesheetContent) throws IOException { - Path staticDir = Paths.get(getServletContext().getRealPath("/static")); Path packageDir = staticDir.resolve(packagePath); Files.createDirectories(packageDir); diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index c0a32f4f5..0db684104 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -25,6 +25,7 @@ import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.UriPath; import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; +import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; import jakarta.inject.Inject; import jakarta.servlet.ServletContext; import jakarta.ws.rs.BadRequestException; @@ -60,6 +61,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import org.apache.jena.ontology.ConversionException; /** * JAX-RS resource that uninstalls a LinkedDataHub package. @@ -77,6 +79,8 @@ public class UninstallPackage { private static final Logger log = LoggerFactory.getLogger(UninstallPackage.class); + public final String MASTER_STYLESHEET_URL = "/static/xsl/layout.xsl"; + private final com.atomgraph.linkeddatahub.apps.model.Application application; private final com.atomgraph.linkeddatahub.Application system; private final DataManager dataManager; @@ -128,23 +132,36 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (log.isInfoEnabled()) log.info("Uninstalling package: {}", packageURI); - String packagePath = UriPath.convert(packageURI); + com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); + if (pkg == null) + { + if (log.isErrorEnabled()) log.error("Loading package failed: {}", packageURI); + throw new WebApplicationException("Loading package failed", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity + } - // 1. Remove package ontology and owl:imports from namespace graph - uninstallOntology(endUserApp, packageURI); + Resource ontology = pkg.getOntology(); + Resource stylesheet = pkg.getStylesheet(); - // 2. Delete stylesheet from /static/<package-path>/ - uninstallStylesheet(packagePath); + // either ontology or stylesheet need to be specified, or both + if (ontology == null && stylesheet == null) + { + if (log.isErrorEnabled()) log.error("Package ontology and stylesheet are both unspecified for package: {}", packageURI); + throw new WebApplicationException("Package ontology and stylesheet are both unspecified", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity + } + + if (ontology != null) uninstallOntology(endUserApp, ontology.getURI()); - // 3. Regenerate master stylesheet - regenerateMasterStylesheet(endUserApp, packagePath); + if (stylesheet != null) + { + String packagePath = UriPath.convert(packageURI); + uninstallStylesheet(Paths.get(getServletContext().getRealPath("/static")), packagePath, endUserApp); + regenerateMasterStylesheet(endUserApp, packagePath); + } - // 4. Remove ldh:import triple from application //removeImportFromApplication(endUserApp, packageURI); if (log.isInfoEnabled()) log.info("Successfully uninstalled package: {}", packageURI); - // Redirect back to referer or application base URI redirectURI = (referer != null) ? referer : endUserApp.getBaseURI(); return Response.seeOther(redirectURI).build(); } @@ -159,31 +176,13 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" * Uninstalls ontology by deleting the package ontology document and removing owl:imports from namespace graph. * * @param app the end-user application - * @param packageURI the package URI + * @param packageOntologyURI the package ONTOLOGY URI * @throws IOException if uninstallation fails */ - private void uninstallOntology(EndUserApplication app, String packageURI) throws IOException + private void uninstallOntology(EndUserApplication app, String packageOntologyURI) throws IOException { AdminApplication adminApp = app.getAdminApplication(); - // 1. Fetch package to get ontology URI - com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); - if (pkg == null) - { - if (log.isWarnEnabled()) log.warn("Package not found, skipping ontology uninstallation: {}", packageURI); - return; - } - - Resource ontology = pkg.getOntology(); - if (ontology == null) - { - if (log.isWarnEnabled()) log.warn("Package ontology not specified, skipping ontology uninstallation"); - return; - } - - String packageOntologyURI = ontology.getURI(); - - // 2. Calculate hash of package ontology URI String hash; try { @@ -252,36 +251,28 @@ private void uninstallOntology(EndUserApplication app, String packageURI) throws /** * Deletes stylesheet from <samp>/static/<package-path>/</samp> */ - private void uninstallStylesheet(String packagePath) throws IOException + private void uninstallStylesheet(Path staticDir, String packagePath, EndUserApplication endUserApp) throws IOException { - EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); - Path staticDir = Paths.get(getServletContext().getRealPath("/static")); Path packageDir = staticDir.resolve(packagePath); - if (Files.exists(packageDir)) + // Delete layout.xsl + Path stylesheetFile = packageDir.resolve("layout.xsl"); + Files.delete(stylesheetFile); + if (log.isDebugEnabled()) log.debug("Deleted package stylesheet: {}", stylesheetFile); + + // Purge stylesheet from frontend proxy cache + String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; + if (endUserApp.getFrontendProxy() != null) { - // Delete layout.xsl - Path stylesheetFile = packageDir.resolve("layout.xsl"); - if (Files.exists(stylesheetFile)) - { - Files.delete(stylesheetFile); - if (log.isDebugEnabled()) log.debug("Deleted package stylesheet: {}", stylesheetFile); - - // Purge stylesheet from frontend proxy cache - String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; - if (endUserApp.getFrontendProxy() != null) - { - if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); - ban(endUserApp.getFrontendProxy(), stylesheetURL, false); - } - } + if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); + ban(endUserApp.getFrontendProxy(), stylesheetURL, false); + } - // Delete directory if empty - if (Files.list(packageDir).count() == 0) - { - Files.delete(packageDir); - if (log.isDebugEnabled()) log.debug("Deleted package directory: {}", packageDir); - } + // Delete directory if empty + if (Files.list(packageDir).count() == 0) + { + Files.delete(packageDir); + if (log.isDebugEnabled()) log.debug("Deleted package directory: {}", packageDir); } } @@ -298,10 +289,7 @@ private void regenerateMasterStylesheet(EndUserApplication app, String removedPa { String pkgPath = UriPath.convert(pkg.getURI()); // Exclude the package being removed - if (!pkgPath.equals(removedPackagePath)) - { - packagePaths.add(pkgPath); - } + if (!pkgPath.equals(removedPackagePath)) packagePaths.add(pkgPath); } // Regenerate master stylesheet @@ -311,9 +299,8 @@ private void regenerateMasterStylesheet(EndUserApplication app, String removedPa // Purge master stylesheet from cache if (app.getFrontendProxy() != null) { - String masterStylesheetURL = "/static/xsl/layout.xsl"; - if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", masterStylesheetURL); - ban(app.getFrontendProxy(), masterStylesheetURL, false); + if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", MASTER_STYLESHEET_URL); + ban(app.getFrontendProxy(), MASTER_STYLESHEET_URL, false); } } @@ -362,35 +349,33 @@ private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String package { if (log.isDebugEnabled()) log.debug("Loading package from: {}", packageURI); - try - { - final Model model; + final Model model; - // check if we have the model in the cache first and if yes, return it from there instead making an HTTP request - if (((FileManager)getDataManager()).hasCachedModel(packageURI) || - (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file - { - if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI)); - if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI)); - model = getDataManager().loadModel(packageURI); - } - else - { - GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); - model = gsc.getModel(packageURI); - } + // check if we have the model in the cache first and if yes, return it from there instead making an HTTP request + if (((FileManager)getDataManager()).hasCachedModel(packageURI) || + (getDataManager().isResolvingMapped() && getDataManager().isMapped(packageURI))) // read mapped URIs (such as system ontologies) from a file + { + if (log.isDebugEnabled()) log.debug("hasCachedModel({}): {}", packageURI, ((FileManager)getDataManager()).hasCachedModel(packageURI)); + if (log.isDebugEnabled()) log.debug("isMapped({}): {}", packageURI, getDataManager().isMapped(packageURI)); + model = getDataManager().loadModel(packageURI); + } + else + { + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + model = gsc.getModel(packageURI); + } + try + { return model.getResource(packageURI).as(com.atomgraph.linkeddatahub.apps.model.Package.class); } - catch (Exception e) + catch (ConversionException ex) { - if (log.isWarnEnabled()) log.warn("Failed to load package: {}", packageURI, e); return null; } } - - public void ban(Resource proxy, String url) + protected void ban(Resource proxy, String url) { ban(proxy, url, true); } @@ -402,7 +387,7 @@ public void ban(Resource proxy, String url) * @param url banned URL * @param urlEncode if true, the banned URL value will be URL-encoded */ - public void ban(Resource proxy, String url, boolean urlEncode) + protected void ban(Resource proxy, String url, boolean urlEncode) { if (url == null) throw new IllegalArgumentException("Resource cannot be null"); From d4081095901c488521158d3675bca9f3042afd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 20:16:13 +0100 Subject: [PATCH 18/64] Debug output --- .../packages/install-package-stylesheet.sh | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index be38f5a31..1daa5bd18 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -euo pipefail +echo "### STEP 1: Initializing datasets" initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" purge_cache "$END_USER_VARNISH_SERVICE" @@ -11,18 +12,35 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" package_uri="https://packages.linkeddatahub.com/skos/#this" # install package via POST to packages/install endpoint -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ +echo "### STEP 2: Installing package" +install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ -| grep -q "$STATUS_SEE_OTHER" + "${ADMIN_BASE_URL}packages/install") +echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" +echo "$install_status" | grep -q "$STATUS_SEE_OTHER" # verify package stylesheet was installed (should return 200) -curl -k -f -s -o /dev/null \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" +echo "### STEP 3: Verifying package stylesheet exists" +stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") +echo "Stylesheet status: $stylesheet_status (expected: 200)" +if [ "$stylesheet_status" != "200" ]; then + echo "ERROR: Expected 200, got $stylesheet_status" + exit 1 +fi # verify master stylesheet was regenerated and includes package import -curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ - | grep -q "com/linkeddatahub/packages/skos/layout.xsl" +echo "### STEP 4: Verifying master stylesheet includes package" +master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") +if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then + echo "OK: Master stylesheet contains SKOS import" +else + echo "ERROR: Master stylesheet does not contain SKOS import" + echo "Master stylesheet content:" + echo "$master_xsl" + exit 1 +fi +echo "All checks passed" From a6e2b57f79b9d2509e948811e52c860c86a8a497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 20:54:43 +0100 Subject: [PATCH 19/64] Test debug output --- .../packages/install-package-stylesheet.sh | 3 ++ http-tests/run.sh | 34 +++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 1daa5bd18..f9f891a7f 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -22,6 +22,9 @@ install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -f -s \ echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" +echo "### STEP 2.5: Verifying stylesheet file exists" +docker-compose exec linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos + # verify package stylesheet was installed (should return 200) echo "### STEP 3: Verifying package stylesheet exists" stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ diff --git a/http-tests/run.sh b/http-tests/run.sh index 49e8ca193..c26246015 100755 --- a/http-tests/run.sh +++ b/http-tests/run.sh @@ -138,24 +138,24 @@ download_dataset "$ADMIN_ENDPOINT_URL" > "$TMP_ADMIN_DATASET" ### Other tests ### -run_tests $(find ./add/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./admin/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./dataspaces/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./access/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./imports/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./document-hierarchy/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./misc/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./proxy/ -type f -name '*.sh') -(( error_count += $? )) -run_tests $(find ./sparql-protocol/ -type f -name '*.sh') +#run_tests $(find ./add/ -type f -name '*.sh') +#(( error_count += $? )) +run_tests $(find ./admin/packages -type f -name 'install-package-stylesheet.sh') (( error_count += $? )) +#run_tests $(find ./dataspaces/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./access/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./imports/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./document-hierarchy/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./misc/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./proxy/ -type f -name '*.sh') +#(( error_count += $? )) +#run_tests $(find ./sparql-protocol/ -type f -name '*.sh') +#(( error_count += $? )) end_time=$(date +%s) runtime=$((end_time-start_time)) From 1c36be1059603055e6b1de863e87fb1bb816f656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 21:01:38 +0100 Subject: [PATCH 20/64] Fixed Docker command --- http-tests/admin/packages/install-package-stylesheet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index f9f891a7f..f2e3057ab 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -23,7 +23,7 @@ echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" echo "### STEP 2.5: Verifying stylesheet file exists" -docker-compose exec linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos +docker compose exec linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos # verify package stylesheet was installed (should return 200) echo "### STEP 3: Verifying package stylesheet exists" From 736a9a717e5deb570e15484d50fb817e160a4555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 21:17:19 +0100 Subject: [PATCH 21/64] Test debug output --- http-tests/admin/packages/install-package-stylesheet.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index f2e3057ab..8160267a3 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -22,8 +22,11 @@ install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -f -s \ echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" -echo "### STEP 2.5: Verifying stylesheet file exists" -docker compose exec linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos +# Verify stylesheet file exists in Tomcat's webapps directory +docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos + +# Make internal request from nginx to Tomcat to warm up static file cache +docker compose exec -T nginx curl -s -o /dev/null http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl # verify package stylesheet was installed (should return 200) echo "### STEP 3: Verifying package stylesheet exists" From bd637a33059a67609bcb03a003a80c4c9416654d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 21:50:09 +0100 Subject: [PATCH 22/64] curl call change --- http-tests/admin/packages/install-package-stylesheet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 8160267a3..f446935e5 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -26,7 +26,7 @@ echo "$install_status" | grep -q "$STATUS_SEE_OTHER" docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos # Make internal request from nginx to Tomcat to warm up static file cache -docker compose exec -T nginx curl -s -o /dev/null http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl +docker compose exec -T nginx curl -s http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl # verify package stylesheet was installed (should return 200) echo "### STEP 3: Verifying package stylesheet exists" From 1f84753482b79ac1169af9d4cf5c3a6a7fc198e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 22:02:13 +0100 Subject: [PATCH 23/64] Debug output --- http-tests/admin/packages/install-package-stylesheet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index f446935e5..ccbbaa73c 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -23,7 +23,7 @@ echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" # Verify stylesheet file exists in Tomcat's webapps directory -docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos +# docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos # Make internal request from nginx to Tomcat to warm up static file cache docker compose exec -T nginx curl -s http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl From 39cf8498579046ecdf2a3515598970294cc6318e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 3 Jan 2026 22:19:27 +0100 Subject: [PATCH 24/64] Debug output --- .../packages/install-package-stylesheet.sh | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index ccbbaa73c..2c2df3d0c 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -1,6 +1,15 @@ #!/usr/bin/env bash set -euo pipefail +# Helper to get millisecond timestamp +get_ms() { + if [[ "$OSTYPE" == "darwin"* ]]; then + python3 -c 'import time; print(int(time.time() * 1000))' + else + date +%s%3N + fi +} + echo "### STEP 1: Initializing datasets" initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" @@ -13,26 +22,33 @@ package_uri="https://packages.linkeddatahub.com/skos/#this" # install package via POST to packages/install endpoint echo "### STEP 2: Installing package" +t1=$(get_ms) install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ "${ADMIN_BASE_URL}packages/install") -echo "Install status: $install_status (expected: $STATUS_SEE_OTHER)" +t2=$(get_ms) +echo "Install status: $install_status (expected: $STATUS_SEE_OTHER) [took $((t2-t1))ms]" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" # Verify stylesheet file exists in Tomcat's webapps directory # docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos # Make internal request from nginx to Tomcat to warm up static file cache -docker compose exec -T nginx curl -s http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl +t3=$(get_ms) +docker compose exec -T nginx curl -s -o /dev/null http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl +t4=$(get_ms) +echo "Internal request took $((t4-t3))ms" # verify package stylesheet was installed (should return 200) -echo "### STEP 3: Verifying package stylesheet exists" +echo "### STEP 3: Verifying package stylesheet exists (delay since install: $((t4-t2))ms)" +t5=$(get_ms) stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") -echo "Stylesheet status: $stylesheet_status (expected: 200)" +t6=$(get_ms) +echo "Stylesheet status: $stylesheet_status (expected: 200) [took $((t6-t5))ms]" if [ "$stylesheet_status" != "200" ]; then echo "ERROR: Expected 200, got $stylesheet_status" exit 1 From 4a90c859d9f91476a889be424a49856191425cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:08:36 +0100 Subject: [PATCH 25/64] Debug output --- .../packages/install-package-stylesheet.sh | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 2c2df3d0c..75533fa05 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -33,6 +33,29 @@ t2=$(get_ms) echo "Install status: $install_status (expected: $STATUS_SEE_OTHER) [took $((t2-t1))ms]" echo "$install_status" | grep -q "$STATUS_SEE_OTHER" +# Wait for package installation to complete (poll for stylesheet availability) +echo "### Waiting for package installation to complete" +max_wait=30 # maximum seconds to wait +wait_interval=0.5 # check every 0.5 seconds +elapsed=0 +stylesheet_status="" + +while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do + stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + if [ "$stylesheet_status" = "200" ]; then + echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" + break + fi + sleep $wait_interval + elapsed=$(echo "$elapsed + $wait_interval" | bc) +done + +if [ "$stylesheet_status" != "200" ]; then + echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" + exit 1 +fi + # Verify stylesheet file exists in Tomcat's webapps directory # docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos From a449edd559e9e62be7e7b43d4473d078a2f118a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:21:23 +0100 Subject: [PATCH 26/64] Wait loops --- .../install-uninstall-package-stylesheet.sh | 48 +++++++++++++++++-- .../packages/uninstall-package-stylesheet.sh | 48 +++++++++++++++++-- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index 768dcfd70..2b8fd1e52 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -19,6 +19,28 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" +# Wait for package installation to complete (poll for stylesheet availability) +max_wait=30 # maximum seconds to wait +wait_interval=0.5 # check every 0.5 seconds +elapsed=0 +stylesheet_status="" + +while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do + stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + if [ "$stylesheet_status" = "200" ]; then + echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" + break + fi + sleep $wait_interval + elapsed=$(echo "$elapsed + $wait_interval" | bc) +done + +if [ "$stylesheet_status" != "200" ]; then + echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" + exit 1 +fi + # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" @@ -36,11 +58,27 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for Tomcat's static resource cache to expire -# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) -# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes -default_ttl=5 -sleep $default_ttl +# Wait for package uninstallation to complete (poll for stylesheet removal) +max_wait=30 # maximum seconds to wait +wait_interval=0.5 # check every 0.5 seconds +elapsed=0 +stylesheet_status="" + +while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do + stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + if [ "$stylesheet_status" = "404" ]; then + echo "Package stylesheet removed after ${elapsed}s (status: $stylesheet_status)" + break + fi + sleep $wait_interval + elapsed=$(echo "$elapsed + $wait_interval" | bc) +done + +if [ "$stylesheet_status" != "404" ]; then + echo "ERROR: Package stylesheet not removed after ${elapsed}s (status: $stylesheet_status)" + exit 1 +fi # verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh index 048b7017c..bc2b0c9a3 100755 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -19,6 +19,28 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" +# Wait for package installation to complete (poll for stylesheet availability) +max_wait=30 # maximum seconds to wait +wait_interval=0.5 # check every 0.5 seconds +elapsed=0 +stylesheet_status="" + +while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do + stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + if [ "$stylesheet_status" = "200" ]; then + echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" + break + fi + sleep $wait_interval + elapsed=$(echo "$elapsed + $wait_interval" | bc) +done + +if [ "$stylesheet_status" != "200" ]; then + echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" + exit 1 +fi + # verify package stylesheet exists before uninstall (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" @@ -32,11 +54,27 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for Tomcat's static resource cache to expire -# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) -# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes -default_ttl=5 -sleep $default_ttl +# Wait for package uninstallation to complete (poll for stylesheet removal) +max_wait=30 # maximum seconds to wait +wait_interval=0.5 # check every 0.5 seconds +elapsed=0 +stylesheet_status="" + +while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do + stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + if [ "$stylesheet_status" = "404" ]; then + echo "Package stylesheet removed after ${elapsed}s (status: $stylesheet_status)" + break + fi + sleep $wait_interval + elapsed=$(echo "$elapsed + $wait_interval" | bc) +done + +if [ "$stylesheet_status" != "404" ]; then + echo "ERROR: Package stylesheet not removed after ${elapsed}s (status: $stylesheet_status)" + exit 1 +fi # verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ From 80ccb52f19326ca0d6c71ccd9db11b04fa381083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:25:47 +0100 Subject: [PATCH 27/64] Test filter --- http-tests/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-tests/run.sh b/http-tests/run.sh index c26246015..6ce78622c 100755 --- a/http-tests/run.sh +++ b/http-tests/run.sh @@ -140,7 +140,7 @@ download_dataset "$ADMIN_ENDPOINT_URL" > "$TMP_ADMIN_DATASET" #run_tests $(find ./add/ -type f -name '*.sh') #(( error_count += $? )) -run_tests $(find ./admin/packages -type f -name 'install-package-stylesheet.sh') +run_tests $(find ./admin/packages -type f -name '*.sh') (( error_count += $? )) #run_tests $(find ./dataspaces/ -type f -name '*.sh') #(( error_count += $? )) From 8fb2597c2d6061d95010783c2857026e533d33e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:39:47 +0100 Subject: [PATCH 28/64] Revert "Wait loops" This reverts commit a449edd559e9e62be7e7b43d4473d078a2f118a1. --- .../install-uninstall-package-stylesheet.sh | 48 ++----------------- .../packages/uninstall-package-stylesheet.sh | 48 ++----------------- 2 files changed, 10 insertions(+), 86 deletions(-) diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index 2b8fd1e52..768dcfd70 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -19,28 +19,6 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for package installation to complete (poll for stylesheet availability) -max_wait=30 # maximum seconds to wait -wait_interval=0.5 # check every 0.5 seconds -elapsed=0 -stylesheet_status="" - -while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do - stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") - if [ "$stylesheet_status" = "200" ]; then - echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" - break - fi - sleep $wait_interval - elapsed=$(echo "$elapsed + $wait_interval" | bc) -done - -if [ "$stylesheet_status" != "200" ]; then - echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" - exit 1 -fi - # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" @@ -58,27 +36,11 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for package uninstallation to complete (poll for stylesheet removal) -max_wait=30 # maximum seconds to wait -wait_interval=0.5 # check every 0.5 seconds -elapsed=0 -stylesheet_status="" - -while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do - stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") - if [ "$stylesheet_status" = "404" ]; then - echo "Package stylesheet removed after ${elapsed}s (status: $stylesheet_status)" - break - fi - sleep $wait_interval - elapsed=$(echo "$elapsed + $wait_interval" | bc) -done - -if [ "$stylesheet_status" != "404" ]; then - echo "ERROR: Package stylesheet not removed after ${elapsed}s (status: $stylesheet_status)" - exit 1 -fi +# Wait for Tomcat's static resource cache to expire +# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) +# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes +default_ttl=5 +sleep $default_ttl # verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh index bc2b0c9a3..048b7017c 100755 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -19,28 +19,6 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for package installation to complete (poll for stylesheet availability) -max_wait=30 # maximum seconds to wait -wait_interval=0.5 # check every 0.5 seconds -elapsed=0 -stylesheet_status="" - -while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do - stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") - if [ "$stylesheet_status" = "200" ]; then - echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" - break - fi - sleep $wait_interval - elapsed=$(echo "$elapsed + $wait_interval" | bc) -done - -if [ "$stylesheet_status" != "200" ]; then - echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" - exit 1 -fi - # verify package stylesheet exists before uninstall (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" @@ -54,27 +32,11 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" -# Wait for package uninstallation to complete (poll for stylesheet removal) -max_wait=30 # maximum seconds to wait -wait_interval=0.5 # check every 0.5 seconds -elapsed=0 -stylesheet_status="" - -while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do - stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") - if [ "$stylesheet_status" = "404" ]; then - echo "Package stylesheet removed after ${elapsed}s (status: $stylesheet_status)" - break - fi - sleep $wait_interval - elapsed=$(echo "$elapsed + $wait_interval" | bc) -done - -if [ "$stylesheet_status" != "404" ]; then - echo "ERROR: Package stylesheet not removed after ${elapsed}s (status: $stylesheet_status)" - exit 1 -fi +# Wait for Tomcat's static resource cache to expire +# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) +# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes +default_ttl=5 +sleep $default_ttl # verify package stylesheet was deleted (should return 404) curl -k -w "%{http_code}\n" -o /dev/null -s \ From 5dffefad8fd4c2820341a4e48f3053055302ea58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:47:15 +0100 Subject: [PATCH 29/64] Test fixes --- .../packages/install-package-stylesheet.sh | 71 +++---------------- .../install-uninstall-package-ontology.sh | 4 +- .../install-uninstall-package-stylesheet.sh | 2 +- 3 files changed, 12 insertions(+), 65 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 75533fa05..5fbfe08ae 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -1,16 +1,6 @@ #!/usr/bin/env bash set -euo pipefail -# Helper to get millisecond timestamp -get_ms() { - if [[ "$OSTYPE" == "darwin"* ]]; then - python3 -c 'import time; print(int(time.time() * 1000))' - else - date +%s%3N - fi -} - -echo "### STEP 1: Initializing datasets" initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" purge_cache "$END_USER_VARNISH_SERVICE" @@ -21,71 +11,28 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" package_uri="https://packages.linkeddatahub.com/skos/#this" # install package via POST to packages/install endpoint -echo "### STEP 2: Installing package" -t1=$(get_ms) -install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -f -s \ +curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install") -t2=$(get_ms) -echo "Install status: $install_status (expected: $STATUS_SEE_OTHER) [took $((t2-t1))ms]" -echo "$install_status" | grep -q "$STATUS_SEE_OTHER" + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_SEE_OTHER" # Wait for package installation to complete (poll for stylesheet availability) -echo "### Waiting for package installation to complete" -max_wait=30 # maximum seconds to wait -wait_interval=0.5 # check every 0.5 seconds -elapsed=0 -stylesheet_status="" - -while [ $(echo "$elapsed < $max_wait" | bc) -eq 1 ]; do +while true; do stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") if [ "$stylesheet_status" = "200" ]; then - echo "Package stylesheet available after ${elapsed}s (status: $stylesheet_status)" break fi - sleep $wait_interval - elapsed=$(echo "$elapsed + $wait_interval" | bc) + sleep 0.5 done -if [ "$stylesheet_status" != "200" ]; then - echo "ERROR: Package stylesheet not available after ${elapsed}s (status: $stylesheet_status)" - exit 1 -fi - -# Verify stylesheet file exists in Tomcat's webapps directory -# docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos - -# Make internal request from nginx to Tomcat to warm up static file cache -t3=$(get_ms) -docker compose exec -T nginx curl -s -o /dev/null http://linkeddatahub:7070/static/com/linkeddatahub/packages/skos/layout.xsl -t4=$(get_ms) -echo "Internal request took $((t4-t3))ms" - # verify package stylesheet was installed (should return 200) -echo "### STEP 3: Verifying package stylesheet exists (delay since install: $((t4-t2))ms)" -t5=$(get_ms) -stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") -t6=$(get_ms) -echo "Stylesheet status: $stylesheet_status (expected: 200) [took $((t6-t5))ms]" -if [ "$stylesheet_status" != "200" ]; then - echo "ERROR: Expected 200, got $stylesheet_status" - exit 1 -fi +curl -k -f -s -o /dev/null \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" # verify master stylesheet was regenerated and includes package import -echo "### STEP 4: Verifying master stylesheet includes package" -master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") -if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then - echo "OK: Master stylesheet contains SKOS import" -else - echo "ERROR: Master stylesheet does not contain SKOS import" - echo "Master stylesheet content:" - echo "$master_xsl" - exit 1 -fi -echo "All checks passed" +curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ + | grep -q "com/linkeddatahub/packages/skos/layout.xsl" diff --git a/http-tests/admin/packages/install-uninstall-package-ontology.sh b/http-tests/admin/packages/install-uninstall-package-ontology.sh index 30a3edfb5..f3562227d 100755 --- a/http-tests/admin/packages/install-uninstall-package-ontology.sh +++ b/http-tests/admin/packages/install-uninstall-package-ontology.sh @@ -18,7 +18,7 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "$ADMIN_BASE_URL"packages/install \ + "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was added @@ -40,7 +40,7 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "package-uri=$package_uri" \ - "$ADMIN_BASE_URL"packages/uninstall \ + "${ADMIN_BASE_URL}packages/uninstall" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was removed diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index 768dcfd70..834fc7234 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -24,7 +24,7 @@ curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" # verify master stylesheet includes package -curl -k -s "$END_USER_BASE_URL"static/xsl/layout.xsl \ +curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ | grep -q "com/linkeddatahub/packages/skos/layout.xsl" # uninstall package From 69333d5f276b894e20fd0745c51c9d3353f877d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 11:48:29 +0100 Subject: [PATCH 30/64] `regenerateMasterStylesheet` refactoring --- .../resource/admin/pkg/UninstallPackage.java | 1 - .../linkeddatahub/server/util/XSLTMasterUpdater.java | 9 +++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index 0db684104..9af8a3a3d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -48,7 +48,6 @@ import org.glassfish.jersey.uri.UriComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.net.URI; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java index 6ba4ffcf4..7f076aedf 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/XSLTMasterUpdater.java @@ -71,16 +71,13 @@ public XSLTMasterUpdater(ServletContext servletContext) */ public void regenerateMasterStylesheet(List<String> packagePaths) throws IOException { - regenerateMasterStylesheet(getStaticPath(), packagePaths); + regenerateMasterStylesheet(getStaticPath().resolve("xsl").resolve("layout.xsl"), packagePaths); // TO-DO: move to configuration } - public void regenerateMasterStylesheet(Path staticDir, List<String> packagePaths) throws IOException + public void regenerateMasterStylesheet(Path masterFile, List<String> packagePaths) throws IOException { try { - Path xslDir = staticDir.resolve("xsl"); - Path masterFile = xslDir.resolve("layout.xsl"); - // Create fresh XML document DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); @@ -123,7 +120,7 @@ public void regenerateMasterStylesheet(Path staticDir, List<String> packagePaths stylesheet.appendChild(doc.createTextNode("\n\n")); // Write to file - Files.createDirectories(xslDir); + Files.createDirectories(masterFile.getParent()); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); From b7e6b6403686e4d58c3d1f4b4b2959391e2063cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 12:16:25 +0100 Subject: [PATCH 31/64] Test fix --- http-tests/admin/packages/install-package-stylesheet.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 5fbfe08ae..103438d4a 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -20,15 +20,21 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ | grep -q "$STATUS_SEE_OTHER" # Wait for package installation to complete (poll for stylesheet availability) -while true; do +elapsed=0 +while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") if [ "$stylesheet_status" = "200" ]; then break fi sleep 0.5 + elapsed=$(echo "$elapsed + 0.5" | bc) done +if [ "$stylesheet_status" != "200" ]; then + exit 1 +fi + # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" From 8ab25d998428620147b4fa88b32bc8b766afd570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 16:53:09 +0100 Subject: [PATCH 32/64] Debug output --- http-tests/admin/packages/install-package-stylesheet.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 103438d4a..82e8212fc 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -20,6 +20,8 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ | grep -q "$STATUS_SEE_OTHER" # Wait for package installation to complete (poll for stylesheet availability) +echo "--- Initial logs after install request ---" +docker compose logs --tail=50 linkeddatahub elapsed=0 while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ @@ -27,11 +29,15 @@ while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do if [ "$stylesheet_status" = "200" ]; then break fi + echo "--- Waiting for stylesheet (${elapsed}s, status: $stylesheet_status) ---" + docker compose logs --tail=50 linkeddatahub sleep 0.5 elapsed=$(echo "$elapsed + 0.5" | bc) done if [ "$stylesheet_status" != "200" ]; then + echo "--- Final logs after timeout ---" + docker compose logs --tail=50 linkeddatahub exit 1 fi From 52fe095980da6a3023efae60057183c38e9163c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 17:05:20 +0100 Subject: [PATCH 33/64] Debug output --- .../admin/packages/install-package-stylesheet.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 82e8212fc..d5cb31387 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -20,8 +20,6 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ | grep -q "$STATUS_SEE_OTHER" # Wait for package installation to complete (poll for stylesheet availability) -echo "--- Initial logs after install request ---" -docker compose logs --tail=50 linkeddatahub elapsed=0 while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ @@ -29,15 +27,15 @@ while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do if [ "$stylesheet_status" = "200" ]; then break fi - echo "--- Waiting for stylesheet (${elapsed}s, status: $stylesheet_status) ---" - docker compose logs --tail=50 linkeddatahub + echo "--- Waiting for stylesheet (${elapsed}s, HTTP status: $stylesheet_status) ---" + docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos || echo "Directory does not exist" sleep 0.5 elapsed=$(echo "$elapsed + 0.5" | bc) done if [ "$stylesheet_status" != "200" ]; then - echo "--- Final logs after timeout ---" - docker compose logs --tail=50 linkeddatahub + echo "--- Final check after timeout ---" + docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos || echo "Directory does not exist" exit 1 fi From 3295cdbc1e06146acf2704de82cbd6b2b1974f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 4 Jan 2026 17:18:15 +0100 Subject: [PATCH 34/64] Debug Varnish cache --- http-tests/admin/packages/install-package-stylesheet.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index d5cb31387..d5d830de0 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -19,6 +19,11 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" +# Purge cache after install to clear any cached 404 responses +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + # Wait for package installation to complete (poll for stylesheet availability) elapsed=0 while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do From e815e8140dde3402e4ab48b985a46f9e774bbeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 12:53:10 +0100 Subject: [PATCH 35/64] Debug output --- .../packages/install-package-stylesheet.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index d5d830de0..d8b275420 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -27,13 +27,25 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" # Wait for package installation to complete (poll for stylesheet availability) elapsed=0 while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do - stylesheet_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + # Get status and headers via proxy in one request + proxy_response=$(curl -k -s -I "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") + stylesheet_status=$(echo "$proxy_response" | head -1 | grep -oE '[0-9]{3}') + if [ "$stylesheet_status" = "200" ]; then break fi - echo "--- Waiting for stylesheet (${elapsed}s, HTTP status: $stylesheet_status) ---" + + echo "--- Waiting for stylesheet (${elapsed}s) ---" + echo "Via proxy: HTTP $stylesheet_status" + echo "$proxy_response" | grep -E "(Age|X-Cache|X-Varnish)" || echo "(no cache headers)" + + # Check file on disk docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos || echo "Directory does not exist" + + # Test direct access to Tomcat (bypasses Varnish/Nginx cache) + internal_status=$(docker compose exec -T nginx curl -s -w "%{http_code}\n" -o /dev/null http://linkeddatahub:8080/static/com/linkeddatahub/packages/skos/layout.xsl) + echo "Direct Tomcat: HTTP $internal_status" + sleep 0.5 elapsed=$(echo "$elapsed + 0.5" | bc) done From 34a132fc1ce19a55c913e50aa0d611c7c856d075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 13:21:27 +0100 Subject: [PATCH 36/64] Debug output --- http-tests/admin/packages/install-package-stylesheet.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index d8b275420..72c17437b 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -26,12 +26,16 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" # Wait for package installation to complete (poll for stylesheet availability) elapsed=0 +iteration=0 while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do # Get status and headers via proxy in one request proxy_response=$(curl -k -s -I "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") stylesheet_status=$(echo "$proxy_response" | head -1 | grep -oE '[0-9]{3}') - if [ "$stylesheet_status" = "200" ]; then + iteration=$((iteration + 1)) + + # Only break on success after at least 2 iterations (to see Age > 0) + if [ "$stylesheet_status" = "200" ] && [ $iteration -ge 2 ]; then break fi From b875af429c50804611815082e79e3f963d5ab2a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 14:37:57 +0100 Subject: [PATCH 37/64] Purge stylesheet from Varnish during installation --- .../atomgraph/linkeddatahub/Application.java | 36 ++++++++- .../linkeddatahub/apps/model/Package.java | 10 +++ .../apps/model/impl/PackageImpl.java | 41 ++++++++++ .../resource/admin/pkg/InstallPackage.java | 63 +++++++++------ .../resource/admin/pkg/UninstallPackage.java | 72 +++++------------- .../linkeddatahub/server/util/UriPath.java | 76 ------------------- 6 files changed, 147 insertions(+), 151 deletions(-) delete mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index bafcc2ef5..e28066e34 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -194,6 +194,7 @@ import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.core.Response; import java.util.concurrent.ConcurrentHashMap; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; @@ -241,6 +242,7 @@ import org.glassfish.jersey.process.internal.RequestScoped; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.server.filter.HttpMethodOverrideFilter; +import org.glassfish.jersey.uri.UriComponent; import org.xml.sax.SAXException; /** @@ -252,9 +254,11 @@ */ public class Application extends ResourceConfig { - + private static final Logger log = LoggerFactory.getLogger(Application.class); + public static final String MASTER_STYLESHEET_PATH = "/static/xsl/layout.xsl"; + private final ExecutorService importThreadPool; private final ServletConfig servletConfig; private final EventBus eventBus = new EventBus(); @@ -1747,7 +1751,7 @@ public Client getClient() /** * Returns the external HTTP client. * It is used by the Linked Data browser to avoid sharing the connection pool with the system client. - * + * * @return client object */ public Client getExternalClient() @@ -1755,6 +1759,34 @@ public Client getExternalClient() return externalClient; } + /** + * Bans URL from the proxy cache. + * + * @param proxy proxy server resource + * @param url banned URL + * @param urlEncode if true, the banned URL value will be URL-encoded + * @throws IllegalArgumentException if url is null + */ + public void ban(Resource proxy, String url, boolean urlEncode) + { + if (url == null) throw new IllegalArgumentException("URL cannot be null"); + + // Extract path from URL - Varnish req.url only contains the path, not the full URL + URI uri = URI.create(url); + String path = uri.getPath(); + if (uri.getQuery() != null) path += "?" + uri.getQuery(); + + final String urlValue = urlEncode ? UriComponent.encode(path, UriComponent.Type.UNRESERVED) : path; + + try (Response cr = getClient().target(proxy.getURI()). + request(). + header(CacheInvalidationFilter.HEADER_NAME, urlValue). + method("BAN", Response.class)) + { + // Response automatically closed by try-with-resources + } + } + /** * Returns the system base URI. * diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java index 4ad8b71e5..1d2d02f9b 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/Package.java @@ -51,4 +51,14 @@ public interface Package extends Resource */ java.util.Set<Resource> getImportedPackages(); + /** + * Returns the filesystem resource path for this package. + * Converts the package URI to a path by reversing hostname components. + * Example: <samp>https://packages.linkeddatahub.com/skos/#this -> com/linkeddatahub/packages/skos</samp> + * + * @return filesystem path relative to static directory + * @throws IllegalArgumentException if package URI is invalid + */ + String getStylesheetPath(); + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java index a431ee262..311a98a78 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/apps/model/impl/PackageImpl.java @@ -27,6 +27,7 @@ import org.apache.jena.rdf.model.StmtIterator; import org.apache.jena.rdf.model.impl.ResourceImpl; +import java.net.URI; import java.util.HashSet; import java.util.Set; @@ -85,4 +86,44 @@ public Set<Resource> getImportedPackages() return packages; } + @Override + public String getStylesheetPath() + { + String uri = getURI(); + if (uri == null) + throw new IllegalArgumentException("Package URI cannot be null"); + + try + { + URI uriObj = URI.create(uri); + String host = uriObj.getHost(); + String path = uriObj.getPath(); + + if (host == null) + throw new IllegalArgumentException("Package URI must have a host: " + uri); + + // Reverse hostname components: packages.linkeddatahub.com -> com/linkeddatahub/packages + String[] hostParts = host.split("\\."); + StringBuilder reversedHost = new StringBuilder(); + for (int i = hostParts.length - 1; i >= 0; i--) + { + reversedHost.append(hostParts[i]); + if (i > 0) reversedHost.append("/"); + } + + // Append path without leading/trailing slashes and fragment + if (path != null && !path.isEmpty() && !path.equals("/")) + { + String cleanPath = path.replaceAll("^/+|/+$", ""); // Remove leading/trailing slashes + return reversedHost + "/" + cleanPath; + } + + return reversedHost.toString(); + } + catch (IllegalArgumentException e) + { + throw new IllegalArgumentException("Invalid package URI: " + uri, e); + } + } + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 3d1e3c292..0a721b18c 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -23,7 +23,6 @@ import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; import com.atomgraph.linkeddatahub.server.security.AgentContext; -import com.atomgraph.linkeddatahub.server.util.UriPath; import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; import jakarta.inject.Inject; @@ -146,8 +145,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" try { - String packagePath = UriPath.convert(packageURI); - if (ontology != null) { if (log.isDebugEnabled()) log.debug("Downloading package ontology from: {}", ontology.getURI()); @@ -158,13 +155,15 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (stylesheet != null) { URI stylesheetURI = URI.create(stylesheet.getURI()); + String packagePath = pkg.getStylesheetPath(); if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); - String stylesheetContent = downloadStylesheet(stylesheetURI); - installStylesheet(Paths.get(getServletContext().getRealPath("/static")), packagePath, stylesheetContent); - + String stylesheetContent = downloadStylesheet(stylesheetURI); + + installStylesheet(Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath).resolve("layout.xsl"), packagePath, stylesheetContent, endUserApp); + // 4. Regenerate master stylesheet - regenerateMasterStylesheet(endUserApp, packagePath); + regenerateMasterStylesheet(endUserApp, pkg); } //addImportToApplication(endUserApp, packageURI); @@ -343,38 +342,58 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String } /** - * Installs stylesheet to /static/<package-path>/layout.xsl + * Installs stylesheet to <samp>/static/<package-path>/layout.xsl</samp> */ - private void installStylesheet(Path staticDir, String packagePath, String stylesheetContent) throws IOException + private void installStylesheet(Path stylesheetFile, String packagePath, String stylesheetContent, EndUserApplication endUserApp) throws IOException { - Path packageDir = staticDir.resolve(packagePath); - Files.createDirectories(packageDir); - - Path stylesheetFile = packageDir.resolve("layout.xsl"); + Files.createDirectories(stylesheetFile.getParent()); Files.writeString(stylesheetFile, stylesheetContent); if (log.isDebugEnabled()) log.debug("Installed package stylesheet at: {}", stylesheetFile); + + // Purge stylesheet from frontend proxy cache to clear any cached 404 responses + String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; + if (endUserApp.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); + getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); + } } /** * Regenerates master stylesheet for the application. + * + * @param app the application + * @param newPackage the package being installed + * @throws IOException if regeneration fails */ - private void regenerateMasterStylesheet(EndUserApplication app, String newPackagePath) throws IOException + private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.linkeddatahub.apps.model.Package newPackage) throws IOException { - // Get all currently installed packages - Set<Resource> packages = app.getImportedPackages(); + // Get all currently installed packages and convert to stylesheet paths + Set<Resource> packageResources = app.getImportedPackages(); List<String> packagePaths = new ArrayList<>(); - for (Resource pkg : packages) - packagePaths.add(UriPath.convert(pkg.getURI())); + for (Resource pkgRes : packageResources) + { + com.atomgraph.linkeddatahub.apps.model.Package pkg = pkgRes.as(com.atomgraph.linkeddatahub.apps.model.Package.class); + packagePaths.add(pkg.getStylesheetPath()); + } - // Add the new package - if (!packagePaths.contains(newPackagePath)) - packagePaths.add(newPackagePath); + // Add the new package path + String newPath = newPackage.getStylesheetPath(); + if (!packagePaths.contains(newPath)) + packagePaths.add(newPath); - // Regenerate master stylesheet + // Regenerate master stylesheet (XSLTMasterUpdater works with paths) XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); updater.regenerateMasterStylesheet(packagePaths); + + // Purge master stylesheet from cache + if (app.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); + getSystem().ban(app.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); + } } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index 9af8a3a3d..94f1b696d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -21,9 +21,7 @@ import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; -import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter; import com.atomgraph.linkeddatahub.server.security.AgentContext; -import com.atomgraph.linkeddatahub.server.util.UriPath; import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; import jakarta.inject.Inject; @@ -45,7 +43,6 @@ import org.apache.jena.update.UpdateFactory; import org.apache.jena.update.UpdateRequest; import org.apache.jena.util.FileManager; -import org.glassfish.jersey.uri.UriComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; @@ -78,8 +75,6 @@ public class UninstallPackage { private static final Logger log = LoggerFactory.getLogger(UninstallPackage.class); - public final String MASTER_STYLESHEET_URL = "/static/xsl/layout.xsl"; - private final com.atomgraph.linkeddatahub.apps.model.Application application; private final com.atomgraph.linkeddatahub.Application system; private final DataManager dataManager; @@ -111,7 +106,7 @@ public UninstallPackage(com.atomgraph.linkeddatahub.apps.model.Application appli /** * Uninstalls a package from the current dataspace. * - * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) + * @param packageURI the package URI (e.g., <samp>https://packages.linkeddatahub.com/skos/#this</samp>) * @param referer the referring URL * @return JAX-RS response */ @@ -147,14 +142,14 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (log.isErrorEnabled()) log.error("Package ontology and stylesheet are both unspecified for package: {}", packageURI); throw new WebApplicationException("Package ontology and stylesheet are both unspecified", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity } - + if (ontology != null) uninstallOntology(endUserApp, ontology.getURI()); if (stylesheet != null) { - String packagePath = UriPath.convert(packageURI); + String packagePath = pkg.getStylesheetPath(); uninstallStylesheet(Paths.get(getServletContext().getRealPath("/static")), packagePath, endUserApp); - regenerateMasterStylesheet(endUserApp, packagePath); + regenerateMasterStylesheet(endUserApp, pkg); } //removeImportFromApplication(endUserApp, packageURI); @@ -264,7 +259,7 @@ private void uninstallStylesheet(Path staticDir, String packagePath, EndUserAppl if (endUserApp.getFrontendProxy() != null) { if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); - ban(endUserApp.getFrontendProxy(), stylesheetURL, false); + getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); } // Delete directory if empty @@ -277,29 +272,36 @@ private void uninstallStylesheet(Path staticDir, String packagePath, EndUserAppl /** * Regenerates master stylesheet for the application without the uninstalled package. + * + * @param app the application + * @param removedPackage the package being uninstalled + * @throws IOException if regeneration fails */ - private void regenerateMasterStylesheet(EndUserApplication app, String removedPackagePath) throws IOException + private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.linkeddatahub.apps.model.Package removedPackage) throws IOException { - // Get all currently installed packages - Set<Resource> packages = app.getImportedPackages(); + // Get all currently installed packages and convert to stylesheet paths + Set<Resource> packageResources = app.getImportedPackages(); List<String> packagePaths = new ArrayList<>(); - for (Resource pkg : packages) + String removedPath = removedPackage.getStylesheetPath(); + for (Resource pkgRes : packageResources) { - String pkgPath = UriPath.convert(pkg.getURI()); + com.atomgraph.linkeddatahub.apps.model.Package pkg = pkgRes.as(com.atomgraph.linkeddatahub.apps.model.Package.class); + String pkgPath = pkg.getStylesheetPath(); // Exclude the package being removed - if (!pkgPath.equals(removedPackagePath)) packagePaths.add(pkgPath); + if (!pkgPath.equals(removedPath)) + packagePaths.add(pkgPath); } - // Regenerate master stylesheet + // Regenerate master stylesheet (XSLTMasterUpdater works with paths) XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); updater.regenerateMasterStylesheet(packagePaths); // Purge master stylesheet from cache if (app.getFrontendProxy() != null) { - if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", MASTER_STYLESHEET_URL); - ban(app.getFrontendProxy(), MASTER_STYLESHEET_URL, false); + if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); + getSystem().ban(app.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); } } @@ -374,38 +376,6 @@ private com.atomgraph.linkeddatahub.apps.model.Package getPackage(String package } } - protected void ban(Resource proxy, String url) - { - ban(proxy, url, true); - } - - /** - * Bans URL from the backend proxy cache. - * - * @param proxy proxy server URL - * @param url banned URL - * @param urlEncode if true, the banned URL value will be URL-encoded - */ - protected void ban(Resource proxy, String url, boolean urlEncode) - { - if (url == null) throw new IllegalArgumentException("Resource cannot be null"); - - // Extract path from URL - Varnish req.url only contains the path, not the full URL - URI uri = URI.create(url); - String path = uri.getPath(); - if (uri.getQuery() != null) path += "?" + uri.getQuery(); - - final String urlValue = urlEncode ? UriComponent.encode(path, UriComponent.Type.UNRESERVED) : path; - - try (Response cr = getSystem().getClient().target(proxy.getURI()). - request(). - header(CacheInvalidationFilter.HEADER_NAME, urlValue). - method("BAN", Response.class)) - { - // Response automatically closed by try-with-resources - } - } - /** * Returns the system application. * diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java deleted file mode 100644 index aa59c9273..000000000 --- a/src/main/java/com/atomgraph/linkeddatahub/server/util/UriPath.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.atomgraph.linkeddatahub.server.util; - -import java.net.URI; - -/** - * Utility for converting URIs to filesystem paths. - * Reverses hostname components following Java package naming conventions. - * - * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} - */ -public class UriPath -{ - - /** - * Converts a URI to a filesystem path by reversing hostname components. - * Example: https://packages.linkeddatahub.com/skos/#this -> com/linkeddatahub/packages/skos - * - * @param uri the URI string - * @return filesystem path relative to static directory - * @throws IllegalArgumentException if URI is invalid - */ - public static String convert(String uri) - { - if (uri == null) - throw new IllegalArgumentException("URI cannot be null"); - - try - { - URI uriObj = URI.create(uri); - String host = uriObj.getHost(); - String path = uriObj.getPath(); - - if (host == null) - throw new IllegalArgumentException("URI must have a host: " + uri); - - // Reverse hostname components: packages.linkeddatahub.com -> com/linkeddatahub/packages - String[] hostParts = host.split("\\."); - StringBuilder reversedHost = new StringBuilder(); - for (int i = hostParts.length - 1; i >= 0; i--) - { - reversedHost.append(hostParts[i]); - if (i > 0) reversedHost.append("/"); - } - - // Append path without leading/trailing slashes and fragment - if (path != null && !path.isEmpty() && !path.equals("/")) - { - String cleanPath = path.replaceAll("^/+|/+$", ""); // Remove leading/trailing slashes - return reversedHost + "/" + cleanPath; - } - - return reversedHost.toString(); - } - catch (IllegalArgumentException e) - { - throw new IllegalArgumentException("Invalid URI: " + uri, e); - } - } - -} From d25dbaff85d1cad8ff668478ad327e0c9139f3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 14:51:49 +0100 Subject: [PATCH 38/64] Sleep before requesting stylesheet --- .../packages/install-package-stylesheet.sh | 43 ++----------------- .../resource/admin/pkg/InstallPackage.java | 22 +++++----- 2 files changed, 14 insertions(+), 51 deletions(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 72c17437b..958eb3b63 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -19,46 +19,9 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ "${ADMIN_BASE_URL}packages/install" \ | grep -q "$STATUS_SEE_OTHER" -# Purge cache after install to clear any cached 404 responses -purge_cache "$END_USER_VARNISH_SERVICE" -purge_cache "$ADMIN_VARNISH_SERVICE" -purge_cache "$FRONTEND_VARNISH_SERVICE" - -# Wait for package installation to complete (poll for stylesheet availability) -elapsed=0 -iteration=0 -while [ $(echo "$elapsed < 30" | bc) -eq 1 ]; do - # Get status and headers via proxy in one request - proxy_response=$(curl -k -s -I "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") - stylesheet_status=$(echo "$proxy_response" | head -1 | grep -oE '[0-9]{3}') - - iteration=$((iteration + 1)) - - # Only break on success after at least 2 iterations (to see Age > 0) - if [ "$stylesheet_status" = "200" ] && [ $iteration -ge 2 ]; then - break - fi - - echo "--- Waiting for stylesheet (${elapsed}s) ---" - echo "Via proxy: HTTP $stylesheet_status" - echo "$proxy_response" | grep -E "(Age|X-Cache|X-Varnish)" || echo "(no cache headers)" - - # Check file on disk - docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos || echo "Directory does not exist" - - # Test direct access to Tomcat (bypasses Varnish/Nginx cache) - internal_status=$(docker compose exec -T nginx curl -s -w "%{http_code}\n" -o /dev/null http://linkeddatahub:8080/static/com/linkeddatahub/packages/skos/layout.xsl) - echo "Direct Tomcat: HTTP $internal_status" - - sleep 0.5 - elapsed=$(echo "$elapsed + 0.5" | bc) -done - -if [ "$stylesheet_status" != "200" ]; then - echo "--- Final check after timeout ---" - docker compose exec -T linkeddatahub ls -l webapps/ROOT/static/com/linkeddatahub/packages/skos || echo "Directory does not exist" - exit 1 -fi +# the stylesheet is not available via URL right away. If we request it right away, Varnish will cache a 404 Not Found response for it +# TO-DO: make sure the stylesheet URL is available immediately after installation +sleep 1 # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 0a721b18c..217767f89 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -352,12 +352,12 @@ private void installStylesheet(Path stylesheetFile, String packagePath, String s if (log.isDebugEnabled()) log.debug("Installed package stylesheet at: {}", stylesheetFile); // Purge stylesheet from frontend proxy cache to clear any cached 404 responses - String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; - if (endUserApp.getFrontendProxy() != null) - { - if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); - getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); - } +// String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; +// if (endUserApp.getFrontendProxy() != null) +// { +// if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); +// getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); +// } } /** @@ -389,11 +389,11 @@ private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.li updater.regenerateMasterStylesheet(packagePaths); // Purge master stylesheet from cache - if (app.getFrontendProxy() != null) - { - if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); - getSystem().ban(app.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); - } +// if (app.getFrontendProxy() != null) +// { +// if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); +// getSystem().ban(app.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); +// } } /** From 98cb64ecc3d55efc0b6092a36475d71ac5d6e7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 14:58:29 +0100 Subject: [PATCH 39/64] Increase sleep --- http-tests/admin/packages/install-package-stylesheet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 958eb3b63..26fb30cf2 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -21,7 +21,7 @@ curl -k -w "%{http_code}\n" -o /dev/null -f -s \ # the stylesheet is not available via URL right away. If we request it right away, Varnish will cache a 404 Not Found response for it # TO-DO: make sure the stylesheet URL is available immediately after installation -sleep 1 +sleep 2 # verify package stylesheet was installed (should return 200) curl -k -f -s -o /dev/null \ From cda5a9ac1bf994426f45212f523b4da88ca9dace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 15:05:10 +0100 Subject: [PATCH 40/64] Run all tests --- http-tests/run.sh | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/http-tests/run.sh b/http-tests/run.sh index 6ce78622c..49e8ca193 100755 --- a/http-tests/run.sh +++ b/http-tests/run.sh @@ -138,24 +138,24 @@ download_dataset "$ADMIN_ENDPOINT_URL" > "$TMP_ADMIN_DATASET" ### Other tests ### -#run_tests $(find ./add/ -type f -name '*.sh') -#(( error_count += $? )) -run_tests $(find ./admin/packages -type f -name '*.sh') +run_tests $(find ./add/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./admin/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./dataspaces/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./access/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./imports/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./document-hierarchy/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./misc/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./proxy/ -type f -name '*.sh') +(( error_count += $? )) +run_tests $(find ./sparql-protocol/ -type f -name '*.sh') (( error_count += $? )) -#run_tests $(find ./dataspaces/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./access/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./imports/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./document-hierarchy/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./misc/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./proxy/ -type f -name '*.sh') -#(( error_count += $? )) -#run_tests $(find ./sparql-protocol/ -type f -name '*.sh') -#(( error_count += $? )) end_time=$(date +%s) runtime=$((end_time-start_time)) From a39792dc77fa98159b459593f1ab171837ce25d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 17:19:31 +0100 Subject: [PATCH 41/64] HTTP tests to use CLI scripts --- bin/admin/packages/install-package.sh | 2 +- bin/admin/packages/uninstall-package.sh | 103 ++++++++++++++++++ .../packages/install-package-stylesheet.sh | 13 +-- .../install-uninstall-package-ontology.sh | 22 ++-- .../install-uninstall-package-stylesheet.sh | 22 ++-- .../packages/uninstall-package-stylesheet.sh | 24 ++-- 6 files changed, 141 insertions(+), 45 deletions(-) create mode 100755 bin/admin/packages/uninstall-package.sh diff --git a/bin/admin/packages/install-package.sh b/bin/admin/packages/install-package.sh index d4316dc1f..df3970f6f 100755 --- a/bin/admin/packages/install-package.sh +++ b/bin/admin/packages/install-package.sh @@ -95,7 +95,7 @@ else fi # POST to packages/install endpoint -curl -k -w "%{http_code}\n" -E "${cert_pem_file}":"${cert_password}" \ +curl -k -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ -X POST \ -H "Accept: text/turtle" \ -H "Content-Type: application/x-www-form-urlencoded" \ diff --git a/bin/admin/packages/uninstall-package.sh b/bin/admin/packages/uninstall-package.sh new file mode 100755 index 000000000..84072ea3a --- /dev/null +++ b/bin/admin/packages/uninstall-package.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +print_usage() +{ + printf "Uninstalls a LinkedDataHub package.\n" + printf "\n" + printf "Usage: %s options\n" "$0" + printf "\n" + printf "Options:\n" + printf " -b, --base BASE_URL Base URL of the application\n" + printf " -f, --cert-pem-file CERT_FILE .pem file with the WebID certificate of the agent\n" + printf " -p, --cert-password CERT_PASSWORD Password of the WebID certificate\n" + printf " --proxy PROXY_URL The host this request will be proxied through (optional)\n" + printf " --package PACKAGE_URI URI of the package to uninstall (e.g., https://packages.linkeddatahub.com/skos/#this)\n" + printf "\n" + printf "Example:\n" + printf " %s -b https://localhost:4443/ -f ssl/owner/cert.pem -p Password --package https://packages.linkeddatahub.com/skos/#this\n" "$0" +} + +hash curl 2>/dev/null || { echo >&2 "curl not on \$PATH. Aborting."; exit 1; } + +unknown=() +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + -b|--base) + base="$2" + shift # past argument + shift # past value + ;; + -f|--cert-pem-file) + cert_pem_file="$2" + shift # past argument + shift # past value + ;; + -p|--cert-password) + cert_password="$2" + shift # past argument + shift # past value + ;; + --proxy) + proxy="$2" + shift # past argument + shift # past value + ;; + --package) + package_uri="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + unknown+=("$1") # save it in an array for later + shift # past argument + ;; + esac +done +set -- "${unknown[@]}" # restore args + +if [ -z "$base" ] ; then + print_usage + exit 1 +fi +if [ -z "$cert_pem_file" ] ; then + print_usage + exit 1 +fi +if [ -z "$cert_password" ] ; then + print_usage + exit 1 +fi +if [ -z "$package_uri" ] ; then + print_usage + exit 1 +fi + +# Convert base URL to admin base URL +admin_uri() { + local uri="$1" + echo "$uri" | sed 's|://|://admin.|' +} + +admin_base=$(admin_uri "$base") +target_url="${admin_base}packages/uninstall" + +if [ -n "$proxy" ]; then + admin_proxy=$(admin_uri "$proxy") + # rewrite target hostname to proxy hostname + url_host=$(echo "$target_url" | cut -d '/' -f 1,2,3) + proxy_host=$(echo "$admin_proxy" | cut -d '/' -f 1,2,3) + final_url="${target_url/$url_host/$proxy_host}" +else + final_url="$target_url" +fi + +# POST to packages/uninstall endpoint +curl -k -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ + -X POST \ + -H "Accept: text/turtle" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=${package_uri}" \ + "${final_url}" diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh index 26fb30cf2..8953d96d0 100755 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ b/http-tests/admin/packages/install-package-stylesheet.sh @@ -10,13 +10,12 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" # test package URI (SKOS package) package_uri="https://packages.linkeddatahub.com/skos/#this" -# install package via POST to packages/install endpoint -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +# install package +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # the stylesheet is not available via URL right away. If we request it right away, Varnish will cache a 404 Not Found response for it diff --git a/http-tests/admin/packages/install-uninstall-package-ontology.sh b/http-tests/admin/packages/install-uninstall-package-ontology.sh index f3562227d..bcccc4f33 100755 --- a/http-tests/admin/packages/install-uninstall-package-ontology.sh +++ b/http-tests/admin/packages/install-uninstall-package-ontology.sh @@ -13,12 +13,11 @@ package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub- namespace_ontology_uri="${END_USER_BASE_URL}ns#" # install package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was added @@ -35,12 +34,11 @@ curl -k -w "%{http_code}\n" -o /dev/null -s \ | grep -qE "^($STATUS_OK|$STATUS_NOT_MODIFIED)$" # uninstall package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/uninstall" \ +uninstall-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was removed diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index 834fc7234..a4e29cf55 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -11,12 +11,11 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" package_uri="https://packages.linkeddatahub.com/skos/#this" # install package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify package stylesheet was installed (should return 200) @@ -28,12 +27,11 @@ curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ | grep -q "com/linkeddatahub/packages/skos/layout.xsl" # uninstall package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/uninstall" \ +uninstall-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # Wait for Tomcat's static resource cache to expire diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh index 048b7017c..803224b38 100755 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/uninstall-package-stylesheet.sh @@ -11,25 +11,23 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" package_uri="https://packages.linkeddatahub.com/skos/#this" # first install the package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify package stylesheet exists before uninstall (should return 200) curl -k -f -s -o /dev/null \ "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" -# uninstall package via POST to packages/uninstall endpoint -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/uninstall" \ +# uninstall package +uninstall-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # Wait for Tomcat's static resource cache to expire From 7b1e834b827a2cab591b1e9f731c39e0e03affcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Mon, 5 Jan 2026 20:20:16 +0100 Subject: [PATCH 42/64] CLI script fixes --- bin/admin/clear-ontology.sh | 1 + bin/admin/packages/install-package.sh | 3 ++- bin/admin/packages/uninstall-package.sh | 3 ++- .../packages/install-package-ontology.sh | 13 +++++----- .../packages/uninstall-package-ontology.sh | 26 +++++++++---------- .../resource/admin/pkg/InstallPackage.java | 19 ++------------ .../resource/admin/pkg/UninstallPackage.java | 17 ++++++------ 7 files changed, 33 insertions(+), 49 deletions(-) diff --git a/bin/admin/clear-ontology.sh b/bin/admin/clear-ontology.sh index a079cf84e..89a72afb1 100755 --- a/bin/admin/clear-ontology.sh +++ b/bin/admin/clear-ontology.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -eo pipefail print_usage() { diff --git a/bin/admin/packages/install-package.sh b/bin/admin/packages/install-package.sh index df3970f6f..86f597c59 100755 --- a/bin/admin/packages/install-package.sh +++ b/bin/admin/packages/install-package.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -eo pipefail print_usage() { @@ -95,7 +96,7 @@ else fi # POST to packages/install endpoint -curl -k -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ +curl -k -f -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ -X POST \ -H "Accept: text/turtle" \ -H "Content-Type: application/x-www-form-urlencoded" \ diff --git a/bin/admin/packages/uninstall-package.sh b/bin/admin/packages/uninstall-package.sh index 84072ea3a..065e48cb8 100755 --- a/bin/admin/packages/uninstall-package.sh +++ b/bin/admin/packages/uninstall-package.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -eo pipefail print_usage() { @@ -95,7 +96,7 @@ else fi # POST to packages/uninstall endpoint -curl -k -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ +curl -k -f -s -w "%{http_code}\n" -E "$cert_pem_file":"$cert_password" \ -X POST \ -H "Accept: text/turtle" \ -H "Content-Type: application/x-www-form-urlencoded" \ diff --git a/http-tests/admin/packages/install-package-ontology.sh b/http-tests/admin/packages/install-package-ontology.sh index fa90359fe..9c9c0a1d0 100755 --- a/http-tests/admin/packages/install-package-ontology.sh +++ b/http-tests/admin/packages/install-package-ontology.sh @@ -12,13 +12,12 @@ package_uri="https://packages.linkeddatahub.com/skos/#this" package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" namespace_ontology_uri="${END_USER_BASE_URL}ns#" -# install package via POST to packages/install endpoint -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +# install package +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was added to namespace graph diff --git a/http-tests/admin/packages/uninstall-package-ontology.sh b/http-tests/admin/packages/uninstall-package-ontology.sh index f73515d27..374b4c0f6 100755 --- a/http-tests/admin/packages/uninstall-package-ontology.sh +++ b/http-tests/admin/packages/uninstall-package-ontology.sh @@ -12,26 +12,24 @@ package_uri="https://packages.linkeddatahub.com/skos/#this" package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" namespace_ontology_uri="${END_USER_BASE_URL}ns#" -# first install the package -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/install" \ +# install package +install-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple exists before uninstall ns_before=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") echo "$ns_before" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" -# uninstall package via POST to packages/uninstall endpoint -curl -k -w "%{http_code}\n" -o /dev/null -f -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - --data-urlencode "package-uri=$package_uri" \ - "${ADMIN_BASE_URL}packages/uninstall" \ +# uninstall package +uninstall-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" # verify owl:imports triple was removed from namespace graph diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 217767f89..57246695d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -160,7 +160,7 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); String stylesheetContent = downloadStylesheet(stylesheetURI); - installStylesheet(Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath).resolve("layout.xsl"), packagePath, stylesheetContent, endUserApp); + installStylesheet(Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath).resolve("layout.xsl"), stylesheetContent, endUserApp); // 4. Regenerate master stylesheet regenerateMasterStylesheet(endUserApp, pkg); @@ -344,20 +344,12 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String /** * Installs stylesheet to <samp>/static/<package-path>/layout.xsl</samp> */ - private void installStylesheet(Path stylesheetFile, String packagePath, String stylesheetContent, EndUserApplication endUserApp) throws IOException + private void installStylesheet(Path stylesheetFile, String stylesheetContent, EndUserApplication endUserApp) throws IOException { Files.createDirectories(stylesheetFile.getParent()); Files.writeString(stylesheetFile, stylesheetContent); if (log.isDebugEnabled()) log.debug("Installed package stylesheet at: {}", stylesheetFile); - - // Purge stylesheet from frontend proxy cache to clear any cached 404 responses -// String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; -// if (endUserApp.getFrontendProxy() != null) -// { -// if (log.isDebugEnabled()) log.debug("Purging stylesheet from frontend proxy cache: {}", stylesheetURL); -// getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); -// } } /** @@ -387,13 +379,6 @@ private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.li // Regenerate master stylesheet (XSLTMasterUpdater works with paths) XSLTMasterUpdater updater = new XSLTMasterUpdater(getServletContext()); updater.regenerateMasterStylesheet(packagePaths); - - // Purge master stylesheet from cache -// if (app.getFrontendProxy() != null) -// { -// if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); -// getSystem().ban(app.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); -// } } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index 94f1b696d..af0856025 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -148,7 +148,10 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (stylesheet != null) { String packagePath = pkg.getStylesheetPath(); - uninstallStylesheet(Paths.get(getServletContext().getRealPath("/static")), packagePath, endUserApp); + Path packageDir = Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath); + Path stylesheetFile = packageDir.resolve("layout.xsl"); + + uninstallStylesheet(stylesheetFile, packagePath, endUserApp); regenerateMasterStylesheet(endUserApp, pkg); } @@ -245,12 +248,8 @@ private void uninstallOntology(EndUserApplication app, String packageOntologyURI /** * Deletes stylesheet from <samp>/static/<package-path>/</samp> */ - private void uninstallStylesheet(Path staticDir, String packagePath, EndUserApplication endUserApp) throws IOException + private void uninstallStylesheet(Path stylesheetFile, String packagePath, EndUserApplication endUserApp) throws IOException { - Path packageDir = staticDir.resolve(packagePath); - - // Delete layout.xsl - Path stylesheetFile = packageDir.resolve("layout.xsl"); Files.delete(stylesheetFile); if (log.isDebugEnabled()) log.debug("Deleted package stylesheet: {}", stylesheetFile); @@ -263,10 +262,10 @@ private void uninstallStylesheet(Path staticDir, String packagePath, EndUserAppl } // Delete directory if empty - if (Files.list(packageDir).count() == 0) + if (Files.list(stylesheetFile.getParent()).count() == 0) { - Files.delete(packageDir); - if (log.isDebugEnabled()) log.debug("Deleted package directory: {}", packageDir); + Files.delete(stylesheetFile.getParent()); + if (log.isDebugEnabled()) log.debug("Deleted package directory: {}", stylesheetFile.getParent()); } } From 1ebf6a6cec9621870a658881ad6bee850210b47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 6 Jan 2026 22:26:23 +0100 Subject: [PATCH 43/64] Web-Client version bump --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 68c4e799b..c0876e171 100644 --- a/pom.xml +++ b/pom.xml @@ -135,13 +135,13 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.10-SNAPSHOT</version> + <version>4.2.10</version> <classifier>classes</classifier> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.10-SNAPSHOT</version> + <version>4.2.10</version> <type>war</type> </dependency> <!-- required by jsonld-java - version same as Jersey's HTTP Client --> From 4c1aab426e3ba0588c9d9f440da0233f8cc3896c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 6 Jan 2026 22:39:40 +0100 Subject: [PATCH 44/64] Incorporated AtomGraph Server code --- pom.xml | 10 +- .../server/exception/ModelException.java | 45 +++++ .../server/exception/OntologyException.java | 50 ++++++ .../SHACLConstraintViolationException.java | 41 +++++ .../SPINConstraintViolationException.java | 47 ++++++ .../exception/SkolemizationException.java | 33 ++++ .../server/io/BasedModelProvider.java | 91 ++++++++++ .../server/io/ValidatingDatasetProvider.java | 126 ++++++++++++++ .../server/io/ValidatingModelProvider.java | 113 +++++++++++++ .../mapper/BadGatewayExceptionMapper.java | 51 ++++++ .../mapper/ConfigurationExceptionMapper.java | 49 ++++++ .../server/mapper/ExceptionMapperBase.java | 157 ++++++++++++++++++ .../server/mapper/ModelExceptionMapper.java | 50 ++++++ .../mapper/NotAcceptableExceptionMapper.java | 48 ++++++ .../mapper/NotFoundExceptionMapper.java | 49 ++++++ .../mapper/NotSupportedExceptionMapper.java | 48 ++++++ .../mapper/OntologyExceptionMapper.java | 48 ++++++ ...ACLConstraintViolationExceptionMapper.java | 54 ++++++ ...PINConstraintViolationExceptionMapper.java | 73 ++++++++ .../jena/DatatypeFormatExceptionMapper.java | 49 ++++++ .../jena/QueryParseExceptionMapper.java | 52 ++++++ .../mapper/jena/RiotExceptionMapper.java | 49 ++++++ .../status/UnprocessableEntityStatus.java | 59 +++++++ .../com/atomgraph/server/util/Validator.java | 55 ++++++ .../com/atomgraph/server/vocabulary/HTTP.java | 64 +++++++ .../com/atomgraph/server/vocabulary/LDT.java | 97 +++++++++++ .../com/atomgraph/server/vocabulary/XHV.java | 66 ++++++++ 27 files changed, 1671 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/atomgraph/server/exception/ModelException.java create mode 100644 src/main/java/com/atomgraph/server/exception/OntologyException.java create mode 100644 src/main/java/com/atomgraph/server/exception/SHACLConstraintViolationException.java create mode 100644 src/main/java/com/atomgraph/server/exception/SPINConstraintViolationException.java create mode 100644 src/main/java/com/atomgraph/server/exception/SkolemizationException.java create mode 100644 src/main/java/com/atomgraph/server/io/BasedModelProvider.java create mode 100644 src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java create mode 100644 src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java create mode 100644 src/main/java/com/atomgraph/server/mapper/BadGatewayExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/ConfigurationExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java create mode 100644 src/main/java/com/atomgraph/server/mapper/ModelExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/NotAcceptableExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/NotFoundExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/NotSupportedExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/OntologyExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/SHACLConstraintViolationExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/SPINConstraintViolationExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/jena/DatatypeFormatExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/jena/QueryParseExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/mapper/jena/RiotExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/server/status/UnprocessableEntityStatus.java create mode 100644 src/main/java/com/atomgraph/server/util/Validator.java create mode 100644 src/main/java/com/atomgraph/server/vocabulary/HTTP.java create mode 100644 src/main/java/com/atomgraph/server/vocabulary/LDT.java create mode 100644 src/main/java/com/atomgraph/server/vocabulary/XHV.java diff --git a/pom.xml b/pom.xml index c0876e171..d745a488e 100644 --- a/pom.xml +++ b/pom.xml @@ -126,11 +126,15 @@ </exclusion> </exclusions> </dependency> - <!-- TO-DO: replace with AtomGraph Core --> + <dependency> + <groupId>org.apache.jena</groupId> + <artifactId>jena-shacl</artifactId> + <version>4.7.0</version> + </dependency> <dependency> <groupId>${project.groupId}</groupId> - <artifactId>server</artifactId> - <version>4.1.15-SNAPSHOT</version> + <artifactId>twirl</artifactId> + <version>1.0.33</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> diff --git a/src/main/java/com/atomgraph/server/exception/ModelException.java b/src/main/java/com/atomgraph/server/exception/ModelException.java new file mode 100644 index 000000000..b8ae5e3fc --- /dev/null +++ b/src/main/java/com/atomgraph/server/exception/ModelException.java @@ -0,0 +1,45 @@ +/* + * Copyright 2016 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.exception; + +import org.apache.jena.rdf.model.Model; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class ModelException extends RuntimeException +{ + + private final Model model; + + public ModelException(Model model) + { + this.model = model; + } + + public ModelException(Throwable throwable, Model model) + { + super(throwable); + this.model = model; + } + + public Model getModel() + { + return model; + } + +} \ No newline at end of file diff --git a/src/main/java/com/atomgraph/server/exception/OntologyException.java b/src/main/java/com/atomgraph/server/exception/OntologyException.java new file mode 100644 index 000000000..b8af3c911 --- /dev/null +++ b/src/main/java/com/atomgraph/server/exception/OntologyException.java @@ -0,0 +1,50 @@ +/* + * Copyright 2015 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.exception; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class OntologyException extends RuntimeException +{ + + public OntologyException() + { + } + + public OntologyException(String message) + { + super(message); + } + + public OntologyException(String message, Throwable cause) + { + super(message, cause); + } + + public OntologyException(Throwable cause) + { + super(cause); + } + + public OntologyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/src/main/java/com/atomgraph/server/exception/SHACLConstraintViolationException.java b/src/main/java/com/atomgraph/server/exception/SHACLConstraintViolationException.java new file mode 100644 index 000000000..585f0ac01 --- /dev/null +++ b/src/main/java/com/atomgraph/server/exception/SHACLConstraintViolationException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2021 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.exception; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.shacl.ValidationReport; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class SHACLConstraintViolationException extends ModelException +{ + + private final ValidationReport report; + + public SHACLConstraintViolationException(ValidationReport report, Model model) + { + super(model); + this.report = report; + } + + public ValidationReport getValidationReport() + { + return report; + } + +} diff --git a/src/main/java/com/atomgraph/server/exception/SPINConstraintViolationException.java b/src/main/java/com/atomgraph/server/exception/SPINConstraintViolationException.java new file mode 100644 index 000000000..59723b418 --- /dev/null +++ b/src/main/java/com/atomgraph/server/exception/SPINConstraintViolationException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.exception; + +import org.apache.jena.rdf.model.Model; +import java.util.List; +import com.atomgraph.spinrdf.constraints.ConstraintViolation; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class SPINConstraintViolationException extends ModelException +{ + private final List<ConstraintViolation> cvs; + + public SPINConstraintViolationException(List<ConstraintViolation> cvs, Model model, String graphURI) + { + super(model); + this.cvs = cvs; + } + + public SPINConstraintViolationException(List<ConstraintViolation> cvs, Model model) + { + this(cvs, model, null); + } + + public List<ConstraintViolation> getConstraintViolations() + { + return cvs; + } + +} diff --git a/src/main/java/com/atomgraph/server/exception/SkolemizationException.java b/src/main/java/com/atomgraph/server/exception/SkolemizationException.java new file mode 100644 index 000000000..3a12ba909 --- /dev/null +++ b/src/main/java/com/atomgraph/server/exception/SkolemizationException.java @@ -0,0 +1,33 @@ +/* + * Copyright 2016 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.exception; + +import org.apache.jena.rdf.model.Model; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class SkolemizationException extends ModelException +{ + + public SkolemizationException(IllegalArgumentException ex, Model model) + { + super(ex, model); + } + +} diff --git a/src/main/java/com/atomgraph/server/io/BasedModelProvider.java b/src/main/java/com/atomgraph/server/io/BasedModelProvider.java new file mode 100644 index 000000000..ba86d7341 --- /dev/null +++ b/src/main/java/com/atomgraph/server/io/BasedModelProvider.java @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.io; + +import com.atomgraph.core.io.ModelProvider; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.UriInfo; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFLanguages; +import org.apache.jena.shared.NoReaderForLangException; +import org.apache.jena.shared.NoWriterForLangException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * A provider that reads/writes model and resolves relative URIs against request base URI. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class BasedModelProvider extends ModelProvider +{ + + private static final Logger log = LoggerFactory.getLogger(BasedModelProvider.class); + + @Context UriInfo uriInfo; + + @Override + public Model readFrom(Class<Model> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException + { + if (log.isTraceEnabled()) log.trace("Reading Model with HTTP headers: {} MediaType: {}", httpHeaders, mediaType); + + Model model = ModelFactory.createDefaultModel(); + + MediaType formatType = new MediaType(mediaType.getType(), mediaType.getSubtype()); // discard charset param + Lang lang = RDFLanguages.contentTypeToLang(formatType.toString()); + if (lang == null) + { + if (log.isErrorEnabled()) log.error("MediaType '{}' not supported by Jena", formatType); + throw new NoReaderForLangException("MediaType not supported: " + formatType); + } + if (log.isDebugEnabled()) log.debug("RDF language used to read Model: {}", lang); + + return read(model, entityStream, lang, getUriInfo().getAbsolutePath().toString()); + } + + @Override + public void writeTo(Model model, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException + { + if (log.isTraceEnabled()) log.trace("Writing Model with HTTP headers: {} MediaType: {}", httpHeaders, mediaType); + + MediaType formatType = new MediaType(mediaType.getType(), mediaType.getSubtype()); // discard charset param + Lang lang = RDFLanguages.contentTypeToLang(formatType.toString()); + if (lang == null) + { + if (log.isErrorEnabled()) log.error("MediaType '{}' not supported by Jena", formatType); + throw new NoWriterForLangException("MediaType not supported: " + formatType); + } + if (log.isDebugEnabled()) log.debug("RDF language used to read Model: {}", lang); + + write(model, entityStream, lang, getUriInfo().getAbsolutePath().toString()); + } + + public UriInfo getUriInfo() + { + return uriInfo; + } + +} diff --git a/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java b/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java new file mode 100644 index 000000000..500fb2e5a --- /dev/null +++ b/src/main/java/com/atomgraph/server/io/ValidatingDatasetProvider.java @@ -0,0 +1,126 @@ +/* + * Copyright 2019 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.io; + +import com.atomgraph.core.io.DatasetProvider; +import com.atomgraph.server.util.Validator; +import com.atomgraph.server.exception.SHACLConstraintViolationException; +import com.atomgraph.server.exception.SPINConstraintViolationException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Iterator; +import java.util.List; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.Providers; +import org.apache.jena.ontology.Ontology; +import org.apache.jena.query.Dataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.atomgraph.spinrdf.constraints.ConstraintViolation; +import java.util.Optional; +import org.apache.jena.shacl.ShaclValidator; +import org.apache.jena.shacl.Shapes; +import org.apache.jena.shacl.ValidationReport; + +/** + * Dataset provider that validates read triples in each graph against SPIN constraints in an ontology. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class ValidatingDatasetProvider extends DatasetProvider +{ + + private static final Logger log = LoggerFactory.getLogger(ValidatingDatasetProvider.class); + + @Context private Providers providers; + + @Inject jakarta.inject.Provider<Optional<Ontology>> ontology; + + @Override + public Dataset readFrom(Class<Dataset> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException + { + return process(super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream)); + } + + public Dataset process(Dataset dataset) + { + return validate(dataset); + } + + public Dataset validate(Dataset dataset) + { + if (getOntology().isPresent()) + { + // SPIN validation + Validator validator = new Validator(getOntology().get().getOntModel()); + List<ConstraintViolation> cvs = validator.validate(dataset.getDefaultModel()); + if (!cvs.isEmpty()) + { + if (log.isDebugEnabled()) log.debug("SPIN constraint violations: {}", cvs); + throw new SPINConstraintViolationException(cvs, dataset.getDefaultModel()); + } + + // SHACL validation + Shapes shapes = Shapes.parse(getOntology().get().getOntModel().getGraph()); + ValidationReport report = ShaclValidator.get().validate(shapes, dataset.getDefaultModel().getGraph()); + if (!report.conforms()) + { + if (log.isDebugEnabled()) log.debug("SHACL constraint violations: {}", report); + throw new SHACLConstraintViolationException(report, dataset.getDefaultModel()); + } + + Iterator<String> it = dataset.listNames(); + while (it.hasNext()) + { + String graphURI = it.next(); + + // SPIN validation + cvs = validator.validate(dataset.getNamedModel(graphURI)); + if (!cvs.isEmpty()) + { + if (log.isDebugEnabled()) log.debug("SPIN constraint violations: {}", cvs); + throw new SPINConstraintViolationException(cvs, dataset.getNamedModel(graphURI), graphURI); + } + + // SHACL validation + report = ShaclValidator.get().validate(shapes, dataset.getNamedModel(graphURI).getGraph()); + if (!report.conforms()) + { + if (log.isDebugEnabled()) log.debug("SHACL constraint violations: {}", report); + throw new SHACLConstraintViolationException(report, dataset.getNamedModel(graphURI)); + } + } + } + + return dataset; + } + + public Optional<Ontology> getOntology() + { + return ontology.get(); + } + + public Providers getProviders() + { + return providers; + } + +} diff --git a/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java b/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java new file mode 100644 index 000000000..416d8ada1 --- /dev/null +++ b/src/main/java/com/atomgraph/server/io/ValidatingModelProvider.java @@ -0,0 +1,113 @@ +/* + * Copyright 2015 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.io; + +import org.apache.jena.ontology.Ontology; +import org.apache.jena.rdf.model.Model; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.List; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.ext.Providers; +import com.atomgraph.server.exception.SPINConstraintViolationException; +import com.atomgraph.server.util.Validator; +import com.atomgraph.server.exception.SHACLConstraintViolationException; +import jakarta.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.atomgraph.spinrdf.constraints.ConstraintViolation; +import java.io.OutputStream; +import java.util.Optional; +import org.apache.jena.shacl.ShaclValidator; +import org.apache.jena.shacl.Shapes; +import org.apache.jena.shacl.ValidationReport; + +/** + * Model provider that validates read triples against SPIN constraints in an ontology. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class ValidatingModelProvider extends BasedModelProvider +{ + private static final Logger log = LoggerFactory.getLogger(ValidatingModelProvider.class); + + @Context private Providers providers; + + @Inject jakarta.inject.Provider<Optional<Ontology>> ontology; + + @Override + public Model readFrom(Class<Model> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException + { + return processRead(super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream)); + } + + public Model processRead(Model model) + { + return validate(model); + } + + public Model validate(Model model) + { + if (getOntology().isPresent()) + { + // SPIN validation + List<ConstraintViolation> cvs = new Validator(getOntology().get().getOntModel()).validate(model); + if (!cvs.isEmpty()) + { + if (log.isDebugEnabled()) log.debug("SPIN constraint violations: {}", cvs); + throw new SPINConstraintViolationException(cvs, model); + } + + // SHACL validation + Shapes shapes = Shapes.parse(getOntology().get().getOntModel().getGraph()); + ValidationReport report = ShaclValidator.get().validate(shapes, model.getGraph()); + if (!report.conforms()) + { + if (log.isDebugEnabled()) log.debug("SHACL constraint violations: {}", report); + throw new SHACLConstraintViolationException(report, model); + } + } + + return model; + } + + @Override + public void writeTo(Model model, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException + { + super.writeTo(processWrite(model), type, genericType, annotations, mediaType, httpHeaders, entityStream); + } + + public Model processWrite(Model model) + { + return model; + } + + public Optional<Ontology> getOntology() + { + return ontology.get(); + } + + public Providers getProviders() + { + return providers; + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/BadGatewayExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/BadGatewayExceptionMapper.java new file mode 100644 index 000000000..6ffb15faa --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/BadGatewayExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright 2015 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import com.atomgraph.core.exception.BadGatewayException; +import jakarta.inject.Inject; +import org.apache.jena.rdf.model.ResourceFactory; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.Resource; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class BadGatewayExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<BadGatewayException> +{ + + @Inject + public BadGatewayExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(BadGatewayException ex) + { + Resource exRes = toResource(ex, Response.Status.INTERNAL_SERVER_ERROR, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadGateway")); + + return getResponseBuilder(exRes.getModel()). + status(Response.Status.INTERNAL_SERVER_ERROR). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/ConfigurationExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/ConfigurationExceptionMapper.java new file mode 100644 index 000000000..b796607c6 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/ConfigurationExceptionMapper.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import org.apache.jena.rdf.model.ResourceFactory; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import com.atomgraph.core.exception.ConfigurationException; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class ConfigurationExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<ConfigurationException> +{ + + @Inject + public ConfigurationExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(ConfigurationException ex) + { + return getResponseBuilder(toResource(ex, Response.Status.INTERNAL_SERVER_ERROR, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#InternalServerError")). + getModel()). + status(Response.Status.INTERNAL_SERVER_ERROR). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java b/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java new file mode 100644 index 000000000..e07b46872 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java @@ -0,0 +1,157 @@ +/* + * Copyright 2014 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.vocabulary.DCTerms; +import org.apache.jena.vocabulary.RDF; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Request; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.UriInfo; +import jakarta.ws.rs.core.Variant; +import jakarta.ws.rs.ext.Provider; +import com.atomgraph.core.MediaTypes; +import com.atomgraph.core.util.Link; +import com.atomgraph.server.vocabulary.LDT; +import com.atomgraph.server.vocabulary.HTTP; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; + +/** + * Abstract base class for ExceptionMappers that build responses with exceptions as RDF resources. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +@Provider +abstract public class ExceptionMapperBase +{ + + @Context private Request request; + @Context private UriInfo uriInfo; + + private final MediaTypes mediaTypes; + + @Inject + public ExceptionMapperBase(MediaTypes mediaTypes) + { + this.mediaTypes = mediaTypes; + } + + public Resource toResource(Exception ex, Response.StatusType status, Resource statusResource) + { + if (ex == null) throw new IllegalArgumentException("Exception cannot be null"); + if (status == null) throw new IllegalArgumentException("Response.Status cannot be null"); + + Resource resource = ModelFactory.createDefaultModel().createResource(). + addProperty(RDF.type, HTTP.Response). + addLiteral(HTTP.statusCodeValue, status.getStatusCode()). + addLiteral(HTTP.reasonPhrase, status.getReasonPhrase()); + + if (statusResource != null) resource.addProperty(HTTP.sc, statusResource); + if (ex.getMessage() != null) resource.addLiteral(DCTerms.title, ex.getMessage()); + + return resource; + } + + // TO-DO: set Link headers in a ContainerResponseFilter instead + public Response.ResponseBuilder getResponseBuilder(Model model) + { + List<Variant> variants = getVariants(Model.class); + Variant variant = getRequest().selectVariant(variants); + if (variant == null) variant = new Variant(com.atomgraph.core.MediaType.TEXT_TURTLE_TYPE, (Locale)null, null); // if still not acceptable, default to Turtle + +// // don't use Response class as it can strip the entity by returning 304 Not Modified +// return new com.atomgraph.core.model.impl.Response(getRequest(), +// model, +// null, +// new EntityTag(Long.toHexString(ModelUtils.hashModel(model))), +// variant). +// getResponseBuilder(). +// header(HttpHeaders.LINK, new Link(getUriInfo().getBaseUri(), LDT.base.getURI(), null)); + + return Response.ok(). // status will be overriden in the subclasses + entity(model). + variant(variant). + header(HttpHeaders.LINK, new Link(getUriInfo().getBaseUri(), LDT.base.getURI(), null)); + } + + /** + * Builds a list of acceptable response variants for a certain class. + * + * @param clazz class + * @return list of variants + */ + public List<Variant> getVariants(Class clazz) + { + return getVariants(getWritableMediaTypes(clazz)); + } + + /** + * Builds a list of acceptable response variants. + * + * @param mediaTypes + * @return supported variants + */ + public List<Variant> getVariants(List<MediaType> mediaTypes) + { + return com.atomgraph.core.model.impl.Response.getVariants(mediaTypes, getLanguages(), getEncodings()); + } + + /** + * Get writable media types for a certain class. + * + * @param clazz class + * @return list of media types + */ + public List<MediaType> getWritableMediaTypes(Class clazz) + { + return getMediaTypes().getWritable(clazz); + } + + public List<Locale> getLanguages() + { + return new ArrayList<>(); + } + + public List<String> getEncodings() + { + return new ArrayList<>(); + } + + public Request getRequest() + { + return request; + } + + public MediaTypes getMediaTypes() + { + return mediaTypes; + } + + public UriInfo getUriInfo() + { + return uriInfo; + } + +} \ No newline at end of file diff --git a/src/main/java/com/atomgraph/server/mapper/ModelExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/ModelExceptionMapper.java new file mode 100644 index 000000000..0ef76de88 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/ModelExceptionMapper.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import com.atomgraph.server.exception.ModelException; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class ModelExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<ModelException> +{ + + @Inject + public ModelExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(ModelException ex) + { + Resource exception = toResource(ex, Response.Status.BAD_REQUEST, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadRequest")); + ex.getModel().add(exception.getModel()); + + return getResponseBuilder(ex.getModel()).status(Response.Status.BAD_REQUEST).build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/NotAcceptableExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/NotAcceptableExceptionMapper.java new file mode 100644 index 000000000..df69687ea --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/NotAcceptableExceptionMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotAcceptableException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class NotAcceptableExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<NotAcceptableException> +{ + + @Inject + public NotAcceptableExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(NotAcceptableException ex) + { + return getResponseBuilder(toResource(ex, ex.getResponse().getStatusInfo(), + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#NotAcceptable")). + getModel()). + status(ex.getResponse().getStatusInfo()). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/NotFoundExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/NotFoundExceptionMapper.java new file mode 100644 index 000000000..1857f3aa5 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/NotFoundExceptionMapper.java @@ -0,0 +1,49 @@ +/* + * Copyright 2014 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotFoundException; +import org.apache.jena.rdf.model.ResourceFactory; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class NotFoundExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<NotFoundException> +{ + + @Inject + public NotFoundExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(NotFoundException ex) + { + return getResponseBuilder(toResource(ex, ex.getResponse().getStatusInfo(), + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#NotFound")). + getModel()). + status(ex.getResponse().getStatusInfo()). + build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atomgraph/server/mapper/NotSupportedExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/NotSupportedExceptionMapper.java new file mode 100644 index 000000000..20e78e04a --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/NotSupportedExceptionMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2020 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import jakarta.inject.Inject; +import jakarta.ws.rs.NotSupportedException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class NotSupportedExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<NotSupportedException> +{ + + @Inject + public NotSupportedExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(NotSupportedException ex) + { + return getResponseBuilder(toResource(ex, ex.getResponse().getStatusInfo(), + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#NotAcceptable")). + getModel()). + status(ex.getResponse().getStatusInfo()). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/OntologyExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/OntologyExceptionMapper.java new file mode 100644 index 000000000..155d4f3b9 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/OntologyExceptionMapper.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import com.atomgraph.server.exception.OntologyException; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class OntologyExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<OntologyException> +{ + + @Inject + public OntologyExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(OntologyException ex) + { + return getResponseBuilder(toResource(ex, Response.Status.INTERNAL_SERVER_ERROR, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#InternalServerError")). + getModel()). + status(Response.Status.INTERNAL_SERVER_ERROR). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/SHACLConstraintViolationExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/SHACLConstraintViolationExceptionMapper.java new file mode 100644 index 000000000..d5277e516 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/SHACLConstraintViolationExceptionMapper.java @@ -0,0 +1,54 @@ +/* + * Copyright 2021 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import com.atomgraph.server.exception.SHACLConstraintViolationException; +import com.atomgraph.server.status.UnprocessableEntityStatus; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class SHACLConstraintViolationExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<SHACLConstraintViolationException> +{ + + @Inject + public SHACLConstraintViolationExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(SHACLConstraintViolationException ex) + { + Resource exception = toResource(ex, UnprocessableEntityStatus.UNPROCESSABLE_ENTITY, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#UnprocessableEntity")); + ex.getModel().add(exception.getModel()); + + ex.getModel().add(ex.getValidationReport().getModel()); + + return getResponseBuilder(ex.getModel()). + status(UnprocessableEntityStatus.UNPROCESSABLE_ENTITY). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/SPINConstraintViolationExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/SPINConstraintViolationExceptionMapper.java new file mode 100644 index 000000000..5da173d19 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/SPINConstraintViolationExceptionMapper.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper; + +import com.atomgraph.core.MediaTypes; +import com.atomgraph.server.exception.SPINConstraintViolationException; +import com.atomgraph.server.status.UnprocessableEntityStatus; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.ResIterator; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.vocabulary.RDF; +import com.atomgraph.spinrdf.constraints.SPINConstraints; +import com.atomgraph.spinrdf.vocabulary.SPIN; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class SPINConstraintViolationExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<SPINConstraintViolationException> +{ + + @Inject + public SPINConstraintViolationExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(SPINConstraintViolationException ex) + { + Resource exception = toResource(ex, UnprocessableEntityStatus.UNPROCESSABLE_ENTITY, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#UnprocessableEntity")); + ex.getModel().add(exception.getModel()); + + SPINConstraints.addConstraintViolationsRDF(ex.getConstraintViolations(), ex.getModel(), true); + ResIterator it = ex.getModel().listSubjectsWithProperty(RDF.type, SPIN.ConstraintViolation); + try + { + while (it.hasNext()) + { + Resource violation = it.next(); + // connect Response to ConstraintViolations + ex.getModel().add(exception, ResourceFactory.createProperty("http://www.w3.org/ns/prov#wasDerivedFrom"), violation); + } + } + finally + { + it.close(); + } + + return getResponseBuilder(ex.getModel()). + status(UnprocessableEntityStatus.UNPROCESSABLE_ENTITY). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/jena/DatatypeFormatExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/jena/DatatypeFormatExceptionMapper.java new file mode 100644 index 000000000..a9218d14a --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/jena/DatatypeFormatExceptionMapper.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper.jena; + +import com.atomgraph.core.MediaTypes; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.datatypes.DatatypeFormatException; +import org.apache.jena.rdf.model.ResourceFactory; +import com.atomgraph.server.mapper.ExceptionMapperBase; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class DatatypeFormatExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<DatatypeFormatException> +{ + + @Inject + public DatatypeFormatExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(DatatypeFormatException ex) + { + return getResponseBuilder(toResource(ex, Response.Status.BAD_REQUEST, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadRequest")). + getModel()). + status(Response.Status.BAD_REQUEST). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/jena/QueryParseExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/jena/QueryParseExceptionMapper.java new file mode 100644 index 000000000..4cb19bf02 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/jena/QueryParseExceptionMapper.java @@ -0,0 +1,52 @@ +/* + * Copyright 2014 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.mapper.jena; + +import com.atomgraph.core.MediaTypes; +import org.apache.jena.query.QueryParseException; +import org.apache.jena.rdf.model.ResourceFactory; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; +import com.atomgraph.server.mapper.ExceptionMapperBase; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +@Provider +public class QueryParseExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<QueryParseException> +{ + + @Inject + public QueryParseExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(QueryParseException ex) + { + return getResponseBuilder(toResource(ex, Response.Status.BAD_REQUEST, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadRequest")). + getModel()). + status(Response.Status.BAD_REQUEST). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/mapper/jena/RiotExceptionMapper.java b/src/main/java/com/atomgraph/server/mapper/jena/RiotExceptionMapper.java new file mode 100644 index 000000000..1b1c8f9e8 --- /dev/null +++ b/src/main/java/com/atomgraph/server/mapper/jena/RiotExceptionMapper.java @@ -0,0 +1,49 @@ +/* + * Copyright 2016 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.atomgraph.server.mapper.jena; + +import com.atomgraph.core.MediaTypes; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.riot.RiotException; +import com.atomgraph.server.mapper.ExceptionMapperBase; +import jakarta.inject.Inject; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class RiotExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<RiotException> +{ + + @Inject + public RiotExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(RiotException ex) + { + return getResponseBuilder(toResource(ex, Response.Status.BAD_REQUEST, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadRequest")). + getModel()). + status(Response.Status.BAD_REQUEST). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/server/status/UnprocessableEntityStatus.java b/src/main/java/com/atomgraph/server/status/UnprocessableEntityStatus.java new file mode 100644 index 000000000..852cce73c --- /dev/null +++ b/src/main/java/com/atomgraph/server/status/UnprocessableEntityStatus.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.status; + +import jakarta.ws.rs.core.Response; + +/** + * Custom response status enum for <code>422 Unprocessable Entity</code>. + * + * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} + */ +public enum UnprocessableEntityStatus implements Response.StatusType +{ + + UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"); + + private final int code; + private final String reason; + private final Response.Status.Family family; + + UnprocessableEntityStatus(int code, String reason) + { + this.code = code; + this.reason = reason; + this.family = Response.Status.Family.familyOf(code); + } + + @Override + public int getStatusCode() + { + return code; + } + + @Override + public Response.Status.Family getFamily() + { + return family; + } + + @Override + public String getReasonPhrase() { + return reason; + } + +} diff --git a/src/main/java/com/atomgraph/server/util/Validator.java b/src/main/java/com/atomgraph/server/util/Validator.java new file mode 100644 index 000000000..fc66576e5 --- /dev/null +++ b/src/main/java/com/atomgraph/server/util/Validator.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.util; + +import org.apache.jena.ontology.OntModel; +import org.apache.jena.rdf.model.Model; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.atomgraph.spinrdf.constraints.ConstraintViolation; +import com.atomgraph.spinrdf.constraints.SPINConstraints; + +/** + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class Validator +{ + private static final Logger log = LoggerFactory.getLogger(Validator.class); + + private final OntModel ontModel; + + public Validator(OntModel ontModel) + { + if (ontModel == null) throw new IllegalArgumentException("OntModel cannot be null"); + this.ontModel = ontModel; + } + + public List<ConstraintViolation> validate(Model model) + { + if (model == null) throw new IllegalArgumentException("Model cannot be null"); + + return SPINConstraints.check(model, getOntModel()); + } + + public OntModel getOntModel() + { + return ontModel; + } + +} diff --git a/src/main/java/com/atomgraph/server/vocabulary/HTTP.java b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java new file mode 100644 index 000000000..e9316e1ee --- /dev/null +++ b/src/main/java/com/atomgraph/server/vocabulary/HTTP.java @@ -0,0 +1,64 @@ +/* + * Copyright 2014 Martynas Jusevičius <martynas@atomgraph.com>. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.atomgraph.server.vocabulary; + +import org.apache.jena.ontology.DatatypeProperty; +import org.apache.jena.ontology.ObjectProperty; +import org.apache.jena.ontology.OntClass; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.OntModelSpec; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; + +/** + * HTTP Vocabulary in RDF + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + * @see <a href="http://www.w3.org/TR/HTTP-in-RDF10/">HTTP Vocabulary in RDF 1.0</a> + */ +public class HTTP +{ + + /** <p>The RDF model that holds the vocabulary terms</p> */ + private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null); + + /** <p>The namespace of the vocabulary as a string</p> */ + public static final String NS = "http://www.w3.org/2011/http#"; + + /** <p>The namespace of the vocabulary as a string</p> + * @see #NS */ + public static String getURI() + { + return NS; + } + + /** <p>The namespace of the vocabulary as a resource</p> */ + public static final Resource NAMESPACE = m_model.createResource( NS ); + + public static final OntClass Response = m_model.createClass( NS + "Response" ); + + public static final ObjectProperty sc = m_model.createObjectProperty( NS + "sc" ); + + public static final DatatypeProperty statusCodeValue = m_model.createDatatypeProperty( NS + "statusCodeValue" ); + + public static final DatatypeProperty reasonPhrase = m_model.createDatatypeProperty( NS + "reasonPhrase" ); + + public static final DatatypeProperty absoluteURI = m_model.createDatatypeProperty( NS + "absoluteURI" ); + + public static final DatatypeProperty absolutePath = m_model.createDatatypeProperty( NS + "absolutePath" ); + +} diff --git a/src/main/java/com/atomgraph/server/vocabulary/LDT.java b/src/main/java/com/atomgraph/server/vocabulary/LDT.java new file mode 100644 index 000000000..5b59ee7f8 --- /dev/null +++ b/src/main/java/com/atomgraph/server/vocabulary/LDT.java @@ -0,0 +1,97 @@ +/** + * Copyright 2014 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.server.vocabulary; + +import org.apache.jena.ontology.DatatypeProperty; +import org.apache.jena.ontology.ObjectProperty; +import org.apache.jena.ontology.OntClass; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.OntModelSpec; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; + +/** + * Linked Data Templates vocabulary. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public final class LDT +{ + /** <p>The RDF model that holds the vocabulary terms</p> */ + private static OntModel m_model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, null); + + /** <p>The namespace of the vocabulary as a string</p> */ + public static final String NS = "https://www.w3.org/ns/ldt#"; + + /** <p>The namespace of the vocabulary as a string</p> + * @see #NS */ + public static String getURI() + { + return NS; + } + + /** <p>The namespace of the vocabulary as a resource</p> */ + public static final Resource NAMESPACE = m_model.createResource( NS ); + + public static final OntClass Application = m_model.createClass( NS + "Application" ); + + public static final OntClass Ontology = m_model.createClass( NS + "Ontology" ); + + public static final OntClass Template = m_model.createClass( NS + "Template" ); + + public static final OntClass Parameter = m_model.createClass( NS + "Parameter" ); + + public static final OntClass TemplateCall = m_model.createClass( NS + "TemplateCall" ); + + public static final OntClass Argument = m_model.createClass( NS + "Argument" ); + + public static final ObjectProperty base = m_model.createObjectProperty( NS + "base" ); + + public static final ObjectProperty ontology = m_model.createObjectProperty( NS + "ontology" ); + + public static final ObjectProperty service = m_model.createObjectProperty( NS + "service" ); + + public static final ObjectProperty arg = m_model.createObjectProperty( NS + "arg" ); + + public static final DatatypeProperty paramName = m_model.createDatatypeProperty( NS + "paramName" ); + + // "extends" is a reserved keyword in Java, obviously + public static final ObjectProperty extends_ = m_model.createObjectProperty( NS + "extends" ); + + public static final DatatypeProperty path = m_model.createDatatypeProperty( NS + "path" ); + + public static final ObjectProperty query = m_model.createObjectProperty( NS + "query" ); + + public static final ObjectProperty update = m_model.createObjectProperty( NS + "update" ); + + public static final DatatypeProperty match = m_model.createDatatypeProperty( NS + "match" ); + + public static final DatatypeProperty priority = m_model.createDatatypeProperty( NS + "priority" ); + + public static final DatatypeProperty fragment = m_model.createDatatypeProperty( NS + "fragment" ); + + public static final ObjectProperty param = m_model.createObjectProperty( NS + "param" ); + + public static final ObjectProperty loadClass = m_model.createObjectProperty( NS + "loadClass" ); + + public static final DatatypeProperty cacheControl = m_model.createDatatypeProperty( NS + "cacheControl" ); + + public static final ObjectProperty lang = m_model.createObjectProperty( NS + "lang" ); + + public static final ObjectProperty template = m_model.createObjectProperty( NS + "template" ); + +} diff --git a/src/main/java/com/atomgraph/server/vocabulary/XHV.java b/src/main/java/com/atomgraph/server/vocabulary/XHV.java new file mode 100644 index 000000000..38361fed7 --- /dev/null +++ b/src/main/java/com/atomgraph/server/vocabulary/XHV.java @@ -0,0 +1,66 @@ +/* + See lda-top/LICENCE (or http://elda.googlecode.com/hg/LICENCE) + for the licence for this software. + + (c) Copyright 2011 Epimorphics Limited + $Id$ +*/ + +/* + (c) Copyright 2010 Epimorphics Limited + [see end of file] + $Id$ +*/ + +package com.atomgraph.server.vocabulary; + +import org.apache.jena.rdf.model.*; + +public class XHV + { + public static final String ns = "http://www.w3.org/1999/xhtml/vocab#"; + + public static final Property first = property( "first" ); + + public static final Property next = property( "next" ); + + public static final Property prev = property( "prev" ); + + public static String getURI() + { return ns; } + + private static Property property( String localName ) + { return ResourceFactory.createProperty( ns + localName ); } + + } + + +/* + (c) Copyright 2010 Epimorphics Limited + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ \ No newline at end of file From ec4e7e6c44e3ff9d692ebf2d5c6dc4ed4bd39647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 6 Jan 2026 23:34:11 +0100 Subject: [PATCH 45/64] README update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11a2c4642..c4c84c9b2 100644 --- a/README.md +++ b/README.md @@ -266,7 +266,6 @@ See the [Web-Algebra repository](https://github.com/AtomGraph/Web-Algebra) for s LinkedDataHub includes an HTTP [test suite](https://github.com/AtomGraph/LinkedDataHub/tree/master/http-tests). The server implementation is also covered by the [Processor test suite](https://github.com/AtomGraph/Processor/tree/master/http-tests). -![HTTP-tests](https://github.com/AtomGraph/LinkedDataHub/actions/workflows/http-tests.yml/badge.svg) ![HTTP-tests](https://github.com/AtomGraph/LinkedDataHub/actions/workflows/http-tests.yml/badge.svg) ## Dependencies @@ -287,8 +286,9 @@ LinkedDataHub includes an HTTP [test suite](https://github.com/AtomGraph/LinkedD * [java-jwt](https://github.com/auth0/java-jwt) * [ExpiringMap](https://github.com/jhalterman/expiringmap) * [CSV2RDF](https://github.com/AtomGraph/CSV2RDF) -* [Processor](https://github.com/AtomGraph/Processor) * [Web-Client](https://github.com/AtomGraph/Web-Client) +* [Twirl](https://github.com/AtomGraph/Twirl) +* [jena-shacl](https://mvnrepository.com/artifact/org.apache.jena/jena-shacl) ### Docker From b9f5c2ac696018681d21f352b770c272d8b93259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 9 Jan 2026 11:09:20 +0100 Subject: [PATCH 46/64] Handle `PATCH` that deletes all document triples as `DELETE` --- .../PATCH-empty-container.sh | 58 +++++++++++++++++++ .../document-hierarchy/PATCH-empty-item.sh | 58 +++++++++++++++++++ .../PATCH-empty-root-405.sh | 38 ++++++++++++ .../linkeddatahub/resource/Graph.java | 4 ++ 4 files changed, 158 insertions(+) create mode 100755 http-tests/document-hierarchy/PATCH-empty-container.sh create mode 100755 http-tests/document-hierarchy/PATCH-empty-item.sh create mode 100755 http-tests/document-hierarchy/PATCH-empty-root-405.sh diff --git a/http-tests/document-hierarchy/PATCH-empty-container.sh b/http-tests/document-hierarchy/PATCH-empty-container.sh new file mode 100755 index 000000000..5b95eb841 --- /dev/null +++ b/http-tests/document-hierarchy/PATCH-empty-container.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# add agent to the writers group + +add-agent-to-group.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --agent "$AGENT_URI" \ + "${ADMIN_BASE_URL}acl/groups/writers/" + +# create a container with random slug + +slug=$(uuidgen | tr '[:upper:]' '[:lower:]') + +container=$(create-container.sh \ + -f "$AGENT_CERT_FILE" \ + -p "$AGENT_CERT_PWD" \ + -b "$END_USER_BASE_URL" \ + --title "Test container" \ + --slug "$slug" \ + --parent "$END_USER_BASE_URL") + +# PATCH with empty result (DELETE all triples) should succeed and delete the container + +update=$(cat <<EOF +DELETE +{ + <${container}> ?p ?o +} +WHERE +{ + <${container}> ?p ?o +} +EOF +) + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -X PATCH \ + -H "Content-Type: application/sparql-update" \ + "$container" \ + --data-binary "$update" \ +| grep -q "$STATUS_NO_CONTENT" + +# verify the container was deleted + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "$container" \ +| grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/document-hierarchy/PATCH-empty-item.sh b/http-tests/document-hierarchy/PATCH-empty-item.sh new file mode 100755 index 000000000..26737efee --- /dev/null +++ b/http-tests/document-hierarchy/PATCH-empty-item.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# add agent to the writers group + +add-agent-to-group.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --agent "$AGENT_URI" \ + "${ADMIN_BASE_URL}acl/groups/writers/" + +# create an item with random slug + +slug=$(uuidgen | tr '[:upper:]' '[:lower:]') + +item=$(create-item.sh \ + -f "$AGENT_CERT_FILE" \ + -p "$AGENT_CERT_PWD" \ + -b "$END_USER_BASE_URL" \ + --title "Test item" \ + --slug "$slug" \ + --container "$END_USER_BASE_URL") + +# PATCH with empty result (DELETE all triples) should succeed and delete the item + +update=$(cat <<EOF +DELETE +{ + <${item}> ?p ?o +} +WHERE +{ + <${item}> ?p ?o +} +EOF +) + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -X PATCH \ + -H "Content-Type: application/sparql-update" \ + "$item" \ + --data-binary "$update" \ +| grep -q "$STATUS_NO_CONTENT" + +# verify the item was deleted + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "$item" \ +| grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/document-hierarchy/PATCH-empty-root-405.sh b/http-tests/document-hierarchy/PATCH-empty-root-405.sh new file mode 100755 index 000000000..88813e525 --- /dev/null +++ b/http-tests/document-hierarchy/PATCH-empty-root-405.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# add agent to the owners group + +add-agent-to-group.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --agent "$AGENT_URI" \ + "${ADMIN_BASE_URL}acl/groups/owners/" + +# check that it's not possible to PATCH the root document with an empty result (which would be treated as DELETE) + +update=$(cat <<EOF +DELETE +{ + <${END_USER_BASE_URL}> ?p ?o +} +WHERE +{ + <${END_USER_BASE_URL}> ?p ?o +} +EOF +) + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$AGENT_CERT_FILE":"$AGENT_CERT_PWD" \ + -X PATCH \ + -H "Content-Type: application/sparql-update" \ + "$END_USER_BASE_URL" \ + --data-binary "$update" \ +| grep -q "$STATUS_METHOD_NOT_ALLOWED" diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java index cdbff42ef..d170d7f56 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java @@ -315,6 +315,7 @@ public Response put(Model model, @QueryParam("default") @DefaultValue("false") B * @return response response object */ @PATCH + @Override public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI graphUriUnused) { if (updateRequest == null) throw new BadRequestException("SPARQL update not specified"); @@ -356,6 +357,9 @@ public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI grap for (Resource resource : changedResources) changedModel.add(existingModel.listStatements(resource, null, (RDFNode) null)); + // if PATCH results in an empty model, treat it as a DELETE request + if (changedModel.isEmpty()) return delete(Boolean.FALSE, getURI()); + validate(changedModel); // this would normally be done transparently by the ValidatingModelProvider put(dataset.getDefaultModel(), Boolean.FALSE, getURI()); From 15994eddaa4007910f086a1bbbdd9ad59a379f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 10 Jan 2026 14:16:12 +0100 Subject: [PATCH 47/64] Application settings feature (#264) * System config dataset uses named graphs * Settings endpoint * Settings endpoint As well as ACL authorizations for it * Test config fix * Frontend * Moved services to their own named graphs * Application settings form is shown New `lapp:application` property More UI labels moved to translations.rdf * `PATCH` gets sent from settings form * Saving app settings to RDF file works * HTTP tests for application settings * Removed unused class * Empty model returns 422 instead of 400 * Button CSS fix --- config/system.trig | 88 ++++--- docker-compose.yml | 2 +- http-tests/config/system.trig | 148 +++++++----- http-tests/misc/GET-settings-etag.sh | 27 +++ http-tests/misc/GET-settings.sh | 41 ++++ http-tests/misc/PATCH-settings-422.sh | 20 ++ http-tests/misc/PATCH-settings-empty-422.sh | 18 ++ http-tests/misc/PATCH-settings.sh | 64 +++++ platform/datasets/end-user.trig | 8 + platform/entrypoint.sh | 4 +- platform/namespace-ontology.trig.template | 2 +- platform/select-root-services.rq | 60 +++-- .../atomgraph/linkeddatahub/Application.java | 98 ++++++-- .../linkeddatahub/resource/Settings.java | 220 ++++++++++++++++++ .../server/model/impl/Dispatcher.java | 12 + .../com/atomgraph/linkeddatahub/lapp.ttl | 15 ++ .../atomgraph/linkeddatahub/css/bootstrap.css | 1 + .../xsl/bootstrap/2.3.2/client/form.xsl | 7 +- .../xsl/bootstrap/2.3.2/client/modal.xsl | 115 +++++++-- .../xsl/bootstrap/2.3.2/layout.xsl | 11 + .../xsl/bootstrap/2.3.2/translations.rdf | 48 ++++ .../atomgraph/linkeddatahub/xsl/client.xsl | 1 + 22 files changed, 852 insertions(+), 158 deletions(-) create mode 100755 http-tests/misc/GET-settings-etag.sh create mode 100755 http-tests/misc/GET-settings.sh create mode 100755 http-tests/misc/PATCH-settings-422.sh create mode 100755 http-tests/misc/PATCH-settings-empty-422.sh create mode 100755 http-tests/misc/PATCH-settings.sh create mode 100644 src/main/java/com/atomgraph/linkeddatahub/resource/Settings.java diff --git a/config/system.trig b/config/system.trig index 21cd69615..19c6a0979 100644 --- a/config/system.trig +++ b/config/system.trig @@ -15,41 +15,59 @@ # root admin -<urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ; - dct:title "LinkedDataHub admin" ; - # ldt:base <https://admin.localhost:4443/> ; - lapp:origin <https://admin.localhost:4443> ; - ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; - ldt:service <urn:linkeddatahub:services/admin> ; - ac:stylesheet <static/xsl/admin/layout.xsl> ; - lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; - lapp:frontendProxy <http://varnish-frontend:6060/> . - -<urn:linkeddatahub:services/admin> a sd:Service ; - dct:title "LinkedDataHub admin service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-admin:3030/ds/> ; - a:graphStore <http://fuseki-admin:3030/ds/> ; - a:quadStore <http://fuseki-admin:3030/ds/> ; - lapp:backendProxy <http://varnish-admin/> . +<urn:linkeddatahub:apps/admin> +{ + <urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ; + dct:title "LinkedDataHub admin" ; + # ldt:base <https://admin.localhost:4443/> ; + lapp:origin <https://admin.localhost:4443> ; + ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; + ldt:service <urn:linkeddatahub:services/admin> ; + ac:stylesheet <static/xsl/admin/layout.xsl> ; + lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; + lapp:frontendProxy <http://varnish-frontend:6060/> . + +} + +<urn:linkeddatahub:services/admin> +{ + + <urn:linkeddatahub:services/admin> a sd:Service ; + dct:title "LinkedDataHub admin service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-admin:3030/ds/> ; + a:graphStore <http://fuseki-admin:3030/ds/> ; + a:quadStore <http://fuseki-admin:3030/ds/> ; + lapp:backendProxy <http://varnish-admin/> . + +} # root end-user -<urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ; - dct:title "LinkedDataHub" ; - # ldt:base <https://localhost:4443/> ; - lapp:origin <https://localhost:4443> ; - ldt:ontology <https://localhost:4443/ns#> ; - ldt:service <urn:linkeddatahub:services/end-user> ; - ac:stylesheet <static/xsl/layout.xsl> ; - lapp:adminApplication <urn:linkeddatahub:apps/admin> ; - lapp:frontendProxy <http://varnish-frontend:6060/> ; - lapp:public true . - -<urn:linkeddatahub:services/end-user> a sd:Service ; - dct:title "LinkedDataHub service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-end-user:3030/ds/> ; - a:graphStore <http://fuseki-end-user:3030/ds/> ; - a:quadStore <http://fuseki-end-user:3030/ds/> ; - lapp:backendProxy <http://varnish-end-user/> . +<urn:linkeddatahub:apps/end-user> +{ + <urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ; + dct:title "LinkedDataHub" ; + # ldt:base <https://localhost:4443/> ; + lapp:origin <https://localhost:4443> ; + ldt:ontology <https://localhost:4443/ns#> ; + ldt:service <urn:linkeddatahub:services/end-user> ; + ac:stylesheet <static/xsl/layout.xsl> ; + lapp:adminApplication <urn:linkeddatahub:apps/admin> ; + lapp:frontendProxy <http://varnish-frontend:6060/> ; + lapp:public true . + +} + +<urn:linkeddatahub:services/end-user> +{ + + <urn:linkeddatahub:services/end-user> a sd:Service ; + dct:title "LinkedDataHub service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-end-user:3030/ds/> ; + a:graphStore <http://fuseki-end-user:3030/ds/> ; + a:quadStore <http://fuseki-end-user:3030/ds/> ; + lapp:backendProxy <http://varnish-end-user/> . + +} diff --git a/docker-compose.yml b/docker-compose.yml index 7b8fffd36..8f16be46b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -93,7 +93,7 @@ services: - ./datasets/secretary:/var/linkeddatahub/datasets/secretary - ./uploads:/var/www/linkeddatahub/uploads - ./config/dev.log4j.properties:/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/log4j.properties:ro - - ./config/system.trig:/var/linkeddatahub/datasets/system.trig:ro + - ./config/system.trig:/var/linkeddatahub/datasets/system.trig fuseki-admin: image: atomgraph/fuseki:4.7.0 user: root # otherwise fuseki user does not have permissions to the mounted folder which is owner by root diff --git a/http-tests/config/system.trig b/http-tests/config/system.trig index 277499e5d..428f205bf 100644 --- a/http-tests/config/system.trig +++ b/http-tests/config/system.trig @@ -15,76 +15,104 @@ # root admin -<urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ; - dct:title "LinkedDataHub admin" ; - # ldt:base <https://admin.localhost:4443/> ; - lapp:origin <https://admin.localhost:4443> ; - ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; - ldt:service <urn:linkeddatahub:services/admin> ; - lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; - lapp:frontendProxy <http://varnish-frontend:6060/> . +<urn:linkeddatahub:apps/admin> +{ + <urn:linkeddatahub:apps/admin> a lapp:Application, lapp:AdminApplication ; + dct:title "LinkedDataHub admin" ; + # ldt:base <https://admin.localhost:4443/> ; + lapp:origin <https://admin.localhost:4443> ; + ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; + ldt:service <urn:linkeddatahub:services/admin> ; + ac:stylesheet <static/xsl/admin/layout.xsl> ; + lapp:endUserApplication <urn:linkeddatahub:apps/end-user> ; + lapp:frontendProxy <http://varnish-frontend:6060/> . +} -<urn:linkeddatahub:services/admin> a sd:Service ; - dct:title "LinkedDataHub admin service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-admin:3030/ds/> ; - a:graphStore <http://fuseki-admin:3030/ds/> ; - a:quadStore <http://fuseki-admin:3030/ds/> ; - lapp:backendProxy <http://varnish-admin/> . +<urn:linkeddatahub:services/admin> +{ + <urn:linkeddatahub:services/admin> a sd:Service ; + dct:title "LinkedDataHub admin service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-admin:3030/ds/> ; + a:graphStore <http://fuseki-admin:3030/ds/> ; + a:quadStore <http://fuseki-admin:3030/ds/> ; + lapp:backendProxy <http://varnish-admin/> . +} # root end-user -<urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ; - dct:title "LinkedDataHub" ; - # ldt:base <https://localhost:4443/> ; - lapp:origin <https://localhost:4443> ; - ldt:ontology <https://localhost:4443/ns#> ; - ldt:service <urn:linkeddatahub:services/end-user> ; - lapp:adminApplication <urn:linkeddatahub:apps/admin> ; - lapp:frontendProxy <http://varnish-frontend:6060/> ; - lapp:public true . +<urn:linkeddatahub:apps/end-user> +{ + <urn:linkeddatahub:apps/end-user> a lapp:Application, lapp:EndUserApplication ; + dct:title "LinkedDataHub" ; + # ldt:base <https://localhost:4443/> ; + lapp:origin <https://localhost:4443> ; + ldt:ontology <https://localhost:4443/ns#> ; + ldt:service <urn:linkeddatahub:services/end-user> ; + ac:stylesheet <static/xsl/layout.xsl> ; + lapp:adminApplication <urn:linkeddatahub:apps/admin> ; + lapp:frontendProxy <http://varnish-frontend:6060/> ; + lapp:public true . +} -<urn:linkeddatahub:services/end-user> a sd:Service ; - dct:title "LinkedDataHub service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-end-user:3030/ds/> ; - a:graphStore <http://fuseki-end-user:3030/ds/> ; - a:quadStore <http://fuseki-end-user:3030/ds/> ; - lapp:backendProxy <http://varnish-end-user/> . +<urn:linkeddatahub:services/end-user> +{ + <urn:linkeddatahub:services/end-user> a sd:Service ; + dct:title "LinkedDataHub service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-end-user:3030/ds/> ; + a:graphStore <http://fuseki-end-user:3030/ds/> ; + a:quadStore <http://fuseki-end-user:3030/ds/> ; + lapp:backendProxy <http://varnish-end-user/> . +} # test admin -<urn:linkeddatahub:apps/test/admin> a lapp:Application, lapp:AdminApplication ; - dct:title "Test admin" ; - lapp:origin <https://admin.test.localhost:4443> ; - ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; - ldt:service <urn:linkeddatahub:services/test/admin> ; - lapp:endUserApplication <urn:linkeddatahub:apps/test/end-user> ; - lapp:frontendProxy <http://varnish-frontend:6060/> . +<urn:linkeddatahub:apps/test/admin> +{ + <urn:linkeddatahub:apps/test/admin> a lapp:Application, lapp:AdminApplication ; + dct:title "Test admin" ; + lapp:origin <https://admin.test.localhost:4443> ; + ldt:ontology <https://w3id.org/atomgraph/linkeddatahub/admin#> ; + ldt:service <urn:linkeddatahub:services/test/admin> ; + ac:stylesheet <static/xsl/admin/layout.xsl> ; + lapp:endUserApplication <urn:linkeddatahub:apps/test/end-user> ; + lapp:frontendProxy <http://varnish-frontend:6060/> . +} -<urn:linkeddatahub:services/test/admin> a sd:Service ; - dct:title "Test admin service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-admin:3030/ds/> ; - a:graphStore <http://fuseki-admin:3030/ds/> ; - a:quadStore <http://fuseki-admin:3030/ds/> ; - lapp:backendProxy <http://varnish-admin/> . +<urn:linkeddatahub:services/test/admin> +{ + <urn:linkeddatahub:services/test/admin> a sd:Service ; + dct:title "Test admin service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-admin:3030/ds/> ; + a:graphStore <http://fuseki-admin:3030/ds/> ; + a:quadStore <http://fuseki-admin:3030/ds/> ; + lapp:backendProxy <http://varnish-admin/> . +} # test end-user -<urn:linkeddatahub:apps/test/end-user> a lapp:Application, lapp:EndUserApplication ; - dct:title "Test" ; - lapp:origin <https://test.localhost:4443> ; - ldt:ontology <https://test.localhost:4443/ns#> ; - ldt:service <urn:linkeddatahub:services/test/end-user> ; - lapp:adminApplication <urn:linkeddatahub:apps/test/admin> ; - lapp:frontendProxy <http://varnish-frontend:6060/> ; - lapp:public true . +<urn:linkeddatahub:apps/test/end-user> +{ + <urn:linkeddatahub:apps/test/end-user> a lapp:Application, lapp:EndUserApplication ; + dct:title "Test" ; + lapp:origin <https://test.localhost:4443> ; + ldt:ontology <https://test.localhost:4443/ns#> ; + ldt:service <urn:linkeddatahub:services/test/end-user> ; + ac:stylesheet <static/xsl/layout.xsl> ; + lapp:adminApplication <urn:linkeddatahub:apps/test/admin> ; + lapp:frontendProxy <http://varnish-frontend:6060/> ; + lapp:public true . +} -<urn:linkeddatahub:services/test/end-user> a sd:Service ; - dct:title "Test service" ; - sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; - sd:endpoint <http://fuseki-end-user:3030/ds/> ; - a:graphStore <http://fuseki-end-user:3030/ds/> ; - a:quadStore <http://fuseki-end-user:3030/ds/> ; - lapp:backendProxy <http://varnish-end-user/> . +<urn:linkeddatahub:services/test/end-user> +{ + <urn:linkeddatahub:services/test/end-user> a sd:Service ; + dct:title "Test service" ; + sd:supportedLanguage sd:SPARQL11Query, sd:SPARQL11Update ; + sd:endpoint <http://fuseki-end-user:3030/ds/> ; + a:graphStore <http://fuseki-end-user:3030/ds/> ; + a:quadStore <http://fuseki-end-user:3030/ds/> ; + lapp:backendProxy <http://varnish-end-user/> . +} diff --git a/http-tests/misc/GET-settings-etag.sh b/http-tests/misc/GET-settings-etag.sh new file mode 100755 index 000000000..d1d837aaf --- /dev/null +++ b/http-tests/misc/GET-settings-etag.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test: GET /settings with If-None-Match - Conditional GET with matching ETag + +# First GET to obtain ETag +response=$(curl -i -k -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}settings") + +# Extract ETag +etag=$(echo "$response" | grep -i "ETag:" | sed 's/ETag: //i' | tr -d '\r\n') + +# Second GET with If-None-Match +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + -H "If-None-Match: $etag" \ + "${END_USER_BASE_URL}settings" \ +| grep -q "$STATUS_NOT_MODIFIED" diff --git a/http-tests/misc/GET-settings.sh b/http-tests/misc/GET-settings.sh new file mode 100755 index 000000000..d28ee1fcc --- /dev/null +++ b/http-tests/misc/GET-settings.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test: GET /settings - Retrieve current application settings + +response=$(curl -k -w "%{http_code}\n" -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}settings") + +# Extract status code (last line) and body (everything else) +status=$(echo "$response" | tail -n 1) +body=$(echo "$response" | sed '$d') + +# Verify 200 OK response +if [ "$status" != "$STATUS_OK" ]; then + exit 1 +fi + +# Verify response contains expected application data +if ! echo "$body" | grep -q '<urn:linkeddatahub:apps/end-user>'; then + exit 1 +fi + +if ! echo "$body" | grep -q '<https://w3id.org/atomgraph/linkeddatahub/apps#EndUserApplication>'; then + exit 1 +fi + +if ! echo "$body" | grep -q '"LinkedDataHub"'; then + exit 1 +fi + +if ! echo "$body" | grep -q '<https://localhost:4443>'; then + exit 1 +fi diff --git a/http-tests/misc/PATCH-settings-422.sh b/http-tests/misc/PATCH-settings-422.sh new file mode 100755 index 000000000..8da3567f9 --- /dev/null +++ b/http-tests/misc/PATCH-settings-422.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test: PATCH /settings - Remove mandatory property (should fail validation) + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -X PATCH \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Content-Type: application/sparql-update" \ + -d "PREFIX lapp: <https://w3id.org/atomgraph/linkeddatahub/apps#> +DELETE { ?app lapp:origin ?origin } +WHERE { ?app lapp:origin ?origin }" \ + "${END_USER_BASE_URL}settings" \ +| grep -q "$STATUS_UNPROCESSABLE_ENTITY" diff --git a/http-tests/misc/PATCH-settings-empty-422.sh b/http-tests/misc/PATCH-settings-empty-422.sh new file mode 100755 index 000000000..7f62c6361 --- /dev/null +++ b/http-tests/misc/PATCH-settings-empty-422.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test: PATCH /settings - Empty result (should fail with 422) + +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -X PATCH \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Content-Type: application/sparql-update" \ + -d "DELETE WHERE { ?s ?p ?o }" \ + "${END_USER_BASE_URL}settings" \ +| grep -q "$STATUS_UNPROCESSABLE_ENTITY" diff --git a/http-tests/misc/PATCH-settings.sh b/http-tests/misc/PATCH-settings.sh new file mode 100755 index 000000000..712bf6315 --- /dev/null +++ b/http-tests/misc/PATCH-settings.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test: PATCH /settings - Valid update (change title) + +# Get initial ETag +initial_response=$(curl -i -k -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}settings") + +etag=$(echo "$initial_response" | grep -i "ETag:" | sed 's/ETag: //i' | tr -d '\r\n') + +# PATCH to update title +( +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -X PATCH \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Content-Type: application/sparql-update" \ + -d "PREFIX dct: <http://purl.org/dc/terms/> +DELETE { ?app dct:title ?title } +INSERT { ?app dct:title \"Updated Title\" } +WHERE { ?app dct:title ?title }" \ + "${END_USER_BASE_URL}settings" +) \ +| grep -q "$STATUS_NO_CONTENT" + +# Verify changes were persisted by GET +verify_response=$(curl -k -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}settings") + +if ! echo "$verify_response" | grep -q "Updated Title"; then + exit 1 +fi + +# Verify ETag changed after update +verify_etag_response=$(curl -i -k -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Accept: application/n-triples" \ + "${END_USER_BASE_URL}settings") + +new_etag=$(echo "$verify_etag_response" | grep -i "ETag:" | sed 's/ETag: //i' | tr -d '\r\n') + +if [ "$etag" = "$new_etag" ]; then + exit 1 +fi + +# Restore original title for subsequent tests +curl -k -w "%{http_code}\n" -o /dev/null -s -X PATCH \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -H "Content-Type: application/sparql-update" \ + -d "PREFIX dct: <http://purl.org/dc/terms/> +DELETE { ?app dct:title ?title } +INSERT { ?app dct:title \"LinkedDataHub\" } +WHERE { ?app dct:title ?title }" \ + "${END_USER_BASE_URL}settings" > /dev/null diff --git a/platform/datasets/end-user.trig b/platform/datasets/end-user.trig index 4c3574b08..2608b6a39 100644 --- a/platform/datasets/end-user.trig +++ b/platform/datasets/end-user.trig @@ -389,6 +389,14 @@ WHERE } +<settings> +{ + + <settings> a foaf:Document ; + dct:title "Settings endpoint" . + +} + <services/dbpedia/> { diff --git a/platform/entrypoint.sh b/platform/entrypoint.sh index 6a4bb2e6d..1fbe571cf 100755 --- a/platform/entrypoint.sh +++ b/platform/entrypoint.sh @@ -625,10 +625,10 @@ for app in "${apps[@]}"; do # append ownership metadata to apps if it's not present (apps have to be URI resources!) if [ -z "$end_user_owner" ]; then - echo "<${end_user_app}> <http://xmlns.com/foaf/0.1/maker> <${OWNER_URI}> ." >> "$based_context_dataset" + echo "<${end_user_app}> <http://xmlns.com/foaf/0.1/maker> <${OWNER_URI}> <${end_user_app}> ." >> "$based_context_dataset" fi if [ -z "$admin_owner" ]; then - echo "<${admin_app}> <http://xmlns.com/foaf/0.1/maker> <${OWNER_URI}> ." >> "$based_context_dataset" + echo "<${admin_app}> <http://xmlns.com/foaf/0.1/maker> <${OWNER_URI}> <${admin_app}> ." >> "$based_context_dataset" fi printf "\n### Quad store URL of the root end-user service: %s\n" "$end_user_quad_store_url" diff --git a/platform/namespace-ontology.trig.template b/platform/namespace-ontology.trig.template index c62472479..a3531ccb8 100644 --- a/platform/namespace-ontology.trig.template +++ b/platform/namespace-ontology.trig.template @@ -107,7 +107,7 @@ rdfs:label "Full control" ; rdfs:comment "Allows full read/write access to all application resources" ; acl:accessToClass dh:Item, dh:Container, def:Root ; - acl:accessTo <${end_user_origin}/sparql>, <${end_user_origin}/importer>, <${end_user_origin}/add>, <${end_user_origin}/generate>, <${end_user_origin}/ns> ; + acl:accessTo <${end_user_origin}/sparql>, <${end_user_origin}/importer>, <${end_user_origin}/add>, <${end_user_origin}/generate>, <${end_user_origin}/ns>, <${end_user_origin}/settings> ; acl:mode acl:Read, acl:Append, acl:Write, acl:Control ; acl:agentGroup <${admin_origin}/acl/groups/owners/#this> . diff --git a/platform/select-root-services.rq b/platform/select-root-services.rq index 4c6d67546..30477551d 100644 --- a/platform/select-root-services.rq +++ b/platform/select-root-services.rq @@ -7,31 +7,45 @@ PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?endUserApp ?endUserOrigin ?endUserQuadStore ?endUserEndpoint ?endUserAuthUser ?endUserAuthPwd ?endUserMaker ?adminApp ?adminOrigin ?adminQuadStore ?adminEndpoint ?adminAuthUser ?adminAuthPwd ?adminMaker { - ?endUserApp lapp:origin ?endUserOrigin ; - ldt:service ?endUserService ; - lapp:adminApplication ?adminApp . - ?adminApp ldt:service ?adminService ; - lapp:origin ?adminOrigin . - ?endUserService a:quadStore ?endUserQuadStore ; - sd:endpoint ?endUserEndpoint . - ?adminService a:quadStore ?adminQuadStore ; - sd:endpoint ?adminEndpoint . - OPTIONAL + GRAPH ?endUserAppGraph { - ?endUserService a:authUser ?endUserAuthUser ; - a:authPwd ?endUserAuthPwd . + ?endUserApp lapp:origin ?endUserOrigin ; + ldt:service ?endUserService ; + lapp:adminApplication ?adminApp . + + GRAPH ?endUserServiceGraph + { + ?endUserService a:quadStore ?endUserQuadStore ; + sd:endpoint ?endUserEndpoint . + OPTIONAL + { + ?endUserService a:authUser ?endUserAuthUser ; + a:authPwd ?endUserAuthPwd . + } + OPTIONAL + { + ?endUserService foaf:maker ?endUserMaker + } + } } - OPTIONAL + GRAPH ?adminAppGraph { - ?adminService a:authUser ?adminAuthUser ; - a:authPwd ?adminAuthPwd . - } - OPTIONAL - { - ?endUserService foaf:maker ?endUserMaker - } - OPTIONAL - { - ?adminService foaf:maker ?adminMaker + ?adminApp ldt:service ?adminService ; + lapp:origin ?adminOrigin . + + GRAPH ?adminServiceGraph + { + ?adminService a:quadStore ?adminQuadStore ; + sd:endpoint ?adminEndpoint . + OPTIONAL + { + ?adminService a:authUser ?adminAuthUser ; + a:authPwd ?adminAuthPwd . + } + OPTIONAL + { + ?adminService foaf:maker ?adminMaker + } + } } } \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index e28066e34..e3b0f30b3 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -294,9 +294,9 @@ public class Application extends ResourceConfig private final boolean enableWebIDSignUp; private final String oidcRefreshTokensPropertiesPath; private final Properties oidcRefreshTokens; + private final URI contextDatasetURI; + private final Dataset contextDataset; - private Dataset contextDataset; - /** * Constructs system application and configures it using sevlet config. * @@ -313,6 +313,7 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti servletConfig.getServletContext().getInitParameter(A.cacheModelLoads.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(A.cacheModelLoads.getURI())) : true, servletConfig.getServletContext().getInitParameter(A.preemptiveAuth.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(A.preemptiveAuth.getURI())) : false, new PrefixMapper(servletConfig.getServletContext().getInitParameter(AC.prefixMapping.getURI()) != null ? servletConfig.getServletContext().getInitParameter(AC.prefixMapping.getURI()) : null), + servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI()) != null ? servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI()) : null, com.atomgraph.client.Application.getSource(servletConfig.getServletContext(), servletConfig.getServletContext().getInitParameter(AC.stylesheet.getURI()) != null ? servletConfig.getServletContext().getInitParameter(AC.stylesheet.getURI()) : null), servletConfig.getServletContext().getInitParameter(AC.cacheStylesheet.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(AC.cacheStylesheet.getURI())) : false, servletConfig.getServletContext().getInitParameter(AC.resolvingUncached.getURI()) != null ? Boolean.parseBoolean(servletConfig.getServletContext().getInitParameter(AC.resolvingUncached.getURI())) : true, @@ -355,14 +356,6 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti servletConfig.getServletContext().getInitParameter(ORCID.clientID.getURI()) != null ? servletConfig.getServletContext().getInitParameter(ORCID.clientID.getURI()) : null, servletConfig.getServletContext().getInitParameter(ORCID.clientSecret.getURI()) != null ? servletConfig.getServletContext().getInitParameter(ORCID.clientSecret.getURI()) : null ); - - URI contextDatasetURI = servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI()) != null ? new URI(servletConfig.getServletContext().getInitParameter(LDHC.contextDataset.getURI())) : null; - if (contextDatasetURI == null) - { - if (log.isErrorEnabled()) log.error("Context dataset URI '{}' not configured", LDHC.contextDataset.getURI()); - throw new ConfigurationException(LDHC.contextDataset); - } - this.contextDataset = getDataset(servletConfig.getServletContext(), contextDatasetURI); } /** @@ -374,6 +367,7 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti * @param cacheModelLoads true if model loads should be cached * @param preemptiveAuth true if HTTP Basic auth credentials should be sent preemptively * @param locationMapper Jena's <code>LocationMapper</code> instance + * @param contextDatasetURIString location of the context dataset * @param stylesheet stylesheet URI * @param cacheStylesheet true if stylesheet should be cached * @param resolvingUncached true if XLST processor should dereference URLs that are not cached @@ -418,7 +412,8 @@ public Application(@Context ServletConfig servletConfig) throws URISyntaxExcepti */ public Application(final ServletConfig servletConfig, final MediaTypes mediaTypes, final Integer maxGetRequestSize, final boolean cacheModelLoads, final boolean preemptiveAuth, - final LocationMapper locationMapper, final Source stylesheet, final boolean cacheStylesheet, final boolean resolvingUncached, + final LocationMapper locationMapper, final String contextDatasetURIString, + final Source stylesheet, final boolean cacheStylesheet, final boolean resolvingUncached, final String clientKeyStoreURIString, final String clientKeyStorePassword, final String secretaryCertAlias, final String clientTrustStoreURIString, final String clientTrustStorePassword, @@ -433,6 +428,13 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType final String googleClientID, final String googleClientSecret, final String orcidClientID, final String orcidClientSecret) { + if (contextDatasetURIString == null) + { + if (log.isErrorEnabled()) log.error("Context dataset URI '{}' not configured", LDHC.contextDataset.getURI()); + throw new ConfigurationException(LDHC.contextDataset); + } + this.contextDatasetURI = URI.create(contextDatasetURIString); + if (clientKeyStoreURIString == null) { if (log.isErrorEnabled()) log.error("Client key store ({}) not configured", LDHC.clientKeyStore.getURI()); @@ -664,6 +666,8 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType try { + this.contextDataset = getDataset(servletConfig.getServletContext(), contextDatasetURI); + keyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream keyStoreInputStream = new FileInputStream(new java.io.File(new URI(clientKeyStoreURIString)))) { @@ -1974,7 +1978,7 @@ public URI getUploadRoot() /** * Returns RDF dataset with LinkedDataHub application descriptions. - * + * * @return RDF dataset */ protected Dataset getContextDataset() @@ -1982,19 +1986,81 @@ protected Dataset getContextDataset() return contextDataset; } + /** + * Returns the URI of the context dataset file. + * + * @return context dataset URI + */ + protected URI getContextDatasetURI() + { + return contextDatasetURI; + } + /** * Returns RDF model with LinkedDataHub application descriptions. - * - * @return RDF model + * This method returns a union of all named graphs from the context dataset. + * + * @return RDF model (read-only union of all named graphs) */ public Model getContextModel() { - return ModelFactory.createModelForGraph(new GraphReadOnly(getContextDataset().getDefaultModel().getGraph())); + return ModelFactory.createModelForGraph(new GraphReadOnly(getContextDataset().getUnionModel().getGraph())); + } + + /** + * Retrieves a dataspace model by application from the context dataset. + * + * @param application the dataspace application + * @return the model for the specified dataspace, or null if not found + */ + public Model getDataspaceModel(com.atomgraph.linkeddatahub.apps.model.Application application) + { + if (application == null) throw new IllegalArgumentException("Application cannot be null"); + return ModelFactory.createModelForGraph(new GraphReadOnly(getContextDataset().getNamedModel(application.getURI()).getGraph())); + } + + /** + * Updates a dataspace by replacing its named graph with a new Model. + * This is a template method that can be overridden by subclasses to provide alternative implementations + * (e.g., HTTP-based updates using GraphStoreClient to a remote triplestore). + * + * Default implementation uses file-based operations via SystemConfigFileManager. + * + * @param application the dataspace application to update + * @param newModel the new RDF model to replace the existing named graph + * @throws IOException if an I/O error occurs + */ + public void updateApp(com.atomgraph.linkeddatahub.apps.model.Application application, Model newModel) throws IOException + { + if (application == null) throw new IllegalArgumentException("Application cannot be null"); + if (newModel == null) throw new IllegalArgumentException("Model cannot be null"); + + synchronized (getContextDataset()) + { + String dataspaceURI = application.getURI(); + + // Update the named graph in the dataset + getContextDataset().removeNamedModel(dataspaceURI). + addNamedModel(dataspaceURI, newModel); + + // Write the updated dataset back to file using RDFDataMgr + // Support both absolute file:// URIs and relative webapp paths (like getDataset does) + try (java.io.OutputStream out = (getContextDatasetURI().isAbsolute() ? + new FileOutputStream(new java.io.File(getContextDatasetURI())) : + new FileOutputStream(getServletConfig().getServletContext().getRealPath(getContextDatasetURI().toString())))) + { + Lang lang = RDFDataMgr.determineLang(getContextDatasetURI().toString(), null, null); + if (lang == null) throw new IOException("Could not determine RDF format from dataset URI: " + getContextDatasetURI().toString()); + + RDFDataMgr.write(out, getContextDataset(), lang); + if (log.isInfoEnabled()) log.info("Updated dataspace <{}> in context dataset: {}", dataspaceURI, getContextDatasetURI()); + } + } } /** * Returns true if configured to invalidate HTTP proxy cache of triplestore results. - * + * * @return true if invalidated */ public boolean isInvalidateCache() diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Settings.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Settings.java new file mode 100644 index 000000000..ea051eec8 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Settings.java @@ -0,0 +1,220 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.resource; + +import com.atomgraph.core.util.ModelUtils; +import com.atomgraph.linkeddatahub.apps.model.Application; +import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; +import com.atomgraph.linkeddatahub.vocabulary.LAPP; +import jakarta.inject.Inject; +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.InternalServerErrorException; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.PATCH; +import jakarta.ws.rs.WebApplicationException; +import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.EntityTag; +import jakarta.ws.rs.core.Request; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.MessageBodyReader; +import jakarta.ws.rs.ext.Providers; +import java.io.IOException; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.update.UpdateAction; +import org.apache.jena.update.UpdateRequest; +import org.apache.jena.vocabulary.RDF; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * JAX-RS resource for updating dataspace settings. + * Handles POST requests with RDF data representing the updated dataspace configuration. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class Settings +{ + private static final Logger log = LoggerFactory.getLogger(Settings.class); + + private final Application application; + private final com.atomgraph.linkeddatahub.Application system; + private final Providers providers; + private final Request request; + + /** + * Constructs the Settings endpoint. + * + * @param application the current dataspace application + * @param system the system application + * @param providers JAX-RS provider registry + * @param request JAX-RS request context + */ + @Inject + public Settings(Application application, com.atomgraph.linkeddatahub.Application system, @Context Providers providers, @Context Request request) + { + this.application = application; + this.system = system; + this.providers = providers; + this.request = request; + } + + /** + * Retrieves the dataspace settings from the context dataset. + * + * @return the dataspace resource as RDF + */ + @GET + public Response get() + { + Model dataspaceModel = getSystem().getDataspaceModel(getApplication()); + + if (dataspaceModel == null || dataspaceModel.isEmpty()) + { + if (log.isWarnEnabled()) log.warn("No settings found for dataspace <{}> in context dataset", getApplication().getURI()); + return Response.status(Response.Status.NOT_FOUND).build(); + } + + if (log.isDebugEnabled()) log.debug("Retrieved settings for dataspace <{}>", getApplication().getURI()); + + EntityTag entityTag = getEntityTag(dataspaceModel); + Response.ResponseBuilder rb = getRequest().evaluatePreconditions(entityTag); + if (rb != null) return rb.build(); + + return Response.ok(dataspaceModel). + tag(entityTag). + build(); + } + + /** + * Updates the dataspace settings by executing a SPARQL UPDATE request. + * Accepts SPARQL update as the request body which is executed in the context of the dataspace named graph. + * + * @param updateRequest SPARQL update + * @return response indicating success or failure + * @throws java.io.IOException + */ + @PATCH + public Response patch(UpdateRequest updateRequest) throws IOException + { + if (updateRequest == null) throw new BadRequestException("SPARQL update not specified"); + + if (log.isDebugEnabled()) log.debug("PATCH request for dataspace <{}>", getApplication().getURI()); + if (log.isDebugEnabled()) log.debug("PATCH update string: {}", updateRequest.toString()); + + Model dataspaceModel = getSystem().getDataspaceModel(getApplication()); + if (dataspaceModel == null || dataspaceModel.isEmpty()) + throw new NotFoundException("No settings found for dataspace <" + getApplication().getURI() + "> in context dataset"); + + // Create a mutable copy since getDataspaceModel() returns a read-only view + Model mutableModel = ModelFactory.createDefaultModel().add(dataspaceModel); + + // Execute the SPARQL UPDATE on the dataspace model in memory + Dataset dataset = DatasetFactory.wrap(mutableModel); + UpdateAction.execute(updateRequest, dataset); + + // Verify the application resource still exists with correct type after PATCH + Resource appResource = ResourceFactory.createResource(getApplication().getURI()); + if (!mutableModel.contains(appResource, RDF.type, LAPP.EndUserApplication)) + { + if (log.isWarnEnabled()) log.warn("PATCH removed application resource or its type for <{}>", getApplication().getURI()); + throw new WebApplicationException("PATCH cannot remove the application resource or its type", UNPROCESSABLE_ENTITY.getStatusCode()); // 422 Unprocessable Entity + } + + // validate the updated model + validate(mutableModel); + + // Write the updated model back to the context dataset file + getSystem().updateApp(getApplication(), mutableModel); + + if (log.isInfoEnabled()) log.info("Updated settings for dataspace <{}> via PATCH", getApplication().getURI()); + + return Response.noContent().build(); + } + + /** + * Returns the current dataspace application. + * + * @return the application + */ + public Application getApplication() + { + return application; + } + + /** + * Returns the system application. + * + * @return the system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns the JAX-RS providers registry. + * + * @return the providers + */ + public Providers getProviders() + { + return providers; + } + + /** + * Validates model against SPIN and SHACL constraints. + * + * @param model RDF model + * @return validated model + */ + public Model validate(Model model) + { + MessageBodyReader<Model> reader = getProviders().getMessageBodyReader(Model.class, null, null, com.atomgraph.core.MediaType.APPLICATION_NTRIPLES_TYPE); + if (reader instanceof ValidatingModelProvider validatingModelProvider) return validatingModelProvider.processRead(model); + + throw new InternalServerErrorException("Could not obtain ValidatingModelProvider instance"); + } + + /** + * Returns the JAX-RS request context. + * + * @return the request + */ + public Request getRequest() + { + return request; + } + + /** + * Generates an ETag for the given model. + * + * @param model RDF model + * @return entity tag + */ + public EntityTag getEntityTag(Model model) + { + return new EntityTag(Long.toHexString(ModelUtils.hashModel(model))); + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java index 430427a60..451dc874f 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java @@ -25,6 +25,7 @@ import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; import com.atomgraph.linkeddatahub.resource.admin.pkg.InstallPackage; import com.atomgraph.linkeddatahub.resource.admin.pkg.UninstallPackage; +import com.atomgraph.linkeddatahub.resource.Settings; import com.atomgraph.linkeddatahub.resource.admin.SignUp; import com.atomgraph.linkeddatahub.resource.Graph; import com.atomgraph.linkeddatahub.resource.acl.Access; @@ -249,6 +250,17 @@ public Class getUninstallPackageEndpoint() return getProxyClass().orElse(UninstallPackage.class); } + /** + * Returns the endpoint for updating dataspace settings. + * + * @return endpoint resource + */ + @Path("settings") + public Class getSettingsEndpoint() + { + return getProxyClass().orElse(Settings.class); + } + /** * Returns the default JAX-RS resource class. * diff --git a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl index 819120f9b..887c75f9c 100644 --- a/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl +++ b/src/main/resources/com/atomgraph/linkeddatahub/lapp.ttl @@ -23,7 +23,21 @@ # PROPERTIES +:origin a owl:ObjectProperty, owl:FunctionalProperty, owl:InverseFunctionalProperty ; + rdfs:domain :Application ; + rdfs:range rdfs:Resource ; + rdfs:label "Origin" ; + rdfs:comment "The origin URI of an application, which serves as the base URI for all resources in the application's dataspace" ; + rdfs:isDefinedBy : . + +:application a owl:ObjectProperty, owl:FunctionalProperty ; + rdfs:range :Application ; + rdfs:label "Application" ; + rdfs:comment "Links a resource to an application" ; + rdfs:isDefinedBy : . + :adminApplication a owl:ObjectProperty, owl:FunctionalProperty, owl:InverseFunctionalProperty ; + rdfs:subPropertyOf :application ; owl:inverseOf :endUserApplication ; rdfs:domain :EndUserApplication ; rdfs:range :AdminApplication ; @@ -32,6 +46,7 @@ rdfs:isDefinedBy : . :endUserApplication a owl:ObjectProperty, owl:FunctionalProperty, owl:InverseFunctionalProperty ; + rdfs:subPropertyOf :application ; owl:inverseOf :adminApplication ; rdfs:domain :AdminApplication ; rdfs:range :EndUserApplication ; diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css index 4a8f2e490..a19d99fc9 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css @@ -9,6 +9,7 @@ body.embed { padding-top: 0; } .btn.dropdown-toggle.btn-apps { background-image: url('../icons/ic_apps_white_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } .btn.dropdown-toggle.btn-settings { background-image: url('../icons/settings_white_24dp.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } .btn.dropdown-toggle.btn-agent { background-image: url('../icons/ic_account_circle_white_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } +.dropdown-menu .btn-app-settings { background-color: inherit; display: block; text-align: left; width: 100%; padding-left: 20px; } .navbar-form .input-append { margin-top: 10px; } .navbar-form .input-append select { margin-top: 0; height: 34px; } .navbar-form .btn-search { background-image: url('../icons/ic_search_white_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl index 9e71186f8..ee16a428c 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl @@ -457,7 +457,8 @@ WHERE </xsl:document> </xsl:variable> <xsl:sequence select="map:merge(($context, map{ - 'document': $document + 'document': $document, + 'action': if (map:contains($context, 'action')) then $context('action') else ldh:href(ac:absolute-path(ldh:base-uri($document)), map{}) }), map{ 'duplicates': 'use-last' })"/> </xsl:function> @@ -514,7 +515,7 @@ WHERE <xsl:variable name="shapes" select="$context('shapes')" as="document-node()"/> <xsl:variable name="object-metadata" select="$context('object-metadata')" as="document-node()?"/> <xsl:variable name="method" select="$context('method')" as="xs:string"/> - <xsl:variable name="action" select="ldh:href(ac:absolute-path(ldh:base-uri($document)), map{})" as="xs:anyURI"/> + <xsl:variable name="action" select="$context('action')" as="xs:anyURI"/> <xsl:for-each select="$block"> <xsl:variable name="form" as="node()*"> @@ -652,13 +653,13 @@ WHERE <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="2"> <xsl:param name="block" select="ancestor::div[contains-token(@class, 'modal-constructor')]" as="element()"/> + <xsl:param name="about" select="$block/@about" as="xs:anyURI"/> <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> <xsl:variable name="form" select="." as="element()"/> <xsl:variable name="method" select="upper-case(@method)" as="xs:string"/> <xsl:variable name="id" select="ixsl:get($form, 'id')" as="xs:string"/> <xsl:variable name="action" select="ixsl:get($form, 'action')" as="xs:anyURI"/> <xsl:variable name="enctype" select="ixsl:get($form, 'enctype')" as="xs:string"/> - <xsl:variable name="about" select="$block/@about" as="xs:anyURI"/> <xsl:variable name="etag" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`'), 'etag')" as="xs:string"/> <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl index 4f63577a7..0ea02080d 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl @@ -362,7 +362,11 @@ LIMIT 10 <xsl:value-of select="$legend-label"/> </legend> - <p class="text-info">Ask for access to a restricted resource by making a request. It will be reviewed by the application's administrators.</p> + <p class="text-info"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'request-access-description', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </p> </div> <div class="modal-body"> @@ -375,10 +379,16 @@ LIMIT 10 <fieldset> <div> - <label for="request-access-for">Request access for</label> + <label for="request-access-for"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'request-access-for', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </label> <select id="request-access-for" class="input-block-level"> <option value="{$agent}"> - <xsl:value-of select="$agent"/> (me) + <xsl:value-of select="$agent"/> (<xsl:value-of> + <xsl:apply-templates select="key('resources', 'me', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of>) </option> </select> </div> @@ -391,8 +401,7 @@ LIMIT 10 <div class="form-actions modal-footer"> <button type="submit" class="{$button-class}"> <xsl:value-of> - <!-- <xsl:apply-templates select="key('resources', 'save', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> --> - Request + <xsl:apply-templates select="key('resources', 'request', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> </xsl:value-of> </button> <button type="button" class="btn btn-close"> @@ -419,7 +428,11 @@ LIMIT 10 <xsl:param name="base" select="lapp:origin($this)" as="xs:anyURI"/> <fieldset> - <legend>URL-based access</legend> + <legend> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'url-based-access', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </legend> <table class="table table-striped"> <colgroup> <col style="width: 55%;"/> @@ -429,7 +442,11 @@ LIMIT 10 </colgroup> <thead> <tr> - <th>URL</th> + <th> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'url', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </th> <xsl:for-each select="$access-modes"> <th> <xsl:value-of> @@ -468,7 +485,11 @@ LIMIT 10 </fieldset> <fieldset> - <legend>Class-based access</legend> + <legend> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'class-based-access', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </legend> <table class="table table-striped"> <colgroup> <col style="width: 55%;"/> @@ -478,7 +499,11 @@ LIMIT 10 </colgroup> <thead> <tr> - <th>Class name</th> + <th> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'class-name', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </th> <xsl:for-each select="$access-modes"> <th> <xsl:value-of> @@ -652,10 +677,9 @@ LIMIT 10 <div class="control-group required"> <input type="hidden" name="pu" value="&owl;sameAs"/> - <!-- TO-DO: localize label --> <label class="control-label" for="same-as-resource"> <xsl:value-of> - Same as + <xsl:apply-templates select="key('resources', 'same-as', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> </xsl:value-of> </label> <div class="controls"> @@ -673,7 +697,7 @@ LIMIT 10 </div> </div> </xsl:template> - + <!-- EVENT HANDLERS --> <!-- close modal first time message --> @@ -712,7 +736,56 @@ LIMIT 10 </xsl:with-param> </xsl:call-template> </xsl:template> - + + <xsl:template match="button[contains-token(@class, 'btn-app-settings')]" mode="ixsl:onclick"> + <xsl:param name="method" select="'patch'" as="xs:string"/> + <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> + + <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> + + <xsl:for-each select="$content-body"> + <xsl:result-document href="?." method="ixsl:append-content"> + <div class="modal modal-constructor fade in" about="{$lapp:application}"> + <div class="modal-header"> + <button type="button" class="close">×</button> + + <legend> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'application-settings', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </legend> + </div> + <div class="modal-body"> + <!-- to be injected --> + </div> + </div> + </xsl:result-document> + </xsl:for-each> + + <xsl:variable name="modal" select="$content-body/div[contains-token(@class, 'modal')][last()]" as="element()"/> + <xsl:variable name="block" select="$modal/div[contains-token(@class, 'modal-body')]" as="element()"/> + <xsl:variable name="request" select="map{ 'method': 'GET', 'href': resolve-uri('settings', ldt:base()), 'headers': map{ 'Accept': 'application/rdf+xml' } }" as="map(*)"/> + <xsl:variable name="context" as="map(*)" select=" + map{ + 'request': $request, + 'block': $block, + 'about': $lapp:application, + 'method': $method, + 'action': resolve-uri('settings', ldt:base()) + }"/> + <ixsl:promise select=" + ixsl:http-request($context('request')) + => ixsl:then(ldh:rethread-response($context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:load-edited-resource#1) + => ixsl:then(ldh:http-request-threaded#1) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:set-type-metadata#1) + => ixsl:then(ldh:wrap-into-document#1) + => ixsl:then(ldh:render-form#1) + " on-failure="ldh:promise-failure#1"/> + </xsl:template> + <xsl:template match="button[contains-token(@class, 'btn-access-form')]" mode="ixsl:onclick"> <!-- TO-DO: fix for admin apps --> <xsl:param name="this" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> @@ -874,7 +947,7 @@ LIMIT 10 </xsl:variable> <xsl:sequence select="$request[current-date() lt xs:date('2000-01-01')]"/> </xsl:template> - + <xsl:template match="input[contains-token(@class, 'subject-slug')]" mode="ixsl:onkeyup" priority="1"> <xsl:param name="slug" select="ixsl:get(., 'value')" as="xs:string?"/> <xsl:param name="rdf-post-subj-input" select="preceding-sibling::input[@name = 'su']" as="element()"/> @@ -941,7 +1014,7 @@ LIMIT 10 </xsl:for-each> </xsl:if> </xsl:template> - + <!-- form is submitted. TO-DO: split into multiple callbacks and avoid <xsl:choose>? --> <xsl:template name="ldh:ModalFormSubmit"> @@ -1081,7 +1154,11 @@ LIMIT 10 <xsl:for-each select="$container[not(./div[contains-token(@class, 'endpoint-classes')])]"> <xsl:result-document href="?." method="ixsl:append-content"> <div class="control-group required endpoint-classes"> - <label class="control-label">Classes</label> + <label class="control-label"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'classes', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </label> <div class="controls"></div> </div> </xsl:result-document> @@ -1136,7 +1213,11 @@ LIMIT 10 <xsl:for-each select="$container//div[contains-token(@class, 'endpoint-classes')]/div"> <xsl:result-document href="?." method="ixsl:replace-content"> <div class="alert alert-block"> - <strong>Error during query execution:</strong> + <strong> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'error-during-query', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </strong> <pre> <xsl:value-of select="$message"/> </pre> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl index 14cdf1a60..08f500bc6 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl @@ -377,6 +377,7 @@ LIMIT 100 //<![CDATA[ </xsl:text> <![CDATA[ + var appUri = ]]><xsl:value-of select="'"' || $lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/@rdf:about || '"'" disable-output-escaping="yes"/><![CDATA[; var baseUri = ]]><xsl:value-of select="'"' || $ldt:base || '"'" disable-output-escaping="yes"/><![CDATA[; var absolutePath = ]]><xsl:value-of select="'"' || ac:absolute-path(ldh:base-uri(.)) || '"'" disable-output-escaping="yes"/><![CDATA[; var ontologyUri = ]]><xsl:value-of select="'"' || $ldt:ontology || '"'" disable-output-escaping="yes"/><![CDATA[; @@ -442,6 +443,7 @@ LIMIT 100 const servicesRequestUri = "]]></xsl:text><xsl:value-of select="$app-request-uri"/><xsl:text disable-output-escaping="yes"><![CDATA["; const stylesheetParams = { "Q{https://w3id.org/atomgraph/client#}contextUri": contextUri, // servlet context URI + "Q{https://w3id.org/atomgraph/linkeddatahub/apps#}application": appUri, "Q{https://www.w3.org/ns/ldt#}base": baseUri, "Q{https://www.w3.org/ns/ldt#}ontology": ontologyUri, "Q{http://www.w3.org/ns/sparql-service-description#}endpoint": endpointUri, @@ -1245,6 +1247,15 @@ LIMIT 100 <ul class="dropdown-menu"> <xsl:if test="$foaf:Agent//@rdf:about and $lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/rdf:type/@rdf:resource = '&lapp;EndUserApplication'"> + <xsl:if test="$acl:mode = '&acl;Control'"> + <li> + <button class="btn btn-app-settings"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', '&lapp;Application', document(ac:document-uri('&lapp;')))" mode="ac:label"/> + </xsl:value-of> + </button> + </li> + </xsl:if> <li> <xsl:for-each select="$lapp:Application"> <a href="{key('resources', //*[lapp:origin/@rdf:resource = $lapp:origin]/lapp:adminApplication/(@rdf:resource, @rdf:nodeID))/lapp:origin/@rdf:resource}" target="_blank"> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf index 6c978c9a4..c56a2ee9c 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf @@ -419,4 +419,52 @@ <rdf:Description rdf:nodeID="remove-stmt"> <rdfs:label xml:lang="en-US">Remove this statement</rdfs:label> </rdf:Description> + <rdf:Description rdf:nodeID="application-settings"> + <rdfs:label xml:lang="en-US">Application settings</rdfs:label> + <rdfs:label xml:lang="es-ES">Ajustes de aplicación</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="request-access-description"> + <rdfs:label xml:lang="en-US">Ask for access to a restricted resource by making a request. It will be reviewed by the application's administrators.</rdfs:label> + <rdfs:label xml:lang="es-ES">Solicite acceso a un recurso restringido haciendo una solicitud. Será revisada por los administradores de la aplicación.</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="request-access-for"> + <rdfs:label xml:lang="en-US">Request access for</rdfs:label> + <rdfs:label xml:lang="es-ES">Solicitar acceso para</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="me"> + <rdfs:label xml:lang="en-US">me</rdfs:label> + <rdfs:label xml:lang="es-ES">yo</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="request"> + <rdfs:label xml:lang="en-US">Request</rdfs:label> + <rdfs:label xml:lang="es-ES">Solicitar</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="url-based-access"> + <rdfs:label xml:lang="en-US">URL-based access</rdfs:label> + <rdfs:label xml:lang="es-ES">Acceso basado en URL</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="url"> + <rdfs:label xml:lang="en-US">URL</rdfs:label> + <rdfs:label xml:lang="es-ES">URL</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="class-based-access"> + <rdfs:label xml:lang="en-US">Class-based access</rdfs:label> + <rdfs:label xml:lang="es-ES">Acceso basado en clase</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="class-name"> + <rdfs:label xml:lang="en-US">Class name</rdfs:label> + <rdfs:label xml:lang="es-ES">Nombre de clase</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="same-as"> + <rdfs:label xml:lang="en-US">Same as</rdfs:label> + <rdfs:label xml:lang="es-ES">Igual a</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="classes"> + <rdfs:label xml:lang="en-US">Classes</rdfs:label> + <rdfs:label xml:lang="es-ES">Clases</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="error-during-query"> + <rdfs:label xml:lang="en-US">Error during query execution:</rdfs:label> + <rdfs:label xml:lang="es-ES">Error durante la ejecución de la consulta:</rdfs:label> + </rdf:Description> </rdf:RDF> \ No newline at end of file diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl index 44f3a7599..2b2d9239a 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl @@ -115,6 +115,7 @@ extension-element-prefixes="ixsl" <xsl:include href="bootstrap/2.3.2/client/block/query.xsl"/> <xsl:param name="ac:contextUri" as="xs:anyURI"/> + <xsl:param name="lapp:application" as="xs:anyURI"/> <xsl:param name="ldt:base" as="xs:anyURI"/> <xsl:param name="ldh:requestUri" select="xs:anyURI(ixsl:location())" as="xs:anyURI"/> <xsl:param name="ldt:ontology" as="xs:anyURI"/> <!-- used in default.xsl --> From 72365010a8446cff16c600049115100bcb7615e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 10 Jan 2026 15:10:31 +0100 Subject: [PATCH 48/64] CHANGELOG update --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc263639f..1537d6751 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [5.2.0] - TBD +### Added +- Application settings form with modal UI for editing dataspace configuration +- Settings endpoint (`/settings`) with `GET` and `PATCH` support for dataspace settings +- HTTP tests for the settings endpoint +- LinkedDataHub packages system with install/uninstall functionality + +### Changed +- **BREAKING**: Incorporated AtomGraph Server code directly into LinkedDataHub codebase +- System configuration dataset now uses named graphs instead of default graph +- Web-Client dependency version bump +- CLI scripts improved for better parameter handling + ## [5.1.0] - 2025-12-12 ### Added - ORCID OpenID Connect login support with JWT token verification From a5363ae33635eda71b5b9f4c30584131475408e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sat, 10 Jan 2026 23:20:05 +0100 Subject: [PATCH 49/64] Callback promise for the settings form --- .../xsl/bootstrap/2.3.2/client/form.xsl | 3 +- .../xsl/bootstrap/2.3.2/client/modal.xsl | 46 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl index ee16a428c..7bcc16a69 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl @@ -654,6 +654,7 @@ WHERE <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="2"> <xsl:param name="block" select="ancestor::div[contains-token(@class, 'modal-constructor')]" as="element()"/> <xsl:param name="about" select="$block/@about" as="xs:anyURI"/> + <xsl:param name="callback" select="ldh:modal-form-response#1" as="function(map(*)) as item()*"/> <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> <xsl:variable name="form" select="." as="element()"/> <xsl:variable name="method" select="upper-case(@method)" as="xs:string"/> @@ -763,7 +764,7 @@ WHERE ixsl:http-request($context('request')) => ixsl:then(ldh:rethread-response($context, ?)) => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:modal-form-response#1) + => ixsl:then($callback) " on-failure="ldh:promise-failure#1"/> </xsl:template> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl index 0ea02080d..78bebbbc4 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl @@ -642,7 +642,7 @@ LIMIT 10 </xsl:template> <xsl:template name="ldh:ReconcileForm"> - <xsl:param name="id" select="'reconcile'" as="xs:string?"/> + <xsl:param name="id" select="'form-reconcile'" as="xs:string?"/> <xsl:param name="button-class" select="'btn btn-primary btn-save'" as="xs:string?"/> <xsl:param name="accept-charset" select="'UTF-8'" as="xs:string?"/> <xsl:param name="action" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> @@ -738,6 +738,7 @@ LIMIT 10 </xsl:template> <xsl:template match="button[contains-token(@class, 'btn-app-settings')]" mode="ixsl:onclick"> + <xsl:param name="id" select="'app-settings'" as="xs:string?"/> <xsl:param name="method" select="'patch'" as="xs:string"/> <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> @@ -746,6 +747,10 @@ LIMIT 10 <xsl:for-each select="$content-body"> <xsl:result-document href="?." method="ixsl:append-content"> <div class="modal modal-constructor fade in" about="{$lapp:application}"> + <xsl:if test="$id"> + <xsl:attribute name="id" select="$id"/> + </xsl:if> + <div class="modal-header"> <button type="button" class="close">×</button> @@ -786,6 +791,14 @@ LIMIT 10 " on-failure="ldh:promise-failure#1"/> </xsl:template> + <!-- submit application settings modal form using PATCH with custom callback --> + + <xsl:template match="div[@id = 'app-settings']//form[upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="3"> + <xsl:next-match> + <xsl:with-param name="callback" select="ldh:settings-form-response#1"/> + </xsl:next-match> + </xsl:template> + <xsl:template match="button[contains-token(@class, 'btn-access-form')]" mode="ixsl:onclick"> <!-- TO-DO: fix for admin apps --> <xsl:param name="this" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> @@ -1303,5 +1316,34 @@ LIMIT 10 </xsl:otherwise> </xsl:choose> </xsl:template> - + + <xsl:function name="ldh:settings-form-response" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="status" select="$response?status" as="xs:double"/> + <xsl:variable name="media-type" select="$response?media-type" as="xs:string?"/> + <xsl:variable name="form" select="$context('form')" as="element()?"/> + + <xsl:message>ldh:settings-form-response</xsl:message> + + <xsl:choose> + <!-- 200/204: settings saved successfully, close the modal --> + <xsl:when test="$status = (200, 204)"> + <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> + <!-- close the modal --> + <xsl:if test="$form"> + <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> + </xsl:if> + </xsl:when> + <!-- validation errors --> + <xsl:when test="$status = (400, 422) and starts-with($media-type, 'application/rdf+xml')"> + <xsl:sequence select="ldh:modal-form-submit-violation($context)"/> + </xsl:when> + <!-- other errors --> + <xsl:otherwise> + <xsl:sequence select="ldh:error-response-alert($context)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + </xsl:stylesheet> \ No newline at end of file From 3c7877d8b6104206df6bf10e3b4d555830a2f0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 11 Jan 2026 00:26:49 +0100 Subject: [PATCH 50/64] Replaced `ldh:ModalFormSubmit` template with promises --- .../xsl/bootstrap/2.3.2/client/modal.xsl | 316 +++++++++--------- 1 file changed, 163 insertions(+), 153 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl index 78bebbbc4..5614468e1 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl @@ -831,16 +831,17 @@ LIMIT 10 </xsl:template> <!-- validate form before submitting it and show errors on required control-groups where input values are missing --> - <xsl:template match="form[@id = 'form-add-data'] | form[@id = 'form-clone-data'] | form[@id = 'form-generate-containers']" mode="ixsl:onsubmit" priority="1"> + <xsl:template match="form[@id = 'form-clone-data'] | form[@id = 'form-generate-containers']" mode="ixsl:onsubmit" priority="1"> + <xsl:param name="callback" as="function(map(*)) as item()*"/> <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> <xsl:variable name="control-groups" select="descendant::div[contains-token(@class, 'control-group')]" as="element()*"/> <xsl:variable name="required-control-groups" select="$control-groups[contains-token(@class, 'required')]" as="element()*"/> - + <!-- clear the errors initially --> <xsl:for-each select="$control-groups"> - <xsl:sequence select="ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'error', false() ])[current-date() lt xs:date('2000-01-01')]"/> + <xsl:sequence select="ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'error', false() ])[current-date() lt xs:date('2000-01-01')]"/> </xsl:for-each> - + <xsl:choose> <!-- required input values missing, throw an error --> <xsl:when test="exists($required-control-groups/descendant::input[@name = ('ol', 'ou')][not(ixsl:get(., 'value'))])"> @@ -860,20 +861,36 @@ LIMIT 10 <xsl:variable name="enctype" select="ixsl:get(., 'enctype')" as="xs:string"/> <xsl:variable name="form-data" select="ixsl:new('URLSearchParams', [ ixsl:new('FormData', [ $form ]) ])"/> <xsl:variable name="request-uri" select="ldh:href($action, map{})" as="xs:anyURI"/> - - <xsl:variable name="request" as="item()*"> - <ixsl:schedule-action http-request="map{ 'method': $method, 'href': $request-uri, 'media-type': $enctype, 'body': $form-data, 'headers': map{} }"> <!-- 'Accept': $accept --> - <xsl:call-template name="ldh:ModalFormSubmit"> - <xsl:with-param name="action" select="$action"/> - <xsl:with-param name="form" select="$form"/> - </xsl:call-template> - </ixsl:schedule-action> - </xsl:variable> - <xsl:sequence select="$request[current-date() lt xs:date('2000-01-01')]"/> + <xsl:variable name="request" select="map{ 'method': $method, 'href': $request-uri, 'media-type': $enctype, 'body': $form-data, 'headers': map{} }" as="map(*)"/> + <xsl:variable name="context" as="map(*)" select=" + map{ + 'request': $request, + 'form': $form + }"/> + <ixsl:promise select=" + ixsl:http-request($context('request')) + => ixsl:then(ldh:rethread-response($context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then($callback) + " on-failure="ldh:promise-failure#1"/> </xsl:otherwise> </xsl:choose> </xsl:template> + <!-- submit generate containers modal form with custom callback --> + <xsl:template match="form[@id = 'form-generate-containers']" mode="ixsl:onsubmit" priority="2"> + <xsl:next-match> + <xsl:with-param name="callback" select="ldh:generate-containers-form-response#1"/> + </xsl:next-match> + </xsl:template> + + <!-- submit add data / clone data modal forms with custom callback --> + <xsl:template match="form[@id = 'form-clone-data']" mode="ixsl:onsubmit" priority="2"> + <xsl:next-match> + <xsl:with-param name="callback" select="ldh:add-data-form-response#1"/> + </xsl:next-match> + </xsl:template> + <xsl:template match="button[contains-token(@class, 'btn-load-endpoint-schema')]" mode="ixsl:onclick"> <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> @@ -932,11 +949,12 @@ LIMIT 10 <!-- validate form before submitting it and show errors on required control-groups where input values are missing --> <xsl:template match="form[@id = 'form-request-access']" mode="ixsl:onsubmit" priority="1"> + <xsl:param name="callback" select="ldh:request-access-form-response#1" as="function(map(*)) as item()*"/> <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> <xsl:variable name="form" select="." as="element()"/> <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> - + <!-- disable hidden inputs on table rows where all acl:mode checkboxes are a) disabled by default b) enabled but left unchecked --> <!-- otherwise RDF/POST will generate acl:Authorization instances without acl:mode values which will fail constraint validation --> <!-- we don't want to use the values of disabled checkboxes in the request because those authorizations already exist --> @@ -949,16 +967,18 @@ LIMIT 10 <xsl:variable name="enctype" select="ixsl:get(., 'enctype')" as="xs:string"/> <xsl:variable name="form-data" select="ixsl:new('URLSearchParams', [ ixsl:new('FormData', [ $form ]) ])"/> <xsl:variable name="request-uri" select="ldh:href($action, map{})" as="xs:anyURI"/> - - <xsl:variable name="request" as="item()*"> - <ixsl:schedule-action http-request="map{ 'method': $method, 'href': $request-uri, 'media-type': $enctype, 'body': $form-data, 'headers': map{} }"> <!-- 'Accept': $accept --> - <xsl:call-template name="ldh:ModalFormSubmit"> - <xsl:with-param name="action" select="$action"/> - <xsl:with-param name="form" select="$form"/> - </xsl:call-template> - </ixsl:schedule-action> - </xsl:variable> - <xsl:sequence select="$request[current-date() lt xs:date('2000-01-01')]"/> + <xsl:variable name="request" select="map{ 'method': $method, 'href': $request-uri, 'media-type': $enctype, 'body': $form-data, 'headers': map{} }" as="map(*)"/> + <xsl:variable name="context" as="map(*)" select=" + map{ + 'request': $request, + 'form': $form + }"/> + <ixsl:promise select=" + ixsl:http-request($context('request')) + => ixsl:then(ldh:rethread-response($context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then($callback) + " on-failure="ldh:promise-failure#1"/> </xsl:template> <xsl:template match="input[contains-token(@class, 'subject-slug')]" mode="ixsl:onkeyup" priority="1"> @@ -1028,134 +1048,6 @@ LIMIT 10 </xsl:if> </xsl:template> - <!-- form is submitted. TO-DO: split into multiple callbacks and avoid <xsl:choose>? --> - - <xsl:template name="ldh:ModalFormSubmit"> - <xsl:context-item as="map(*)" use="required"/> - <xsl:param name="container" select="id('content-body', ixsl:page())" as="element()"/> - <xsl:param name="action" as="xs:anyURI"/> - <xsl:param name="form" as="element()"/> - - <xsl:choose> - <!-- special case for add/clone data forms: redirect to the container --> - <xsl:when test="ixsl:get($form, 'id') = ('form-add-data', 'form-clone-data')"> - <xsl:variable name="control-group" select="$form/descendant::div[contains-token(@class, 'control-group')][input[@name = 'pu'][@value = '&sd;name']]" as="element()*"/> - <xsl:variable name="uri" select="$control-group/descendant::input[@name = 'ou']/ixsl:get(., 'value')" as="xs:anyURI"/> - - <xsl:choose> - <xsl:when test="?status = (200, 204)"> - <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }" as="map(*)"/> - <xsl:variable name="context" select=" - map{ - 'request': $request, - 'href': ac:build-uri(ac:absolute-path($uri), map{ 'mode': '∾ReadMode'}), - 'push-state': true() - }" as="map(*)"/> - <ixsl:promise select=" - ixsl:http-request($context('request')) - => ixsl:then(ldh:rethread-response($context, ?)) - => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:xhtml-document-loaded#1) - " on-failure="ldh:promise-failure#1"/> - - <!-- remove the modal div --> - <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> - </xsl:when> - <xsl:otherwise> - <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> - - <xsl:variable name="status-code" select="xs:integer(?status)" as="xs:integer"/> - <xsl:variable name="message" select="?message" as="xs:string?"/> - <!-- render error message --> - <xsl:for-each select="$form//fieldset"> - <xsl:result-document href="?." method="ixsl:append-content"> - <div class="alert"> - <p> - <!-- lookup status message by code because Tomcat does not send any --> - <xsl:apply-templates select="key('status-by-code', $status-code, document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/http-statusCodes.rdf', $ac:contextUri)))" mode="ac:label"/> - </p> - <xsl:if test="$message"> - <p> - <xsl:value-of select="$message"/> - </p> - </xsl:if> - </div> - </xsl:result-document> - </xsl:for-each> - </xsl:otherwise> - </xsl:choose> - </xsl:when> - <!-- special case for generate containers form: redirect to the parent container --> - <xsl:when test="ixsl:get($form, 'id') = 'form-generate-containers'"> - <xsl:variable name="control-group" select="$form/descendant::div[contains-token(@class, 'control-group')][input[@name = 'pu'][@value = '&sioc;has_parent']]" as="element()*"/> - <xsl:variable name="uri" select="$control-group/descendant::input[@name = 'ou']/ixsl:get(., 'value')" as="xs:anyURI"/> - <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }" as="map(*)"/> - <xsl:variable name="context" select=" - map{ - 'request': $request, - 'href': ac:absolute-path($uri), - 'push-state': true(), - 'refresh-content': true() - }" as="map(*)"/> - <ixsl:promise select=" - ixsl:http-request($context('request')) - => ixsl:then(ldh:rethread-response($context, ?)) - => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:xhtml-document-loaded#1) - " on-failure="ldh:promise-failure#1"/> - - <!-- remove the modal div --> - <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> - </xsl:when> - <xsl:when test="?status = 200 and ixsl:get($form, 'id') = 'form-request-access'"> - <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> - - <!-- remove the modal div --> - <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> - </xsl:when> - <!-- POST created new resource successfully --> - <xsl:when test="?status = 201 and ?headers?location"> - <xsl:variable name="created-uri" select="?headers?location" as="xs:anyURI"/> - <xsl:choose> - <!-- special case for signup form --> - <xsl:when test="ixsl:get($form, 'id') = 'form-signup'"> - <xsl:call-template name="bs2:SignUpComplete"/> - </xsl:when> - <!-- if the form submit did not originate from a typeahead (target), load the created resource --> - <xsl:otherwise> -<!-- <xsl:variable name="request" as="item()*"> - <ixsl:schedule-action http-request="map{ 'method': 'GET', 'href': $created-uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }"> - <xsl:call-template name="ldh:DocumentLoaded"> - <xsl:with-param name="href" select="ac:absolute-path($created-uri)"/> - </xsl:call-template> - </ixsl:schedule-action> - </xsl:variable> - <xsl:sequence select="$request[current-date() lt xs:date('2000-01-01')]"/>--> - - <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $created-uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }" as="map(*)"/> - <xsl:variable name="context" select=" - map{ - 'request': $request, - 'href': ac:absolute-path($created-uri), - 'push-state': true(), - 'refresh-content': true() - }" as="map(*)"/> - <ixsl:promise select=" - ixsl:http-request($context('request')) - => ixsl:then(ldh:rethread-response($context, ?)) - => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:xhtml-document-loaded#1) - " on-failure="ldh:promise-failure#1"/> - </xsl:otherwise> - </xsl:choose> - </xsl:when> - <xsl:otherwise> - <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> - <xsl:sequence select="ixsl:call(ixsl:window(), 'alert', [ ?message ])"/> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - <!-- render schema classes loaded from a SPARQL endpoint --> <xsl:template name="onEndpointClassesLoad"> @@ -1346,4 +1238,122 @@ LIMIT 10 </xsl:choose> </xsl:function> + <xsl:function name="ldh:request-access-form-response" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="status" select="$response?status" as="xs:double"/> + <xsl:variable name="form" select="$context('form')" as="element()?"/> + + <xsl:message>ldh:request-access-form-response</xsl:message> + + <xsl:choose> + <!-- Success: close the modal --> + <xsl:when test="$status = 200"> + <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> + <!-- close the modal --> + <xsl:if test="$form"> + <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> + </xsl:if> + </xsl:when> + <!-- Error --> + <xsl:otherwise> + <xsl:sequence select="ldh:error-response-alert($context)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + + <xsl:function name="ldh:generate-containers-form-response" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="status" select="$response?status" as="xs:double"/> + <xsl:variable name="form" select="$context('form')" as="element()?"/> + + <xsl:message>ldh:generate-containers-form-response</xsl:message> + + <xsl:choose> + <!-- Success: redirect to parent container with refresh --> + <xsl:when test="$status = (200, 201, 204)"> + <xsl:variable name="control-group" select="$form/descendant::div[contains-token(@class, 'control-group')][input[@name = 'pu'][@value = '&sioc;has_parent']]" as="element()*"/> + <xsl:variable name="uri" select="$control-group/descendant::input[@name = 'ou']/ixsl:get(., 'value')" as="xs:anyURI"/> + <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }" as="map(*)"/> + <xsl:variable name="redirect-context" select=" + map{ + 'request': $request, + 'href': ac:absolute-path($uri), + 'push-state': true(), + 'refresh-content': true() + }" as="map(*)"/> + <ixsl:promise select=" + ixsl:http-request($redirect-context('request')) + => ixsl:then(ldh:rethread-response($redirect-context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:xhtml-document-loaded#1) + " on-failure="ldh:promise-failure#1"/> + + <!-- Remove the modal --> + <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> + </xsl:when> + <!-- Error --> + <xsl:otherwise> + <xsl:sequence select="ldh:error-response-alert($context)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + + <xsl:function name="ldh:add-data-form-response" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="status" select="$response?status" as="xs:double"/> + <xsl:variable name="form" select="$context('form')" as="element()?"/> + + <xsl:message>ldh:add-data-form-response</xsl:message> + + <xsl:choose> + <!-- Success: redirect to target container with ReadMode --> + <xsl:when test="$status = (200, 204)"> + <xsl:variable name="control-group" select="$form/descendant::div[contains-token(@class, 'control-group')][input[@name = 'pu'][@value = '&sd;name']]" as="element()*"/> + <xsl:variable name="uri" select="$control-group/descendant::input[@name = 'ou']/ixsl:get(., 'value')" as="xs:anyURI"/> + <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $uri, 'headers': map{ 'Accept': 'application/xhtml+xml' } }" as="map(*)"/> + <xsl:variable name="redirect-context" select=" + map{ + 'request': $request, + 'href': ac:build-uri(ac:absolute-path($uri), map{ 'mode': '∾ReadMode'}), + 'push-state': true() + }" as="map(*)"/> + <ixsl:promise select=" + ixsl:http-request($redirect-context('request')) + => ixsl:then(ldh:rethread-response($redirect-context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:xhtml-document-loaded#1) + " on-failure="ldh:promise-failure#1"/> + + <!-- Remove the modal --> + <xsl:sequence select="ixsl:call($form/ancestor::div[contains-token(@class, 'modal')], 'remove', [])[current-date() lt xs:date('2000-01-01')]"/> + </xsl:when> + <!-- Error: render error message inline in the form's fieldset --> + <xsl:otherwise> + <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> + + <xsl:variable name="status-code" select="xs:integer($status)" as="xs:integer"/> + <xsl:variable name="message" select="$response?message" as="xs:string?"/> + <!-- render error message --> + <xsl:for-each select="$form//fieldset"> + <xsl:result-document href="?." method="ixsl:append-content"> + <div class="alert"> + <p> + <!-- lookup status message by code because Tomcat does not send any --> + <xsl:apply-templates select="key('status-by-code', $status-code, document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/http-statusCodes.rdf', $ac:contextUri)))" mode="ac:label"/> + </p> + <xsl:if test="$message"> + <p> + <xsl:value-of select="$message"/> + </p> + </xsl:if> + </div> + </xsl:result-document> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + </xsl:stylesheet> \ No newline at end of file From 48741643654e64d87ab9affa40e618b7cdd1af9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 11 Jan 2026 11:14:06 +0100 Subject: [PATCH 51/64] Moved modal form-related templates --- .../xsl/bootstrap/2.3.2/client/form.xsl | 370 +----------------- .../xsl/bootstrap/2.3.2/client/modal.xsl | 368 +++++++++++++++++ 2 files changed, 369 insertions(+), 369 deletions(-) diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl index 7bcc16a69..ef590b72d 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/form.xsl @@ -296,62 +296,6 @@ WHERE " on-failure="ldh:promise-failure#1"/> </xsl:template> - <!-- open a form for document editing --> - - <xsl:template match="div[contains-token(@class, 'action-bar')]//button[contains-token(@class, 'btn-edit')]" mode="ixsl:onclick"> - <xsl:param name="about" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> <!-- editing the current document resources --> - <xsl:param name="method" select="'patch'" as="xs:string"/> - <xsl:param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> - <xsl:param name="button-class" select="'btn btn-primary wymupdate'" as="xs:string?"/> - <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> - - <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> - -<!-- <xsl:if test="ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`')"> - <xsl:variable name="etag" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`'), 'etag')" as="xs:string"/> - </xsl:if>--> - <xsl:if test="not(ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $about || '`'))"> - <ixsl:set-property name="{'`' || $about || '`'}" select="ldh:new-object()" object="ixsl:get(ixsl:window(), 'LinkedDataHub.contents')"/> - </xsl:if> - - <xsl:variable name="block-id" select="'block-' || generate-id()" as="xs:string"/> - <xsl:for-each select="$content-body"> - <xsl:result-document href="?." method="ixsl:append-content"> - <div class="modal modal-constructor fade in" about="{$about}"> - <div class="modal-header"> - <button type="button" class="close">×</button> - </div> - <div class="modal-body" id="{$block-id}"> - <!-- to be injected --> - </div> - </div> - </xsl:result-document> - </xsl:for-each> - <xsl:variable name="block" select="id($block-id, ixsl:page())" as="element()"/> - - <!-- if the URI is external, dereference it through the proxy --> - <xsl:variable name="request-uri" select="ldh:href($about)" as="xs:anyURI"/> - <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $request-uri, 'headers': map{ 'Accept': 'application/rdf+xml' } }" as="map(*)"/> - <xsl:variable name="context" as="map(*)" select=" - map{ - 'request': $request, - 'block': $block, - 'about': $about, - 'method': $method - }"/> - <ixsl:promise select=" - ixsl:http-request($context('request')) - => ixsl:then(ldh:rethread-response($context, ?)) - => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:load-edited-resource#1) - => ixsl:then(ldh:http-request-threaded#1) - => ixsl:then(ldh:handle-response#1) - => ixsl:then(ldh:set-type-metadata#1) - => ixsl:then(ldh:wrap-into-document#1) - => ixsl:then(ldh:render-form#1) - " on-failure="ldh:promise-failure#1"/> - </xsl:template> - <xsl:function name="ldh:load-edited-resource" as="map(*)" ixsl:updating="yes"> <xsl:param name="context" as="map(*)"/> <xsl:variable name="response" select="$context('response')" as="map(*)"/> @@ -572,14 +516,6 @@ WHERE <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> </xsl:template> - <!-- submit instance creation modal form using PUT --> - - <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PUT']" mode="ixsl:onsubmit" priority="2"> - <xsl:next-match> - <xsl:with-param name="callback" select="ldh:modal-form-response#1"/> - </xsl:next-match> - </xsl:template> - <!-- submit instance creation row-form using POST --> <xsl:template match="form[ancestor::div[@typeof]][contains-token(@class, 'form-horizontal')]" mode="ixsl:onsubmit"> @@ -649,125 +585,6 @@ WHERE </xsl:choose> </xsl:template> - <!-- submit document update modal form using PATCH TO-DO: unify!!! --> - - <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="2"> - <xsl:param name="block" select="ancestor::div[contains-token(@class, 'modal-constructor')]" as="element()"/> - <xsl:param name="about" select="$block/@about" as="xs:anyURI"/> - <xsl:param name="callback" select="ldh:modal-form-response#1" as="function(map(*)) as item()*"/> - <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> - <xsl:variable name="form" select="." as="element()"/> - <xsl:variable name="method" select="upper-case(@method)" as="xs:string"/> - <xsl:variable name="id" select="ixsl:get($form, 'id')" as="xs:string"/> - <xsl:variable name="action" select="ixsl:get($form, 'action')" as="xs:anyURI"/> - <xsl:variable name="enctype" select="ixsl:get($form, 'enctype')" as="xs:string"/> - <xsl:variable name="etag" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`'), 'etag')" as="xs:string"/> - - <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> - - <!-- pre-process form before submitting it --> - <xsl:apply-templates select="." mode="ldh:FormPreSubmit"/> - - <xsl:variable name="elements" select=".//input | .//textarea | .//select" as="element()*"/> - <xsl:variable name="triples" select="ldh:parse-rdf-post($elements)" as="element()*"/> - <!-- canonicalize XML in rdf:XMLLiterals --> - <xsl:variable name="triples" as="element()*"> - <xsl:apply-templates select="$triples" mode="ldh:CanonicalizeXML"/> - </xsl:variable> - <!-- need a customer DELETE/WHERE pattern because the default $about ?p ?o would delete system properties such as dct:created or sioc:has_parent --> - <xsl:variable name="where-pattern" as="element()*"> - <json:map> - <json:string key="type">bgp</json:string> - <json:array key="triples"> - <json:map> - <json:string key="subject"><xsl:value-of select="$about"/></json:string> - <json:string key="predicate">?p</json:string> - <json:string key="object">?o</json:string> - </json:map> - </json:array> - </json:map> - <json:map> - <json:string key="type">filter</json:string> - <json:map key="expression"> - <json:string key="type">operation</json:string> - <json:string key="operator">notin</json:string> - <json:array key="args"> - <json:string>?p</json:string> - <json:array> - <json:string>&dct;reated</json:string> - <json:string>&dct;modified</json:string> - <json:string>&sioc;has_parent</json:string> - <json:string>&sioc;has_container</json:string> - <json:string>&dct;creator</json:string> - <json:string>&acl;owner</json:string> - </json:array> - </json:array> - </json:map> - </json:map> - <json:map> - <json:string key="type">filter</json:string> - <json:map key="expression"> - <json:string key="type">operation</json:string> - <json:string key="operator">!</json:string> - <json:array key="args"> - <json:map> - <json:string key="type">operation</json:string> - <json:string key="operator">strstarts</json:string> - <json:array key="args"> - <json:map> - <json:string key="type">operation</json:string> - <json:string key="operator">str</json:string> - <json:array key="args"> - <json:string>?p</json:string> - </json:array> - </json:map> - <json:map> - <json:string key="type">operation</json:string> - <json:string key="operator">concat</json:string> - <json:array key="args"> - <json:map> - <json:string key="type">operation</json:string> - <json:string key="operator">str</json:string> - <json:array key="args"> - <json:string>http://www.w3.org/1999/02/22-rdf-syntax-ns#</json:string> - </json:array> - </json:map> - <json:string>"_"</json:string> - </json:array> - </json:map> - </json:array> - </json:map> - </json:array> - </json:map> - </json:map> - </xsl:variable> - <xsl:variable name="update-string" select="ldh:insertdelete-update(ldh:triples-to-bgp(ldh:uri-po-pattern($about)), ldh:triples-to-bgp($triples), $where-pattern)" as="xs:string"/> - <xsl:variable name="resources" as="document-node()"> - <xsl:document> - <rdf:RDF> - <xsl:sequence select="ldh:triples-to-descriptions($triples)"/> - </rdf:RDF> - </xsl:document> - </xsl:variable> - <xsl:variable name="request-uri" select="ldh:href($action, map{})" as="xs:anyURI"/> - <!-- If-Match header checks preconditions, i.e. that the graph has not been modified in the meanwhile --> - <xsl:variable name="request" select="map{ 'method': $method, 'href': $request-uri, 'media-type': 'application/sparql-update', 'body': $update-string, 'headers': map{ 'If-Match': $etag, 'Accept': 'application/rdf+xml', 'Cache-Control': 'no-cache' } }" as="map(*)"/> - <xsl:variable name="context" as="map(*)" select=" - map{ - 'request': $request, - 'doc-uri': ac:absolute-path(ldh:base-uri(.)), - 'block': $block, - 'form': $form, - 'resources': $resources - }"/> - <ixsl:promise select=" - ixsl:http-request($context('request')) - => ixsl:then(ldh:rethread-response($context, ?)) - => ixsl:then(ldh:handle-response#1) - => ixsl:then($callback) - " on-failure="ldh:promise-failure#1"/> - </xsl:template> - <!-- submit instance update row-form using PATCH --> <xsl:template match="div[contains-token(@class, 'block')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="1"> @@ -906,30 +723,6 @@ WHERE </xsl:choose> </xsl:function> - <xsl:function name="ldh:modal-form-response" ixsl:updating="yes"> - <xsl:param name="context" as="map(*)"/> - <xsl:variable name="response" select="$context('response')" as="map(*)"/> - <xsl:variable name="status" select="$response?status" as="xs:double"/> - <xsl:variable name="media-type" select="$response?media-type" as="xs:string?"/> - - <xsl:message>ldh:modal-form-response</xsl:message> - - <xsl:choose> - <xsl:when test="$status = (200, 204)"> - <xsl:sequence select="ldh:form-horizontal-submit-success($context)"/> - </xsl:when> - <xsl:when test="$status = 201 and map:contains($response?headers, 'location')"> - <xsl:sequence select="ldh:form-submit-created($context)"/> - </xsl:when> - <xsl:when test="$status = (400, 422) and starts-with($media-type, 'application/rdf+xml')"> - <xsl:sequence select="ldh:modal-form-submit-violation($context)"/> - </xsl:when> - <xsl:otherwise> - <xsl:sequence select="ldh:error-response-alert($context)"/> - </xsl:otherwise> - </xsl:choose> - </xsl:function> - <xsl:function name="ldh:form-horizontal-submit-success" ixsl:updating="yes"> <xsl:param name="context" as="map(*)"/> <xsl:variable name="response" select="$context('response')" as="map(*)"/> @@ -1009,92 +802,6 @@ WHERE </xsl:for-each> </xsl:function> - <xsl:function name="ldh:modal-form-submit-violation" ixsl:updating="yes"> - <xsl:param name="context" as="map(*)"/> - <xsl:variable name="response" select="$context('response')" as="map(*)"/> - <xsl:variable name="doc-uri" select="$context('doc-uri')" as="xs:anyURI"/> - <xsl:variable name="block" select="$context('block')" as="element()"/> - <xsl:variable name="form" select="$context('form')" as="element()?"/> - - <xsl:message>ldh:modal-form-submit-violation</xsl:message> - - <xsl:for-each select="$response"> - <xsl:variable name="body" select="?body" as="document-node()"/> - <!-- TO-DO: refactor to use asynchronous HTTP requests --> - <!-- inverse $types expression compared to ldh:row-form-submit-violation --> - <xsl:variable name="types" select="distinct-values($body/rdf:RDF/*[@rdf:about = $doc-uri]/rdf:type/@rdf:resource)" as="xs:anyURI*"/> - <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="type-metadata" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:variable name="property-uris" select="distinct-values($body/rdf:RDF/*[not(@rdf:about = $doc-uri)]/*/concat(namespace-uri(), local-name()))" as="xs:string*"/> - <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $uri in $property-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="property-metadata" select="document($request-uri)" as="document-node()"/> - - <xsl:variable name="query-string" select="$constructor-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> - <xsl:variable name="constructors" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:variable name="query-string" select="$constraint-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> - <xsl:variable name="constraints" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:variable name="query-string" select="$shape-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="shapes" select="document($request-uri)" as="document-node()"/> - - <xsl:variable name="object-uris" select="distinct-values($body/rdf:RDF/*/*/@rdf:resource[not(key('resources', .))])" as="xs:string*"/> - <xsl:variable name="query-string" select="$object-metadata-query || ' VALUES $this { ' || string-join(for $uri in $object-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('sparql', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="object-metadata" select="if (doc-available($request-uri)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:variable name="form" as="element()*"> - <xsl:for-each select="$body"> - <xsl:apply-templates select="." mode="bs2:Form"> <!-- document level template --> - <xsl:with-param name="about" select="()"/> <!-- don't set @about on the container until after the resource is saved --> - <xsl:with-param name="method" select="$form/@method"/> - <xsl:with-param name="action" select="$form/@action" as="xs:anyURI" tunnel="yes"/> - <xsl:with-param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> - <xsl:with-param name="classes" select="()"/> - <xsl:with-param name="type-metadata" select="$type-metadata" tunnel="yes"/> - <xsl:with-param name="property-metadata" select="$property-metadata" tunnel="yes"/> - <xsl:with-param name="constructors" select="()" tunnel="yes"/> <!-- can be empty because modal form is only used to create Container/Item instances --> - <xsl:with-param name="constraints" select="$constraints" tunnel="yes"/> - <xsl:with-param name="shapes" select="()" tunnel="yes"/> <!-- there will be no shapes as modal form is only used to create Container/Item instances --> - <xsl:with-param name="base-uri" select="ac:absolute-path(ldh:base-uri(.))" tunnel="yes"/> <!-- ac:absolute-path(ldh:base-uri(.)) is empty on constructed documents --> - <!-- <xsl:sort select="ac:label(.)"/> --> - </xsl:apply-templates> - </xsl:for-each> - </xsl:variable> - - <xsl:for-each select="$block"> - <xsl:result-document href="?." method="ixsl:replace-content"> - <div class="modal-header"> - <button type="button" class="close">×</button> - - <legend> - <!-- <xsl:value-of select="$legend-label"/> --> - </legend> - </div> - - <div class="modal-body"> - <xsl:copy-of select="$form"/> - </div> - </xsl:result-document> - </xsl:for-each> - - <!-- cannot be in $form context because it contains old DOM (pre-ixsl:replace-content) --> - <xsl:for-each select="id($form/@id, ixsl:page())"> - <xsl:apply-templates select="." mode="ldh:RenderRowForm"/> - </xsl:for-each> - - <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> - </xsl:for-each> - - <xsl:sequence select="$context"/> - </xsl:function> - <xsl:function name="ldh:row-form-submit-violation" ixsl:updating="yes"> <xsl:param name="context" as="map(*)"/> <xsl:variable name="response" select="$context('response')" as="map(*)"/> @@ -1195,81 +902,6 @@ WHERE </xsl:for-each> </xsl:template> - <!-- shows new SPIN-constructed document as a modal form --> - <xsl:template match="div[contains-token(@class, 'action-bar')]//button[contains-token(@class, 'add-constructor')][@data-for-class]" mode="ixsl:onclick" priority="2"> - <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])[current-date() lt xs:date('2000-01-01')]"/> - <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> - <xsl:variable name="forClass" select="@data-for-class" as="xs:anyURI"/> - <xsl:variable name="constructed-doc" select="ldh:construct-forClass($forClass)" as="document-node()"/> - <xsl:variable name="doc-uri" select="resolve-uri(ac:uuid() || '/', ac:absolute-path(ldh:base-uri(.)))" as="xs:anyURI"/> <!-- build a relative URI for the child document --> - <xsl:variable name="this" select="$doc-uri" as="xs:anyURI"/> - <xsl:variable name="classes" select="()" as="element()*"/> - - <xsl:for-each select="$content-body"> - <xsl:variable name="resource" select="key('resources-by-type', $forClass, $constructed-doc)[not(key('predicates-by-object', @rdf:nodeID))]" as="element()"/> - <xsl:variable name="form" as="element()*"> - <!-- TO-DO: refactor to use asynchronous HTTP requests --> - <xsl:variable name="types" select="distinct-values($resource/rdf:type/@rdf:resource)" as="xs:anyURI*"/> - <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="type-metadata" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:variable name="property-uris" select="distinct-values($resource/*/concat(namespace-uri(), local-name()))" as="xs:string*"/> - <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $uri in $property-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> - <xsl:variable name="property-metadata" select="document($request-uri)" as="document-node()"/> - - <xsl:variable name="query-string" select="$constraint-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> - <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> - <xsl:variable name="constraints" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> - - <xsl:apply-templates select="$constructed-doc" mode="bs2:Form"> <!-- document level template --> - <xsl:with-param name="about" select="()"/> <!-- don't set @about on the container until after the resource is saved --> - <xsl:with-param name="method" select="'put'"/> - <xsl:with-param name="action" select="ldh:href($doc-uri)" as="xs:anyURI" tunnel="yes"/> - <xsl:with-param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> - <xsl:with-param name="classes" select="$classes"/> - <xsl:with-param name="type-metadata" select="$type-metadata" tunnel="yes"/> - <xsl:with-param name="property-metadata" select="$property-metadata" tunnel="yes"/> - <xsl:with-param name="constructor" select="$constructed-doc" tunnel="yes"/> - <xsl:with-param name="constructors" select="()" tunnel="yes"/> <!-- can be empty because modal form is only used to create Container/Item instances --> - <xsl:with-param name="constraints" select="$constraints" tunnel="yes"/> - <xsl:with-param name="shapes" select="()" tunnel="yes"/> <!-- there will be no shapes as modal form is only used to create Container/Item instances --> - <xsl:with-param name="base-uri" select="ac:absolute-path(ldh:base-uri(.))" tunnel="yes"/> <!-- ac:absolute-path(ldh:base-uri(.)) is empty on constructed documents --> - <!-- <xsl:sort select="ac:label(.)"/> --> - </xsl:apply-templates> - </xsl:variable> - - <xsl:result-document href="?." method="ixsl:append-content"> - <div class="modal modal-constructor fade in" typeof="{$forClass}"> <!-- $forClass used by ldh:ResourceUpdated in case of 4xx response --> - <!-- - <xsl:if test="$id"> - <xsl:attribute name="id" select="$id"/> - </xsl:if> - --> - - <div class="modal-header"> - <button type="button" class="close">×</button> - - <legend> - <!-- <xsl:value-of select="$legend-label"/> --> - </legend> - </div> - - <div class="modal-body"> - <xsl:copy-of select="$form"/> - </div> - </div> - </xsl:result-document> - - <xsl:if test="id($form/@id, ixsl:page())"> - <xsl:apply-templates select="id($form/@id, ixsl:page())" mode="ldh:RenderRowForm"/> - </xsl:if> - </xsl:for-each> - - <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> - </xsl:template> - <!-- appends new SPIN-constructed instance to the page --> <xsl:template match="div[contains-token(@class, 'row-fluid')]//button[contains-token(@class, 'add-constructor')][@data-for-class]" mode="ixsl:onclick" priority="1"> <xsl:param name="method" select="'post'" as="xs:string"/> @@ -1910,7 +1542,7 @@ WHERE 'form': $form, 'resources': $resources }"/> - <xsl:sequence select="ldh:modal-form-response($context)"/> + <xsl:sequence select="ldh:row-form-response($context)"/> </xsl:template> </xsl:stylesheet> \ No newline at end of file diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl index 5614468e1..97a4e39c8 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/modal.xsl @@ -717,6 +717,264 @@ LIMIT 10 </xsl:for-each> </xsl:template> + <!-- submit instance creation modal form using PUT --> + + <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PUT']" mode="ixsl:onsubmit" priority="2"> + <xsl:next-match> + <xsl:with-param name="callback" select="ldh:modal-form-response#1"/> + </xsl:next-match> + </xsl:template> + + <!-- shows new SPIN-constructed document as a modal form --> + <xsl:template match="div[contains-token(@class, 'action-bar')]//button[contains-token(@class, 'add-constructor')][@data-for-class]" mode="ixsl:onclick" priority="2"> + <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])[current-date() lt xs:date('2000-01-01')]"/> + <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> + <xsl:variable name="forClass" select="@data-for-class" as="xs:anyURI"/> + <xsl:variable name="constructed-doc" select="ldh:construct-forClass($forClass)" as="document-node()"/> + <xsl:variable name="doc-uri" select="resolve-uri(ac:uuid() || '/', ac:absolute-path(ldh:base-uri(.)))" as="xs:anyURI"/> <!-- build a relative URI for the child document --> + <xsl:variable name="this" select="$doc-uri" as="xs:anyURI"/> + <xsl:variable name="classes" select="()" as="element()*"/> + + <xsl:for-each select="$content-body"> + <xsl:variable name="resource" select="key('resources-by-type', $forClass, $constructed-doc)[not(key('predicates-by-object', @rdf:nodeID))]" as="element()"/> + <xsl:variable name="form" as="element()*"> + <!-- TO-DO: refactor to use asynchronous HTTP requests --> + <xsl:variable name="types" select="distinct-values($resource/rdf:type/@rdf:resource)" as="xs:anyURI*"/> + <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="type-metadata" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:variable name="property-uris" select="distinct-values($resource/*/concat(namespace-uri(), local-name()))" as="xs:string*"/> + <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $uri in $property-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="property-metadata" select="document($request-uri)" as="document-node()"/> + + <xsl:variable name="query-string" select="$constraint-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> + <xsl:variable name="constraints" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:apply-templates select="$constructed-doc" mode="bs2:Form"> <!-- document level template --> + <xsl:with-param name="about" select="()"/> <!-- don't set @about on the container until after the resource is saved --> + <xsl:with-param name="method" select="'put'"/> + <xsl:with-param name="action" select="ldh:href($doc-uri)" as="xs:anyURI" tunnel="yes"/> + <xsl:with-param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> + <xsl:with-param name="classes" select="$classes"/> + <xsl:with-param name="type-metadata" select="$type-metadata" tunnel="yes"/> + <xsl:with-param name="property-metadata" select="$property-metadata" tunnel="yes"/> + <xsl:with-param name="constructor" select="$constructed-doc" tunnel="yes"/> + <xsl:with-param name="constructors" select="()" tunnel="yes"/> <!-- can be empty because modal form is only used to create Container/Item instances --> + <xsl:with-param name="constraints" select="$constraints" tunnel="yes"/> + <xsl:with-param name="shapes" select="()" tunnel="yes"/> <!-- there will be no shapes as modal form is only used to create Container/Item instances --> + <xsl:with-param name="base-uri" select="ac:absolute-path(ldh:base-uri(.))" tunnel="yes"/> <!-- ac:absolute-path(ldh:base-uri(.)) is empty on constructed documents --> + <!-- <xsl:sort select="ac:label(.)"/> --> + </xsl:apply-templates> + </xsl:variable> + + <xsl:result-document href="?." method="ixsl:append-content"> + <div class="modal modal-constructor fade in" typeof="{$forClass}"> <!-- $forClass used by ldh:ResourceUpdated in case of 4xx response --> + <!-- + <xsl:if test="$id"> + <xsl:attribute name="id" select="$id"/> + </xsl:if> + --> + + <div class="modal-header"> + <button type="button" class="close">×</button> + + <legend> + <!-- <xsl:value-of select="$legend-label"/> --> + </legend> + </div> + + <div class="modal-body"> + <xsl:copy-of select="$form"/> + </div> + </div> + </xsl:result-document> + + <xsl:if test="id($form/@id, ixsl:page())"> + <xsl:apply-templates select="id($form/@id, ixsl:page())" mode="ldh:RenderRowForm"/> + </xsl:if> + </xsl:for-each> + + <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> + </xsl:template> + + <!-- open a form for document editing --> + + <xsl:template match="div[contains-token(@class, 'action-bar')]//button[contains-token(@class, 'btn-edit')]" mode="ixsl:onclick"> + <xsl:param name="about" select="ac:absolute-path(ldh:base-uri(.))" as="xs:anyURI"/> <!-- editing the current document resources --> + <xsl:param name="method" select="'patch'" as="xs:string"/> + <xsl:param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> + <xsl:param name="button-class" select="'btn btn-primary wymupdate'" as="xs:string?"/> + <xsl:variable name="content-body" select="id('content-body', ixsl:page())" as="element()"/> + + <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> + +<!-- <xsl:if test="ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`')"> + <xsl:variable name="etag" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`'), 'etag')" as="xs:string"/> + </xsl:if>--> + <xsl:if test="not(ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || $about || '`'))"> + <ixsl:set-property name="{'`' || $about || '`'}" select="ldh:new-object()" object="ixsl:get(ixsl:window(), 'LinkedDataHub.contents')"/> + </xsl:if> + + <xsl:variable name="block-id" select="'block-' || generate-id()" as="xs:string"/> + <xsl:for-each select="$content-body"> + <xsl:result-document href="?." method="ixsl:append-content"> + <div class="modal modal-constructor fade in" about="{$about}"> + <div class="modal-header"> + <button type="button" class="close">×</button> + </div> + <div class="modal-body" id="{$block-id}"> + <!-- to be injected --> + </div> + </div> + </xsl:result-document> + </xsl:for-each> + <xsl:variable name="block" select="id($block-id, ixsl:page())" as="element()"/> + + <!-- if the URI is external, dereference it through the proxy --> + <xsl:variable name="request-uri" select="ldh:href($about)" as="xs:anyURI"/> + <xsl:variable name="request" select="map{ 'method': 'GET', 'href': $request-uri, 'headers': map{ 'Accept': 'application/rdf+xml' } }" as="map(*)"/> + <xsl:variable name="context" as="map(*)" select=" + map{ + 'request': $request, + 'block': $block, + 'about': $about, + 'method': $method + }"/> + <ixsl:promise select=" + ixsl:http-request($context('request')) + => ixsl:then(ldh:rethread-response($context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:load-edited-resource#1) + => ixsl:then(ldh:http-request-threaded#1) + => ixsl:then(ldh:handle-response#1) + => ixsl:then(ldh:set-type-metadata#1) + => ixsl:then(ldh:wrap-into-document#1) + => ixsl:then(ldh:render-form#1) + " on-failure="ldh:promise-failure#1"/> + </xsl:template> + + <!-- submit document update modal form using PATCH TO-DO: unify!!! --> + + <xsl:template match="div[contains-token(@class, 'modal-constructor')]//form[contains-token(@class, 'form-horizontal')][upper-case(@method) = 'PATCH']" mode="ixsl:onsubmit" priority="2"> + <xsl:param name="block" select="ancestor::div[contains-token(@class, 'modal-constructor')]" as="element()"/> + <xsl:param name="about" select="$block/@about" as="xs:anyURI"/> + <xsl:param name="callback" select="ldh:modal-form-response#1" as="function(map(*)) as item()*"/> + <xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/> + <xsl:variable name="form" select="." as="element()"/> + <xsl:variable name="method" select="upper-case(@method)" as="xs:string"/> + <xsl:variable name="id" select="ixsl:get($form, 'id')" as="xs:string"/> + <xsl:variable name="action" select="ixsl:get($form, 'action')" as="xs:anyURI"/> + <xsl:variable name="enctype" select="ixsl:get($form, 'enctype')" as="xs:string"/> + <xsl:variable name="etag" select="ixsl:get(ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.contents'), '`' || ac:absolute-path(ldh:base-uri(.)) || '`'), 'etag')" as="xs:string"/> + + <ixsl:set-style name="cursor" select="'progress'" object="ixsl:page()//body"/> + + <!-- pre-process form before submitting it --> + <xsl:apply-templates select="." mode="ldh:FormPreSubmit"/> + + <xsl:variable name="elements" select=".//input | .//textarea | .//select" as="element()*"/> + <xsl:variable name="triples" select="ldh:parse-rdf-post($elements)" as="element()*"/> + <!-- canonicalize XML in rdf:XMLLiterals --> + <xsl:variable name="triples" as="element()*"> + <xsl:apply-templates select="$triples" mode="ldh:CanonicalizeXML"/> + </xsl:variable> + <!-- need a customer DELETE/WHERE pattern because the default $about ?p ?o would delete system properties such as dct:created or sioc:has_parent --> + <xsl:variable name="where-pattern" as="element()*"> + <json:map> + <json:string key="type">bgp</json:string> + <json:array key="triples"> + <json:map> + <json:string key="subject"><xsl:value-of select="$about"/></json:string> + <json:string key="predicate">?p</json:string> + <json:string key="object">?o</json:string> + </json:map> + </json:array> + </json:map> + <json:map> + <json:string key="type">filter</json:string> + <json:map key="expression"> + <json:string key="type">operation</json:string> + <json:string key="operator">notin</json:string> + <json:array key="args"> + <json:string>?p</json:string> + <json:array> + <json:string>&dct;reated</json:string> + <json:string>&dct;modified</json:string> + <json:string>&sioc;has_parent</json:string> + <json:string>&sioc;has_container</json:string> + <json:string>&dct;creator</json:string> + <json:string>&acl;owner</json:string> + </json:array> + </json:array> + </json:map> + </json:map> + <json:map> + <json:string key="type">filter</json:string> + <json:map key="expression"> + <json:string key="type">operation</json:string> + <json:string key="operator">!</json:string> + <json:array key="args"> + <json:map> + <json:string key="type">operation</json:string> + <json:string key="operator">strstarts</json:string> + <json:array key="args"> + <json:map> + <json:string key="type">operation</json:string> + <json:string key="operator">str</json:string> + <json:array key="args"> + <json:string>?p</json:string> + </json:array> + </json:map> + <json:map> + <json:string key="type">operation</json:string> + <json:string key="operator">concat</json:string> + <json:array key="args"> + <json:map> + <json:string key="type">operation</json:string> + <json:string key="operator">str</json:string> + <json:array key="args"> + <json:string>http://www.w3.org/1999/02/22-rdf-syntax-ns#</json:string> + </json:array> + </json:map> + <json:string>"_"</json:string> + </json:array> + </json:map> + </json:array> + </json:map> + </json:array> + </json:map> + </json:map> + </xsl:variable> + <xsl:variable name="update-string" select="ldh:insertdelete-update(ldh:triples-to-bgp(ldh:uri-po-pattern($about)), ldh:triples-to-bgp($triples), $where-pattern)" as="xs:string"/> + <xsl:variable name="resources" as="document-node()"> + <xsl:document> + <rdf:RDF> + <xsl:sequence select="ldh:triples-to-descriptions($triples)"/> + </rdf:RDF> + </xsl:document> + </xsl:variable> + <xsl:variable name="request-uri" select="ldh:href($action, map{})" as="xs:anyURI"/> + <!-- If-Match header checks preconditions, i.e. that the graph has not been modified in the meanwhile --> + <xsl:variable name="request" select="map{ 'method': $method, 'href': $request-uri, 'media-type': 'application/sparql-update', 'body': $update-string, 'headers': map{ 'If-Match': $etag, 'Accept': 'application/rdf+xml', 'Cache-Control': 'no-cache' } }" as="map(*)"/> + <xsl:variable name="context" as="map(*)" select=" + map{ + 'request': $request, + 'doc-uri': ac:absolute-path(ldh:base-uri(.)), + 'block': $block, + 'form': $form, + 'resources': $resources + }"/> + <ixsl:promise select=" + ixsl:http-request($context('request')) + => ixsl:then(ldh:rethread-response($context, ?)) + => ixsl:then(ldh:handle-response#1) + => ixsl:then($callback) + " on-failure="ldh:promise-failure#1"/> + </xsl:template> + <xsl:template match="button[contains-token(@class, 'btn-add-ontology')]" mode="ixsl:onclick"> <xsl:call-template name="ldh:ShowAddDataForm"> <xsl:with-param name="form" as="element()"> @@ -996,6 +1254,30 @@ LIMIT 10 <!-- CALLBACKS --> + <xsl:function name="ldh:modal-form-response" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="status" select="$response?status" as="xs:double"/> + <xsl:variable name="media-type" select="$response?media-type" as="xs:string?"/> + + <xsl:message>ldh:modal-form-response</xsl:message> + + <xsl:choose> + <xsl:when test="$status = (200, 204)"> + <xsl:sequence select="ldh:form-horizontal-submit-success($context)"/> + </xsl:when> + <xsl:when test="$status = 201 and map:contains($response?headers, 'location')"> + <xsl:sequence select="ldh:form-submit-created($context)"/> + </xsl:when> + <xsl:when test="$status = (400, 422) and starts-with($media-type, 'application/rdf+xml')"> + <xsl:sequence select="ldh:modal-form-submit-violation($context)"/> + </xsl:when> + <xsl:otherwise> + <xsl:sequence select="ldh:error-response-alert($context)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:function> + <!-- show "Add data"/"Save as" form --> <xsl:template name="ldh:ShowAddDataForm"> @@ -1356,4 +1638,90 @@ LIMIT 10 </xsl:choose> </xsl:function> + <xsl:function name="ldh:modal-form-submit-violation" ixsl:updating="yes"> + <xsl:param name="context" as="map(*)"/> + <xsl:variable name="response" select="$context('response')" as="map(*)"/> + <xsl:variable name="doc-uri" select="$context('doc-uri')" as="xs:anyURI"/> + <xsl:variable name="block" select="$context('block')" as="element()"/> + <xsl:variable name="form" select="$context('form')" as="element()?"/> + + <xsl:message>ldh:modal-form-submit-violation</xsl:message> + + <xsl:for-each select="$response"> + <xsl:variable name="body" select="?body" as="document-node()"/> + <!-- TO-DO: refactor to use asynchronous HTTP requests --> + <!-- inverse $types expression compared to ldh:row-form-submit-violation --> + <xsl:variable name="types" select="distinct-values($body/rdf:RDF/*[@rdf:about = $doc-uri]/rdf:type/@rdf:resource)" as="xs:anyURI*"/> + <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="type-metadata" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:variable name="property-uris" select="distinct-values($body/rdf:RDF/*[not(@rdf:about = $doc-uri)]/*/concat(namespace-uri(), local-name()))" as="xs:string*"/> + <xsl:variable name="query-string" select="'DESCRIBE $Type VALUES $Type { ' || string-join(for $uri in $property-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="property-metadata" select="document($request-uri)" as="document-node()"/> + + <xsl:variable name="query-string" select="$constructor-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> + <xsl:variable name="constructors" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:variable name="query-string" select="$constraint-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/sparql-results+xml' })" as="xs:anyURI"/> + <xsl:variable name="constraints" select="if (exists($types)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:variable name="query-string" select="$shape-query || ' VALUES $Type { ' || string-join(for $type in $types return '<' || $type || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('ns', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="shapes" select="document($request-uri)" as="document-node()"/> + + <xsl:variable name="object-uris" select="distinct-values($body/rdf:RDF/*/*/@rdf:resource[not(key('resources', .))])" as="xs:string*"/> + <xsl:variable name="query-string" select="$object-metadata-query || ' VALUES $this { ' || string-join(for $uri in $object-uris return '<' || $uri || '>', ' ') || ' }'" as="xs:string"/> + <xsl:variable name="request-uri" select="ac:build-uri(resolve-uri('sparql', ldt:base()), map{ 'query': $query-string, 'accept': 'application/rdf+xml' })" as="xs:anyURI"/> + <xsl:variable name="object-metadata" select="if (doc-available($request-uri)) then document($request-uri) else ()" as="document-node()?"/> + + <xsl:variable name="form" as="element()*"> + <xsl:for-each select="$body"> + <xsl:apply-templates select="." mode="bs2:Form"> <!-- document level template --> + <xsl:with-param name="about" select="()"/> <!-- don't set @about on the container until after the resource is saved --> + <xsl:with-param name="method" select="$form/@method"/> + <xsl:with-param name="action" select="$form/@action" as="xs:anyURI" tunnel="yes"/> + <xsl:with-param name="form-actions-class" select="'form-actions modal-footer'" as="xs:string?"/> + <xsl:with-param name="classes" select="()"/> + <xsl:with-param name="type-metadata" select="$type-metadata" tunnel="yes"/> + <xsl:with-param name="property-metadata" select="$property-metadata" tunnel="yes"/> + <xsl:with-param name="constructors" select="()" tunnel="yes"/> <!-- can be empty because modal form is only used to create Container/Item instances --> + <xsl:with-param name="constraints" select="$constraints" tunnel="yes"/> + <xsl:with-param name="shapes" select="()" tunnel="yes"/> <!-- there will be no shapes as modal form is only used to create Container/Item instances --> + <xsl:with-param name="base-uri" select="ac:absolute-path(ldh:base-uri(.))" tunnel="yes"/> <!-- ac:absolute-path(ldh:base-uri(.)) is empty on constructed documents --> + <!-- <xsl:sort select="ac:label(.)"/> --> + </xsl:apply-templates> + </xsl:for-each> + </xsl:variable> + + <xsl:for-each select="$block"> + <xsl:result-document href="?." method="ixsl:replace-content"> + <div class="modal-header"> + <button type="button" class="close">×</button> + + <legend> + <!-- <xsl:value-of select="$legend-label"/> --> + </legend> + </div> + + <div class="modal-body"> + <xsl:copy-of select="$form"/> + </div> + </xsl:result-document> + </xsl:for-each> + + <!-- cannot be in $form context because it contains old DOM (pre-ixsl:replace-content) --> + <xsl:for-each select="id($form/@id, ixsl:page())"> + <xsl:apply-templates select="." mode="ldh:RenderRowForm"/> + </xsl:for-each> + + <ixsl:set-style name="cursor" select="'default'" object="ixsl:page()//body"/> + </xsl:for-each> + + <xsl:sequence select="$context"/> + </xsl:function> + </xsl:stylesheet> \ No newline at end of file From c847873d606c96cec40d872ede9a71274dc9e09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Sun, 11 Jan 2026 16:29:12 +0100 Subject: [PATCH 52/64] `Add` endpoint does not need to extend `Graph` Since it's not an RDF-backed document --- .../atomgraph/linkeddatahub/resource/Add.java | 166 ++++++------------ 1 file changed, 56 insertions(+), 110 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java index 64c2a4494..0a12c036d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java @@ -20,42 +20,29 @@ import com.atomgraph.core.vocabulary.SD; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.Service; -import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; -import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; -import com.atomgraph.linkeddatahub.vocabulary.NFO; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; -import java.net.URISyntaxException; -import java.util.Map; import java.util.Optional; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.StreamingOutput; import jakarta.ws.rs.core.UriInfo; -import jakarta.ws.rs.ext.MessageBodyReader; import jakarta.ws.rs.ext.Providers; -import org.apache.jena.atlas.RuntimeIOException; import org.apache.jena.ontology.Ontology; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ResIterator; import org.apache.jena.rdf.model.Resource; import org.apache.jena.vocabulary.DCTerms; -import org.glassfish.jersey.media.multipart.FormDataBodyPart; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,11 +51,16 @@ * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class Add extends GraphStoreImpl // TO-DO: does not need to extend GraphStore is the multipart/form-data is not RDF/POST. Replace with ProxyResourceBase? +public class Add { private static final Logger log = LoggerFactory.getLogger(Add.class); + private final UriInfo uriInfo; + private final MediaTypes mediaTypes; + private final Optional<AgentContext> agentContext; + private final com.atomgraph.linkeddatahub.Application system; + /** * Constructs endpoint for synchronous RDF data imports. * @@ -89,18 +81,22 @@ public Add(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaT @Context SecurityContext securityContext, Optional<AgentContext> agentContext, @Context Providers providers, com.atomgraph.linkeddatahub.Application system) { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system); - } - - @GET - @Override - public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) - { - return super.get(false, getURI()); + this.uriInfo = uriInfo; + this.mediaTypes = mediaTypes; + this.agentContext = agentContext; + this.system = system; } - + + /** + * Adds RDF data from a remote source to a named graph. + * Expects a model containing a resource with dct:source (source URI) and sd:name (target graph URI) properties. + * + * @param model the RDF model containing the import parameters + * @param defaultGraph whether to import into the default graph + * @param graphUri the target graph URI + * @return JAX-RS response with the imported data + */ @POST - @Override public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) { ResIterator it = model.listSubjectsWithProperty(DCTerms.source); @@ -126,86 +122,6 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") } } - /** - * Handles multipart requests with RDF files. - * - * @param multiPart multipart request object - * @param defaultGraph true if default graph was specified - * @param graphUri graph name - * @return response - */ - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response postMultipart(FormDataMultiPart multiPart, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) - { - if (log.isDebugEnabled()) log.debug("MultiPart fields: {} body parts: {}", multiPart.getFields(), multiPart.getBodyParts()); - - try - { - Model model = parseModel(multiPart); // do not skolemize because we don't know the graphUri yet - MessageBodyReader<Model> reader = getProviders().getMessageBodyReader(Model.class, null, null, com.atomgraph.core.MediaType.APPLICATION_NTRIPLES_TYPE); - if (reader instanceof ValidatingModelProvider validatingModelProvider) model = validatingModelProvider.processRead(model); - if (log.isDebugEnabled()) log.debug("POSTed Model size: {}", model.size()); - - return postFileBodyPart(model, getFileNameBodyPartMap(multiPart)); // do not write the uploaded file -- instead append its triples/quads - } - catch (URISyntaxException ex) - { - if (log.isErrorEnabled()) log.error("URI '{}' has syntax error in request with media type: {}", ex.getInput(), multiPart.getMediaType()); - throw new BadRequestException(ex); - } - catch (RuntimeIOException ex) - { - if (log.isErrorEnabled()) log.error("Could not read uploaded file as media type: {}", multiPart.getMediaType()); - throw new BadRequestException(ex); - } - } - - /** - * Handles uploaded RDF file. - * - * @param model RDF graph - * @param fileNameBodyPartMap parts of the multipart request - * @return response response - */ - public Response postFileBodyPart(Model model, Map<String, FormDataBodyPart> fileNameBodyPartMap) - { - if (model == null) throw new IllegalArgumentException("Model cannot be null"); - if (fileNameBodyPartMap == null) throw new IllegalArgumentException("Map<String, FormDataBodyPart> cannot be null"); - - ResIterator resIt = model.listResourcesWithProperty(NFO.fileName); - try - { - if (!resIt.hasNext()) throw new BadRequestException("File body part not found in the multipart request"); - - Resource file = resIt.next(); - String fileName = file.getProperty(NFO.fileName).getString(); - FormDataBodyPart bodyPart = fileNameBodyPartMap.get(fileName); - - Resource graph = file.getPropertyResourceValue(SD.name); - if (graph == null || !graph.isURIResource()) throw new BadRequestException("Graph URI (sd:name) not provided"); - if (!file.hasProperty(DCTerms.format)) throw new BadRequestException("RDF format (dct:format) not provided"); - - MediaType mediaType = com.atomgraph.linkeddatahub.MediaType.valueOf(file.getPropertyResourceValue(DCTerms.format)); - bodyPart.setMediaType(mediaType); - - try (InputStream is = bodyPart.getValueAs(InputStream.class)) - { - // forward the stream to the named graph document -- do not directly append triples to graph because the agent might not have access to it - return forwardPost(Entity.entity(getStreamingOutput(is), mediaType), graph.getURI()); - - } - catch (IOException ex) - { - throw new BadRequestException(ex); - } - } - finally - { - resIt.close(); - } - } - /** * Forwards <code>POST</code> request to a graph. * @@ -237,15 +153,45 @@ public StreamingOutput getStreamingOutput(InputStream is) is.transferTo(os); }; } - + /** - * Returns URI of this resource. - * - * @return URI + * Returns the supported media types. + * + * @return media types + */ + public MediaTypes getMediaTypes() + { + return mediaTypes; + } + + /** + * Returns the current URI info. + * + * @return URI info + */ + public UriInfo getUriInfo() + { + return uriInfo; + } + + /** + * Returns the authenticated agent's context. + * + * @return optional agent context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + + /** + * Returns the system application. + * + * @return system application */ - public URI getURI() + public com.atomgraph.linkeddatahub.Application getSystem() { - return getUriInfo().getAbsolutePath(); + return system; } } From 96f86104450e63870f4b8ef77bb83322df1e7197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 13 Jan 2026 22:09:08 +0100 Subject: [PATCH 53/64] Extend `DirectGraphStoreImpl` (#266) * Extending `DirectGraphStoreImpl` instead of `GraphStoreImpl` * `SignUp` endpoint fix * Cleaned up REST method annotations * More annotation cleanup * Moved `Graph` logic into `DirectGraphStoreImpl` * `Item` endpoint fix * `PATCH` fix for empty models --- pom.xml | 4 +- .../atomgraph/linkeddatahub/resource/Add.java | 16 +- .../linkeddatahub/resource/Generate.java | 141 ++++-- .../linkeddatahub/resource/Transform.java | 145 +++++-- .../linkeddatahub/resource/acl/Access.java | 11 +- .../resource/acl/AccessRequest.java | 12 +- .../linkeddatahub/resource/admin/SignUp.java | 26 +- .../linkeddatahub/resource/upload/Item.java | 213 ++++++---- .../resource/upload/sha1/Item.java | 98 ----- .../linkeddatahub/server/model/Patchable.java | 5 +- .../model/impl/DirectGraphStoreImpl.java} | 401 ++++++++++++++---- .../server/model/impl/Dispatcher.java | 10 +- .../server/model/impl/GraphStoreImpl.java | 322 -------------- ...oxyResourceBase.java => ProxiedGraph.java} | 8 +- .../model/impl/ProxyResourceBaseTest.java | 16 +- 15 files changed, 695 insertions(+), 733 deletions(-) delete mode 100644 src/main/java/com/atomgraph/linkeddatahub/resource/upload/sha1/Item.java rename src/main/java/com/atomgraph/linkeddatahub/{resource/Graph.java => server/model/impl/DirectGraphStoreImpl.java} (77%) delete mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java rename src/main/java/com/atomgraph/linkeddatahub/server/model/impl/{ProxyResourceBase.java => ProxiedGraph.java} (98%) diff --git a/pom.xml b/pom.xml index d745a488e..4000207a9 100644 --- a/pom.xml +++ b/pom.xml @@ -139,13 +139,13 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.10</version> + <version>4.2.11-SNAPSHOT</version> <classifier>classes</classifier> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.10</version> + <version>4.2.11-SNAPSHOT</version> <type>war</type> </dependency> <!-- required by jsonld-java - version same as Jersey's HTTP Client --> diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java index 0a12c036d..9bc6b93ad 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Add.java @@ -19,7 +19,6 @@ import com.atomgraph.core.MediaTypes; import com.atomgraph.core.vocabulary.SD; import com.atomgraph.linkeddatahub.client.GraphStoreClient; -import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.security.AgentContext; import java.io.InputStream; import java.io.OutputStream; @@ -27,18 +26,14 @@ import java.util.Optional; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.POST; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.StreamingOutput; import jakarta.ws.rs.core.UriInfo; import jakarta.ws.rs.ext.Providers; -import org.apache.jena.ontology.Ontology; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ResIterator; import org.apache.jena.rdf.model.Resource; @@ -67,18 +62,13 @@ public class Add * @param request current request * @param uriInfo current URI info * @param mediaTypes supported media types - * @param application matched application - * @param ontology matched application's ontology - * @param service matched application's service * @param providers JAX-RS providers * @param system system application - * @param securityContext JAX-RS security context * @param agentContext authenticated agent's context */ @Inject public Add(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, + Optional<AgentContext> agentContext, @Context Providers providers, com.atomgraph.linkeddatahub.Application system) { this.uriInfo = uriInfo; @@ -92,12 +82,10 @@ public Add(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaT * Expects a model containing a resource with dct:source (source URI) and sd:name (target graph URI) properties. * * @param model the RDF model containing the import parameters - * @param defaultGraph whether to import into the default graph - * @param graphUri the target graph URI * @return JAX-RS response with the imported data */ @POST - public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response post(Model model) { ResIterator it = model.listSubjectsWithProperty(DCTerms.source); try diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java index f4a1ccea9..716289439 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Generate.java @@ -16,13 +16,11 @@ */ package com.atomgraph.linkeddatahub.resource; -import com.atomgraph.client.util.DataManager; import com.atomgraph.core.MediaTypes; +import com.atomgraph.linkeddatahub.apps.model.Application; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.imports.QueryLoader; -import com.atomgraph.linkeddatahub.model.Service; -import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter; -import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; +import com.atomgraph.linkeddatahub.server.model.impl.DirectGraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.Skolemizer; import com.atomgraph.linkeddatahub.vocabulary.LDH; @@ -37,18 +35,15 @@ import java.util.UUID; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; -import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.POST; -import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.container.ResourceContext; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.SecurityContext; +import jakarta.ws.rs.core.Response.Status; import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.core.UriInfo; -import jakarta.ws.rs.ext.Providers; -import org.apache.jena.ontology.Ontology; import org.apache.jena.query.ParameterizedSparqlString; import org.apache.jena.query.Query; import org.apache.jena.query.Syntax; @@ -56,10 +51,8 @@ import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.ResIterator; import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.vocabulary.DCTerms; import org.apache.jena.vocabulary.RDF; -import org.glassfish.jersey.uri.UriComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,39 +61,53 @@ * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class Generate extends GraphStoreImpl +public class Generate { private static final Logger log = LoggerFactory.getLogger(Generate.class); + + private final UriInfo uriInfo; + private final MediaTypes mediaTypes; + private final Application application; + private final Optional<AgentContext> agentContext; + private final com.atomgraph.linkeddatahub.Application system; + private final ResourceContext resourceContext; /** * Constructs endpoint for container generation. - * + * * @param request current request * @param uriInfo current URI info * @param mediaTypes supported media types * @param application matched application - * @param ontology matched application's ontology - * @param service matched application's service - * @param providers JAX-RS providers * @param system system application - * @param securityContext JAX-RS security context * @param agentContext authenticated agent's context - * @param dataManager RDF data manager + * @param resourceContext resource context for creating resources */ @Inject public Generate(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, - @Context Providers providers, com.atomgraph.linkeddatahub.Application system, - DataManager dataManager) + com.atomgraph.linkeddatahub.apps.model.Application application, Optional<AgentContext> agentContext, + com.atomgraph.linkeddatahub.Application system, @Context ResourceContext resourceContext) { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system); + this.uriInfo = uriInfo; + this.mediaTypes = mediaTypes; + this.application = application; + this.agentContext = agentContext; + this.system = system; + this.resourceContext = resourceContext; } - + + /** + * Generates containers for given classes. + * Expects a model containing a parent container (<samp>sioc:has_parent</samp>) and one or more class specifications + * with <samp>void:class</samp> and <samp>spin:query</samp> properties. Creates a new container for each class with a view based + * on the provided SPARQL <samp>SELECT</samp> query. + * + * @param model the RDF model containing the generation parameters + * @return JAX-RS response indicating success or failure + */ @POST - @Override - public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response post(Model model) { ResIterator it = model.listSubjectsWithProperty(SIOC.HAS_PARENT); try @@ -143,9 +150,10 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") service))); new Skolemizer(containerGraphURI.toString()).apply(containerModel); - try (Response containerResponse = super.post(containerModel, false, containerGraphURI)) + // append triples directly to the graph store without doing an HTTP request (and thus no ACL check) + try (Response containerResponse = getResourceContext().getResource(DirectGraphStoreImpl.class).post(containerModel, false, containerGraphURI)) { - if (containerResponse.getStatus() != Response.Status.CREATED.getStatusCode()) + if (!containerResponse.getStatusInfo().getFamily().equals(Status.Family.SUCCESSFUL)) { if (log.isErrorEnabled()) log.error("Cannot create container"); throw new InternalServerErrorException("Cannot create container"); @@ -159,10 +167,7 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") } // ban the parent container URI from proxy cache to make sure the next query using it will be fresh (e.g. SELECT that loads children) - try (Response response = ban(getApplication().getService().getBackendProxy(), parent.getURI())) - { - // Response automatically closed by try-with-resources - } + getSystem().ban(getApplication().getService().getBackendProxy(), parent.getURI(), true); return Response.ok().build(); } @@ -211,7 +216,7 @@ public Resource createContainer(Model model, URI graphURI, Resource parent, Stri addLiteral(DCTerms.title, title). addLiteral(DH.slug, UUID.randomUUID().toString()). addLiteral(DCTerms.created, Calendar.getInstance()). - addProperty(ResourceFactory.createProperty(RDF.getURI(), "_1"), content); + addProperty(model.createProperty(RDF.getURI(), "_1"), content); // TO-DO: make sure we're creating sequence value larger than the existing ones? } /** @@ -228,20 +233,64 @@ public Resource createView(Model model, Resource query) addProperty(SPIN.query, query); } - /** - * Bans URL from the backend proxy cache. - * - * @param proxy proxy server URL - * @param url banned URL - * @return proxy server response + /** + * Returns the supported media types. + * + * @return media types */ - public Response ban(Resource proxy, String url) + public MediaTypes getMediaTypes() { - if (url == null) throw new IllegalArgumentException("Resource cannot be null"); - - return getSystem().getClient().target(proxy.getURI()).request(). - header(CacheInvalidationFilter.HEADER_NAME, UriComponent.encode(url, UriComponent.Type.UNRESERVED)). // the value has to be URL-encoded in order to match request URLs in Varnish - method("BAN", Response.class); + return mediaTypes; } - + + /** + * Returns the current application. + * + * @return the application + */ + public Application getApplication() + { + return application; + } + + /** + * Returns the current URI info. + * + * @return URI info + */ + public UriInfo getUriInfo() + { + return uriInfo; + } + + /** + * Returns the authenticated agent's context. + * + * @return optional agent context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + + /** + * Returns the system application. + * + * @return system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns the resource context. + * + * @return resource context + */ + public ResourceContext getResourceContext() + { + return resourceContext; + } + } \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java index cc449de4f..19366b18c 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java @@ -16,14 +16,12 @@ */ package com.atomgraph.linkeddatahub.resource; -import com.atomgraph.client.util.DataManager; import com.atomgraph.core.MediaTypes; import com.atomgraph.core.vocabulary.SD; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.imports.QueryLoader; -import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; -import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; +import com.atomgraph.linkeddatahub.server.model.impl.DirectGraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.vocabulary.NFO; import com.atomgraph.spinrdf.vocabulary.SPIN; @@ -36,20 +34,19 @@ import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.NotAllowedException; import jakarta.ws.rs.POST; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.container.ResourceContext; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.UriInfo; import jakarta.ws.rs.ext.MessageBodyReader; import jakarta.ws.rs.ext.Providers; import org.apache.jena.atlas.RuntimeIOException; -import org.apache.jena.ontology.Ontology; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; import org.apache.jena.query.Syntax; @@ -67,39 +64,69 @@ * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class Transform extends GraphStoreImpl +public class Transform { private static final Logger log = LoggerFactory.getLogger(Transform.class); + private final UriInfo uriInfo; + private final MediaTypes mediaTypes; + private final com.atomgraph.linkeddatahub.apps.model.Application application; + private final Optional<AgentContext> agentContext; + private final Providers providers; + private final com.atomgraph.linkeddatahub.Application system; + private final ResourceContext resourceContext; + /** * Constructs endpoint for synchronous RDF data imports. * * @param request current request * @param uriInfo current URI info * @param mediaTypes supported media types - * @param application matched application - * @param ontology matched application's ontology - * @param service matched application's service + * @param application current application * @param providers JAX-RS providers * @param system system application - * @param securityContext JAX-RS security context * @param agentContext authenticated agent's context - * @param dataManager RDF data manager + * @param resourceContext resource context */ @Inject public Transform(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, + com.atomgraph.linkeddatahub.apps.model.Application application, + Optional<AgentContext> agentContext, @Context Providers providers, com.atomgraph.linkeddatahub.Application system, - DataManager dataManager) + @Context ResourceContext resourceContext) + { + this.uriInfo = uriInfo; + this.mediaTypes = mediaTypes; + this.application = application; + this.agentContext = agentContext; + this.providers = providers; + this.system = system; + this.resourceContext = resourceContext; + } + + /** + * Rejects GET requests on this endpoint. + * + * @return never returns normally + * @throws NotAllowedException always thrown to indicate GET is not supported + */ + @GET + public Response get() { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system); + throw new NotAllowedException("GET is not allowed on this endpoint"); } + /** + * Transforms RDF data from a remote source using a SPARQL CONSTRUCT query and adds it to a target graph. + * Validates URIs to prevent SSRF attacks before processing. + * + * @param model RDF model containing transformation parameters (dct:source, sd:name, spin:query) + * @return HTTP response from forwarding the transformed data to the target graph + * @throws BadRequestException if required parameters are missing or invalid + */ @POST - @Override - public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response post(Model model) { ResIterator it = model.listSubjectsWithProperty(DCTerms.source); try @@ -145,24 +172,24 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") * Handles multipart requests with RDF files. * * @param multiPart multipart request object - * @param defaultGraph true if default graph was specified - * @param graphUri graph name * @return response */ @POST @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response postMultipart(FormDataMultiPart multiPart, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response postMultipart(FormDataMultiPart multiPart) { if (log.isDebugEnabled()) log.debug("MultiPart fields: {} body parts: {}", multiPart.getFields(), multiPart.getBodyParts()); try { - Model model = parseModel(multiPart); // do not skolemize because we don't know the graphUri yet + DirectGraphStoreImpl graphStore = getResourceContext().getResource(DirectGraphStoreImpl.class); + + Model model = graphStore.parseModel(multiPart); // do not skolemize because we don't know the graphUri yet MessageBodyReader<Model> reader = getProviders().getMessageBodyReader(Model.class, null, null, com.atomgraph.core.MediaType.APPLICATION_NTRIPLES_TYPE); if (reader instanceof ValidatingModelProvider validatingModelProvider) model = validatingModelProvider.processRead(model); if (log.isDebugEnabled()) log.debug("POSTed Model size: {}", model.size()); - return postFileBodyPart(model, getFileNameBodyPartMap(multiPart)); // do not write the uploaded file -- instead append its triples/quads + return postFileBodyPart(model, graphStore.getFileNameBodyPartMap(multiPart)); // do not write the uploaded file -- instead append its triples/quads } catch (URISyntaxException ex) { @@ -287,4 +314,74 @@ protected static void validateNotInternalURL(URI uri) } } + /** + * Returns the supported media types. + * + * @return media types + */ + public MediaTypes getMediaTypes() + { + return mediaTypes; + } + + /** + * Returns the current application. + * + * @return application resource + */ + public com.atomgraph.linkeddatahub.apps.model.Application getApplication() + { + return application; + } + + /** + * Returns the current URI info. + * + * @return URI info + */ + public UriInfo getUriInfo() + { + return uriInfo; + } + + /** + * Returns the authenticated agent's context. + * + * @return optional agent context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + + /** + * Returns the registry of JAX-RS providers. + * + * @return JAX-RS providers registry + */ + public Providers getProviders() + { + return providers; + } + + /** + * Returns the system application. + * + * @return system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns the JAX-RS resource context. + * + * @return resource context + */ + public ResourceContext getResourceContext() + { + return resourceContext; + } + } diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/acl/Access.java b/src/main/java/com/atomgraph/linkeddatahub/resource/acl/Access.java index 021523308..f22b7378e 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/acl/Access.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/acl/Access.java @@ -18,9 +18,6 @@ import com.atomgraph.client.util.HTMLMediaTypePredicate; import com.atomgraph.core.MediaTypes; -import static com.atomgraph.core.model.SPARQLEndpoint.DEFAULT_GRAPH_URI; -import static com.atomgraph.core.model.SPARQLEndpoint.NAMED_GRAPH_URI; -import static com.atomgraph.core.model.SPARQLEndpoint.QUERY; import com.atomgraph.core.util.ModelUtils; import com.atomgraph.linkeddatahub.apps.model.AdminApplication; import com.atomgraph.linkeddatahub.apps.model.Application; @@ -36,7 +33,6 @@ import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.GET; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.EntityTag; import jakarta.ws.rs.core.Request; @@ -47,7 +43,6 @@ import java.util.List; import java.util.Optional; import org.apache.jena.query.ParameterizedSparqlString; -import org.apache.jena.query.Query; import org.apache.jena.query.QuerySolutionMap; import org.apache.jena.query.ResultSetRewindable; import org.apache.jena.rdf.model.Model; @@ -106,14 +101,10 @@ public Access(@Context Request request, @Context UriInfo uriInfo, MediaTypes med /** * Implements the HTTP GET method for retrieving access control information. * - * @param unused SPARQL query parameter (unused) - * @param defaultGraphUris default graph URIs - * @param namedGraphUris named graph URIs * @return response with access control data */ @GET - public Response get(@QueryParam(QUERY) Query unused, - @QueryParam(DEFAULT_GRAPH_URI) List<URI> defaultGraphUris, @QueryParam(NAMED_GRAPH_URI) List<URI> namedGraphUris) + public Response get() { final Agent agent = getAgentContext().map(AgentContext::getAgent).orElse(null); diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/acl/AccessRequest.java b/src/main/java/com/atomgraph/linkeddatahub/resource/acl/AccessRequest.java index 8e2a60699..859efa01f 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/acl/AccessRequest.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/acl/AccessRequest.java @@ -30,12 +30,10 @@ import com.atomgraph.linkeddatahub.vocabulary.SIOC; import jakarta.inject.Inject; import jakarta.servlet.ServletConfig; -import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.NotAllowedException; import jakarta.ws.rs.POST; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.UriBuilder; @@ -100,12 +98,10 @@ public AccessRequest(com.atomgraph.linkeddatahub.apps.model.Application applicat /** * Implements the HTTP GET method. * - * @param defaultGraph default graph flag - * @param graphUri graph URI * @return response object */ @GET - public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response get() { throw new NotAllowedException("GET is not allowed on this endpoint"); } @@ -114,12 +110,10 @@ public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaul * Implements the HTTP POST method for submitting access requests. * * @param model RDF model with access request data - * @param defaultGraph default graph flag - * @param graphUri graph URI * @return response object */ @POST - public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response post(Model model) { ResIterator it = model.listResourcesWithProperty(RDF.type, ACL.Authorization); try @@ -128,7 +122,7 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") { Resource authorization = it.next(); - graphUri = getAuthRequestContainerUriBuilder().path(UUID.randomUUID().toString() + "/").build(); // URI of the new access request graph + URI graphUri = getAuthRequestContainerUriBuilder().path(UUID.randomUUID().toString() + "/").build(); // URI of the new access request graph Model requestModel = ModelFactory.createDefaultModel(); Resource agent = authorization.getPropertyResourceValue(ACL.agent); diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java index c8f65f42a..bb161a509 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/SignUp.java @@ -26,7 +26,7 @@ import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.listener.EMailListener; import com.atomgraph.linkeddatahub.server.filter.response.CacheInvalidationFilter; -import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; +import com.atomgraph.linkeddatahub.server.model.impl.DirectGraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.MessageBuilder; import com.atomgraph.linkeddatahub.server.util.Skolemizer; @@ -64,10 +64,7 @@ import jakarta.inject.Inject; import jakarta.mail.MessagingException; import jakarta.servlet.ServletConfig; -import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -101,7 +98,7 @@ * * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ -public class SignUp extends GraphStoreImpl +public class SignUp extends DirectGraphStoreImpl { private static final Logger log = LoggerFactory.getLogger(SignUp.class); @@ -180,16 +177,9 @@ public SignUp(@Context Request request, @Context UriInfo uriInfo, MediaTypes med download = uriInfo.getQueryParameters().containsKey("download"); // debug param that allows downloading the certificate } - @GET - @Override - public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) - { - return super.get(false, getURI()); - } - @POST @Override - public Response post(Model agentModel, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response post(Model agentModel) { URI agentGraphUri = getUriInfo().getBaseUriBuilder().path(AGENT_PATH).path("{slug}/").build(UUID.randomUUID().toString()); new Skolemizer(agentGraphUri.toString()).apply(agentModel); @@ -519,16 +509,6 @@ public Service getAgentService() { return getApplication().getService(); } - - /** - * Returns URI of this resource. - * - * @return resource URI - */ - public URI getURI() - { - return getUriInfo().getAbsolutePath(); - } /** * Returns the number of days until the WebID certificate expires. diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/upload/Item.java b/src/main/java/com/atomgraph/linkeddatahub/resource/upload/Item.java index 41876ac2d..90fae8a00 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/upload/Item.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/upload/Item.java @@ -29,29 +29,24 @@ import com.atomgraph.core.MediaTypes; import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.FileRangeOutput; -import com.atomgraph.linkeddatahub.server.security.AgentContext; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; import java.util.Optional; import jakarta.annotation.PostConstruct; import jakarta.inject.Inject; -import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.NotAcceptableException; import jakarta.ws.rs.NotFoundException; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.EntityTag; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response.Status; -import jakarta.ws.rs.core.SecurityContext; import jakarta.ws.rs.core.UriInfo; -import org.apache.jena.ontology.Ontology; +import jakarta.ws.rs.core.Variant.VariantListBuilder; import org.apache.jena.query.QueryFactory; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.Resource; +import org.apache.jena.sparql.vocabulary.FOAF; import org.apache.jena.vocabulary.DCTerms; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,8 +56,9 @@ * * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ -public class Item extends com.atomgraph.linkeddatahub.resource.Graph +public class Item { + private static final Logger log = LoggerFactory.getLogger(Item.class); private static final String ACCEPT_RANGES = "Accept-Ranges"; @@ -71,7 +67,11 @@ public class Item extends com.atomgraph.linkeddatahub.resource.Graph private static final String CONTENT_RANGE = "Content-Range"; private static final int CHUNK_SIZE = 1024 * 1024; // 1MB chunks + private final Request request; + private final UriInfo uriInfo; + private final Service service; private final Resource resource; + private final com.atomgraph.linkeddatahub.Application system; private final HttpHeaders httpHeaders; /** @@ -80,26 +80,24 @@ public class Item extends com.atomgraph.linkeddatahub.resource.Graph * @param request current request * @param uriInfo URI information of the current request * @param mediaTypes a registry of readable/writable media types - * @param application current application - * @param ontology ontology of the current application * @param service SPARQL service of the current application - * @param securityContext JAX-RS security context - * @param agentContext authenticated agent's context * @param providers JAX-RS provider registry * @param system system application * @param httpHeaders request headers */ @Inject public Item(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, + Optional<Service> service, @Context Providers providers, com.atomgraph.linkeddatahub.Application system, @Context HttpHeaders httpHeaders) { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system); + this.request = request; + this.uriInfo = uriInfo; + this.service = service.get(); this.resource = ModelFactory.createDefaultModel().createResource(uriInfo.getAbsolutePath().toString()); - if (log.isDebugEnabled()) log.debug("Constructing {}", getClass()); + this.system = system; this.httpHeaders = httpHeaders; + if (log.isDebugEnabled()) log.debug("Constructing {}", getClass()); } /** @@ -110,38 +108,52 @@ public void init() { getResource().getModel().add(describe()); } - + + /** + * Handles GET requests for uploaded files. + * Evaluates HTTP preconditions and serves file content with appropriate Content-Security-Policy headers. + * + * @return HTTP response with file content or 304 Not Modified + */ @GET - @Override - public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUri) + public Response get() { - return getResponseBuilder(getResource().getModel(), graphUri).build(); + return getResponseBuilder(getResource().getModel(), getURI()).build(); } - - @Override + + /** + * Builds HTTP response for file requests. + * Handles content negotiation, HTTP precondition evaluation (ETag-based caching), + * byte-range requests, and applies Content-Security-Policy headers. + * + * @param model RDF model describing the file + * @param graphUri the graph URI (not used for binary file responses) + * @return response builder configured for file serving + */ public ResponseBuilder getResponseBuilder(Model model, URI graphUri) { // do not pass language list as languages do not apply to binary files - List<Variant> variants = com.atomgraph.core.model.impl.Response.getVariants(getWritableMediaTypes(Model.class), Collections.emptyList(), getEncodings()); + List<Variant> variants = VariantListBuilder.newInstance().mediaTypes(getMediaType()).build(); Variant variant = getRequest().selectVariant(variants); - if (variant == null) + if (variant == null || !getMediaType().isCompatible(variant.getMediaType())) { if (log.isTraceEnabled()) log.trace("Requested Variant {} is not on the list of acceptable Response Variants: {}", variant, variants); throw new NotAcceptableException(); } - // respond with file content if Variant is compatible with the File's MediaType. otherwise, send RDF - if (getMediaType().isCompatible(variant.getMediaType())) - { - URI fileURI = getSystem().getUploadRoot().resolve(getUriInfo().getPath()); - File file = new File(fileURI); + EntityTag entityTag = getEntityTag(); + ResponseBuilder rb = getRequest().evaluatePreconditions(entityTag); + if (rb != null) return rb; // file not modified + + URI fileURI = getSystem().getUploadRoot().resolve(getUriInfo().getPath()); + File file = new File(fileURI); - if (!file.exists()) throw new NotFoundException(new FileNotFoundException("File '" + getUriInfo().getPath() + "' not found")); + if (!file.exists()) throw new NotFoundException(new FileNotFoundException("File '" + getUriInfo().getPath() + "' not found")); + + if (getHttpHeaders().getRequestHeaders().containsKey(RANGE)) + { + String range = getHttpHeaders().getHeaderString(RANGE); - if (getHttpHeaders().getRequestHeaders().containsKey(RANGE)) - { - String range = getHttpHeaders().getHeaderString(RANGE); - // if (getHttpHeaders().getRequestHeaders().containsKey(IF_RANGE)) { // String ifRangeHeader = getHttpHeaders().getHeaderString(IF_RANGE); // @@ -157,34 +169,32 @@ public ResponseBuilder getResponseBuilder(Model model, URI graphUri) //// } // } // else - { - FileRangeOutput rangeOutput = getFileRangeOutput(file, range); - final long to = rangeOutput.getLength() + rangeOutput.getFrom(); - String contentRangeValue = String.format("bytes %d-%d/%d", rangeOutput.getFrom(), to - 1, rangeOutput.getFile().length()); - - return super.getResponseBuilder(model, graphUri). - status(Status.PARTIAL_CONTENT). - entity(rangeOutput). - type(variant.getMediaType()). - lastModified(getLastModified(file)). - header(HttpHeaders.CONTENT_LENGTH, rangeOutput.getLength()). // should override Transfer-Encoding: chunked - header(ACCEPT_RANGES, BYTES_RANGE). - header(CONTENT_RANGE, contentRangeValue). - header("Content-Security-Policy", "default-src 'none'; sandbox"); // LNK-011 fix: prevent XSS in uploaded HTML files - } - } + { + FileRangeOutput rangeOutput = getFileRangeOutput(file, range); + final long to = rangeOutput.getLength() + rangeOutput.getFrom(); + String contentRangeValue = String.format("bytes %d-%d/%d", rangeOutput.getFrom(), to - 1, rangeOutput.getFile().length()); - return super.getResponseBuilder(model, graphUri). - entity(file). - type(variant.getMediaType()). - lastModified(getLastModified(file)). - header(HttpHeaders.CONTENT_LENGTH, file.length()). // should override Transfer-Encoding: chunked - header(ACCEPT_RANGES, BYTES_RANGE). - header("Content-Security-Policy", "default-src 'none'; sandbox"); // LNK-011 fix: prevent XSS in uploaded HTML files - //header("Content-Disposition", "attachment; filename=\"" + getRequiredProperty(NFO.fileName).getString() + "\""). + return Response.status(Status.PARTIAL_CONTENT). + entity(rangeOutput). + type(variant.getMediaType()). + tag(entityTag). + lastModified(getLastModified(file)). + header(HttpHeaders.CONTENT_LENGTH, rangeOutput.getLength()). // should override Transfer-Encoding: chunked + header(ACCEPT_RANGES, BYTES_RANGE). + header(CONTENT_RANGE, contentRangeValue). + header("Content-Security-Policy", "default-src 'none'; sandbox"); // LNK-011 fix: prevent XSS in uploaded HTML files + } } - - return super.getResponseBuilder(model, graphUri); + + return Response.ok(). + entity(file). + type(variant.getMediaType()). + tag(entityTag). + lastModified(getLastModified(file)). + header(HttpHeaders.CONTENT_LENGTH, file.length()). // should override Transfer-Encoding: chunked + header(ACCEPT_RANGES, BYTES_RANGE). + header("Content-Security-Policy", "default-src 'none'; sandbox"); // LNK-011 fix: prevent XSS in uploaded HTML files + //header("Content-Disposition", "attachment; filename=\"" + getRequiredProperty(NFO.fileName).getString() + "\""). } /** @@ -237,11 +247,15 @@ public FileRangeOutput getFileRangeOutput(File file, String range) final long length = to - from; return new FileRangeOutput(file, from, length); } - - @Override - public EntityTag getEntityTag(Model model) + + /** + * Returns the ETag for HTTP caching based on the file's SHA1 hash. + * + * @return entity tag for cache validation + */ + public EntityTag getEntityTag() { - return null; // disable ETag based on Model hash + return new EntityTag(getSHA1Hash(getResource())); } /** @@ -271,14 +285,16 @@ public jakarta.ws.rs.core.MediaType getMediaType() return com.atomgraph.linkeddatahub.MediaType.valueOf(format); } - - @Override + + /** + * Returns the list of media types that can be used to write this file's content. + * + * @param clazz the class type (not used, file has single media type) + * @return list containing the file's media type + */ public List<jakarta.ws.rs.core.MediaType> getWritableMediaTypes(Class clazz) { - List<jakarta.ws.rs.core.MediaType> list = new ArrayList<>(); - list.add(getMediaType()); - - return list; + return List.of(getMediaType()); } /** @@ -293,14 +309,55 @@ public Model describe() } /** - * Returns URI of this file. + * Returns SHA1 property value of the specified resource. * - * @return file URI + * @param resource RDF resource + * @return SHA1 hash string + */ + public String getSHA1Hash(Resource resource) + { + return resource.getRequiredProperty(FOAF.sha1).getString(); + } + + /** + * Returns the absolute URI of this file resource. + * + * @return the file's URI */ public URI getURI() { return getUriInfo().getAbsolutePath(); } + + /** + * Returns the current JAX-RS request. + * + * @return request object + */ + public Request getRequest() + { + return request; + } + + /** + * Returns the URI information of the current request. + * + * @return URI info + */ + public UriInfo getUriInfo() + { + return uriInfo; + } + + /** + * Returns the SPARQL service of the current application. + * + * @return SPARQL service + */ + public Service getService() + { + return service; + } /** * Returns RDF resource of this file. @@ -311,7 +368,17 @@ public Resource getResource() { return resource; } - + + /** + * Returns the system application instance. + * + * @return system application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + /** * Returns HTTP headers of the current request. * diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/upload/sha1/Item.java b/src/main/java/com/atomgraph/linkeddatahub/resource/upload/sha1/Item.java deleted file mode 100644 index a0120e520..000000000 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/upload/sha1/Item.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright 2019 Martynas Jusevičius <martynas@atomgraph.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.atomgraph.linkeddatahub.resource.upload.sha1; - -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Request; -import jakarta.ws.rs.ext.Providers; -import com.atomgraph.core.MediaTypes; -import com.atomgraph.linkeddatahub.model.Service; -import com.atomgraph.linkeddatahub.server.security.AgentContext; -import java.io.File; -import java.util.Date; -import java.util.Optional; -import jakarta.inject.Inject; -import jakarta.ws.rs.core.EntityTag; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.SecurityContext; -import jakarta.ws.rs.core.UriInfo; -import org.apache.jena.ontology.Ontology; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.sparql.vocabulary.FOAF; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * JAX-RS resource that serves content-addressed (using SHA1 hash) file data. - * - * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} - */ -public class Item extends com.atomgraph.linkeddatahub.resource.upload.Item -{ - private static final Logger log = LoggerFactory.getLogger(Item.class); - - /** - * Constructs resource. - * - * @param request current request - * @param uriInfo URI information of the current request - * @param mediaTypes a registry of readable/writable media types - * @param application current application - * @param ontology ontology of the current application - * @param service SPARQL service of the current application - * @param securityContext JAX-RS security context - * @param agentContext authenticated agent's context - * @param providers JAX-RS provider registry - * @param system system application - * @param httpHeaders request headers - */ - @Inject - public Item(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, - @Context Providers providers, com.atomgraph.linkeddatahub.Application system, - @Context HttpHeaders httpHeaders) - { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system, httpHeaders); - if (log.isDebugEnabled()) log.debug("Constructing {}", getClass()); - } - - @Override - protected Date getLastModified(File file) - { - return null; // disable Last-Modified because we're using ETag here - } - - @Override - public EntityTag getEntityTag(Model model) - { - return new EntityTag(getSHA1Hash(getResource())); - } - - /** - * Returns SHA1 property value of the specified resource. - * - * @param resource RDF resource - * @return SHA1 hash string - */ - public String getSHA1Hash(Resource resource) - { - return resource.getRequiredProperty(FOAF.sha1).getString(); - } - -} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/Patchable.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/Patchable.java index 773074251..9c60b8c96 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/Patchable.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/Patchable.java @@ -16,9 +16,7 @@ */ package com.atomgraph.linkeddatahub.server.model; -import java.net.URI; import jakarta.ws.rs.PATCH; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Response; import org.apache.jena.update.UpdateRequest; @@ -34,10 +32,9 @@ public interface Patchable * Handles <code>PATCH</code> request.SPARQL update is used as the patch format. * * @param updateRequest SPARQL update - * @param graphUri named graph URI * @return response * @see <a href="https://www.w3.org/TR/sparql11-http-rdf-update/#http-patch">HTTP PATCH</a> */ - @PATCH Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI graphUri); + @PATCH Response patch(UpdateRequest updateRequest); } diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java similarity index 77% rename from src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java rename to src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java index d170d7f56..e5a73fcd7 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Graph.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java @@ -1,5 +1,5 @@ /** - * Copyright 2021 Martynas Jusevičius <martynas@atomgraph.com> + * Copyright 2019 Martynas Jusevičius <martynas@atomgraph.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,13 @@ * limitations under the License. * */ -package com.atomgraph.linkeddatahub.resource; +package com.atomgraph.linkeddatahub.server.model.impl; import com.atomgraph.client.util.HTMLMediaTypePredicate; import com.atomgraph.client.vocabulary.AC; import com.atomgraph.core.MediaTypes; import com.atomgraph.core.model.EndpointAccessor; +import com.atomgraph.core.riot.lang.RDFPostReader; import com.atomgraph.linkeddatahub.apps.model.EndUserApplication; import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.model.CSVImport; @@ -27,7 +28,6 @@ import com.atomgraph.linkeddatahub.model.Service; import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; import com.atomgraph.linkeddatahub.server.model.Patchable; -import com.atomgraph.linkeddatahub.server.model.impl.GraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.util.PatchUpdateVisitor; import com.atomgraph.linkeddatahub.server.util.Skolemizer; @@ -38,16 +38,15 @@ import com.atomgraph.linkeddatahub.vocabulary.SIOC; import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; +import java.net.URISyntaxException; +import java.security.MessageDigest; import java.util.List; +import java.util.Locale; import java.util.Optional; import jakarta.inject.Inject; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.NotFoundException; @@ -55,16 +54,15 @@ import jakarta.ws.rs.PATCH; import jakarta.ws.rs.POST; import jakarta.ws.rs.PUT; -import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Request; import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.Response.ResponseBuilder; import static jakarta.ws.rs.core.Response.Status.PERMANENT_REDIRECT; import jakarta.ws.rs.core.SecurityContext; +import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.core.UriInfo; import jakarta.ws.rs.ext.MessageBodyReader; import jakarta.ws.rs.ext.Providers; @@ -73,15 +71,18 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URISyntaxException; import java.nio.channels.Channels; import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; import java.security.DigestInputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.codec.binary.Hex; @@ -109,45 +110,83 @@ import org.apache.jena.util.iterator.ExtendedIterator; import org.apache.jena.vocabulary.DCTerms; import org.apache.jena.vocabulary.RDF; +import org.glassfish.jersey.media.multipart.BodyPart; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * JAX-RS resource that handles requests to directly-identified named graphs. - * Direct identification is specified in the Graph Store Protocol. + * LinkedDataHub Graph Store implementation. + * We need to subclass the Core class because we're injecting a subclass of Service. * - * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ -public class Graph extends GraphStoreImpl implements Patchable +public class DirectGraphStoreImpl extends com.atomgraph.core.model.impl.DirectGraphStoreImpl implements Patchable { - private static final Logger log = LoggerFactory.getLogger(Graph.class); + private static final Logger log = LoggerFactory.getLogger(DirectGraphStoreImpl.class); - private final Set<String> allowedMethods; + /** + * The relative path of the content-addressed file container. + */ + public static final String UPLOADS_PATH = "uploads"; + private final com.atomgraph.linkeddatahub.apps.model.Application application; + private final Ontology ontology; + private final Service service; + private final Providers providers; + private final com.atomgraph.linkeddatahub.Application system; + private final UriBuilder uploadsUriBuilder; + private final MessageDigest messageDigest; + /** The URIs for owner and secretary documents. */ + protected final URI ownerDocURI, secretaryDocURI; + private final SecurityContext securityContext; + private final Optional<AgentContext> agentContext; + private final Set<String> allowedMethods; + /** - * Constructs resource. + * Constructs Graph Store. * * @param request current request - * @param uriInfo URI information of the current request + * @param uriInfo URI info of the current request * @param mediaTypes a registry of readable/writable media types * @param application current application * @param ontology ontology of the current application * @param service SPARQL service of the current application * @param securityContext JAX-RS security context * @param agentContext authenticated agent's context - * @param providers JAX-RS provider registry + * @param providers registry of JAX-RS providers * @param system system application */ @Inject - public Graph(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, + public DirectGraphStoreImpl(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, @Context SecurityContext securityContext, Optional<AgentContext> agentContext, @Context Providers providers, com.atomgraph.linkeddatahub.Application system) { - super(request, uriInfo, mediaTypes, application, ontology, service, securityContext, agentContext, providers, system); + super(request, service.get(), mediaTypes, uriInfo); + if (ontology.isEmpty()) throw new InternalServerErrorException("Ontology is not specified"); + if (service.isEmpty()) throw new InternalServerErrorException("Service is not specified"); + this.application = application; + this.ontology = ontology.get(); + this.service = service.get(); + this.securityContext = securityContext; + this.agentContext = agentContext; + this.providers = providers; + this.system = system; + this.messageDigest = system.getMessageDigest(); + uploadsUriBuilder = uriInfo.getBaseUriBuilder().path(UPLOADS_PATH); + URI ownerURI = URI.create(application.getMaker().getURI()); + try + { + this.ownerDocURI = new URI(ownerURI.getScheme(), ownerURI.getSchemeSpecificPart(), null).normalize(); + this.secretaryDocURI = new URI(system.getSecretaryWebIDURI().getScheme(), system.getSecretaryWebIDURI().getSchemeSpecificPart(), null).normalize(); + } + catch (URISyntaxException ex) + { + throw new InternalServerErrorException(ex); + } URI uri = uriInfo.getAbsolutePath(); allowedMethods = new HashSet<>(); @@ -163,23 +202,23 @@ public Graph(@Context Request request, @Context UriInfo uriInfo, MediaTypes medi !secretaryDocURI.equals(uri)) allowedMethods.add(HttpMethod.DELETE); } - - @Override - @GET - public Response get(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) - { - return super.get(false, getURI()); - } + /** + * Implements <code>POST</code> method of SPARQL Graph Store Protocol. + * Adds triples to the existing graph, skolemizes blank nodes, updates modification timestamp, and submits any imports. + * + * @param model RDF model to add to the graph + * @return HTTP response with updated entity tag + */ @Override @POST - public Response post(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) + public Response post(Model model) { if (log.isTraceEnabled()) log.trace("POST Graph Store request with RDF payload: {} payload size(): {}", model, model.size()); final Model existingModel = getService().getGraphStoreClient().getModel(getURI().toString()); - ResponseBuilder rb = evaluatePreconditions(existingModel); + Response.ResponseBuilder rb = evaluatePreconditions(existingModel); if (rb != null) return rb.build(); // preconditions not met model.createResource(getURI().toString()). @@ -203,10 +242,18 @@ public Response post(Model model, @QueryParam("default") @DefaultValue("false") build(); } + /** + * Implements <code>PUT</code> method of SPARQL Graph Store Protocol. + * Creates a new graph or updates an existing one. Enforces trailing slash in URIs, skolemizes blank nodes, + * establishes parent/container relationships, and manages metadata (created, modified, creator, owner timestamps). + * + * @param model RDF model to create or update + * @return HTTP response with 201 Created for new graphs or 200 OK for updates + */ @Override @PUT // the AuthorizationFilter only allows creating new child URIs for existing containers (i.e. there has to be a .. container already) - public Response put(Model model, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) + public Response put(Model model) { if (log.isTraceEnabled()) log.trace("PUT Graph Store request with RDF payload: {} payload size(): {}", model, model.size()); @@ -239,7 +286,7 @@ public Response put(Model model, @QueryParam("default") @DefaultValue("false") B { existingModel = getService().getGraphStoreClient().getModel(getURI().toString()); - ResponseBuilder rb = evaluatePreconditions(existingModel); + Response.ResponseBuilder rb = evaluatePreconditions(existingModel); if (rb != null) return rb.build(); // preconditions not met } catch (NotFoundException ex) @@ -311,12 +358,11 @@ public Response put(Model model, @QueryParam("default") @DefaultValue("false") B * The <code>GRAPH</code> keyword is therefore not allowed in the update string. * * @param updateRequest SPARQL update - * @param graphUriUnused named graph URI (unused) * @return response response object */ @PATCH @Override - public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI graphUriUnused) + public Response patch(UpdateRequest updateRequest) { if (updateRequest == null) throw new BadRequestException("SPARQL update not specified"); if (log.isDebugEnabled()) log.debug("PATCH request on named graph with URI: {}", getURI()); @@ -343,7 +389,7 @@ public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI grap final Model existingModel = getService().getGraphStoreClient().getModel(getURI().toString()); if (existingModel == null) throw new NotFoundException("Named graph with URI <" + getURI() + "> not found"); - ResponseBuilder rb = evaluatePreconditions(existingModel); + Response.ResponseBuilder rb = evaluatePreconditions(existingModel); if (rb != null) return rb.build(); // preconditions not met Model beforeUpdateModel = ModelFactory.createDefaultModel().add(existingModel); @@ -358,7 +404,7 @@ public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI grap changedModel.add(existingModel.listStatements(resource, null, (RDFNode) null)); // if PATCH results in an empty model, treat it as a DELETE request - if (changedModel.isEmpty()) return delete(Boolean.FALSE, getURI()); + if (changedModel.isEmpty()) return delete(); validate(changedModel); // this would normally be done transparently by the ValidatingModelProvider put(dataset.getDefaultModel(), Boolean.FALSE, getURI()); @@ -371,32 +417,6 @@ public Response patch(UpdateRequest updateRequest, @QueryParam("graph") URI grap build(); } - /** - * Gets a diff of triples between two models and returns a set of their subject resources. - * - * @param beforeUpdateModel model before the update - * @param afterUpdateModel model after the update - * @return set of changed resources - */ - public Set<Resource> getChangedResources(Model beforeUpdateModel, Model afterUpdateModel) - { - if (beforeUpdateModel == null) throw new IllegalArgumentException("Model before update cannot be null"); - if (afterUpdateModel == null) throw new IllegalArgumentException("Model after update cannot be null"); - - Model addedTriples = afterUpdateModel.difference(beforeUpdateModel); - Model removedTriples = beforeUpdateModel.difference(afterUpdateModel); - - Set<Resource> changedResources = new HashSet<>(); - addedTriples.listStatements().forEachRemaining(statement -> { - changedResources.add(statement.getSubject()); - }); - removedTriples.listStatements().forEachRemaining(statement -> { - changedResources.add(statement.getSubject()); - }); - - return changedResources; - } - /** * Overrides <code>OPTIONS</code> HTTP header values.Specifies allowed methods. * @@ -420,13 +440,11 @@ public Response options() * Files are written to storage before the RDF data is passed to the default <code>POST</code> handler method. * * @param multiPart multipart form data - * @param defaultGraph true if default graph is requested - * @param graphUriUnused named graph URI (unused) * @return HTTP response */ @POST @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response postMultipart(FormDataMultiPart multiPart, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) + public Response postMultipart(FormDataMultiPart multiPart) { if (log.isDebugEnabled()) log.debug("MultiPart fields: {} body parts: {}", multiPart.getFields(), multiPart.getBodyParts()); @@ -464,13 +482,11 @@ public Response postMultipart(FormDataMultiPart multiPart, @QueryParam("default" * Files are written to storage before the RDF data is passed to the default <code>PUT</code> handler method. * * @param multiPart multipart form data - * @param defaultGraph true if default graph is requested - * @param graphUriUnused named graph URI (unused) * @return HTTP response */ @PUT @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response putMultipart(FormDataMultiPart multiPart, @QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) + public Response putMultipart(FormDataMultiPart multiPart) { if (log.isDebugEnabled()) log.debug("MultiPart fields: {} body parts: {}", multiPart.getFields(), multiPart.getBodyParts()); @@ -486,7 +502,7 @@ public Response putMultipart(FormDataMultiPart multiPart, @QueryParam("default") int fileCount = writeFiles(model, getFileNameBodyPartMap(multiPart)); if (log.isDebugEnabled()) log.debug("# of files uploaded: {} ", fileCount); - return put(model, defaultGraph, getURI()); // ignore the @QueryParam("graph") value + return put(model, false, getURI()); } catch (URISyntaxException ex) { @@ -503,13 +519,11 @@ public Response putMultipart(FormDataMultiPart multiPart, @QueryParam("default") /** * Implements DELETE method of SPARQL Graph Store Protocol. * - * @param defaultGraph true if default graph is requested - * @param graphUriUnused named graph URI (unused) * @return response */ @DELETE @Override - public Response delete(@QueryParam("default") @DefaultValue("false") Boolean defaultGraph, @QueryParam("graph") URI graphUriUnused) + public Response delete() { if (!getAllowedMethods().contains(HttpMethod.DELETE)) throw new WebApplicationException("Cannot delete document", Response.status(Response.Status.METHOD_NOT_ALLOWED).allow(getAllowedMethods()).build()); @@ -518,7 +532,7 @@ public Response delete(@QueryParam("default") @DefaultValue("false") Boolean def { Model existingModel = getService().getGraphStoreClient().getModel(getURI().toString()); - ResponseBuilder rb = evaluatePreconditions(existingModel); + Response.ResponseBuilder rb = evaluatePreconditions(existingModel); if (rb != null) return rb.build(); // preconditions not met } catch (NotFoundException ex) @@ -529,6 +543,32 @@ public Response delete(@QueryParam("default") @DefaultValue("false") Boolean def return super.delete(false, getURI()); } + /** + * Gets a diff of triples between two models and returns a set of their subject resources. + * + * @param beforeUpdateModel model before the update + * @param afterUpdateModel model after the update + * @return set of changed resources + */ + public Set<Resource> getChangedResources(Model beforeUpdateModel, Model afterUpdateModel) + { + if (beforeUpdateModel == null) throw new IllegalArgumentException("Model before update cannot be null"); + if (afterUpdateModel == null) throw new IllegalArgumentException("Model after update cannot be null"); + + Model addedTriples = afterUpdateModel.difference(beforeUpdateModel); + Model removedTriples = beforeUpdateModel.difference(afterUpdateModel); + + Set<Resource> changedResources = new HashSet<>(); + addedTriples.listStatements().forEachRemaining(statement -> { + changedResources.add(statement.getSubject()); + }); + removedTriples.listStatements().forEachRemaining(statement -> { + changedResources.add(statement.getSubject()); + }); + + return changedResources; + } + /** * Get internal response object. * @@ -556,22 +596,11 @@ public com.atomgraph.core.model.impl.Response getInternalResponse(Model model, U * @return response builder */ @Override - public ResponseBuilder getResponseBuilder(Model model, URI graphUri) + public Response.ResponseBuilder getResponseBuilder(Model model, URI graphUri) { return getInternalResponse(model, graphUri).getResponseBuilder(); } - /** - * List allowed HTTP methods for the current graph URI. - * Exceptions apply to the application's Root document, owner's WebID document, and secretary's WebID document. - * - * @return list of HTTP methods - */ - public Set<String> getAllowedMethods() - { - return allowedMethods; - } - /** * Writes all files from the multipart RDF/POST request body. * @@ -860,19 +889,88 @@ public Model validate(Model model) * @param model RDF model * @return {@code jakarta.ws.rs.core.Response.ResponseBuilder} instance. <code>null</code> if preconditions are not met. */ - public ResponseBuilder evaluatePreconditions(Model model) + public Response.ResponseBuilder evaluatePreconditions(Model model) { return getInternalResponse(model, getURI()).evaluatePreconditions(); } /** - * Returns the named graph URI. + * Parses multipart RDF/POST request. + * + * @param multiPart multipart form data + * @return RDF graph + * @throws URISyntaxException thrown if there is a syntax error in RDF/POST data + * @see <a href="https://atomgraph.github.io/RDF-POST/">RDF/POST Encoding for RDF</a> + */ + public Model parseModel(FormDataMultiPart multiPart) throws URISyntaxException + { + if (multiPart == null) throw new IllegalArgumentException("FormDataMultiPart cannot be null"); + + List<String> keys = new ArrayList<>(), values = new ArrayList<>(); + Iterator<BodyPart> it = multiPart.getBodyParts().iterator(); // not using getFields() to retain ordering + + while (it.hasNext()) + { + FormDataBodyPart bodyPart = (FormDataBodyPart)it.next(); + if (log.isDebugEnabled()) log.debug("Body part media type: {} headers: {}", bodyPart.getMediaType(), bodyPart.getHeaders()); + + // it's a file (if the filename is not empty) + if (bodyPart.getContentDisposition().getFileName() != null && + !bodyPart.getContentDisposition().getFileName().isEmpty()) + { + keys.add(bodyPart.getName()); + if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getContentDisposition().getFileName()); + values.add(bodyPart.getContentDisposition().getFileName()); + } + else + { + if (bodyPart.isSimple() && !bodyPart.getValue().isEmpty()) + { + keys.add(bodyPart.getName()); + if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getValue()); + values.add(bodyPart.getValue()); + } + } + } + + return RDFPostReader.parse(keys, values); + } + + /** + * Gets a map of file parts from multipart form data. * - * @return graph URI + * @param multiPart multipart form data + * @return map of file parts */ - public URI getURI() + public Map<String, FormDataBodyPart> getFileNameBodyPartMap(FormDataMultiPart multiPart) { - return getUriInfo().getAbsolutePath(); + if (multiPart == null) throw new IllegalArgumentException("FormDataMultiPart cannot be null"); + + Map<String, FormDataBodyPart> fileNameBodyPartMap = new HashMap<>(); + Iterator<BodyPart> it = multiPart.getBodyParts().iterator(); // not using getFields() to retain ordering + while (it.hasNext()) + { + FormDataBodyPart bodyPart = (FormDataBodyPart)it.next(); + if (log.isDebugEnabled()) log.debug("Body part media type: {} headers: {}", bodyPart.getMediaType(), bodyPart.getHeaders()); + + if (bodyPart.getContentDisposition().getFileName() != null) // it's a file + { + if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getContentDisposition().getFileName()); + fileNameBodyPartMap.put(bodyPart.getContentDisposition().getFileName(), bodyPart); + } + } + return fileNameBodyPartMap; + } + + /** + * List allowed HTTP methods for the current graph URI. + * Exceptions apply to the application's Root document, owner's WebID document, and secretary's WebID document. + * + * @return list of HTTP methods + */ + public Set<String> getAllowedMethods() + { + return allowedMethods; } /** @@ -885,4 +983,125 @@ public EndpointAccessor getEndpointAccessor() return getService().getEndpointAccessor(); } -} + /** + * Returns a list of supported languages. + * + * @return list of languages + */ + @Override + public List<Locale> getLanguages() + { + return getSystem().getSupportedLanguages(); + } + + /** + * Returns URI builder for uploaded file resources. + * + * @return URI builder + */ + public UriBuilder getUploadsUriBuilder() + { + return uploadsUriBuilder.clone(); + } + + /** + * Returns message digest used in SHA1 hashing. + * + * @return message digest + */ + public MessageDigest getMessageDigest() + { + return messageDigest; + } + + /** + * Returns the current application. + * + * @return application resource + */ + public com.atomgraph.linkeddatahub.apps.model.Application getApplication() + { + return application; + } + + /** + * Returns the ontology of the current application. + * + * @return ontology resource + */ + public Ontology getOntology() + { + return ontology; + } + + /** + * Returns the SPARQL service of the current application. + * + * @return service resource + */ + public Service getService() + { + return service; + } + + /** + * Get JAX-RS security context + * + * @return security context object + */ + public SecurityContext getSecurityContext() + { + return securityContext; + } + + /** + * Gets authenticated agent's context + * + * @return optional agent's context + */ + public Optional<AgentContext> getAgentContext() + { + return agentContext; + } + + /** + * Returns a registry of JAX-RS providers. + * + * @return provider registry + */ + public Providers getProviders() + { + return providers; + } + + /** + * Returns the system application. + * + * @return JAX-RS application + */ + public com.atomgraph.linkeddatahub.Application getSystem() + { + return system; + } + + /** + * Returns URI of the WebID document of the applications owner. + * + * @return document URI + */ + public URI getOwnerDocURI() + { + return ownerDocURI; + } + + /** + * Returns URI of the WebID document of the applications secretary. + * + * @return document URI + */ + public URI getSecretaryDocURI() + { + return secretaryDocURI; + } + +} \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java index 451dc874f..1ad8f8002 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java @@ -27,7 +27,6 @@ import com.atomgraph.linkeddatahub.resource.admin.pkg.UninstallPackage; import com.atomgraph.linkeddatahub.resource.Settings; import com.atomgraph.linkeddatahub.resource.admin.SignUp; -import com.atomgraph.linkeddatahub.resource.Graph; import com.atomgraph.linkeddatahub.resource.acl.Access; import com.atomgraph.linkeddatahub.resource.acl.AccessRequest; import java.util.Optional; @@ -82,12 +81,12 @@ public Optional<Class> getProxyClass() if (getUriInfo().getQueryParameters().containsKey(AC.uri.getLocalName())) { if (log.isDebugEnabled()) log.debug("No Application matched request URI <{}>, dispatching to ProxyResourceBase", getUriInfo().getQueryParameters().getFirst(AC.uri.getLocalName())); - return Optional.of(ProxyResourceBase.class); + return Optional.of(ProxiedGraph.class); } if (getDataset().isPresent()) { if (log.isDebugEnabled()) log.debug("Serving request URI <{}> from Dataset <{}>, dispatching to ProxyResourceBase", getUriInfo().getAbsolutePath(), getDataset().get()); - return Optional.of(ProxyResourceBase.class); + return Optional.of(ProxiedGraph.class); } return Optional.empty(); @@ -181,7 +180,7 @@ public Class getAccessRequest() @Path("uploads/{sha1sum}") public Class getFileItem() { - return getProxyClass().orElse(com.atomgraph.linkeddatahub.resource.upload.sha1.Item.class); + return getProxyClass().orElse(com.atomgraph.linkeddatahub.resource.upload.Item.class); } /** @@ -263,12 +262,13 @@ public Class getSettingsEndpoint() /** * Returns the default JAX-RS resource class. + * Only directly identified access to named graphs is allowed (the Graph Store Protocol endpoint is not exposed). * * @return resource class */ public Class getDocumentClass() { - return Graph.class; + return DirectGraphStoreImpl.class; } /** diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java deleted file mode 100644 index 1c25cd2a2..000000000 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/GraphStoreImpl.java +++ /dev/null @@ -1,322 +0,0 @@ -/** - * Copyright 2019 Martynas Jusevičius <martynas@atomgraph.com> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.atomgraph.linkeddatahub.server.model.impl; - -import com.atomgraph.core.MediaTypes; -import com.atomgraph.core.riot.lang.RDFPostReader; -import com.atomgraph.linkeddatahub.model.Service; -import com.atomgraph.linkeddatahub.server.security.AgentContext; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.MessageDigest; -import java.util.List; -import java.util.Locale; -import java.util.Optional; -import jakarta.inject.Inject; -import jakarta.ws.rs.InternalServerErrorException; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.Request; -import jakarta.ws.rs.core.SecurityContext; -import jakarta.ws.rs.core.UriBuilder; -import jakarta.ws.rs.core.UriInfo; -import jakarta.ws.rs.ext.Providers; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.apache.jena.ontology.Ontology; -import org.apache.jena.rdf.model.Model; -import org.glassfish.jersey.media.multipart.BodyPart; -import org.glassfish.jersey.media.multipart.FormDataBodyPart; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * LinkedDataHub Graph Store implementation. - * We need to subclass the Core class because we're injecting a subclass of Service. - * - * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} - */ -public abstract class GraphStoreImpl extends com.atomgraph.core.model.impl.GraphStoreImpl -{ - - private static final Logger log = LoggerFactory.getLogger(GraphStoreImpl.class); - - /** - * The relative path of the content-addressed file container. - */ - public static final String UPLOADS_PATH = "uploads"; - - private final UriInfo uriInfo; - private final com.atomgraph.linkeddatahub.apps.model.Application application; - private final Ontology ontology; - private final Service service; - private final Providers providers; - private final com.atomgraph.linkeddatahub.Application system; - private final UriBuilder uploadsUriBuilder; - private final MessageDigest messageDigest; - /** The URIs for owner and secretary documents. */ - protected final URI ownerDocURI, secretaryDocURI; - private final SecurityContext securityContext; - private final Optional<AgentContext> agentContext; - - /** - * Constructs Graph Store. - * - * @param request current request - * @param uriInfo URI info of the current request - * @param mediaTypes a registry of readable/writable media types - * @param application current application - * @param ontology ontology of the current application - * @param service SPARQL service of the current application - * @param securityContext JAX-RS security context - * @param agentContext authenticated agent's context - * @param providers registry of JAX-RS providers - * @param system system application - */ - @Inject - public GraphStoreImpl(@Context Request request, @Context UriInfo uriInfo, MediaTypes mediaTypes, - com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Ontology> ontology, Optional<Service> service, - @Context SecurityContext securityContext, Optional<AgentContext> agentContext, - @Context Providers providers, com.atomgraph.linkeddatahub.Application system) - { - super(request, service.get(), mediaTypes); - if (ontology.isEmpty()) throw new InternalServerErrorException("Ontology is not specified"); - if (service.isEmpty()) throw new InternalServerErrorException("Service is not specified"); - this.uriInfo = uriInfo; - this.application = application; - this.ontology = ontology.get(); - this.service = service.get(); - this.securityContext = securityContext; - this.agentContext = agentContext; - this.providers = providers; - this.system = system; - this.messageDigest = system.getMessageDigest(); - uploadsUriBuilder = uriInfo.getBaseUriBuilder().path(UPLOADS_PATH); - URI ownerURI = URI.create(application.getMaker().getURI()); - try - { - this.ownerDocURI = new URI(ownerURI.getScheme(), ownerURI.getSchemeSpecificPart(), null).normalize(); - this.secretaryDocURI = new URI(system.getSecretaryWebIDURI().getScheme(), system.getSecretaryWebIDURI().getSchemeSpecificPart(), null).normalize(); - } - catch (URISyntaxException ex) - { - throw new InternalServerErrorException(ex); - } - } - - /** - * Parses multipart RDF/POST request. - * - * @param multiPart multipart form data - * @return RDF graph - * @throws URISyntaxException thrown if there is a syntax error in RDF/POST data - * @see <a href="https://atomgraph.github.io/RDF-POST/">RDF/POST Encoding for RDF</a> - */ - public Model parseModel(FormDataMultiPart multiPart) throws URISyntaxException - { - if (multiPart == null) throw new IllegalArgumentException("FormDataMultiPart cannot be null"); - - List<String> keys = new ArrayList<>(), values = new ArrayList<>(); - Iterator<BodyPart> it = multiPart.getBodyParts().iterator(); // not using getFields() to retain ordering - - while (it.hasNext()) - { - FormDataBodyPart bodyPart = (FormDataBodyPart)it.next(); - if (log.isDebugEnabled()) log.debug("Body part media type: {} headers: {}", bodyPart.getMediaType(), bodyPart.getHeaders()); - - // it's a file (if the filename is not empty) - if (bodyPart.getContentDisposition().getFileName() != null && - !bodyPart.getContentDisposition().getFileName().isEmpty()) - { - keys.add(bodyPart.getName()); - if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getContentDisposition().getFileName()); - values.add(bodyPart.getContentDisposition().getFileName()); - } - else - { - if (bodyPart.isSimple() && !bodyPart.getValue().isEmpty()) - { - keys.add(bodyPart.getName()); - if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getValue()); - values.add(bodyPart.getValue()); - } - } - } - - return RDFPostReader.parse(keys, values); - } - - /** - * Gets a map of file parts from multipart form data. - * - * @param multiPart multipart form data - * @return map of file parts - */ - public Map<String, FormDataBodyPart> getFileNameBodyPartMap(FormDataMultiPart multiPart) - { - if (multiPart == null) throw new IllegalArgumentException("FormDataMultiPart cannot be null"); - - Map<String, FormDataBodyPart> fileNameBodyPartMap = new HashMap<>(); - Iterator<BodyPart> it = multiPart.getBodyParts().iterator(); // not using getFields() to retain ordering - while (it.hasNext()) - { - FormDataBodyPart bodyPart = (FormDataBodyPart)it.next(); - if (log.isDebugEnabled()) log.debug("Body part media type: {} headers: {}", bodyPart.getMediaType(), bodyPart.getHeaders()); - - if (bodyPart.getContentDisposition().getFileName() != null) // it's a file - { - if (log.isDebugEnabled()) log.debug("FormDataBodyPart name: {} value: {}", bodyPart.getName(), bodyPart.getContentDisposition().getFileName()); - fileNameBodyPartMap.put(bodyPart.getContentDisposition().getFileName(), bodyPart); - } - } - return fileNameBodyPartMap; - } - - /** - * Returns a list of supported languages. - * - * @return list of languages - */ - @Override - public List<Locale> getLanguages() - { - return getSystem().getSupportedLanguages(); - } - - /** - * Returns URI builder for uploaded file resources. - * - * @return URI builder - */ - public UriBuilder getUploadsUriBuilder() - { - return uploadsUriBuilder.clone(); - } - - /** - * Returns message digest used in SHA1 hashing. - * - * @return message digest - */ - public MessageDigest getMessageDigest() - { - return messageDigest; - } - - /** - * Returns the request URI information. - * - * @return URI info - */ - public UriInfo getUriInfo() - { - return uriInfo; - } - - /** - * Returns the current application. - * - * @return application resource - */ - public com.atomgraph.linkeddatahub.apps.model.Application getApplication() - { - return application; - } - - /** - * Returns the ontology of the current application. - * - * @return ontology resource - */ - public Ontology getOntology() - { - return ontology; - } - - /** - * Returns the SPARQL service of the current application. - * - * @return service resource - */ - public Service getService() - { - return service; - } - - /** - * Get JAX-RS security context - * - * @return security context object - */ - public SecurityContext getSecurityContext() - { - return securityContext; - } - - /** - * Gets authenticated agent's context - * - * @return optional agent's context - */ - public Optional<AgentContext> getAgentContext() - { - return agentContext; - } - - /** - * Returns a registry of JAX-RS providers. - * - * @return provider registry - */ - public Providers getProviders() - { - return providers; - } - - /** - * Returns the system application. - * - * @return JAX-RS application - */ - public com.atomgraph.linkeddatahub.Application getSystem() - { - return system; - } - - /** - * Returns URI of the WebID document of the applications owner. - * - * @return document URI - */ - public URI getOwnerDocURI() - { - return ownerDocURI; - } - - /** - * Returns URI of the WebID document of the applications secretary. - * - * @return document URI - */ - public URI getSecretaryDocURI() - { - return secretaryDocURI; - } - -} \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java similarity index 98% rename from src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java rename to src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java index 5665a8e72..02eb59f62 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBase.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java @@ -83,10 +83,10 @@ * * @author {@literal Martynas Jusevičius <martynas@atomgraph.com>} */ -public class ProxyResourceBase extends com.atomgraph.client.model.impl.ProxyResourceBase +public class ProxiedGraph extends com.atomgraph.client.model.impl.ProxiedGraph { - private static final Logger log = LoggerFactory.getLogger(ProxyResourceBase.class); + private static final Logger log = LoggerFactory.getLogger(ProxiedGraph.class); private final UriInfo uriInfo; private final ContainerRequestContext crc; @@ -117,7 +117,7 @@ public class ProxyResourceBase extends com.atomgraph.client.model.impl.ProxyReso * @param dataset optional dataset */ @Inject - public ProxyResourceBase(@Context UriInfo uriInfo, @Context Request request, @Context HttpHeaders httpHeaders, MediaTypes mediaTypes, + public ProxiedGraph(@Context UriInfo uriInfo, @Context Request request, @Context HttpHeaders httpHeaders, MediaTypes mediaTypes, com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Service> service, @Context SecurityContext securityContext, @Context ContainerRequestContext crc, com.atomgraph.linkeddatahub.Application system, @Context HttpServletRequest httpServletRequest, DataManager dataManager, Optional<AgentContext> agentContext, @@ -157,7 +157,7 @@ public ProxyResourceBase(@Context UriInfo uriInfo, @Context Request request, @Co * @param agentContext authenticated agent's context * @param providers registry of JAX-RS providers */ - protected ProxyResourceBase(@Context UriInfo uriInfo, @Context Request request, @Context HttpHeaders httpHeaders, MediaTypes mediaTypes, + protected ProxiedGraph(@Context UriInfo uriInfo, @Context Request request, @Context HttpHeaders httpHeaders, MediaTypes mediaTypes, com.atomgraph.linkeddatahub.apps.model.Application application, Optional<Service> service, @Context SecurityContext securityContext, @Context ContainerRequestContext crc, @QueryParam("uri") URI uri, @QueryParam("endpoint") URI endpoint, @QueryParam("query") String query, @QueryParam("accept") MediaType accept, @QueryParam("mode") URI mode, diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java index 7e9cc8c43..4e8687796 100644 --- a/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java +++ b/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java @@ -33,51 +33,51 @@ public class ProxyResourceBaseTest @Test(expected = IllegalArgumentException.class) public void testNullURI() { - ProxyResourceBase.validateNotInternalURL(null); + ProxiedGraph.validateNotInternalURL(null); } @Test(expected = ForbiddenException.class) public void testLinkLocalIPv4Blocked() { - ProxyResourceBase.validateNotInternalURL(URI.create("http://169.254.1.1:8080/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://169.254.1.1:8080/test")); } @Test(expected = ForbiddenException.class) public void testPrivateClass10Blocked() { - ProxyResourceBase.validateNotInternalURL(URI.create("http://10.0.0.1:8080/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://10.0.0.1:8080/test")); } @Test(expected = ForbiddenException.class) public void testPrivateClass172Blocked() { - ProxyResourceBase.validateNotInternalURL(URI.create("http://172.16.0.0:8080/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://172.16.0.0:8080/test")); } @Test(expected = ForbiddenException.class) public void testPrivateClass192Blocked() { - ProxyResourceBase.validateNotInternalURL(URI.create("http://192.168.1.1:8080/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://192.168.1.1:8080/test")); } @Test public void testExternalURLAllowed() { // Public IPs should be allowed (no exception thrown) - ProxyResourceBase.validateNotInternalURL(URI.create("http://8.8.8.8:80/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://8.8.8.8:80/test")); } @Test public void testPublicDomainAllowed() { // Public domains should be allowed (no exception thrown) - ProxyResourceBase.validateNotInternalURL(URI.create("http://example.org/test")); + ProxiedGraph.validateNotInternalURL(URI.create("http://example.org/test")); } @Test public void testHTTPSAllowed() { // HTTPS to public domain should be allowed (no exception thrown) - ProxyResourceBase.validateNotInternalURL(URI.create("https://www.w3.org/ns/ldp")); + ProxiedGraph.validateNotInternalURL(URI.create("https://www.w3.org/ns/ldp")); } } From 5cc571309ad5d2f893b87c51cf568629acda1809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Tue, 13 Jan 2026 23:20:43 +0100 Subject: [PATCH 54/64] Web-Client version bump CHANGELOG update --- CHANGELOG.md | 5 +++-- pom.xml | 4 ++-- .../server/security/IDTokenSecurityContext.java | 15 +++++++++++++-- .../server/security/WebIDSecurityContext.java | 13 ++++++++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1537d6751..1dc5343e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [5.2.0] - TBD +## [5.2.0] - 2026-01-14 ### Added - Application settings form with modal UI for editing dataspace configuration - Settings endpoint (`/settings`) with `GET` and `PATCH` support for dataspace settings @@ -6,7 +6,8 @@ - LinkedDataHub packages system with install/uninstall functionality ### Changed -- **BREAKING**: Incorporated AtomGraph Server code directly into LinkedDataHub codebase +- Core library refactored Graph Store Protocol implementation - split into `GraphStoreBase` (common functionality), `DirectGraphStoreImpl` (direct graph identification), and `GraphStoreImpl` (indirect graph identification with query parameters) +- Incorporated AtomGraph Server code directly into LinkedDataHub codebase - System configuration dataset now uses named graphs instead of default graph - Web-Client dependency version bump - CLI scripts improved for better parameter handling diff --git a/pom.xml b/pom.xml index 4000207a9..9f6275a8d 100644 --- a/pom.xml +++ b/pom.xml @@ -139,13 +139,13 @@ <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.11-SNAPSHOT</version> + <version>4.2.11</version> <classifier>classes</classifier> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>client</artifactId> - <version>4.2.11-SNAPSHOT</version> + <version>4.2.11</version> <type>war</type> </dependency> <!-- required by jsonld-java - version same as Jersey's HTTP Client --> diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/security/IDTokenSecurityContext.java b/src/main/java/com/atomgraph/linkeddatahub/server/security/IDTokenSecurityContext.java index 40e04bcc1..252686133 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/security/IDTokenSecurityContext.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/security/IDTokenSecurityContext.java @@ -43,12 +43,23 @@ public IDTokenSecurityContext(String authScheme, Agent account, String jwtToken) /** * Returns JWT ID token content. - * + * * @return ID token content */ public String getJWTToken() { return jwtToken; } - + + /** + * Returns string representation of this security context. + * + * @return the agent's URI + */ + @Override + public String toString() + { + return getAgent().getURI(); + } + } \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/security/WebIDSecurityContext.java b/src/main/java/com/atomgraph/linkeddatahub/server/security/WebIDSecurityContext.java index b8ffee70e..c5a10ba54 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/security/WebIDSecurityContext.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/security/WebIDSecurityContext.java @@ -28,7 +28,7 @@ public class WebIDSecurityContext extends AgentSecurityContext /** * Constructs context from authentication scheme and agent instance. - * + * * @param authScheme auth scheme * @param agent authenticated agent */ @@ -37,4 +37,15 @@ public WebIDSecurityContext(String authScheme, Agent agent) super(authScheme, agent); } + /** + * Returns string representation of this security context. + * + * @return the agent's URI + */ + @Override + public String toString() + { + return getAgent().getURI(); + } + } From 32ecba7eb68b8f0af777e043a64f7d8016c4b04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Wed, 14 Jan 2026 22:21:59 +0100 Subject: [PATCH 55/64] Creating package document in admin Package test updates --- CHANGELOG.md | 2 +- ...ntology.sh => install-package-document.sh} | 28 +-- .../packages/install-package-stylesheet.sh | 31 --- .../install-uninstall-package-ontology.sh | 15 +- .../install-uninstall-package-stylesheet.sh | 45 +++-- .../packages/uninstall-package-ontology.sh | 46 ----- .../packages/uninstall-package-stylesheet.sh | 48 ----- .../resource/admin/pkg/InstallPackage.java | 177 +++++++++++++----- .../resource/admin/pkg/UninstallPackage.java | 15 -- 9 files changed, 193 insertions(+), 214 deletions(-) rename http-tests/admin/packages/{install-package-ontology.sh => install-package-document.sh} (53%) delete mode 100755 http-tests/admin/packages/install-package-stylesheet.sh delete mode 100755 http-tests/admin/packages/uninstall-package-ontology.sh delete mode 100755 http-tests/admin/packages/uninstall-package-stylesheet.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dc5343e6..751f5ded0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ ### Added - ORCID OpenID Connect login support with JWT token verification - `CORSFilter` response filter for cross-origin resource sharing on static assets -- Cache invalidation (BAN requests) for agent and user account lookup queries +- Cache invalidation (`BAN` requests) for agent and user account lookup queries - New `Application::normalizeOrigin` method for origin normalization - `ldh:parent-origin` XPath function for parent origin retrieval - HTTP tests for CORS functionality, internal IP blocking, and form proxying diff --git a/http-tests/admin/packages/install-package-ontology.sh b/http-tests/admin/packages/install-package-document.sh similarity index 53% rename from http-tests/admin/packages/install-package-ontology.sh rename to http-tests/admin/packages/install-package-document.sh index 9c9c0a1d0..f12073a66 100755 --- a/http-tests/admin/packages/install-package-ontology.sh +++ b/http-tests/admin/packages/install-package-document.sh @@ -9,8 +9,6 @@ purge_cache "$FRONTEND_VARNISH_SERVICE" # test package URI (SKOS package) package_uri="https://packages.linkeddatahub.com/skos/#this" -package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" -namespace_ontology_uri="${END_USER_BASE_URL}ns#" # install package install-package.sh \ @@ -20,15 +18,23 @@ install-package.sh \ --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" -# verify owl:imports triple was added to namespace graph -curl -k -s \ - -H "Accept: application/n-triples" \ - "${END_USER_BASE_URL}ns" \ -| grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" - -# verify package ontology document was created (hash of package ontology URI) -package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) +# verify package document was created (hash of package URI) +package_hash=$(echo -n "$package_uri" | shasum -a 1 | cut -d' ' -f1) curl -k -w "%{http_code}\n" -o /dev/null -s \ -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/" \ + "${ADMIN_BASE_URL}packages/${package_hash}/" \ | grep -qE "^($STATUS_OK|$STATUS_NOT_MODIFIED)$" + +# uninstall package +uninstall-package.sh \ + -b "$END_USER_BASE_URL" \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --package "$package_uri" \ +| grep -q "$STATUS_SEE_OTHER" + +# verify package document was deleted +#curl -k -w "%{http_code}\n" -o /dev/null -s \ +# -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ +# "${ADMIN_BASE_URL}packages/${package_hash}/" \ +#| grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/admin/packages/install-package-stylesheet.sh b/http-tests/admin/packages/install-package-stylesheet.sh deleted file mode 100755 index 8953d96d0..000000000 --- a/http-tests/admin/packages/install-package-stylesheet.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" -initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" -purge_cache "$END_USER_VARNISH_SERVICE" -purge_cache "$ADMIN_VARNISH_SERVICE" -purge_cache "$FRONTEND_VARNISH_SERVICE" - -# test package URI (SKOS package) -package_uri="https://packages.linkeddatahub.com/skos/#this" - -# install package -install-package.sh \ - -b "$END_USER_BASE_URL" \ - -f "$OWNER_CERT_FILE" \ - -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" - -# the stylesheet is not available via URL right away. If we request it right away, Varnish will cache a 404 Not Found response for it -# TO-DO: make sure the stylesheet URL is available immediately after installation -sleep 2 - -# verify package stylesheet was installed (should return 200) -curl -k -f -s -o /dev/null \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" - -# verify master stylesheet was regenerated and includes package import -curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ - | grep -q "com/linkeddatahub/packages/skos/layout.xsl" diff --git a/http-tests/admin/packages/install-uninstall-package-ontology.sh b/http-tests/admin/packages/install-uninstall-package-ontology.sh index bcccc4f33..b96db04fd 100755 --- a/http-tests/admin/packages/install-uninstall-package-ontology.sh +++ b/http-tests/admin/packages/install-uninstall-package-ontology.sh @@ -12,6 +12,12 @@ package_uri="https://packages.linkeddatahub.com/skos/#this" package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" namespace_ontology_uri="${END_USER_BASE_URL}ns#" +# verify owl:imports triple does NOT exist before install +if curl -k -s -H "Accept: application/n-triples" -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" "${ADMIN_BASE_URL}ontologies/namespace/" \ +| grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>"; then + exit 1 +fi + # install package install-package.sh \ -b "$END_USER_BASE_URL" \ @@ -20,10 +26,11 @@ install-package.sh \ --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" -# verify owl:imports triple was added +# verify owl:imports triple was added (check graph store directly, not cached endpoint) curl -k -s \ -H "Accept: application/n-triples" \ - "${END_USER_BASE_URL}ns" \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + "${ADMIN_BASE_URL}ontologies/namespace/" \ | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" # verify package ontology document exists @@ -41,8 +48,8 @@ uninstall-package.sh \ --package "$package_uri" \ | grep -q "$STATUS_SEE_OTHER" -# verify owl:imports triple was removed -ns_after=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") +# verify owl:imports triple was removed (check graph store directly, not cached endpoint) +ns_after=$(curl -k -s -H "Accept: application/n-triples" -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" "${ADMIN_BASE_URL}ontologies/namespace/") if echo "$ns_after" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>"; then exit 1 fi diff --git a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh index a4e29cf55..02452d711 100755 --- a/http-tests/admin/packages/install-uninstall-package-stylesheet.sh +++ b/http-tests/admin/packages/install-uninstall-package-stylesheet.sh @@ -7,37 +7,57 @@ purge_cache "$END_USER_VARNISH_SERVICE" purge_cache "$ADMIN_VARNISH_SERVICE" purge_cache "$FRONTEND_VARNISH_SERVICE" +# Clean up any leftover package stylesheet files from previous test runs +docker compose exec -T linkeddatahub rm -rf /usr/local/tomcat/webapps/ROOT/static/com/linkeddatahub/packages/skos 2>/dev/null || true +docker compose exec -T linkeddatahub sed -i '/linkeddatahub\/packages\/skos\/layout.xsl/d' /usr/local/tomcat/webapps/ROOT/static/xsl/layout.xsl 2>/dev/null || true + +# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) +# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes +default_ttl=5 + # test package URI (SKOS package) package_uri="https://packages.linkeddatahub.com/skos/#this" +# verify package stylesheet does NOT exist initially (should return 404) +curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ +| grep -q "$STATUS_NOT_FOUND" + +# verify master stylesheet does NOT include package initially +if curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then + exit 1 +fi + # install package install-package.sh \ -b "$END_USER_BASE_URL" \ -f "$OWNER_CERT_FILE" \ -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" + --package "$package_uri" + +# Wait for Tomcat's static resource cache to expire +sleep $default_ttl # verify package stylesheet was installed (should return 200) -curl -k -f -s -o /dev/null \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" +install_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ + "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl") +if [ "$install_status" != "200" ]; then + exit 1 +fi # verify master stylesheet includes package -curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" \ - | grep -q "com/linkeddatahub/packages/skos/layout.xsl" +if ! curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then + exit 1 +fi # uninstall package uninstall-package.sh \ -b "$END_USER_BASE_URL" \ -f "$OWNER_CERT_FILE" \ -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" + --package "$package_uri" # Wait for Tomcat's static resource cache to expire -# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) -# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes -default_ttl=5 sleep $default_ttl # verify package stylesheet was deleted (should return 404) @@ -46,7 +66,6 @@ curl -k -w "%{http_code}\n" -o /dev/null -s \ | grep -q "$STATUS_NOT_FOUND" # verify master stylesheet no longer includes package -master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") -if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then +if curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then exit 1 fi diff --git a/http-tests/admin/packages/uninstall-package-ontology.sh b/http-tests/admin/packages/uninstall-package-ontology.sh deleted file mode 100755 index 374b4c0f6..000000000 --- a/http-tests/admin/packages/uninstall-package-ontology.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" -initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" -purge_cache "$END_USER_VARNISH_SERVICE" -purge_cache "$ADMIN_VARNISH_SERVICE" -purge_cache "$FRONTEND_VARNISH_SERVICE" - -# test package URI (SKOS package) -package_uri="https://packages.linkeddatahub.com/skos/#this" -package_ontology_uri="https://raw.githubusercontent.com/AtomGraph/LinkedDataHub-Apps/refs/heads/develop/packages/skos/ns.ttl#" -namespace_ontology_uri="${END_USER_BASE_URL}ns#" - -# install package -install-package.sh \ - -b "$END_USER_BASE_URL" \ - -f "$OWNER_CERT_FILE" \ - -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" - -# verify owl:imports triple exists before uninstall -ns_before=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") -echo "$ns_before" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>" - -# uninstall package -uninstall-package.sh \ - -b "$END_USER_BASE_URL" \ - -f "$OWNER_CERT_FILE" \ - -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" - -# verify owl:imports triple was removed from namespace graph -ns_after=$(curl -k -s -H "Accept: application/n-triples" "${END_USER_BASE_URL}ns") -if echo "$ns_after" | grep -q "<${namespace_ontology_uri}> <http://www.w3.org/2002/07/owl#imports> <${package_ontology_uri}>"; then - exit 1 -fi - -# verify package ontology document was deleted -package_ontology_hash=$(echo -n "$package_ontology_uri" | shasum -a 1 | cut -d' ' -f1) -ontology_status=$(curl -k -w "%{http_code}\n" -o /dev/null -s \ - -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ - "${ADMIN_BASE_URL}ontologies/${package_ontology_hash}/") -echo "$ontology_status" | grep -q "$STATUS_FORBIDDEN" diff --git a/http-tests/admin/packages/uninstall-package-stylesheet.sh b/http-tests/admin/packages/uninstall-package-stylesheet.sh deleted file mode 100755 index 803224b38..000000000 --- a/http-tests/admin/packages/uninstall-package-stylesheet.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" -initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" -purge_cache "$END_USER_VARNISH_SERVICE" -purge_cache "$ADMIN_VARNISH_SERVICE" -purge_cache "$FRONTEND_VARNISH_SERVICE" - -# test package URI (SKOS package) -package_uri="https://packages.linkeddatahub.com/skos/#this" - -# first install the package -install-package.sh \ - -b "$END_USER_BASE_URL" \ - -f "$OWNER_CERT_FILE" \ - -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" - -# verify package stylesheet exists before uninstall (should return 200) -curl -k -f -s -o /dev/null \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" - -# uninstall package -uninstall-package.sh \ - -b "$END_USER_BASE_URL" \ - -f "$OWNER_CERT_FILE" \ - -p "$OWNER_CERT_PWD" \ - --package "$package_uri" \ -| grep -q "$STATUS_SEE_OTHER" - -# Wait for Tomcat's static resource cache to expire -# Tomcat caches static files with default cacheTtl=5000ms (5 seconds) -# See: https://tomcat.apache.org/tomcat-10.1-doc/config/resources.html#Attributes -default_ttl=5 -sleep $default_ttl - -# verify package stylesheet was deleted (should return 404) -curl -k -w "%{http_code}\n" -o /dev/null -s \ - "${END_USER_BASE_URL}static/com/linkeddatahub/packages/skos/layout.xsl" \ -| grep -q "$STATUS_NOT_FOUND" - -# verify master stylesheet was regenerated without package import -master_xsl=$(curl -k -s "${END_USER_BASE_URL}static/xsl/layout.xsl") -if echo "$master_xsl" | grep -q "com/linkeddatahub/packages/skos/layout.xsl"; then - exit 1 -fi diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 57246695d..5b10378d2 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -62,16 +62,23 @@ import org.apache.jena.update.UpdateFactory; import org.apache.jena.update.UpdateRequest; import org.apache.jena.util.FileManager; +import com.atomgraph.linkeddatahub.vocabulary.DH; +import com.atomgraph.linkeddatahub.vocabulary.FOAF; +import com.atomgraph.linkeddatahub.vocabulary.SIOC; +import com.atomgraph.linkeddatahub.server.util.Skolemizer; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.vocabulary.RDF; /** * JAX-RS resource that installs a LinkedDataHub package. * Package installation involves: * 1. Fetching package metadata - * 2. Downloading package ontology and PUTting as new document under model/ontologies/{hash}/ - * 3. Adding owl:imports of package ontology to namespace ontology - * 4. Downloading package stylesheet (layout.xsl) and saving to /static/{package-path}/ - * 5. Regenerating application master stylesheet - * 6. Adding ldh:import triple to application (TODO) + * 2. Downloading and validating package resources (ontology and stylesheet) + * 3. Creating item document under packages/ container with package metadata + * 4. PUTting package ontology as new document under ontologies/{hash}/ + * 5. Adding owl:imports of package ontology to namespace ontology + * 6. Saving package stylesheet (layout.xsl) to /static/{package-path}/ + * 7. Regenerating application master stylesheet * * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ @@ -124,8 +131,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" throw new BadRequestException("Package URI not specified"); } - EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); - if (log.isInfoEnabled()) log.info("Installing package: {}", packageURI); com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); if (pkg == null) @@ -145,10 +150,14 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" try { + EndUserApplication endUserApp = getApplication().as(AdminApplication.class).getEndUserApplication(); + AdminApplication adminApp = endUserApp.getAdminApplication(); + if (ontology != null) { if (log.isDebugEnabled()) log.debug("Downloading package ontology from: {}", ontology.getURI()); Model ontologyModel = downloadOntology(ontology.getURI()); + installOntology(endUserApp, ontologyModel, ontology.getURI()); } @@ -158,16 +167,43 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" String packagePath = pkg.getStylesheetPath(); if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); - String stylesheetContent = downloadStylesheet(stylesheetURI); - - installStylesheet(Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath).resolve("layout.xsl"), stylesheetContent, endUserApp); + String stylesheetContent = downloadStylesheet(stylesheetURI); + + installStylesheet(Paths.get(getServletContext().getRealPath("/static")).resolve(packagePath).resolve("layout.xsl"), stylesheetContent); + + // Purge package stylesheet from frontend proxy cache + String stylesheetURL = "/static/" + packagePath + "/layout.xsl"; + if (endUserApp.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purging package stylesheet from frontend proxy cache: {}", stylesheetURL); + getSystem().ban(endUserApp.getFrontendProxy(), stylesheetURL, false); + } - // 4. Regenerate master stylesheet regenerateMasterStylesheet(endUserApp, pkg); - } - //addImportToApplication(endUserApp, packageURI); + // Purge master stylesheet from frontend proxy cache + if (endUserApp.getFrontendProxy() != null) + { + if (log.isDebugEnabled()) log.debug("Purging master stylesheet from frontend proxy cache: {}", com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH); + getSystem().ban(endUserApp.getFrontendProxy(), com.atomgraph.linkeddatahub.Application.MASTER_STYLESHEET_PATH, false); + } + } + GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); + if (getAgentContext().isPresent()) gsc = gsc.delegation(adminApp.getBaseURI(), getAgentContext().get()); + + String slug = hashURI(packageURI); + URI packageDocumentURI = adminApp.getUriBuilder(). + path("packages/"). + path("{slug}/"). + build(slug); + Model packageDocModel = ModelFactory.createDefaultModel(); + packageDocModel.add(pkg.getModel()); + Resource container = packageDocModel.createResource(adminApp.getBaseURI().resolve("packages/").toString()); + createPackageDocument(packageDocModel, packageDocumentURI, container, pkg, slug); + new Skolemizer(packageDocumentURI.toString()).apply(packageDocModel); + putPackageDocument(gsc, packageDocumentURI, packageDocModel); + if (log.isInfoEnabled()) log.info("Successfully installed package: {}", packageURI); // Redirect back to referer or application base @@ -185,6 +221,7 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" * Loads package metadata from its URI using GraphStoreClient. * Package metadata is expected to be available as Linked Data. * + * @param gsc the graph store client * @param packageURI the package URI (e.g., https://packages.linkeddatahub.com/skos/#this) * @return Package instance * @throws NotFoundException if package cannot be found (404) @@ -264,35 +301,43 @@ private String downloadStylesheet(URI uri) throws IOException } /** - * Installs ontology by PUTting as a new document and adding owl:imports to namespace ontology. + * Hashes a URI using SHA-1 to create a unique document slug. * - * @param app the end-user application - * @param ontologyModel the package ontology model - * @param packageOntologyURI the package ontology URI - * @throws IOException if installation fails + * @param uri the URI to hash + * @return the SHA-1 hash as a hexadecimal string + * @throws IOException if hashing fails */ - private void installOntology(EndUserApplication app, Model ontologyModel, String packageOntologyURI) throws IOException + private String hashURI(String uri) throws IOException { - AdminApplication adminApp = app.getAdminApplication(); - - // 1. Create hash of package URI to use as document slug - String hash; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); - md.update(packageOntologyURI.getBytes(StandardCharsets.UTF_8)); - hash = Hex.encodeHexString(md.digest()); - if (log.isDebugEnabled()) log.debug("Package ontology URI '{}' hashed to '{}'", packageOntologyURI, hash); + md.update(uri.getBytes(StandardCharsets.UTF_8)); + String hash = Hex.encodeHexString(md.digest()); + if (log.isDebugEnabled()) log.debug("URI '{}' hashed to '{}'", uri, hash); + return hash; } catch (NoSuchAlgorithmException e) { - if (log.isErrorEnabled()) log.error("Failed to hash package ontology URI: {}", packageOntologyURI, e); - throw new IOException("Failed to hash package ontology URI", e); + if (log.isErrorEnabled()) log.error("Failed to hash URI: {}", uri, e); + throw new IOException("Failed to hash URI", e); } + } - // 2. PUT package ontology as a document under model/ontologies/{hash}/ (overwrites if exists) - URI ontologyDocumentURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/{hash}/").build(hash); - if (log.isDebugEnabled()) log.debug("PUTting package ontology to document: {}", ontologyDocumentURI); + /** + * Installs ontology by PUTting as a new document and adding owl:imports to namespace ontology. + * + * @param app the end-user application + * @param ontologyModel the package ontology model + * @param packageOntologyURI the package ontology URI + * @throws IOException if installation fails + */ + private void installOntology(EndUserApplication app, Model ontologyModel, String packageOntologyURI) throws IOException + { + AdminApplication adminApp = app.getAdminApplication(); + + // 1. Create hash of package ontology URI to use as document slug + String hash = hashURI(packageOntologyURI); GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()); @@ -302,6 +347,10 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String if (log.isDebugEnabled()) log.debug("Delegating agent credentials for PUT request"); gsc = gsc.delegation(adminApp.getBaseURI(), getAgentContext().get()); } + + // 2. PUT package ontology as a document under model/ontologies/{hash}/ (overwrites if exists) + URI ontologyDocumentURI = UriBuilder.fromUri(adminApp.getBaseURI()).path("ontologies/{hash}/").build(hash); + if (log.isDebugEnabled()) log.debug("PUTting package ontology to document: {}", ontologyDocumentURI); try (Response putResponse = gsc.put(ontologyDocumentURI, ontologyModel)) { @@ -337,14 +386,16 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String } // 4. Clear and reload namespace ontology from cache - if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); - getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); + // TODO: This causes deadlock when OntologyModelGetter makes synchronous HTTP requests back to /ns + // Need to either make this async or find alternative way to refresh ontology cache + // if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); + // getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); } /** * Installs stylesheet to <samp>/static/<package-path>/layout.xsl</samp> */ - private void installStylesheet(Path stylesheetFile, String stylesheetContent, EndUserApplication endUserApp) throws IOException + private void installStylesheet(Path stylesheetFile, String stylesheetContent) throws IOException { Files.createDirectories(stylesheetFile.getParent()); Files.writeString(stylesheetFile, stylesheetContent); @@ -382,18 +433,54 @@ private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.li } /** - * Adds ldh:import triple to the end-user application resource. + * Creates a package document item. + * + * @param packageDocModel the model to populate + * @param packageDocumentURI the document URI + * @param container the container resource + * @param pkg the package resource + * @param slug the document slug + * @return the document item resource + */ + private Resource createPackageDocument(Model packageDocModel, + URI packageDocumentURI, + Resource container, + com.atomgraph.linkeddatahub.apps.model.Package pkg, + String slug) + { + Resource packageDocItem = packageDocModel.createResource(packageDocumentURI.toString()). + addProperty(RDF.type, DH.Item). + addProperty(SIOC.HAS_CONTAINER, container). + addLiteral(DH.slug, slug). + addProperty(FOAF.primaryTopic, pkg); + + return packageDocItem; + } + + /** + * PUTs a package document to the specified URI. + * + * @param gsc the graph store client + * @param packageDocumentURI the document URI + * @param packageDocModel the package document model + * @throws IOException if PUT fails */ -// private void addImportToApplication(EndUserApplication app, String packageURI) -// { -// // This would need to modify system.trig via SPARQL UPDATE -// // For now, log a warning that this needs manual configuration -// if (log.isWarnEnabled()) -// { -// log.warn("TODO: Add ldh:import triple to application. Manual edit required:"); -// log.warn(" <{}> ldh:import <{}> .", app.getURI(), packageURI); -// } -// } + private void putPackageDocument(GraphStoreClient gsc, URI packageDocumentURI, Model packageDocModel) throws IOException + { + if (log.isDebugEnabled()) log.debug("PUTting package document to: {}", packageDocumentURI); + + try (Response putResponse = gsc.put(packageDocumentURI, packageDocModel)) + { + if (!putResponse.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL)) + { + if (log.isErrorEnabled()) log.error("Failed to PUT package document to {}: {}", packageDocumentURI, putResponse.getStatus()); + throw new IOException("Failed to PUT package document to " + packageDocumentURI + ": " + putResponse.getStatus()); + } + if (log.isDebugEnabled()) log.debug("Package document PUT response status: {}", putResponse.getStatus()); + } + + if (log.isInfoEnabled()) log.info("Successfully created package document at: {}", packageDocumentURI); + } /** * Returns the current application. diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index af0856025..30038d92a 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -67,7 +67,6 @@ * 3. Clearing and reloading namespace ontology from cache * 4. Deleting package stylesheet from /static/{package-path}/ * 5. Regenerating application master stylesheet - * 6. Removing ldh:import triple from application (TODO) * * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ @@ -304,20 +303,6 @@ private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.li } } - /** - * Removes <samp>ldh:import</samp> triple from the end-user application resource. - */ -// private void removeImportFromApplication(EndUserApplication app, String packageURI) -// { -// // This would need to modify system.trig via SPARQL UPDATE -// // For now, log a warning that this needs manual configuration -// if (log.isWarnEnabled()) -// { -// log.warn("TODO: Remove ldh:import triple from application. Manual edit required:"); -// log.warn(" DELETE DATA {{ <{}> ldh:import <{}> }}", app.getURI(), packageURI); -// } -// } - /** * Returns the current application. * From 745fc5d8df35267cd3b3504ac1e74ece3e19c238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Wed, 14 Jan 2026 22:54:18 +0100 Subject: [PATCH 56/64] Extracted `URLValidator` class Improved its tests --- .../install-package-internal-url-400.sh | 44 ++++++++ .../atomgraph/linkeddatahub/Application.java | 2 + .../linkeddatahub/resource/Transform.java | 45 +------- .../resource/admin/pkg/InstallPackage.java | 10 ++ .../exception/InternalURLException.java | 72 ++++++++++++ .../filter/request/auth/WebIDFilter.java | 45 +------- .../mapper/InternalURLExceptionMapper.java | 59 ++++++++++ .../server/model/impl/ProxiedGraph.java | 46 +------- .../server/util/URLValidator.java | 105 ++++++++++++++++++ .../linkeddatahub/resource/TransformTest.java | 83 -------------- .../model/impl/ProxyResourceBaseTest.java | 83 -------------- .../URLValidatorTest.java} | 36 +++--- 12 files changed, 321 insertions(+), 309 deletions(-) create mode 100755 http-tests/admin/packages/install-package-internal-url-400.sh create mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/exception/InternalURLException.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/mapper/InternalURLExceptionMapper.java create mode 100644 src/main/java/com/atomgraph/linkeddatahub/server/util/URLValidator.java delete mode 100644 src/test/java/com/atomgraph/linkeddatahub/resource/TransformTest.java delete mode 100644 src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java rename src/test/java/com/atomgraph/linkeddatahub/server/{filter/request/auth/WebIDFilterTest.java => util/URLValidatorTest.java} (55%) diff --git a/http-tests/admin/packages/install-package-internal-url-400.sh b/http-tests/admin/packages/install-package-internal-url-400.sh new file mode 100755 index 000000000..a5ba23d36 --- /dev/null +++ b/http-tests/admin/packages/install-package-internal-url-400.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# Test SSRF protection: package-uri with link-local address (169.254.0.0/16) should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=http://169.254.1.1/package#this" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_BAD_REQUEST" + +# Test SSRF protection: package-uri with private class A address (10.0.0.0/8) should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=http://10.0.0.1/package#this" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_BAD_REQUEST" + +# Test SSRF protection: package-uri with private class B address (172.16.0.0/12) should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=http://172.16.0.0/package#this" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_BAD_REQUEST" + +# Test SSRF protection: package-uri with private class C address (192.168.0.0/16) should return 400 Bad Request +curl -k -w "%{http_code}\n" -o /dev/null -s \ + -E "$OWNER_CERT_FILE":"$OWNER_CERT_PWD" \ + -X POST \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "package-uri=http://192.168.1.1/package#this" \ + "${ADMIN_BASE_URL}packages/install" \ +| grep -q "$STATUS_BAD_REQUEST" diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index e3b0f30b3..9e59ef69a 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -18,6 +18,7 @@ import com.atomgraph.linkeddatahub.server.mapper.ResourceExistsExceptionMapper; import com.atomgraph.linkeddatahub.server.mapper.HttpHostConnectExceptionMapper; +import com.atomgraph.linkeddatahub.server.mapper.InternalURLExceptionMapper; import com.atomgraph.linkeddatahub.server.mapper.MessagingExceptionMapper; import com.atomgraph.linkeddatahub.server.mapper.auth.webid.WebIDLoadingExceptionMapper; import com.atomgraph.linkeddatahub.server.mapper.auth.webid.InvalidWebIDURIExceptionMapper; @@ -1090,6 +1091,7 @@ protected void registerExceptionMappers() register(NotAcceptableExceptionMapper.class); register(ClientErrorExceptionMapper.class); register(HttpHostConnectExceptionMapper.class); + register(InternalURLExceptionMapper.class); register(BadGatewayExceptionMapper.class); register(OntClassNotFoundExceptionMapper.class); register(InvalidWebIDPublicKeyExceptionMapper.class); diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java index 19366b18c..b3575b7ac 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/Transform.java @@ -23,12 +23,11 @@ import com.atomgraph.linkeddatahub.server.io.ValidatingModelProvider; import com.atomgraph.linkeddatahub.server.model.impl.DirectGraphStoreImpl; import com.atomgraph.linkeddatahub.server.security.AgentContext; +import com.atomgraph.linkeddatahub.server.util.URLValidator; import com.atomgraph.linkeddatahub.vocabulary.NFO; import com.atomgraph.spinrdf.vocabulary.SPIN; -import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.util.Map; import java.util.Optional; import jakarta.inject.Inject; @@ -144,8 +143,8 @@ public Response post(Model model) if (queryRes == null) throw new BadRequestException("Transformation query string (spin:query) not provided"); // LNK-002: Validate URIs to prevent SSRF attacks - validateNotInternalURL(URI.create(queryRes.getURI())); - validateNotInternalURL(URI.create(source.getURI())); + new URLValidator(URI.create(queryRes.getURI())).validate(); + new URLValidator(URI.create(source.getURI())).validate(); GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); @@ -236,7 +235,7 @@ public Response postFileBodyPart(Model model, Map<String, FormDataBodyPart> file if (queryRes == null) throw new BadRequestException("Transformation query string (spin:query) not provided"); // LNK-002: Validate query URI to prevent SSRF attacks - validateNotInternalURL(URI.create(queryRes.getURI())); + new URLValidator(URI.create(queryRes.getURI())).validate(); GraphStoreClient gsc = GraphStoreClient.create(getSystem().getClient(), getSystem().getMediaTypes()). delegation(getUriInfo().getBaseUri(), getAgentContext().orElse(null)); @@ -278,42 +277,6 @@ protected Response forwardPost(Entity entity, String graphURI) } } - /** - * Validates that the given URI does not point to an internal/private network address. - * Prevents SSRF attacks by blocking access to RFC 1918 private addresses and link-local addresses. - * - * @param uri the URI to validate - * @throws IllegalArgumentException if URI or host is null - * @throws BadRequestException if the URI resolves to an internal address - * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/253">LNK-002: SSRF primitives in admin endpoint</a> - */ - protected static void validateNotInternalURL(URI uri) - { - if (uri == null) throw new IllegalArgumentException("URI cannot be null"); - - String host = uri.getHost(); - if (host == null) throw new IllegalArgumentException("URI host cannot be null"); - - // Resolve hostname to IP and check if it's private/internal - try - { - InetAddress address = InetAddress.getByName(host); - - // Note: We don't block loopback addresses (127.0.0.1, localhost) because transformation queries - // and data sources may legitimately reference resources on the same server - - if (address.isLinkLocalAddress()) - throw new BadRequestException("URI cannot resolve to link-local addresses: " + address.getHostAddress()); - if (address.isSiteLocalAddress()) - throw new BadRequestException("URI cannot resolve to private addresses (RFC 1918): " + address.getHostAddress()); - } - catch (UnknownHostException e) - { - if (log.isWarnEnabled()) log.warn("Could not resolve hostname for SSRF validation: {}", host); - // Allow request to proceed - will fail later with better error message - } - } - /** * Returns the supported media types. * diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 5b10378d2..117abc3ca 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -23,6 +23,7 @@ import com.atomgraph.linkeddatahub.client.GraphStoreClient; import com.atomgraph.linkeddatahub.resource.admin.ClearOntology; import com.atomgraph.linkeddatahub.server.security.AgentContext; +import com.atomgraph.linkeddatahub.server.util.URLValidator; import com.atomgraph.linkeddatahub.server.util.XSLTMasterUpdater; import static com.atomgraph.server.status.UnprocessableEntityStatus.UNPROCESSABLE_ENTITY; import jakarta.inject.Inject; @@ -131,6 +132,9 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" throw new BadRequestException("Package URI not specified"); } + // Validate package URI to prevent SSRF attacks + new URLValidator(URI.create(packageURI)).validate(); + if (log.isInfoEnabled()) log.info("Installing package: {}", packageURI); com.atomgraph.linkeddatahub.apps.model.Package pkg = getPackage(packageURI); if (pkg == null) @@ -155,6 +159,9 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" if (ontology != null) { + // Validate ontology URI to prevent SSRF attacks + new URLValidator(URI.create(ontology.getURI())).validate(); + if (log.isDebugEnabled()) log.debug("Downloading package ontology from: {}", ontology.getURI()); Model ontologyModel = downloadOntology(ontology.getURI()); @@ -166,6 +173,9 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" URI stylesheetURI = URI.create(stylesheet.getURI()); String packagePath = pkg.getStylesheetPath(); + // Validate stylesheet URI to prevent SSRF attacks + new URLValidator(stylesheetURI).validate(); + if (log.isDebugEnabled()) log.debug("Downloading package stylesheet from: {}", stylesheetURI); String stylesheetContent = downloadStylesheet(stylesheetURI); diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/exception/InternalURLException.java b/src/main/java/com/atomgraph/linkeddatahub/server/exception/InternalURLException.java new file mode 100644 index 000000000..24c857372 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/server/exception/InternalURLException.java @@ -0,0 +1,72 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.server.exception; + +import java.net.URI; + +/** + * Exception thrown when attempting to load data from an internal/private network address. + * This is part of SSRF (Server-Side Request Forgery) attack prevention. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/252">LNK-004: SSRF primitive via On-Behalf-Of header</a> + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/253">LNK-002: SSRF primitives in admin endpoint</a> + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/287">LNK-009: SSRF via proxy URI parameter</a> + */ +public class InternalURLException extends RuntimeException +{ + + /** The URI that resolves to an internal address */ + private final URI uri; + + /** The resolved IP address */ + private final String ipAddress; + + /** + * Constructs exception for link-local address. + * + * @param uri the URI that resolves to a link-local address + * @param ipAddress the resolved link-local IP address + */ + public InternalURLException(URI uri, String ipAddress) + { + super("URL cannot resolve to internal addresses: " + ipAddress); + this.uri = uri; + this.ipAddress = ipAddress; + } + + /** + * Returns the URI that resolves to an internal address. + * + * @return the URI + */ + public URI getURI() + { + return uri; + } + + /** + * Returns the resolved IP address. + * + * @return the IP address + */ + public String getIPAddress() + { + return ipAddress; + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilter.java b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilter.java index 1fdd78a12..bdbd4da8d 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilter.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilter.java @@ -25,13 +25,12 @@ import com.atomgraph.linkeddatahub.server.exception.auth.webid.WebIDLoadingException; import com.atomgraph.linkeddatahub.server.exception.auth.webid.WebIDDelegationException; import com.atomgraph.linkeddatahub.server.security.WebIDSecurityContext; +import com.atomgraph.linkeddatahub.server.util.URLValidator; import com.atomgraph.linkeddatahub.vocabulary.ACL; import com.atomgraph.linkeddatahub.vocabulary.Cert; import com.atomgraph.linkeddatahub.vocabulary.FOAF; -import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; @@ -130,7 +129,7 @@ public SecurityContext authenticate(ContainerRequestContext request) } if (log.isTraceEnabled()) log.trace("Client WebID: {}", webID); - validateNotInternalURL(webID); // LNK-004: Prevent SSRF via WebID URI + new URLValidator(webID).validate(); // LNK-004: Prevent SSRF via WebID URI Resource agent = authenticate(loadWebID(webID), webID, publicKey); if (agent == null) { @@ -143,7 +142,7 @@ public SecurityContext authenticate(ContainerRequestContext request) if (onBehalfOf != null) { URI principalWebID = new URI(onBehalfOf); - validateNotInternalURL(principalWebID); // LNK-004: Prevent SSRF via On-Behalf-Of header + new URLValidator(principalWebID).validate(); // LNK-004: Prevent SSRF via On-Behalf-Of header Model principalWebIDModel = loadWebID(principalWebID); Resource principal = principalWebIDModel.createResource(onBehalfOf); // if we verify that the current agent is a secretary of the principal, that principal becomes current agent. Else throw error @@ -301,7 +300,7 @@ public Model loadWebIDFromURI(URI webID) if (certKeyRes != null && certKeyRes.isURIResource()) { URI certKey = URI.create(certKeyRes.getURI()); - validateNotInternalURL(certKey); // LNK-004: Prevent SSRF via cert:key reference in WebID document + new URLValidator(certKey).validate(); // LNK-004: Prevent SSRF via cert:key reference in WebID document // remove fragment identifier to get document URI URI certKeyDoc = new URI(certKey.getScheme(), certKey.getSchemeSpecificPart(), null).normalize(); @@ -383,40 +382,4 @@ public void logout(Application app, ContainerRequestContext request) throw new UnsupportedOperationException("Not supported yet."); // logout not really possible with HTTP certificates } - /** - * Validates that the given URI does not point to an internal/private network address. - * Prevents SSRF attacks by blocking access to RFC 1918 private addresses and link-local addresses. - * - * @param uri the URI to validate - * @throws IllegalArgumentException if URI or host is null - * @throws BadRequestException if the URI resolves to an internal address - * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/252">LNK-004: SSRF primitive via On-Behalf-Of header</a> - */ - protected static void validateNotInternalURL(URI uri) - { - if (uri == null) throw new IllegalArgumentException("URI cannot be null"); - - String host = uri.getHost(); - if (host == null) throw new IllegalArgumentException("URI host cannot be null"); - - // Resolve hostname to IP and check if it's private/internal - try - { - InetAddress address = InetAddress.getByName(host); - - // Note: We don't block loopback addresses (127.0.0.1, localhost) because WebID documents - // may legitimately be hosted on the same server during development/testing - - if (address.isLinkLocalAddress()) - throw new BadRequestException("WebID URI cannot resolve to link-local addresses: " + address.getHostAddress()); - if (address.isSiteLocalAddress()) - throw new BadRequestException("WebID URI cannot resolve to private addresses (RFC 1918): " + address.getHostAddress()); - } - catch (UnknownHostException e) - { - if (log.isWarnEnabled()) log.warn("Could not resolve hostname for SSRF validation: {}", host); - // Allow request to proceed - will fail later with better error message - } - } - } \ No newline at end of file diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/mapper/InternalURLExceptionMapper.java b/src/main/java/com/atomgraph/linkeddatahub/server/mapper/InternalURLExceptionMapper.java new file mode 100644 index 000000000..4e8e007e6 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/server/mapper/InternalURLExceptionMapper.java @@ -0,0 +1,59 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.server.mapper; + +import com.atomgraph.core.MediaTypes; +import com.atomgraph.linkeddatahub.server.exception.InternalURLException; +import com.atomgraph.server.mapper.ExceptionMapperBase; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * JAX-RS mapper for internal URL exceptions. + * Maps {@link InternalURLException} to HTTP 400 Bad Request response. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + */ +public class InternalURLExceptionMapper extends ExceptionMapperBase implements ExceptionMapper<InternalURLException> +{ + + /** + * Constructs exception mapper from media type registry. + * + * @param mediaTypes registry of readable/writable media types + */ + @Inject + public InternalURLExceptionMapper(MediaTypes mediaTypes) + { + super(mediaTypes); + } + + @Override + public Response toResponse(InternalURLException ex) + { + Resource resource = toResource(ex, Response.Status.BAD_REQUEST, + ResourceFactory.createResource("http://www.w3.org/2011/http-statusCodes#BadRequest")); + + return getResponseBuilder(resource.getModel()). + status(Response.Status.BAD_REQUEST). + build(); + } + +} diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java index 02eb59f62..4c371007b 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java @@ -31,9 +31,8 @@ import com.atomgraph.linkeddatahub.server.security.AgentContext; import com.atomgraph.linkeddatahub.server.security.IDTokenSecurityContext; import com.atomgraph.linkeddatahub.server.security.WebIDSecurityContext; -import java.net.InetAddress; +import com.atomgraph.linkeddatahub.server.util.URLValidator; import java.net.URI; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -167,7 +166,7 @@ protected ProxiedGraph(@Context UriInfo uriInfo, @Context Request request, @Cont super(uriInfo, request, httpHeaders, mediaTypes, uri, endpoint, query, accept, mode, system.getExternalClient(), httpServletRequest); // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) - if (uri != null) validateNotInternalURL(uri); + if (uri != null) new URLValidator(uri).validate(); this.uriInfo = uriInfo; this.application = application; @@ -569,45 +568,4 @@ public String getUserAgentHeaderValue() return GraphStoreClient.USER_AGENT; } - /** - * Validates that a URI does not point to an internal/private network resource. - * This prevents SSRF (Server-Side Request Forgery) attacks by resolving the hostname - * and checking if the IP address is in a private/internal range. - * - * Blocks access to: - * - Loopback addresses (127.0.0.0/8, ::1) - * - RFC 1918 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - * - Link-local addresses (169.254.0.0/16, fe80::/10) - * - * @param uri the URI to validate - * @throws IllegalArgumentException if the URI or host is null - * @throws ForbiddenException if the URI resolves to an internal IP address - */ - protected static void validateNotInternalURL(URI uri) - { - if (uri == null) throw new IllegalArgumentException("URI cannot be null"); - - String host = uri.getHost(); - if (host == null) throw new IllegalArgumentException("URI host cannot be null"); - - // Resolve hostname to IP and check if it's private/internal - try - { - InetAddress address = InetAddress.getByName(host); - - // Note: We don't block loopback addresses (127.0.0.1, localhost) because the application - // legitimately proxies its own endpoints (e.g., /clear, admin operations) - - if (address.isLinkLocalAddress()) - throw new ForbiddenException("Access to link-local addresses is not allowed: " + address.getHostAddress()); - if (address.isSiteLocalAddress()) - throw new ForbiddenException("Access to private addresses (RFC 1918) is not allowed: " + address.getHostAddress()); - } - catch (UnknownHostException e) - { - if (log.isWarnEnabled()) log.warn("Could not resolve hostname for SSRF validation: {}", host); - // Allow request to proceed - will fail later with better error message - } - } - } diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/util/URLValidator.java b/src/main/java/com/atomgraph/linkeddatahub/server/util/URLValidator.java new file mode 100644 index 000000000..1df960678 --- /dev/null +++ b/src/main/java/com/atomgraph/linkeddatahub/server/util/URLValidator.java @@ -0,0 +1,105 @@ +/** + * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.atomgraph.linkeddatahub.server.util; + +import com.atomgraph.linkeddatahub.server.exception.InternalURLException; +import java.net.InetAddress; +import java.net.URI; +import java.net.UnknownHostException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Validator for URLs when loading data from external sources. + * Prevents SSRF (Server-Side Request Forgery) attacks by validating that URLs + * don't resolve to internal/private network addresses. + * + * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/252">LNK-004: SSRF primitive via On-Behalf-Of header</a> + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/253">LNK-002: SSRF primitives in admin endpoint</a> + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/287">LNK-009: SSRF via proxy URI parameter</a> + */ +public class URLValidator +{ + private static final Logger log = LoggerFactory.getLogger(URLValidator.class); + + private final URI uri; + + /** + * Constructs URL validator for the given URI. + * + * @param uri the URI to validate + * @throws IllegalArgumentException if the URI is null + */ + public URLValidator(URI uri) + { + if (uri == null) throw new IllegalArgumentException("URI cannot be null"); + this.uri = uri; + } + + /** + * Validates that the URI does not point to an internal/private network address. + * Prevents SSRF attacks by blocking access to: + * - RFC 1918 private addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7) + * - Link-local addresses (169.254.0.0/16, fe80::/10) + * + * Note: Loopback addresses (127.0.0.1, localhost, ::1) are NOT blocked as the application + * may legitimately need to access resources on the same server (e.g., transformation queries, + * WebID documents during development, admin operations). + * + * @return the validated URI + * @throws IllegalArgumentException if the URI host is null + * @throws InternalURLException if the URI resolves to an internal IP address + */ + public URI validate() + { + String host = uri.getHost(); + if (host == null) throw new IllegalArgumentException("URI host cannot be null"); + + // Resolve hostname to IP and check if it's private/internal + try + { + InetAddress address = InetAddress.getByName(host); + + // Note: We don't block loopback addresses (127.0.0.1, localhost) because the application + // legitimately accesses its own endpoints for various operations + + if (address.isLinkLocalAddress()) + throw new InternalURLException(uri, address.getHostAddress()); + if (address.isSiteLocalAddress()) + throw new InternalURLException(uri, address.getHostAddress()); + } + catch (UnknownHostException e) + { + if (log.isWarnEnabled()) log.warn("Could not resolve hostname for SSRF validation: {}", host); + // Allow request to proceed - will fail later with better error message + } + + return uri; + } + + /** + * Returns the URI being validated. + * + * @return the URI + */ + public URI getURI() + { + return uri; + } + +} diff --git a/src/test/java/com/atomgraph/linkeddatahub/resource/TransformTest.java b/src/test/java/com/atomgraph/linkeddatahub/resource/TransformTest.java deleted file mode 100644 index 16e2da0f5..000000000 --- a/src/test/java/com/atomgraph/linkeddatahub/resource/TransformTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com>. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.atomgraph.linkeddatahub.resource; - -import jakarta.ws.rs.BadRequestException; -import org.junit.Test; - -import java.net.URI; - -/** - * Unit tests for Transform SSRF protection. - * Tests the validateNotInternalURL method to ensure it properly blocks access to internal addresses. - * - * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/253">LNK-002: SSRF primitives in admin endpoint</a> - * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} - */ -public class TransformTest -{ - - @Test(expected = IllegalArgumentException.class) - public void testNullURI() - { - Transform.validateNotInternalURL(null); - } - - @Test(expected = BadRequestException.class) - public void testLinkLocalIPv4Blocked() - { - Transform.validateNotInternalURL(URI.create("http://169.254.1.1:8080/query.rq")); - } - - @Test(expected = BadRequestException.class) - public void testPrivateClass10Blocked() - { - Transform.validateNotInternalURL(URI.create("http://10.0.0.1:8080/data.ttl")); - } - - @Test(expected = BadRequestException.class) - public void testPrivateClass172Blocked() - { - Transform.validateNotInternalURL(URI.create("http://172.16.0.0:8080/query.rq")); - } - - @Test(expected = BadRequestException.class) - public void testPrivateClass192Blocked() - { - Transform.validateNotInternalURL(URI.create("http://192.168.1.1:8080/data.ttl")); - } - - @Test - public void testExternalURLAllowed() - { - // Public IPs should be allowed (no exception thrown) - Transform.validateNotInternalURL(URI.create("http://8.8.8.8:80/query.rq")); - } - - @Test - public void testPublicDomainAllowed() - { - // Public domains should be allowed (no exception thrown) - Transform.validateNotInternalURL(URI.create("http://example.org/data.ttl")); - } - - @Test - public void testHTTPSAllowed() - { - // HTTPS to public domain should be allowed (no exception thrown) - Transform.validateNotInternalURL(URI.create("https://dbpedia.org/sparql")); - } -} diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java deleted file mode 100644 index 4e8687796..000000000 --- a/src/test/java/com/atomgraph/linkeddatahub/server/model/impl/ProxyResourceBaseTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com>. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.atomgraph.linkeddatahub.server.model.impl; - -import jakarta.ws.rs.ForbiddenException; -import org.junit.Test; - -import java.net.URI; - -/** - * Unit tests for ProxyResourceBase SSRF protection. - * Tests the validateNotInternalURL method to ensure it properly blocks access to internal addresses. - * - * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/250">LNK-009: SSRF vulnerability</a> - * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} - */ -public class ProxyResourceBaseTest -{ - - @Test(expected = IllegalArgumentException.class) - public void testNullURI() - { - ProxiedGraph.validateNotInternalURL(null); - } - - @Test(expected = ForbiddenException.class) - public void testLinkLocalIPv4Blocked() - { - ProxiedGraph.validateNotInternalURL(URI.create("http://169.254.1.1:8080/test")); - } - - @Test(expected = ForbiddenException.class) - public void testPrivateClass10Blocked() - { - ProxiedGraph.validateNotInternalURL(URI.create("http://10.0.0.1:8080/test")); - } - - @Test(expected = ForbiddenException.class) - public void testPrivateClass172Blocked() - { - ProxiedGraph.validateNotInternalURL(URI.create("http://172.16.0.0:8080/test")); - } - - @Test(expected = ForbiddenException.class) - public void testPrivateClass192Blocked() - { - ProxiedGraph.validateNotInternalURL(URI.create("http://192.168.1.1:8080/test")); - } - - @Test - public void testExternalURLAllowed() - { - // Public IPs should be allowed (no exception thrown) - ProxiedGraph.validateNotInternalURL(URI.create("http://8.8.8.8:80/test")); - } - - @Test - public void testPublicDomainAllowed() - { - // Public domains should be allowed (no exception thrown) - ProxiedGraph.validateNotInternalURL(URI.create("http://example.org/test")); - } - - @Test - public void testHTTPSAllowed() - { - // HTTPS to public domain should be allowed (no exception thrown) - ProxiedGraph.validateNotInternalURL(URI.create("https://www.w3.org/ns/ldp")); - } -} diff --git a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilterTest.java b/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java similarity index 55% rename from src/test/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilterTest.java rename to src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java index de5c1008d..41028cea6 100644 --- a/src/test/java/com/atomgraph/linkeddatahub/server/filter/request/auth/WebIDFilterTest.java +++ b/src/test/java/com/atomgraph/linkeddatahub/server/util/URLValidatorTest.java @@ -13,71 +13,73 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.atomgraph.linkeddatahub.server.filter.request.auth; +package com.atomgraph.linkeddatahub.server.util; -import jakarta.ws.rs.BadRequestException; +import com.atomgraph.linkeddatahub.server.exception.InternalURLException; import org.junit.Test; import java.net.URI; /** - * Unit tests for WebIDFilter SSRF protection. - * Tests the validateNotInternalURL method to ensure it properly blocks access to internal addresses. + * Unit tests for URLValidator SSRF protection. + * Tests the URLValidator to ensure it properly blocks access to internal addresses. * + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/250">LNK-009: SSRF vulnerability</a> * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/252">LNK-004: SSRF primitive via On-Behalf-Of header</a> + * @see <a href="https://github.com/AtomGraph/LinkedDataHub/issues/253">LNK-002: SSRF primitives in admin endpoint</a> * @author Martynas Jusevičius {@literal <martynas@atomgraph.com>} */ -public class WebIDFilterTest +public class URLValidatorTest { @Test(expected = IllegalArgumentException.class) public void testNullURI() { - WebIDFilter.validateNotInternalURL(null); + new URLValidator(null); } - @Test(expected = BadRequestException.class) + @Test(expected = InternalURLException.class) public void testLinkLocalIPv4Blocked() { - WebIDFilter.validateNotInternalURL(URI.create("http://169.254.1.1:8080/webid#me")); + new URLValidator(URI.create("http://169.254.1.1:8080/test")).validate(); } - @Test(expected = BadRequestException.class) + @Test(expected = InternalURLException.class) public void testPrivateClass10Blocked() { - WebIDFilter.validateNotInternalURL(URI.create("http://10.0.0.1:8080/webid#me")); + new URLValidator(URI.create("http://10.0.0.1:8080/test")).validate(); } - @Test(expected = BadRequestException.class) + @Test(expected = InternalURLException.class) public void testPrivateClass172Blocked() { - WebIDFilter.validateNotInternalURL(URI.create("http://172.16.0.0:8080/webid#me")); + new URLValidator(URI.create("http://172.16.0.0:8080/test")).validate(); } - @Test(expected = BadRequestException.class) + @Test(expected = InternalURLException.class) public void testPrivateClass192Blocked() { - WebIDFilter.validateNotInternalURL(URI.create("http://192.168.1.1:8080/webid#me")); + new URLValidator(URI.create("http://192.168.1.1:8080/test")).validate(); } @Test public void testExternalURLAllowed() { // Public IPs should be allowed (no exception thrown) - WebIDFilter.validateNotInternalURL(URI.create("http://8.8.8.8:80/webid#me")); + new URLValidator(URI.create("http://8.8.8.8:80/test")).validate(); } @Test public void testPublicDomainAllowed() { // Public domains should be allowed (no exception thrown) - WebIDFilter.validateNotInternalURL(URI.create("http://example.org/webid#me")); + new URLValidator(URI.create("http://example.org/test")).validate(); } @Test public void testHTTPSAllowed() { // HTTPS to public domain should be allowed (no exception thrown) - WebIDFilter.validateNotInternalURL(URI.create("https://alice.example.com/profile/card#me")); + new URLValidator(URI.create("https://www.w3.org/ns/ldp")).validate(); } } From 9e45c8ab85355d18f886594714831f1603fd3388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Thu, 15 Jan 2026 00:10:11 +0100 Subject: [PATCH 57/64] `URLValidator` usage fix --- http-tests/proxy/GET-proxied-internal-403.sh | 8 ++++---- http-tests/proxy/GET-proxied-rfc1918-403.sh | 12 ++++++------ .../server/model/impl/ProxiedGraph.java | 15 ++++++++++++--- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/http-tests/proxy/GET-proxied-internal-403.sh b/http-tests/proxy/GET-proxied-internal-403.sh index 1a1b88632..865411f23 100755 --- a/http-tests/proxy/GET-proxied-internal-403.sh +++ b/http-tests/proxy/GET-proxied-internal-403.sh @@ -17,7 +17,7 @@ add-agent-to-group.sh \ # LNK-009: Test that internal Docker services are blocked via SSRF protection # Attempt to access the internal fuseki-admin SPARQL endpoint via the proxy -# This should be blocked and return 403 Forbidden +# This should be blocked and return 400 Bad Request http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ -G \ @@ -26,8 +26,8 @@ http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ --data-urlencode "uri=http://fuseki-admin:3030/ds" \ "$END_USER_BASE_URL" || true) -# Verify that access was forbidden (403) -if [ "$http_status" != "403" ]; then - echo "Expected HTTP 403 Forbidden for internal service access, got: $http_status" +# Verify that access was rejected (400) +if [ "$http_status" != "400" ]; then + echo "Expected HTTP 400 Bad Request for internal service access, got: $http_status" exit 1 fi diff --git a/http-tests/proxy/GET-proxied-rfc1918-403.sh b/http-tests/proxy/GET-proxied-rfc1918-403.sh index a5726f58e..eb50c3e88 100755 --- a/http-tests/proxy/GET-proxied-rfc1918-403.sh +++ b/http-tests/proxy/GET-proxied-rfc1918-403.sh @@ -25,8 +25,8 @@ http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ --data-urlencode "uri=http://10.0.0.1:8080/test" \ "$END_USER_BASE_URL" || true) -if [ "$http_status" != "403" ]; then - echo "Expected HTTP 403 Forbidden for 10.0.0.1 access, got: $http_status" +if [ "$http_status" != "400" ]; then + echo "Expected HTTP 400 Bad Request for 10.0.0.1 access, got: $http_status" exit 1 fi @@ -39,8 +39,8 @@ http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ --data-urlencode "uri=http://172.16.0.1:8080/test" \ "$END_USER_BASE_URL" || true) -if [ "$http_status" != "403" ]; then - echo "Expected HTTP 403 Forbidden for 172.16.0.1 access, got: $http_status" +if [ "$http_status" != "400" ]; then + echo "Expected HTTP 400 Bad Request for 172.16.0.1 access, got: $http_status" exit 1 fi @@ -53,7 +53,7 @@ http_status=$(curl -k -s -o /dev/null -w "%{http_code}" \ --data-urlencode "uri=http://192.168.1.1:8080/test" \ "$END_USER_BASE_URL" || true) -if [ "$http_status" != "403" ]; then - echo "Expected HTTP 403 Forbidden for 192.168.1.1 access, got: $http_status" +if [ "$http_status" != "400" ]; then + echo "Expected HTTP 400 Bad Request for 192.168.1.1 access, got: $http_status" exit 1 fi diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java index 4c371007b..f5d183e32 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/ProxiedGraph.java @@ -165,9 +165,6 @@ protected ProxiedGraph(@Context UriInfo uriInfo, @Context Request request, @Cont { super(uriInfo, request, httpHeaders, mediaTypes, uri, endpoint, query, accept, mode, system.getExternalClient(), httpServletRequest); - // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) - if (uri != null) new URLValidator(uri).validate(); - this.uriInfo = uriInfo; this.application = application; this.service = service.get(); @@ -311,6 +308,8 @@ public Response get(WebTarget target, Invocation.Builder builder) } if (!getSystem().isEnableLinkedDataProxy()) throw new NotAllowedException("Linked Data proxy not enabled"); + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(target.getUri()).validate(); return super.get(target, builder); } @@ -326,6 +325,8 @@ public Response get(WebTarget target, Invocation.Builder builder) public Response post(String sparqlQuery) { if (getWebTarget() == null) throw new NotFoundException("Resource URI not supplied"); + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(getWebTarget().getUri()).validate(); if (log.isDebugEnabled()) log.debug("POSTing SPARQL query to URI: {}", getWebTarget().getUri()); @@ -358,6 +359,8 @@ public Response post(String sparqlQuery) public Response postForm(String formData) { if (getWebTarget() == null) throw new NotFoundException("Resource URI not supplied"); + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(getWebTarget().getUri()).validate(); if (log.isDebugEnabled()) log.debug("POSTing form data to URI: {}", getWebTarget().getUri()); @@ -390,6 +393,8 @@ public Response postForm(String formData) public Response patch(String sparqlUpdate) { if (getWebTarget() == null) throw new NotFoundException("Resource URI not supplied"); + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(getWebTarget().getUri()).validate(); if (log.isDebugEnabled()) log.debug("PATCHing SPARQL update to URI: {}", getWebTarget().getUri()); @@ -423,6 +428,8 @@ public Response postMultipart(FormDataMultiPart multiPart) { if (!getSystem().isEnableLinkedDataProxy()) throw new NotAllowedException("Linked Data proxy not enabled"); if (getWebTarget() == null) throw new NotFoundException("Resource URI not supplied"); // cannot throw Exception in constructor: https://github.com/eclipse-ee4j/jersey/issues/4436 + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(getWebTarget().getUri()).validate(); try (Response cr = getWebTarget().request(). accept(getMediaTypes().getReadable(Model.class).toArray(jakarta.ws.rs.core.MediaType[]::new)). @@ -445,6 +452,8 @@ public Response putMultipart(FormDataMultiPart multiPart) { if (!getSystem().isEnableLinkedDataProxy()) throw new NotAllowedException("Linked Data proxy not enabled"); if (getWebTarget() == null) throw new NotFoundException("Resource URI not supplied"); // cannot throw Exception in constructor: https://github.com/eclipse-ee4j/jersey/issues/4436 + // LNK-009: Validate that proxied URI is not internal/private (SSRF protection) + new URLValidator(getWebTarget().getUri()).validate(); try (Response cr = getWebTarget().request(). accept(getMediaTypes().getReadable(Model.class).toArray(jakarta.ws.rs.core.MediaType[]::new)). From 41cd85a4a3c0410c7e9240c69b842646fad69118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Thu, 15 Jan 2026 12:48:34 +0100 Subject: [PATCH 58/64] Fixed `PATCH` case which clears the graph --- .../PATCH-delete-where-no-match.sh | 57 +++++++++++++++++++ .../resource/admin/pkg/UninstallPackage.java | 4 +- .../model/impl/DirectGraphStoreImpl.java | 4 +- 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100755 http-tests/document-hierarchy/PATCH-delete-where-no-match.sh diff --git a/http-tests/document-hierarchy/PATCH-delete-where-no-match.sh b/http-tests/document-hierarchy/PATCH-delete-where-no-match.sh new file mode 100755 index 000000000..f6eda91f1 --- /dev/null +++ b/http-tests/document-hierarchy/PATCH-delete-where-no-match.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +initialize_dataset "$END_USER_BASE_URL" "$TMP_END_USER_DATASET" "$END_USER_ENDPOINT_URL" +initialize_dataset "$ADMIN_BASE_URL" "$TMP_ADMIN_DATASET" "$ADMIN_ENDPOINT_URL" +purge_cache "$END_USER_VARNISH_SERVICE" +purge_cache "$ADMIN_VARNISH_SERVICE" +purge_cache "$FRONTEND_VARNISH_SERVICE" + +# add agent to the writers group + +add-agent-to-group.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --agent "$AGENT_URI" \ + "${ADMIN_BASE_URL}acl/groups/writers/" + +# Test that PATCH with DELETE WHERE that matches no triples does NOT delete the entire graph +# This is a regression test for bug where changedModel.isEmpty() incorrectly triggered graph deletion + +# Create test graph URI +test_graph_uri="${ADMIN_BASE_URL}test-graph-$(date +%s)/" + +# Create test graph with multiple triples using bin/put.sh +echo "<http://example.org/resource1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/TestClass> . +<http://example.org/resource1> <http://example.org/property1> \"value1\" . +<http://example.org/resource1> <http://example.org/property2> \"value2\" . +<http://example.org/resource2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherClass> . +<http://example.org/resource2> <http://example.org/property3> \"value3\" ." | \ + put.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + -t "application/n-triples" \ + "$test_graph_uri" + +# Execute PATCH with DELETE WHERE that matches nothing (non-existent triple) +echo "PREFIX ex: <http://example.org/> +PREFIX owl: <http://www.w3.org/2002/07/owl#> + +DELETE WHERE { ex:nonExistentResource owl:imports ex:nonExistentOntology }" | \ + patch.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + "$test_graph_uri" + +# Verify graph still exists and contains original triples +graph_content=$(get.sh \ + -f "$OWNER_CERT_FILE" \ + -p "$OWNER_CERT_PWD" \ + --accept "application/n-triples" \ + "$test_graph_uri") + +# Verify essential triples are still present (grep for exact n-triples format) +echo "$graph_content" | grep -q "<http://example.org/resource1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/TestClass>" +echo "$graph_content" | grep -q "<http://example.org/resource1> <http://example.org/property1> \"value1\"" +echo "$graph_content" | grep -q "<http://example.org/resource2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/OtherClass>" +echo "$graph_content" | grep -q "<http://example.org/resource2> <http://example.org/property3> \"value3\"" diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java index 30038d92a..7f72abe54 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/UninstallPackage.java @@ -154,8 +154,6 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" regenerateMasterStylesheet(endUserApp, pkg); } - //removeImportFromApplication(endUserApp, packageURI); - if (log.isInfoEnabled()) log.info("Successfully uninstalled package: {}", packageURI); URI redirectURI = (referer != null) ? referer : endUserApp.getBaseURI(); @@ -169,7 +167,7 @@ public Response post(@FormParam("package-uri") String packageURI, @HeaderParam(" } /** - * Uninstalls ontology by deleting the package ontology document and removing owl:imports from namespace graph. + * Uninstalls ontology by deleting the package ontology document. * * @param app the end-user application * @param packageOntologyURI the package ONTOLOGY URI diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java index e5a73fcd7..191a95d0f 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/DirectGraphStoreImpl.java @@ -403,8 +403,8 @@ public Response patch(UpdateRequest updateRequest) for (Resource resource : changedResources) changedModel.add(existingModel.listStatements(resource, null, (RDFNode) null)); - // if PATCH results in an empty model, treat it as a DELETE request - if (changedModel.isEmpty()) return delete(); + // if PATCH results in an empty graph, treat it as a DELETE request + if (existingModel.isEmpty()) return delete(); validate(changedModel); // this would normally be done transparently by the ValidatingModelProvider put(dataset.getDefaultModel(), Boolean.FALSE, getURI()); From 421593642b1e613f9369a90bd77f0641fe9ca474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Thu, 15 Jan 2026 13:53:45 +0100 Subject: [PATCH 59/64] Test fix --- http-tests/document-hierarchy/PATCH-empty-root-405.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/http-tests/document-hierarchy/PATCH-empty-root-405.sh b/http-tests/document-hierarchy/PATCH-empty-root-405.sh index 88813e525..eda7a677f 100755 --- a/http-tests/document-hierarchy/PATCH-empty-root-405.sh +++ b/http-tests/document-hierarchy/PATCH-empty-root-405.sh @@ -20,11 +20,11 @@ add-agent-to-group.sh \ update=$(cat <<EOF DELETE { - <${END_USER_BASE_URL}> ?p ?o + ?s ?p ?o } WHERE { - <${END_USER_BASE_URL}> ?p ?o + ?s ?p ?o } EOF ) From 29893ecf9e82c58b113a379c402b8a3846ab9a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Thu, 15 Jan 2026 22:46:02 +0100 Subject: [PATCH 60/64] Package install/uninstall UI --- .../resource/admin/pkg/InstallPackage.java | 7 +-- .../atomgraph/linkeddatahub/css/bootstrap.css | 6 +- .../bootstrap/2.3.2/admin/acl/imports/owl.xsl | 52 +++++++++++++++ .../xsl/bootstrap/2.3.2/admin/acl/layout.xsl | 1 + .../xsl/bootstrap/2.3.2/admin/layout.xsl | 14 ----- .../xsl/bootstrap/2.3.2/imports/lapp.xsl | 63 +++++++++++++++++++ .../xsl/bootstrap/2.3.2/layout.xsl | 28 +++------ .../xsl/bootstrap/2.3.2/translations.rdf | 16 +++++ .../atomgraph/linkeddatahub/xsl/client.xsl | 2 +- 9 files changed, 149 insertions(+), 40 deletions(-) create mode 100644 src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/imports/owl.xsl create mode 100644 src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/imports/lapp.xsl diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index 117abc3ca..a0ecce521 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -395,11 +395,8 @@ private void installOntology(EndUserApplication app, Model ontologyModel, String if (log.isDebugEnabled()) log.debug("Namespace graph PATCH response status: {}", patchResponse.getStatus()); } - // 4. Clear and reload namespace ontology from cache - // TODO: This causes deadlock when OntologyModelGetter makes synchronous HTTP requests back to /ns - // Need to either make this async or find alternative way to refresh ontology cache - // if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); - // getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); + if (log.isDebugEnabled()) log.debug("Clearing and reloading namespace ontology '{}'", namespaceOntologyURI); + getResourceContext().getResource(ClearOntology.class).post(namespaceOntologyURI, null); } /** diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css index a19d99fc9..66155e480 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/css/bootstrap.css @@ -1,6 +1,8 @@ html { height: 100%; } body { height: calc(100% - 120px); padding-top: 120px; padding-bottom: 0; } body.embed { padding-top: 0; } +ul.dropdown-menu { max-height: 26em; overflow-x: hidden; overflow-y: auto; } +ul.dropdown-menu ul { margin: 0; } .label { min-width: unset; min-height: unset; } .brand.context { background-image: url('../icons/baseline_arrow_upward_white_18dp.png'); background-repeat: no-repeat; background-position: center center; height: 20px; width: 20px; background-size: 20px 20px; } .brand.admin { background-image: url('../icons/ic_settings_white_24px.svg'); background-repeat: no-repeat; background-position: right center; padding-right: 30px; } @@ -10,6 +12,8 @@ body.embed { padding-top: 0; } .btn.dropdown-toggle.btn-settings { background-image: url('../icons/settings_white_24dp.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } .btn.dropdown-toggle.btn-agent { background-image: url('../icons/ic_account_circle_white_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } .dropdown-menu .btn-app-settings { background-color: inherit; display: block; text-align: left; width: 100%; padding-left: 20px; } +.dropdown-menu li form { margin-bottom: 0; } +.dropdown-menu li form button { width: 100%; text-align: left; } .navbar-form .input-append { margin-top: 10px; } .navbar-form .input-append select { margin-top: 0; height: 34px; } .navbar-form .btn-search { background-image: url('../icons/ic_search_white_24px.svg'); background-position: center center; background-repeat: no-repeat; width: 34px; height: 34px; } @@ -27,8 +31,6 @@ body.embed { padding-top: 0; } .action-bar #doc-controls .btn-edit { margin-top: -5px; margin-left: 10px; } .action-bar p.alert { margin-bottom: 0; } .nav-header.btn { color: inherit; } -ul.dropdown-menu { max-height: 26em; overflow-x: hidden; overflow-y: auto; } -ul.dropdown-menu ul { margin: 0; } .btn.btn-primary.create-action { background-image: url('../icons/ic_note_add_white_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding-left: 40px; /* height: 30px; */ } .btn.create-action, a.create-action { background-image: url('../icons/ic_note_add_black_24px.svg'); background-position: 12px center; background-repeat: no-repeat; padding-left: 40px; /* height: 30px; */ } button.btn.create-action { height: 30px; } diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/imports/owl.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/imports/owl.xsl new file mode 100644 index 000000000..06e4801e8 --- /dev/null +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/imports/owl.xsl @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE xsl:stylesheet [ + <!ENTITY adm "https://w3id.org/atomgraph/linkeddatahub/admin#"> + <!ENTITY ldh "https://w3id.org/atomgraph/linkeddatahub#"> + <!ENTITY ac "https://w3id.org/atomgraph/client#"> + <!ENTITY a "https://w3id.org/atomgraph/core#"> + <!ENTITY lacl "https://w3id.org/atomgraph/linkeddatahub/admin/acl#"> + <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#"> + <!ENTITY owl "http://www.w3.org/2002/07/owl#"> + <!ENTITY ldt "https://www.w3.org/ns/ldt#"> + <!ENTITY dh "https://www.w3.org/ns/ldt/document-hierarchy#"> + <!ENTITY prov "http://www.w3.org/ns/prov#"> + <!ENTITY foaf "http://xmlns.com/foaf/0.1/"> + <!ENTITY sioc "http://rdfs.org/sioc/ns#"> + <!ENTITY dct "http://purl.org/dc/terms/"> +]> +<xsl:stylesheet version="3.0" +xmlns="http://www.w3.org/1999/xhtml" +xmlns:xhtml="http://www.w3.org/1999/xhtml" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +xmlns:xs="http://www.w3.org/2001/XMLSchema" +xmlns:ldh="&ldh;" +xmlns:ac="∾" +xmlns:a="&a;" +xmlns:lacl="&lacl;" +xmlns:rdf="&rdf;" +xmlns:rdfs="&rdfs;" +xmlns:owl="&owl;" +xmlns:ldt="&ldt;" +xmlns:dh="&dh;" +xmlns:foaf="&foaf;" +xmlns:sioc="&sioc;" +xmlns:bs2="http://graphity.org/xsl/bootstrap/2.3.2" +exclude-result-prefixes="#all"> + + <!-- show "Clear" button for ontologies --> + <xsl:template match="*[rdf:type/@rdf:resource = '&owl;Ontology'][$foaf:Agent//@rdf:about]" mode="bs2:Actions"> + <form class="pull-right" action="{resolve-uri('clear', $ldt:base)}" method="post"> + <input type="hidden" name="uri" value="{@rdf:about}"/> + + <button class="btn btn-primary" type="submit"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'clear', document('../../../translations.rdf'))" mode="ac:label"/> + </xsl:value-of> + </button> + </form> + + <xsl:next-match/> + </xsl:template> + +</xsl:stylesheet> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/layout.xsl index 3f2b8f356..0c4a69c4f 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/acl/layout.xsl @@ -26,6 +26,7 @@ exclude-result-prefixes="#all"> <xsl:import href="imports/acl.xsl"/> <xsl:import href="imports/cert.xsl"/> + <xsl:import href="imports/owl.xsl"/> <!-- TO-DO: refactor into component templates --> <xsl:template match="rdf:RDF" mode="bs2:NavBarNavList"> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl index 67735f206..9a5cdaf41 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/admin/layout.xsl @@ -135,19 +135,5 @@ exclude-result-prefixes="#all"> </xsl:apply-imports> </xsl:template> - <!-- show "Clear" button for ontologies --> - <xsl:template match="*[rdf:type/@rdf:resource = '&owl;Ontology'][$foaf:Agent//@rdf:about]" mode="bs2:Actions"> - <form class="pull-right" action="{resolve-uri('clear', $ldt:base)}" method="post"> - <input type="hidden" name="uri" value="{@rdf:about}"/> - - <button class="btn btn-primary" type="submit"> - <xsl:value-of> - <xsl:apply-templates select="key('resources', 'clear', document('../translations.rdf'))" mode="ac:label"/> - </xsl:value-of> - </button> - </form> - <xsl:next-match/> - </xsl:template> - </xsl:stylesheet> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/imports/lapp.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/imports/lapp.xsl new file mode 100644 index 000000000..3ab8706bc --- /dev/null +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/imports/lapp.xsl @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE xsl:stylesheet [ + <!ENTITY ac "https://w3id.org/atomgraph/client#"> + <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#"> + <!ENTITY owl "http://www.w3.org/2002/07/owl#"> + <!ENTITY ldt "https://www.w3.org/ns/ldt#"> + <!ENTITY lapp "https://w3id.org/atomgraph/linkeddatahub/apps#"> +]> +<xsl:stylesheet version="3.0" +xmlns="http://www.w3.org/1999/xhtml" +xmlns:xhtml="http://www.w3.org/1999/xhtml" +xmlns:xsl="http://www.w3.org/1999/XSL/Transform" +xmlns:xs="http://www.w3.org/2001/XMLSchema" +xmlns:ac="∾" +xmlns:rdf="&rdf;" +xmlns:rdfs="&rdfs;" +xmlns:owl="&owl;" +xmlns:ldt="&ldt;" +xmlns:lapp="&lapp;" +xmlns:bs2="http://graphity.org/xsl/bootstrap/2.3.2" +exclude-result-prefixes="#all"> + + <!-- show "Actions" dropdown with Install/Uninstall options for packages --> + <xsl:template match="*[rdf:type/@rdf:resource = '&lapp;Package']" mode="bs2:Actions"> + <xsl:variable name="admin-origin" select="(key('resources', $lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/lapp:adminApplication/(@rdf:resource, @rdf:nodeID), $lapp:Application)/lapp:origin/@rdf:resource, $ldt:base)[1]" as="xs:anyURI"/> + + <div class="btn-group pull-right"> + <button type="button" class="btn dropdown-toggle"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'actions', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + <xsl:text> </xsl:text> + <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li> + <form action="{resolve-uri('packages/install', $admin-origin)}" method="post"> + <input type="hidden" name="package-uri" value="{@rdf:about}"/> + <button class="btn btn-primary" type="submit"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'install', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </button> + </form> + </li> + <li> + <form action="{resolve-uri('packages/uninstall', $admin-origin)}" method="post"> + <input type="hidden" name="package-uri" value="{@rdf:about}"/> + <button class="btn btn-danger" type="submit"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', 'uninstall', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/> + </xsl:value-of> + </button> + </form> + </li> + </ul> + </div> + + <xsl:next-match/> + </xsl:template> + +</xsl:stylesheet> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl index 08f500bc6..b879ab199 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl @@ -81,16 +81,17 @@ exclude-result-prefixes="#all"> <xsl:import href="../../../../client/xsl/converters/RDFXML2JSON-LD.xsl"/> <xsl:import href="../../../../client/xsl/bootstrap/2.3.2/internal-layout.xsl"/> + <xsl:import href="resource.xsl"/> <xsl:import href="imports/default.xsl"/> <xsl:import href="imports/ac.xsl"/> <xsl:import href="imports/dct.xsl"/> <xsl:import href="imports/nfo.xsl"/> <xsl:import href="imports/rdf.xsl"/> - <xsl:import href="imports/rdfs.xsl"/> + <xsl:import href="imports/rdfs.xsl"/> <xsl:import href="imports/sioc.xsl"/> <xsl:import href="imports/sp.xsl"/> <xsl:import href="imports/sh.xsl"/> - <xsl:import href="resource.xsl"/> + <xsl:import href="imports/lapp.xsl"/> <xsl:import href="imports/services/youtube.xsl"/> <xsl:import href="document.xsl"/> @@ -1247,15 +1248,13 @@ LIMIT 100 <ul class="dropdown-menu"> <xsl:if test="$foaf:Agent//@rdf:about and $lapp:Application//*[lapp:origin/@rdf:resource = $lapp:origin]/rdf:type/@rdf:resource = '&lapp;EndUserApplication'"> - <xsl:if test="$acl:mode = '&acl;Control'"> - <li> - <button class="btn btn-app-settings"> - <xsl:value-of> - <xsl:apply-templates select="key('resources', '&lapp;Application', document(ac:document-uri('&lapp;')))" mode="ac:label"/> - </xsl:value-of> - </button> - </li> - </xsl:if> + <li> + <button class="btn btn-app-settings"> + <xsl:value-of> + <xsl:apply-templates select="key('resources', '&lapp;Application', document(ac:document-uri('&lapp;')))" mode="ac:label"/> + </xsl:value-of> + </button> + </li> <li> <xsl:for-each select="$lapp:Application"> <a href="{key('resources', //*[lapp:origin/@rdf:resource = $lapp:origin]/lapp:adminApplication/(@rdf:resource, @rdf:nodeID))/lapp:origin/@rdf:resource}" target="_blank"> @@ -1273,13 +1272,6 @@ LIMIT 100 </a> </li> </xsl:if> - <li> - <a href="https://atomgraph.github.io/LinkedDataHub/linkeddatahub/docs/" target="_blank"> - <xsl:value-of> - <xsl:apply-templates select="key('resources', 'documentation', document('translations.rdf'))" mode="ac:label"/> - </xsl:value-of> - </a> - </li> </ul> </div> </xsl:template> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf index c56a2ee9c..a7dfaff31 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf @@ -330,6 +330,22 @@ <rdfs:label xml:lang="en-US">Clear</rdfs:label> <rdfs:label xml:lang="es-ES">Limpiar</rdfs:label> </rdf:Description> + <rdf:Description rdf:nodeID="install"> + <rdfs:label xml:lang="en-US">Install</rdfs:label> + <rdfs:label xml:lang="es-ES">Instalar</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="uninstall"> + <rdfs:label xml:lang="en-US">Uninstall</rdfs:label> + <rdfs:label xml:lang="es-ES">Desinstalar</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="package"> + <rdfs:label xml:lang="en-US">Package</rdfs:label> + <rdfs:label xml:lang="es-ES">Paquete</rdfs:label> + </rdf:Description> + <rdf:Description rdf:nodeID="ontology"> + <rdfs:label xml:lang="en-US">Ontology</rdfs:label> + <rdfs:label xml:lang="es-ES">Ontología</rdfs:label> + </rdf:Description> <rdf:Description rdf:nodeID="related-results"> <rdfs:label xml:lang="en-US">Related results</rdfs:label> <rdfs:label xml:lang="es-ES">Resultados relacionados</rdfs:label> diff --git a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl index 2b2d9239a..052116f39 100644 --- a/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl +++ b/src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/client.xsl @@ -82,6 +82,7 @@ extension-element-prefixes="ixsl" <xsl:import href="../../../../com/atomgraph/client/xsl/bootstrap/2.3.2/resource.xsl"/> <xsl:import href="../../../../com/atomgraph/client/xsl/bootstrap/2.3.2/document.xsl"/> <xsl:import href="../../../../com/atomgraph/client/xsl/bootstrap/2.3.2/container.xsl"/> + <xsl:import href="bootstrap/2.3.2/resource.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/ac.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/ldh.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/dct.xsl"/> @@ -91,7 +92,6 @@ extension-element-prefixes="ixsl" <xsl:import href="bootstrap/2.3.2/imports/sioc.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/sp.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/sh.xsl"/> - <xsl:import href="bootstrap/2.3.2/resource.xsl"/> <xsl:import href="bootstrap/2.3.2/document.xsl"/> <xsl:import href="bootstrap/2.3.2/imports/services/youtube.xsl"/> <xsl:import href="converters/RDFXML2DataTable.xsl"/> From f8a769c5a3e9c6f9bd3d9d6c1ba44a2079a97287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 16 Jan 2026 11:00:20 +0100 Subject: [PATCH 61/64] Set title of the package document --- .../resource/admin/pkg/InstallPackage.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java index a0ecce521..1dd1fe494 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java +++ b/src/main/java/com/atomgraph/linkeddatahub/resource/admin/pkg/InstallPackage.java @@ -68,6 +68,7 @@ import com.atomgraph.linkeddatahub.vocabulary.SIOC; import com.atomgraph.linkeddatahub.server.util.Skolemizer; import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.vocabulary.DCTerms; import org.apache.jena.vocabulary.RDF; /** @@ -442,26 +443,25 @@ private void regenerateMasterStylesheet(EndUserApplication app, com.atomgraph.li /** * Creates a package document item. * - * @param packageDocModel the model to populate + * @param model the model to populate * @param packageDocumentURI the document URI * @param container the container resource * @param pkg the package resource * @param slug the document slug * @return the document item resource */ - private Resource createPackageDocument(Model packageDocModel, + private Resource createPackageDocument(Model model, URI packageDocumentURI, Resource container, com.atomgraph.linkeddatahub.apps.model.Package pkg, String slug) { - Resource packageDocItem = packageDocModel.createResource(packageDocumentURI.toString()). + return model.createResource(packageDocumentURI.toString()). addProperty(RDF.type, DH.Item). addProperty(SIOC.HAS_CONTAINER, container). addLiteral(DH.slug, slug). + addLiteral(DCTerms.title, pkg.getProperty(DCTerms.title).getString()). addProperty(FOAF.primaryTopic, pkg); - - return packageDocItem; } /** From 8390267e355e3a8492901ebb670214098be70227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 16 Jan 2026 11:39:40 +0100 Subject: [PATCH 62/64] SNAPSHOT bump --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f6275a8d..dc0e3037d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ <groupId>com.atomgraph</groupId> <artifactId>linkeddatahub</artifactId> - <version>5.1.2-SNAPSHOT</version> + <version>5.2.0-SNAPSHOT</version> <packaging>${packaging.type}</packaging> <name>AtomGraph LinkedDataHub</name> From 04fdf81fd156b07d911953a709ad119f51f7e412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 16 Jan 2026 14:37:34 +0100 Subject: [PATCH 63/64] README update --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index c4c84c9b2..affc0dc85 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,21 @@ The following tools are required for CLI scripts in the `bin/` directory: * There might go up to a minute before the web server is available because the nginx server depends on healthy LinkedDataHub and the healthcheck is done every 20s * You will likely get a browser warning such as `Your connection is not private` in Chrome or `Warning: Potential Security Risk Ahead` in Firefox due to the self-signed server certificate. Ignore it: click `Advanced` and `Proceed` or `Accept the risk` to proceed. * If this option does not appear in Chrome (as observed on some MacOS), you can open `chrome://flags/#allow-insecure-localhost`, switch `Allow invalid certificates for resources loaded from localhost` to `Enabled` and restart Chrome + * MacOS: Chrome subdomain support: Chrome on macOS requires the server certificate to be installed to the System keychain to properly load resources from dataspace subdomains (e.g., `admin.localhost:4443`). Firefox is more lenient and will work without this step. + 1. Open **Keychain Access** (Applications > Utilities > Keychain Access) + 2. Select **System** keychain in the left sidebar + 3. **File** → **Import Items** → select `ssl/server/server.crt` + 4. Enter your admin password when prompted + 5. Double-click the "localhost" certificate + 6. Expand the **Trust** section + 7. Set "When using this certificate:" to **Always Trust** + 8. Close the window (enter password again) + 9. Completely quit Chrome (Cmd+Q) and restart + + Alternatively, use the command line: + ```shell + sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ssl/server/server.crt + ``` * `.env_sample` and `.env` files might be invisible in MacOS Finder which hides filenames starting with a dot. You should be able to [create it using Terminal](https://stackoverflow.com/questions/5891365/mac-os-x-doesnt-allow-to-name-files-starting-with-a-dot-how-do-i-name-the-hta) however. * On Linux your user may need to be a member of the `docker` group. Add it using ```shell From 9acd1f2610bc64bf184681bec740ee586170c1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Jusevi=C4=8Dius?= <martynas@atomgraph.com> Date: Fri, 16 Jan 2026 23:15:40 +0100 Subject: [PATCH 64/64] Javadoc fixes --- src/main/java/com/atomgraph/linkeddatahub/Application.java | 4 ++++ .../atomgraph/linkeddatahub/server/model/impl/Dispatcher.java | 3 +-- .../java/com/atomgraph/server/mapper/ExceptionMapperBase.java | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/atomgraph/linkeddatahub/Application.java b/src/main/java/com/atomgraph/linkeddatahub/Application.java index 9e59ef69a..0a5851110 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/Application.java +++ b/src/main/java/com/atomgraph/linkeddatahub/Application.java @@ -258,6 +258,10 @@ public class Application extends ResourceConfig private static final Logger log = LoggerFactory.getLogger(Application.class); + /** + * Path to the master XSLT stylesheet for server-side transformations. + * Package stylesheets are imported into this master stylesheet. + */ public static final String MASTER_STYLESHEET_PATH = "/static/xsl/layout.xsl"; private final ExecutorService importThreadPool; diff --git a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java index 1ad8f8002..6aec6c975 100644 --- a/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java +++ b/src/main/java/com/atomgraph/linkeddatahub/server/model/impl/Dispatcher.java @@ -173,9 +173,8 @@ public Class getAccessRequest() /** * Returns content-addressed file item resource. - * + * * @return resource - * @see com.atomgraph.linkeddatahub.apps.model.Application#UPLOADS_PATH */ @Path("uploads/{sha1sum}") public Class getFileItem() diff --git a/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java b/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java index e07b46872..829526854 100644 --- a/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java +++ b/src/main/java/com/atomgraph/server/mapper/ExceptionMapperBase.java @@ -109,8 +109,8 @@ public List<Variant> getVariants(Class clazz) /** * Builds a list of acceptable response variants. - * - * @param mediaTypes + * + * @param mediaTypes list of media types to build variants from * @return supported variants */ public List<Variant> getVariants(List<MediaType> mediaTypes)