diff --git a/0.1.x/examples/reference-openbis-export/metadata.xlsx b/0.1.x/examples/reference-openbis-export/metadata.xlsx new file mode 100644 index 0000000..5ef8f85 Binary files /dev/null and b/0.1.x/examples/reference-openbis-export/metadata.xlsx differ diff --git a/0.1.x/examples/ro-crate-1.1/dist/rocrate.zip b/0.1.x/examples/ro-crate-1.1/dist/rocrate.zip new file mode 100644 index 0000000..498d3c9 Binary files /dev/null and b/0.1.x/examples/ro-crate-1.1/dist/rocrate.zip differ diff --git a/0.1.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json b/0.1.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json new file mode 100644 index 0000000..59bcbe9 --- /dev/null +++ b/0.1.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json @@ -0,0 +1,581 @@ +{ + "@context" : [ "https://w3id.org/ro/crate/1.1/context", { + "rdfs:subClassOf" : "https://www.w3.org/TR/rdf-schema/#ch_subclassof", + "rdfs:Property" : "https://www.w3.org/TR/rdf-schema/#ch_properties", + "schema:domainIncludes" : "https://www.w3.org/TR/rdf-schema/#ch_domain", + "owl:equivalentClass" : "https://www.w3.org/TR/owl-ref/#equivalentClass-def", + "owl:equivalentProperty" : "https://www.w3.org/TR/owl-ref/#equivalentProperty-def", + "schema:rangeIncludes" : "https://www.w3.org/TR/rdf-schema/#ch_range", + "rdfs:Class" : "https://www.w3.org/TR/rdf-schema/#ch_class" + } ], + "@graph" : [ { + "name" : "name", + "description" : "description", + "@id" : "./", + "@type" : "Dataset", + "license" : { + "@id" : "licenseIdentifier" + }, + "datePublished" : "2024-12-04T07:53:11Z", + "hasPart" : [ { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" + }, { + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME_URI" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME" + }, { + "@id" : "hasPUBLICATION_CREATOR.GIVEN_NAME" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, { + "@id" : "hasPUBLICATION.ORGANIZATION" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27" + }, { + "@id" : "hasPUBLICATION.TYPE" + }, { + "@id" : "PUBLICATIONS" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB29" + }, { + "@id" : ":Space" + }, { + "@id" : "hasDEFAULT_COLLECTION_VIEW" + }, { + "@id" : ":Object" + }, { + "@id" : ":Vocabulary" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, { + "@id" : "hasPUBLICATION.CONTRIBUTOR" + }, { + "@id" : ":Dataset" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION" + }, { + "@id" : "hasDEFAULT_OBJECT_TYPE" + }, { + "@id" : "hasXMLCOMMENTS" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB25" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, { + "@id" : ":Collection" + }, { + "@id" : "hasNAME" + }, { + "@id" : "hasPUBLICATION_CREATOR.IDENTIFIER" + }, { + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" + }, { + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME_URI" + }, { + "@id" : "hasPUBLICATION.IDENTIFIER" + }, { + "@id" : "hasPUBLICATION.CREATOR" + }, { + "@id" : "hasPUBLICATION.PUBLISHER" + }, { + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER" + }, { + "@id" : "hasPUBLICATION.PUBLICATION_YEAR" + }, { + "@id" : "hasPUBLICATION.DESCRIPTION" + }, { + "@id" : "hasPUBLICATION.OPENBIS_RELATED_IDENTIFIERS" + }, { + "@id" : ":Project" + }, { + "@id" : "PUBLICATION_PUBLISHER" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23" + }, { + "@id" : "hasPUBLICATION.URL" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB30" + }, { + "@id" : "hasPUBLICATION_CREATOR.FAMILY_NAME" + }, { + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME" + }, { + "@id" : "hasPUBLICATION.STATUS" + } ] + }, { + "about" : { + "@id" : "./" + }, + "conformsTo" : { + "@id" : "https://w3id.org/ro/crate/1.1" + }, + "@id" : "ro-crate-metadata.json", + "@type" : "CreativeWork" + }, { + "@type" : "COLLECTION", + "hasNAME" : "Publications Collection", + "hasDEFAULT_OBJECT_TYPE" : "PUBLICATION", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.DESCRIPTION", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#descriptions" + }, { + "@id" : "https://schema.org/description" + }, { + "@id" : "https://schema.org/abstract" + } ] + }, { + "@id" : ":Space", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.PUBLICATION_YEAR", + "schema:rangeIncludes" : { + "@id" : "xsd:dateTime" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publicationYear" + }, { + "@id" : "https://schema.org/datePublished" + } ] + }, { + "@id" : ":Collection", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.URL", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#url" + }, { + "@id" : "https://schema.org/url" + } ] + }, { + "@type" : "PUBLICATION_CREATOR", + "hasPUBLICATION_CREATOR.GIVEN_NAME" : "Elhacham", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22" + }, { + "@id" : ":Object", + "@type" : "rdfs:Class" + }, { + "@type" : "PUBLICATION", + "hasNAME" : "Genetic mechanisms of critical illness in COVID-19", + "hasPUBLICATION.URL" : "https://www.nature.com/articles/s41586-020-03065-y#citeas", + "hasPUBLICATION.IDENTIFIER" : "https://doi.org/10.1038/s41586-020-03065-y", + "hasPUBLICATION.STATUS" : "Registered", + "hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-11 15:48:55 +0100", + "hasPUBLICATION.TYPE" : "DataPaper", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB29", + "hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23" + }, + "hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "COLLECTION", + "hasNAME" : "Publications creator collection", + "hasDEFAULT_OBJECT_TYPE" : "PUBLICATION_CREATOR", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.GIVEN_NAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#givenName" + }, { + "@id" : "https://schema.org/givenName" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#doi" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#publisherIdentifierScheme" + } + }, { + "@type" : ":Space", + "description" : "Public Repositories", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME_URI", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "PUBLICATION_PUBLISHER", + "hasPUBLICATION_PUBLISHER.IDENTIFIER" : "Science", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.CONTRIBUTOR", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#doi" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.FAMILY_NAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#familyName" + }, { + "@id" : "https://schema.org/familyName" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasDEFAULT_COLLECTION_VIEW", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "COLLECTION" + } + }, { + "@type" : "COLLECTION", + "hasNAME" : "Publications Publisher Collection", + "hasDEFAULT_COLLECTION_VIEW" : "LIST_VIEW", + "hasDEFAULT_OBJECT_TYPE" : "PUBLICATION_PUBLISHER", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION" + }, { + "@type" : ":Space", + "@id" : "PUBLICATIONS" + }, { + "@type" : "rdfs:Property", + "@id" : "hasXMLCOMMENTS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.ORGANIZATION", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + } + }, { + "@id" : "COLLECTION", + "@type" : "rdfs:Class", + "rdfs:subClassOf" : { + "@id" : ":Collection" + } + }, { + "@type" : "PUBLICATION_CREATOR", + "hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" : "https://orcid.org", + "hasPUBLICATION_CREATOR.IDENTIFIER" : "https://orcid.org/0000-0001-9844-8214", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27" + }, { + "@type" : "PUBLICATION_CREATOR", + "hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" : "https://orcid.org/", + "hasPUBLICATION_CREATOR.IDENTIFIER" : "https://orcid.org/0000-0002-2423-3090", + "hasPUBLICATION_CREATOR.GIVEN_NAME" : "Pairo-Castineira", + "hasPUBLICATION_CREATOR.FAMILY_NAME" : "Erola", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.STATUS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#stateSelection" + }, { + "@id" : "https://schema.org/creativeWorkStatus" + } ] + }, { + "@type" : "PUBLICATION", + "hasNAME" : "Global human-made mass exceeds all living biomass", + "hasPUBLICATION.URL" : "https://www.nature.com/articles/s41586-020-3010-5#citeas", + "hasPUBLICATION.IDENTIFIER" : "https://doi.org/10.1038/s41586-020-3010-5", + "hasPUBLICATION.STATUS" : "Registered", + "hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-09 15:43:20 +0100", + "hasPUBLICATION.TYPE" : "DataPaper", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB25", + "hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22" + }, + "hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24" + } + }, { + "@id" : "PUBLICATION_PUBLISHER", + "@type" : "rdfs:Class", + "rdfs:subClassOf" : { + "@id" : ":Object" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.TYPE", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.CREATOR", + "schema:rangeIncludes" : { + "@id" : ":Object" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#creator" + }, { + "@id" : "https://schema.org/author" + }, { + "@id" : "https://schema.org/creator" + } ] + }, { + "@id" : ":Vocabulary", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_CREATOR.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publisherIdentifier" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@id" : ":Project", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME_URI", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#schemeURI" + } + }, { + "@id" : "PUBLICATION", + "@type" : "rdfs:Class", + "rdfs:subClassOf" : { + "@id" : ":Object" + } + }, { + "@type" : "PUBLICATION", + "hasNAME" : "Quantum computational advantage using photons", + "hasPUBLICATION.URL" : "https://www.science.org/doi/10.1126/science.abe8770", + "hasPUBLICATION.IDENTIFIER" : "DOI: 10.1126/science.abe8770", + "hasPUBLICATION.STATUS" : "Registered", + "hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-11 15:50:44 +0100", + "hasPUBLICATION.TYPE" : "DataPaper", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB30", + "hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27" + }, + "hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.PUBLISHER", + "schema:rangeIncludes" : { + "@id" : ":Object" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publisher" + }, { + "@id" : "https://schema.org/publisher" + } ] + }, { + "@id" : ":Dataset", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "hasDEFAULT_OBJECT_TYPE", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "COLLECTION" + } + }, { + "@type" : "rdfs:Property", + "@id" : "hasNAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : [ { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "PUBLICATION_PUBLISHER" + } ], + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#title" + }, { + "@id" : "https://schema.org/headline" + }, { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@type" : "PUBLICATION_PUBLISHER", + "hasPUBLICATION_PUBLISHER.IDENTIFIER" : "https://www.nature.com", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24" + }, { + "@id" : "PUBLICATION_CREATOR", + "@type" : "rdfs:Class", + "rdfs:subClassOf" : { + "@id" : ":Object" + }, + "owl:equivalentClass" : [ { + "@id" : "http://datacite.org/schema/kernel-4#creator" + }, { + "@id" : "https://schema.org/author" + }, { + "@id" : "https://schema.org/creator" + } ] + }, { + "@type" : "rdfs:Property", + "@id" : "hasPUBLICATION.OPENBIS_RELATED_IDENTIFIERS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#relatedIdentifiers" + } + } ] +} \ No newline at end of file diff --git a/0.1.x/lib/java/bin/lib-ro-crate.jar b/0.1.x/lib/java/bin/lib-ro-crate.jar new file mode 100644 index 0000000..7efd1dc Binary files /dev/null and b/0.1.x/lib/java/bin/lib-ro-crate.jar differ diff --git a/0.1.x/lib/java/src/build.gradle b/0.1.x/lib/java/src/build.gradle new file mode 100644 index 0000000..7d6816f --- /dev/null +++ b/0.1.x/lib/java/src/build.gradle @@ -0,0 +1,74 @@ +plugins { + id 'java' + id 'application' +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType(JavaCompile) { + options.compilerArgs << '-parameters' +} + +repositories { + ivy { + ivyPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/ivy.xml" + artifactPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" + } + mavenCentral() +} + +//'openbis:openbis-v3-api-batteries-included:6.5.0', +//files('libs/openBIS-API-V3-batteries-included-SNAPSHOT-r1718006152.jar'), +dependencies { + implementation 'com.fasterxml.jackson.core:jackson-core' + implementation 'com.fasterxml.jackson.core:jackson-databind' + implementation 'org.slf4j:slf4j-api:2.0.16' + + implementation 'edu.kit.datamanager:ro-crate-java:2.0.1' + testImplementation 'junit:junit:4.13.1' + testImplementation('jmock:jmock:2.5.1') + +} + +configurations.configureEach { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + + // https://docs.gradle.org/current/userguide/resolution_rules.html + if (details.requested.group == 'com.fasterxml.jackson.core' && details.requested.name == 'jackson-databind') { + details.useVersion '2.18.0' + } + if (details.requested.group == 'com.fasterxml.jackson.core' && details.requested.name == 'jackson-core') { + details.useVersion '2.18.0' + } + if (details.requested.group == 'org.slf4j') { + details.useVersion '2.0.16' + } + } +} + + +tasks.register('buildRdfTool', Jar) { + dependsOn tasks.build + duplicatesStrategy 'include' + + archiveBaseName.set('lib-rdf-tool') + includeEmptyDirs = false + + manifest { + attributes( + 'Main-Class': 'ch.ethz.sis.rdf.main.RDFCommandLine' + ) + } + + from(zipTree(tasks.jar.outputs.files.singleFile)) { + include '**/*' + } + + from(configurations.runtimeClasspath.collect { zipTree(it) }) { + include '**/*' + exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/SchemaFacade.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/SchemaFacade.java new file mode 100644 index 0000000..41dbcc3 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/SchemaFacade.java @@ -0,0 +1,258 @@ +package ch.eth.sis.rocrate; + +import ch.eth.sis.rocrate.facade.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import edu.kit.datamanager.ro_crate.RoCrate; +import edu.kit.datamanager.ro_crate.entities.data.DataEntity; + +import java.io.Serializable; +import java.util.*; + +public class SchemaFacade implements ISchemaFacade +{ + + private final static String RDFS_CLASS = "rdfs:Class"; + + private final static String RDFS_PROPERTY = "rdfs:Property"; + + public static final String EQUIVALENT_CLASS = "owl:equivalentClass"; + + public static final String EQUIVALENT_CONCEPT = "owl:equivalentProperty"; + + + private Map types; + + private Map propertyTypes; + + private Map metadataEntries; + + private final RoCrate crate; + + public SchemaFacade(RoCrate crate) + { + this.crate = crate; + this.types = new LinkedHashMap<>(); + this.propertyTypes = new LinkedHashMap<>(); + this.metadataEntries = new LinkedHashMap<>(); + } + + public static SchemaFacade of(RoCrate crate) throws JsonProcessingException + { + SchemaFacade schemaFacade = new SchemaFacade(crate); + schemaFacade.parseEntities(); + return schemaFacade; + + } + + @Override + public void addType(IType rdfsClass) + { + + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + builder.addProperty("@id", rdfsClass.getId()); + builder.addProperty("@type", RDFS_CLASS); + rdfsClass.getSubClassOf().forEach(x -> builder.addIdProperty("rdfs:subClassOf", x)); + this.types.put(rdfsClass.getId(), rdfsClass); + DataEntity entity = builder.build(); + entity.addIdListProperties(EQUIVALENT_CLASS, rdfsClass.getOntologicalAnnotations()); + crate.addDataEntity(entity); + + } + + @Override + public List getTypes() + { + return this.types.values().stream().toList(); + } + + @Override + public IType getTypes(String id) + { + return this.types.get(id); + } + + @Override + public void addPropertyType(IPropertyType rdfsProperty) + { + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + + builder.setId(rdfsProperty.getId()); + builder.addProperty("@type", RDFS_PROPERTY); + + var stuff = builder.build(); + stuff.addIdListProperties("schema:rangeIncludes", + rdfsProperty.getRange()); + stuff.addIdListProperties("schema:domainIncludes", + rdfsProperty.getDomain()); + stuff.addIdListProperties(EQUIVALENT_CONCEPT, + rdfsProperty.getOntologicalAnnotations()); + crate.addDataEntity(stuff); + propertyTypes.put(rdfsProperty.getId(), rdfsProperty); + + } + + @Override + public List getPropertyTypes() + { + return propertyTypes.values().stream().toList(); + } + + @Override + public IPropertyType getPropertyType(String id) + { + return propertyTypes.get(id); + } + + @Override + public void addEntry(IMetadataEntry metaDataEntry) + { + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + builder.setId(metaDataEntry.getId()); + builder.addProperty("@type", metaDataEntry.getClassId()); + ObjectMapper objectMapper = new ObjectMapper(); + + metaDataEntry.getValues().forEach((s, o) -> { + if (o instanceof Double) + { + builder.addProperty(s, (Double) o); + } else if (o instanceof Integer) + { + builder.addProperty(s, (Integer) o); + } else if (o instanceof Boolean) + { + builder.addProperty(s, (Boolean) o); + } else if (o instanceof String) + { + builder.addProperty(s, o.toString()); + } else if (o == null) + { + builder.addProperty(s, objectMapper.nullNode()); + } + }); + DataEntity dataEntity = builder.build(); + metaDataEntry.getReferences().forEach(dataEntity::addIdListProperties); + + crate.addDataEntity(dataEntity); + + } + + @Override + public IMetadataEntry getEntry(String id) + { + return metadataEntries.get(id); + } + + @Override + public List getEntries(String rdfsClassId) + { + return metadataEntries.values().stream().toList(); + } + + private void parseEntities() throws JsonProcessingException + { + Map properties = new LinkedHashMap<>(); + Map classes = new LinkedHashMap<>(); + Map entries = new LinkedHashMap<>(); + + for (DataEntity entity : crate.getAllDataEntities()) + { + String type = entity + .getProperty("@type").asText(); + String id = + entity.getProperty("@id") + .asText(); + + switch (type) + { + case "rdfs:Class" -> + { + RdfsClass rdfsClass = new RdfsClass(); + rdfsClass.setSubClassOf(parseMultiValued(entity, "rdfs:subClassOf")); + rdfsClass.setOntologicalAnnotations( + parseMultiValued(entity, EQUIVALENT_CLASS)); + rdfsClass.setId(id); + classes.put(id, rdfsClass); + + } + case "rdfs:Property" -> + { + TypeProperty rdfsProperty = new TypeProperty(); + rdfsProperty.setId(id); + rdfsProperty.setOntologicalAnnotations( + parseMultiValued(entity, EQUIVALENT_CONCEPT)); + rdfsProperty.setRangeIncludes( + parseMultiValued(entity, "schema:rangeIncludes")); + rdfsProperty.setDomainIncludes( + parseMultiValued(entity, "schema:domainIncludes")); + properties.put(id, rdfsProperty); + + } + + } + + } + + for (var entity : crate.getAllDataEntities()) + { + String type = entity + .getProperty("@type").asText(); + String id = + entity.getProperty("@id") + .asText(); + if (!classes.containsKey(type)) + { + continue; + } + + Map entryProperties = new LinkedHashMap<>(); + MetadataEntry entry = new MetadataEntry(); + entry.setId(id); + entry.setType(type); + ObjectMapper objectMapper = new ObjectMapper(); + Map keyVals = + objectMapper.readValue(entity.getProperties().toString(), HashMap.class); + for (Map.Entry a : keyVals.entrySet()) + { + if (properties.containsKey(a.getKey())) + { + IPropertyType property = properties.get(a.getKey()); + if (property.getRange().stream().anyMatch(x -> x.equals("xsd:string"))) + { + entryProperties.put(a.getKey(), a.getValue().toString()); + } + } + } + entry.setProps(entryProperties); + entry.setReferences(new HashMap<>()); + entries.put(id, entry); + } + System.out.println("Done"); + this.types = classes; + this.propertyTypes = properties; + this.metadataEntries = entries; + + } + + private List parseMultiValued(DataEntity dataEntity, String key) + { + JsonNode node = dataEntity.getProperty(key); + if (node instanceof ObjectNode) + { + return List.of(node.get("@id").textValue()); + } + if (node instanceof ArrayNode arrayNode) + { + List accumulator = new ArrayList<>(); + arrayNode.elements().forEachRemaining( + x -> accumulator.add(x.get("@id").textValue()) + ); + return accumulator; + } + return List.of(); + + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/ReadExample.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/ReadExample.java new file mode 100644 index 0000000..3e70a2c --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/ReadExample.java @@ -0,0 +1,31 @@ +package ch.eth.sis.rocrate.example; + +import ch.eth.sis.rocrate.SchemaFacade; +import com.fasterxml.jackson.core.JsonProcessingException; +import edu.kit.datamanager.ro_crate.RoCrate; +import edu.kit.datamanager.ro_crate.reader.FolderReader; +import edu.kit.datamanager.ro_crate.reader.RoCrateReader; + +public class ReadExample +{ + + public static void main(String[] args) throws JsonProcessingException + { + String path = args.length >= 1 ? args[0] : "out"; + RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader()); + RoCrate crate = roCrateFolderReader.readCrate(path); + SchemaFacade schemaFacade = SchemaFacade.of(crate); + schemaFacade.getTypes().forEach( + x -> System.out.println("RDFS Class " + x.getId()) + ); + schemaFacade.getPropertyTypes().forEach( + x -> System.out.println("RDFS Property " + x.getId()) + ); + schemaFacade.getEntries(schemaFacade.getTypes().get(0).getId()).forEach( + x -> System.out.println("Metadata entry " + x.getId()) + ); + + } + + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/WriteExample.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/WriteExample.java new file mode 100644 index 0000000..880affd --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/example/WriteExample.java @@ -0,0 +1,58 @@ +package ch.eth.sis.rocrate.example; + +import ch.eth.sis.rocrate.SchemaFacade; +import ch.eth.sis.rocrate.facade.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import edu.kit.datamanager.ro_crate.RoCrate; +import edu.kit.datamanager.ro_crate.writer.FolderWriter; + +import java.util.List; +import java.util.Map; + +public class WriteExample +{ + public static void main(String[] args) throws JsonProcessingException + { + RoCrate.RoCrateBuilder roCrateBuilder = + new RoCrate.RoCrateBuilder("name", "description", "2024-12-04T07:53:11Z", + "licenseIdentifier"); + ISchemaFacade schemaFacade = SchemaFacade.of(roCrateBuilder.build()); + + { + RdfsClass rdfsClass = new RdfsClass(); + rdfsClass.setId("TextResource"); + rdfsClass.setSubClassOf(List.of("https://schema.org/Thing")); + rdfsClass.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/dcmitype/Text/")); + schemaFacade.addType(rdfsClass); + + TypeProperty property = new TypeProperty(); + property.setId("hasDateSubmitted"); + property.setTypes(List.of(LiteralType.DATETIME)); + rdfsClass.addProperty(property); + + + property.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/terms/dateSubmitted/")); + schemaFacade.addPropertyType(property); + + } + { + IMetadataEntry metadataEntry = new MetadataEntry("TextResource1", "TextResource", + Map.of("hasDate", "2025-01-21T07:12:20Z"), Map.of()); + schemaFacade.addEntry(metadataEntry); + + } + + String path = args.length >= 1 ? args[0] : "out"; + + + + roCrateBuilder.build(); + + FolderWriter folderWriter = new FolderWriter(); + folderWriter.save(roCrateBuilder.build(), path); + + } + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IDataType.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IDataType.java new file mode 100644 index 0000000..6c9eb38 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IDataType.java @@ -0,0 +1,21 @@ +package ch.eth.sis.rocrate.facade; + +public interface IDataType +{ + String getTypeName(); + + static IDataType getArray(LiteralType literalType) + { //TODO static IDataType getArray(LiteralType literalType) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } + + static IDataType getEnumerationf(String... values) + { //TODO static IDataType getEnumerationf(String... values) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } + + static IDataType getCustomType(LiteralType basicType, String pattern) + { //TODO static IDataType getCustomType(LiteralType basicType, String pattern) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IMetadataEntry.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IMetadataEntry.java new file mode 100644 index 0000000..2bc4ff2 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IMetadataEntry.java @@ -0,0 +1,29 @@ +package ch.eth.sis.rocrate.facade; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public interface IMetadataEntry +{ + + /** + * Returns the ID of this entry + */ + String getId(); + + /* Returns the type ID of this entry */ + String getClassId(); + + /* Returns the type of the entry */ + String getType(); + + /* These are key-value pairs for serialization. These are single-valued. + * Serializable classes are: String, Number and Boolean */ + Map getValues(); + + /* These are references to other objects in the graph. + * Each key may have one or more references */ + Map> getReferences(); + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IPropertyType.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IPropertyType.java new file mode 100644 index 0000000..6c7eec1 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IPropertyType.java @@ -0,0 +1,19 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.List; + +public interface IPropertyType +{ + /* Returns the ID of this property type */ + String getId(); + + /* Return possible values for the subject of this property type */ + List getDomain(); + + /* Return possible values for the object of this property type */ + List getRange(); + + /* Returns the ontological annotations of this property type */ + List getOntologicalAnnotations(); + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/ISchemaFacade.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/ISchemaFacade.java new file mode 100644 index 0000000..2c6b8b9 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/ISchemaFacade.java @@ -0,0 +1,35 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.List; + +public interface ISchemaFacade +{ + + /* Adds a single class */ + void addType(IType rdfsClass); + + /** Retrieves all Classes */ + List getTypes(); + + /* Get a single type by its ID */ + IType getTypes(String id); + + /* Adds a single property */ + void addPropertyType(IPropertyType property); + + /* Get all Properties */ + List getPropertyTypes(); + + /* Gets a single property by its ID. */ + IPropertyType getPropertyType(String id); + + /* Add a single metadata entry */ + void addEntry(IMetadataEntry entry); + + /* Get a single metadata entry by its ID */ + IMetadataEntry getEntry(String id); + + /* Get all metadata entities */ + List getEntries(String rdfsClassId); + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IType.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IType.java new file mode 100644 index 0000000..f1d3c01 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/IType.java @@ -0,0 +1,18 @@ +package ch.eth.sis.rocrate.facade; + + +import java.util.List; + +public interface IType +{ + /* Returns the ID of this type */ + String getId(); + + /* Returns IDs of the types this type inherits from */ + List getSubClassOf(); + + /* Returns the ontological annotations of this type */ + List getOntologicalAnnotations(); + + +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/LiteralType.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/LiteralType.java new file mode 100644 index 0000000..99a5174 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/LiteralType.java @@ -0,0 +1,32 @@ +package ch.eth.sis.rocrate.facade; + +/** + * List of primitives as supported by xsd + * https://www.ibm.com/docs/en/jfsm/1.1.2.1?topic=queries-xsd-data-types + */ +public enum LiteralType implements IDataType +{ + + BOOLEAN("xsd:boolean"), + INTEGER("xsd:integer"), + DOUBLE("xsd:double"), + + DECIMAL("xsd:decimal"), + FLOAT("xsd:float"), + DATETIME("xsd:dateTime"), + STRING("xsd:string"), + XML_LITERAL("rdf:XMLLiteral"); + + final String typeName; + + LiteralType(String typeName) + { + this.typeName = typeName; + } + + @Override + public String getTypeName() + { + return typeName; + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/MetadataEntry.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/MetadataEntry.java new file mode 100644 index 0000000..bba81cf --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/MetadataEntry.java @@ -0,0 +1,103 @@ +package ch.eth.sis.rocrate.facade; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MetadataEntry implements IMetadataEntry +{ + String id; + + String type; + + Map props; + + Map> references; + + List childrenIdentifiers = new ArrayList<>(); + + List parentIdentifiers = new ArrayList<>(); + + public MetadataEntry() + { + } + + public MetadataEntry(String id, String type, Map props, + Map> references) + { + this.id = id; + this.type = type; + this.props = props; + this.references = references; + } + + public String getId() + { + return id; + } + + @Override + public String getClassId() + { + return type; + } + + @Override + public Map getValues() + { + return props; + } + + @Override + public Map> getReferences() + { + return references; + } + + public void setId(String id) + { + this.id = id; + } + + @Override + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public void addChildIdentifier(String a) + { + childrenIdentifiers.add(a); + } + + public void addParentIdentifier(String a) + { + parentIdentifiers.add(a); + } + + public List getChildrenIdentifiers() + { + return childrenIdentifiers; + } + + public List getParentIdentifiers() + { + return parentIdentifiers; + } + + public void setProps(Map props) + { + this.props = props; + } + + public void setReferences(Map> references) + { + this.references = references; + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/RdfsClass.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/RdfsClass.java new file mode 100644 index 0000000..cc50d79 --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/RdfsClass.java @@ -0,0 +1,86 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.ArrayList; +import java.util.List; + +public class RdfsClass implements IType +{ + String id; + + String type; + + List subClassOf; + + List ontologicalAnnotations; + + List rdfsProperties; + + public RdfsClass() + { + this.subClassOf = new ArrayList<>(); + this.ontologicalAnnotations = new ArrayList<>(); + this.rdfsProperties = new ArrayList<>(); + + } + + public String getId() + { + return id; + } + + @Override + public List getSubClassOf() + { + return subClassOf; + } + + @Override + public List getOntologicalAnnotations() + { + return ontologicalAnnotations; + } + + /** + * This is a convenience method for adding a property to a class. + * + */ + public void addProperty(TypeProperty rdfsProperty) + { + List domainIncludes = rdfsProperty.getDomainIncludes(); + if (domainIncludes == null) + { + domainIncludes = new ArrayList<>(); + rdfsProperty.setDomainIncludes(domainIncludes); + } + if (id == null) + { + throw new IllegalArgumentException("Class id is null"); + } + domainIncludes.add(id); + } + + public void setId(String id) + { + this.id = id; + } + + public String getType() + { + return "rdfs:Class"; + } + + public void setType(String type) + { + this.type = type; + } + + public void setSubClassOf(List subClassOf) + { + this.subClassOf = subClassOf; + } + + public void setOntologicalAnnotations(List ontologicalAnnotations) + { + this.ontologicalAnnotations = ontologicalAnnotations; + } +} diff --git a/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/TypeProperty.java b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/TypeProperty.java new file mode 100644 index 0000000..98ddb0f --- /dev/null +++ b/0.1.x/lib/java/src/java/ch/eth/sis/rocrate/facade/TypeProperty.java @@ -0,0 +1,81 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.ArrayList; +import java.util.List; + +public class TypeProperty implements IPropertyType +{ + List domainIncludes; + + List rangeIncludes; + + String id; + + List ontologicalAnnotations = new ArrayList<>(); + + public List getDomainIncludes() + { + return domainIncludes; + } + + public void setDomainIncludes(List domainIncludes) + { + this.domainIncludes = domainIncludes; + } + + public void setRangeIncludes(List rangeIncludes) + { + this.rangeIncludes = rangeIncludes; + } + + public String getId() + { + return id; + } + + @Override + public List getDomain() + { + return getDomainIncludes(); + } + + @Override + public List getRange() + { + return rangeIncludes; + } + + @Override + public List getOntologicalAnnotations() + { + return ontologicalAnnotations; + } + + public void setId(String id) + { + this.id = id; + } + + public void setOntologicalAnnotations(List ontologicalAnnotations) + { + this.ontologicalAnnotations = ontologicalAnnotations; + } + + public void setTypes(List types) + { + this.rangeIncludes = new ArrayList<>(types.stream().map(IDataType::getTypeName).toList()); + } + + public void addType(IDataType type) + { + if (this.rangeIncludes == null) + { + this.rangeIncludes = new ArrayList<>(); + } + if (!this.rangeIncludes.contains(type.getTypeName())) + { + this.rangeIncludes.add(type.getTypeName()); + } + + } +} diff --git a/0.1.x/spec.md b/0.1.x/spec.md new file mode 100644 index 0000000..6dcf541 --- /dev/null +++ b/0.1.x/spec.md @@ -0,0 +1,300 @@ +# Profile/Module - RO-Crate Convention to Include Schema and Metadata + +**Index:** + +- [Version](#version) +- [Definitions](#definitions) +- [Goals](#goals) +- [Technologies and Usage](#technologies-and-usage) + - [Schema Representation](#schema-representation) + - [RDFS Class](#rdfs-class) + - [RDFS Property](#rdfs-class) + - [Metadata Representation](#metadata-representation) + - [RDF Metadata Entry](#rdf-metadata-entry) +- [Reference Examples](#reference-examples-for-both-schema-and-entries) +- [API](#api) + - [Schema Representation DTOs](#schema-representation-dtos) + - [Metadata Representation DTOs](#metadata-representation-dtos) + - [Additional RO-Crate API Methods](#additional-ro-crate-api-methods) +- [API Reference Implementation in Java](#api-reference-implementation-in-java) +- [API Reference Examples in Java](#api-reference-examples-in-java) +- [Ongoing Work](#ongoing-work) +- [Possible Future Directions](#possible-future-directions) +- [People](#people) + +# Version + +0.1.0, initial version, compatible with RO-Crate 1.1 + + +# Definitions + +We use the following definitions in our proposal. + +- Schema: A logical design that defines the structure, organization and relationship between data. +- Metadata: data of a database adhering to the schema. +- Ontology: A set of concepts and the relationships between these concepts. + +# Goals + +This proposal SHOULD allow the means to exchange a database schema and database contents in a +standardized way. + +As consequence, Integrations SHOULD NOT need to parse individual files in non-standardized formats +anymore to obtain such information but MAY use the Ro-Crate API for such purpose. + +Since the goal is that multiple established systems can adhere to it, this poses the +additional problem that are multiple schemas in use for similar concepts. +To address this, we propose a way to annotate our schemas with ontological information. +The ontologies allow identification of shared concepts. +Knowing which concepts are shared allows easier integration for different schemas. + +Establishing such a format for interoperability would also benefit independent interoperability +efforts, as they would be available for reuse in other interoperability projects. + +This specification is made to be usable in Ro-Crate 1.1, as such: +- It SHOULD NOT add new keywords. +- It SHOULD establish a convention that can be used by the RO-Crate API to read/write the information. + +# Technologies and Usage + +- [RDF](https://www.w3.org/RDF/): Resource Description Framework is a specification developed by the + World Wide Web + Consortium (W3C) to provide a framework for representing and exchanging data on the web in a + structured way. RDF allows information to be described in terms of subject-predicate-object + triples, which form a graph of interconnected data. RDF can be serialized in different formats, + including JSON-LD as used by RO-Crate. +- [RDFS](https://www.w3.org/TR/rdf-schema/): Resource Description Framework Schema is a + specification developed by the World Wide Web Consortium (W3C) that extends RDF (Resource + Description Framework). RDFS provides a way to define the structure and relationships of RDF data, + allowing for the creation of vocabularies and the specification of classes, properties, and + hierarchies in an RDF dataset. +- [OWL](https://www.w3.org/OWL/): Web Ontology Language is a formal language used to define and + represent ontologies on the web. +- [XSD](https://www.w3.org/TR/xmlschema11-1/): XML Schema Definition is a language used to define + the structure, content, and constraints of XML documents. It will be used in this specification to + express primitive type. + +## Schema Representation +Because the schema is graph-based this can be easily integrated into the RO-Crate graph. + +The schema could also be included in a separate file in a future version of this specification. + +Ontologies are added using OWL's `equivalentClass` and `equivalentProperty` properties. + +What are the advantages of this? + +- the format is backward compatible +- this only uses features that RO-Crate already provides, no additional keywords are required +- Common format for export that prevents `n * (n - 1)` integration situation +- Thorough description of metadata, better automated checking and read-in + +**Formal description:** + +RO-Crate MUST include a graph description of the schema. +This is expressed using 2 types: + +- RDFS Class +- RDFS Property + +### RDFS Class + +Based on RDFS classes, these can be used as object and subjects of triples. + +| Type/Property | Required? | Description | +|---------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Is `rdfs:Class` | +| owl:equivalentClass | MAY | Ontological annotation https://www.w3.org/TR/owl-ref/#equivalentClass-def | +| rdfs:subClassOf | MUST | Used to indicate inheritance. Each entry has to inherit from something, this can be a base type. https://www.w3.org/TR/rdf-schema/#ch_subclassof | + +### RDFS Property + +RDFS Properties, these represent predicates in triples. +They also specify, which classes they can interact with. + +| Type/Property | Required? | Description | +|------------------------|-----------|----------------------------------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Is `rdfs:Property` | +| owl:equivalentProperty | MAY | Ontological annotation https://www.w3.org/TR/owl-ref/#equivalentClass-def | +| schema:domainIncludes | MUST | Describes the possible types of the subject. This can be one or many. | +| schema:rangeIncludes | MUST | Describes the possible types of the object. This can be one or many. | + +## Metadata Representation + +**Formal description:** + +RO-Crate MUST include a graph description of the metadata entries. +This is expressed using 1 type: + +- Metadata Entry + +### RDF Metadata Entry + +A metadata entry, described by a RDFS class. + +| Type/Property | Required? | Description | +|---------------|-----------|-----------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Type of the entry, MUST be a RDFS Class | + +Further properties are included as specified in the RDFS description as fields. + +# Reference Examples for both Schema and Entries + +We created a small example. It can be found under: +`./examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json.` +This describes the export +of `./examples/reference-openbis-export`. + +# API + +**Formal description:** + +To be general, the API uses a lot of strings. This allows flexibility in the classes being used. + +The interfaces are shown using Java since is a statically typed language, but they can be +implemented in most languages, +including Python and Javascript. + +## Schema Representation DTOs + +```Java + +/* Represents a class, if we are talking about a schema, it is closely related with the definition of a table or type */ +interface IType +{ + + /* Returns the ID of this type */ + String getId(); + + /* Returns IDs of the types this type inherits from */ + List getSubClassOf(); + + /* Returns the ontological annotations of this type */ + List getOntologicalAnnotations(); + +} + +/* Represents a property in a graph, if we are talking about a schema, is closely related with a table column or type property */ +interface IPropertyType +{ + + /* Returns the ID of this property type */ + String getId(); + + /* Return possible values for the subject of this property type */ + List getDomain(); + + /* Return possible values for the object of this property type */ + List getRange(); + + /* Returns the ontological annotations of this property type */ + List getOntologicalAnnotations(); + + } +``` + +## Metadata Representation DTOs + +```Java +/* Represents a metadata entity. It is described */ +interface IMetadataEntry +{ + + + /** + * Returns the ID of this entry + */ + String getId(); + + /* Returns the type ID of this entry */ + String getClassId(); + + /* These are key-value pairs for serialization. These are single-valued. + * Serializable classes are: String, Number and Boolean */ + Map getValues(); + + /* These are references to other objects in the graph. + * Each key may have one or more references */ + Map> getReferences(); +} +``` + +## Additional RO-Crate API Methods + + +```Java +/* The API to program against, this wraps around existing RO-Crate APIs. */ +interface ISchemaFacade +{ + + /* Adds a single class */ + void addType(IType rdfsClass); + + /** Retrieves all Classes */ + List getTypes(); + + /* Get a single type by its ID */ + IType getTypes(String id); + + /* Adds a single property */ + void addPropertyType(IPropertyType property); + + /* Get all Properties */ + List getPropertyTypes(); + + /* Gets a single property by its ID. */ + IPropertyType getPropertyType(String id); + + /* Add a single metadata entry */ + void addEntry(IMetadataEntry entry); + + /* Get a single metadata entry by its ID */ + IMetadataEntry getEntry(String id); + + /* Get all metadata entities */ + List getEntries(String rdfsClassId); + +} +``` + +# API Reference Implementation in Java + +A working implementation of the API for Java (source and compiled) can be found +under: `./lib/src`. + +A compiled jar can be found under: `./lib/java/bin`. +The dependencies are specified in the module's `build.gradle` +file: `./lib/java/src/build.gradle`. + +# API Reference Examples in Java + +Working examples of the API in java to read and write can be found +at: `./`, specifically the class +files + +- `./lib/java/src/java/ch/eth/sis/rocrate/example/ReadExample.java` +- `./lib/java/src/java/ch/eth/sis/rocrate/example/WriteExample.java` + +# Ongoing Work + +- Adding complex data types +- Using `rdfs:Label` to indicate the original name of a property (this could also help in resolving + properties with the same name) +- Validation of data types expressed in the schema, e.g. enforcing ISO 8601 for dates +- Bundling ontologies in the RO-Crate +- Find a way of specifying other data formats + +# Possible Future Directions + +- We would like to store the schema and metadata information in separate files and indicate the + format of the file in `ro-crate-metadata.json` +- Other serialization formats could be supported when using separate files +- Adding methods for deleting to facade to have all CRUD operations + +# People + +- Andreas Meier (andreas.meier@ethz.ch) +- Juan Fuentes (juan.fuentes@id.ethz.ch) diff --git a/0.2.x/examples/reference-openbis-export/metadata.xlsx b/0.2.x/examples/reference-openbis-export/metadata.xlsx new file mode 100644 index 0000000..f4fbf4d Binary files /dev/null and b/0.2.x/examples/reference-openbis-export/metadata.xlsx differ diff --git a/0.2.x/examples/ro-crate-1.1/dist/rocrate.zip b/0.2.x/examples/ro-crate-1.1/dist/rocrate.zip new file mode 100644 index 0000000..498d3c9 Binary files /dev/null and b/0.2.x/examples/ro-crate-1.1/dist/rocrate.zip differ diff --git a/0.2.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json b/0.2.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json new file mode 100644 index 0000000..610dc23 --- /dev/null +++ b/0.2.x/examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json @@ -0,0 +1,1218 @@ +{ + "@context" : [ "https://w3id.org/ro/crate/1.1/context", { + "schema" : "https://www.w3.org/TR/rdf-schema", + "owl" : "https://www.w3.org/TR/owl-ref", + "openBIS" : "_:" + } ], + "@graph" : [ { + "name" : "name", + "description" : "description", + "@id" : "./", + "@type" : "Dataset", + "license" : { + "@id" : "licenseIdentifier" + }, + "datePublished" : "2024-12-04T07:53:11Z", + "hasPart" : [ { + "@id" : "fdf9de4a-9233-4f9a-beee-b16c85ac7899" + }, { + "@id" : "7c6a44df-1a55-4476-b853-198d12402059" + }, { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "77d6d4d6-b90c-4545-952f-8b42426dc04b" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "79b88764-999f-47b8-9989-b88f82cc2e9b" + }, { + "@id" : "openBIS:hasPUBLICATION.STATUS" + }, { + "@id" : "788899b6-1365-46eb-9539-3c084011fa1b" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27" + }, { + "@id" : "openBIS:hasPUBLICATION.CREATOR" + }, { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME" + }, { + "@id" : "9a9c4a68-31ae-4e4b-bb5c-9743e40d0fa8" + }, { + "@id" : "PUBLICATIONS" + }, { + "@id" : "7b5e347f-e111-44aa-a9ce-9fc2faa567d9" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB29" + }, { + "@id" : "openBIS:hasDEFAULT_OBJECT_TYPE" + }, { + "@id" : "openBIS:hasCOLLECTION" + }, { + "@id" : ":Object" + }, { + "@id" : ":Vocabulary" + }, { + "@id" : "af9516ee-5a24-42de-acfc-19513b12930a" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, { + "@id" : ":Dataset" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB25" + }, { + "@id" : ":Collection" + }, { + "@id" : "openBIS:hasDEFAULT_COLLECTION_VIEW" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" + }, { + "@id" : "c163d26d-9c5f-4afe-944b-361f27bef535" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME" + }, { + "@id" : "openBIS:hasSPACE" + }, { + "@id" : ":Project" + }, { + "@id" : "PUBLICATION_PUBLISHER" + }, { + "@id" : "openBIS:hasPUBLICATION.ORGANIZATION" + }, { + "@id" : "openBIS:Collection" + }, { + "@id" : "83be7d34-91ac-4d08-9cd5-4f9cb758a967" + }, { + "@id" : "77a00451-b1af-4994-9a65-ecf3cc791e3b" + }, { + "@id" : "261b1281-1f90-4202-b725-a1c6ed1eca87" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.FULL_NAME" + }, { + "@id" : "35db541a-c52c-49f0-bd46-9a8f60b4a537" + }, { + "@id" : "openBIS:hasPUBLICATION.DESCRIPTION" + }, { + "@id" : "fde51c61-c5c6-4097-89c9-d1acfbf9e417" + }, { + "@id" : "openBIS:hasPUBLICATION.TYPE" + }, { + "@id" : "146a6aba-10bd-49f4-a51c-6c450cb60d91" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, { + "@id" : "019e020d-03c0-4eea-ad11-3a698e486ebe" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME_URI" + }, { + "@id" : "9c2fedaf-6216-4fd3-8668-d075aa3466b6" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME" + }, { + "@id" : "openBIS:hasPUBLICATION.PUBLICATION_YEAR" + }, { + "@id" : ":Space" + }, { + "@id" : "openBIS:hasPUBLICATION.ABSTRACT" + }, { + "@id" : "openBIS:hasPUBLICATION.PUBLISHER" + }, { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER" + }, { + "@id" : "openBIS:hasNAME" + }, { + "@id" : "openBIS:hasPUBLICATION.CONTRIBUTOR" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION" + }, { + "@id" : "8483940c-966c-4269-a521-7adb0a62cc43" + }, { + "@id" : "openBIS:Space" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, { + "@id" : "7f7e5302-0cc0-4e6e-b9bd-bf266527800b" + }, { + "@id" : "275097ea-cd84-496e-ac1a-22581d432ab1" + }, { + "@id" : "bc8c9b69-4c1a-4cfa-91f8-c806a6d910f7" + }, { + "@id" : "58f40086-3cde-463f-8957-d59a5069bbfd" + }, { + "@id" : "openBIS:hasPUBLICATION.DATASETS" + }, { + "@id" : "00d262cf-ead1-4264-8b0b-475cdd2b42c2" + }, { + "@id" : "b1d4ba2e-de11-4ad1-aed1-c0e8c8bbac36" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" + }, { + "@id" : "89f64955-375a-4978-8eda-a1c0d03fe7ac" + }, { + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER" + }, { + "@id" : "66b2dfc2-3ea1-4d85-91a7-f6e2a3690980" + }, { + "@id" : "c5184a73-c6db-4b38-8b88-21ce9d3a1d95" + }, { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME_URI" + }, { + "@id" : "2b7168ea-1595-438c-b4f7-28fa042e5257" + }, { + "@id" : "openBIS:hasPUBLICATION.URL" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24" + }, { + "@id" : "openBIS:hasPUBLICATION.IDENTIFIER" + }, { + "@id" : "openBIS:hasPUBLICATION.OPENBIS_RELATED_IDENTIFIERS" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22" + }, { + "@id" : "openBIS:Project" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23" + }, { + "@id" : "00c7421f-c174-4f52-a8d0-151a9f1a727a" + }, { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB30" + }, { + "@id" : "c05e0978-cc96-40b1-8453-a02e6e70b83b" + }, { + "@id" : "75d20b19-8020-4728-bc16-f3700f9377e2" + }, { + "@id" : "openBIS:hasXMLCOMMENTS" + } ] + }, { + "about" : { + "@id" : "./" + }, + "conformsTo" : { + "@id" : "https://w3id.org/ro/crate/1.1" + }, + "@id" : "ro-crate-metadata.json", + "@type" : "CreativeWork" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Affilition", + "rdfs:comment" : "Affiliation Identifier", + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : { + "@id" : "https://schema.org/affiliation" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Comments", + "rdfs:comment" : "Comments log", + "@id" : "openBIS:hasXMLCOMMENTS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + } + }, { + "@id" : "PUBLICATION_PUBLISHER", + "@type" : "rdfs:Class", + "owl:restriction" : [ { + "@id" : "af9516ee-5a24-42de-acfc-19513b12930a" + }, { + "@id" : "c163d26d-9c5f-4afe-944b-361f27bef535" + }, { + "@id" : "b1d4ba2e-de11-4ad1-aed1-c0e8c8bbac36" + }, { + "@id" : "7b5e347f-e111-44aa-a9ce-9fc2faa567d9" + } ], + "rdfs:subClassOf" : { + "@id" : ":Object" + }, + "owl:equivalentClass" : { + "@id" : "https://schema.org/publisher" + } + }, { + "@id" : "c05e0978-cc96-40b1-8453-a02e6e70b83b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.DATASETS" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@id" : ":Dataset", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Description", + "rdfs:comment" : "Description", + "@id" : "openBIS:hasPUBLICATION.DESCRIPTION", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#descriptions" + }, { + "@id" : "https://schema.org/description" + }, { + "@id" : "https://schema.org/abstract" + } ] + }, { + "@id" : "9c2fedaf-6216-4fd3-8668-d075aa3466b6", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.ABSTRACT" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@id" : "c163d26d-9c5f-4afe-944b-361f27bef535", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER" : "https://orcid.org/0000-0002-2423-3090", + "openBIS:hasPUBLICATION_CREATOR.FULL_NAME" : "Erola Pairo-Castineira", + "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" : "Roslin Institute, University of Edinburgh, Edinburgh, UK", + "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME" : "Pairo-Castineira", + "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME" : "Castineira", + "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" : "https://orcid.org/", + "openBIS:hasNAME" : "Erola Pairo-Castineira", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, + "@type" : "PUBLICATION_CREATOR" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Publisher", + "rdfs:comment" : "Publisher", + "@id" : "openBIS:hasPUBLICATION.PUBLISHER", + "schema:rangeIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publisher" + }, { + "@id" : "https://schema.org/publisher" + } ] + }, { + "@id" : "b1d4ba2e-de11-4ad1-aed1-c0e8c8bbac36", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasNAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : ":Collection", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "openBIS Related Identifiers", + "rdfs:comment" : "openBIS Related Identifiers", + "@id" : "openBIS:hasPUBLICATION.OPENBIS_RELATED_IDENTIFIERS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#relatedIdentifiers" + } + }, { + "@id" : "75d20b19-8020-4728-bc16-f3700f9377e2", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME_URI" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "66b2dfc2-3ea1-4d85-91a7-f6e2a3690980", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasDEFAULT_OBJECT_TYPE" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "openBIS:Collection", + "@type" : "rdfs:Class" + }, { + "@id" : ":Space", + "@type" : "rdfs:Class" + }, { + "@id" : ":Vocabulary", + "@type" : "rdfs:Class" + }, { + "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER" : "https://www.nature.com", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION" + }, + "@type" : "PUBLICATION_PUBLISHER" + }, { + "openBIS:hasDEFAULT_OBJECT_TYPE" : "PUBLICATION_CREATOR", + "openBIS:hasNAME" : "Publications creator collection", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION", + "@type" : "COLLECTION" + }, { + "@id" : "77a00451-b1af-4994-9a65-ecf3cc791e3b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasDEFAULT_OBJECT_TYPE" : "PUBLICATION", + "openBIS:hasNAME" : "Publications Collection", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION", + "@type" : "COLLECTION" + }, { + "@id" : "openBIS:Project", + "@type" : "rdfs:Class" + }, { + "@id" : "00d262cf-ead1-4264-8b0b-475cdd2b42c2", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.OPENBIS_RELATED_IDENTIFIERS" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Identifier Scheme", + "rdfs:comment" : "Identifier Scheme", + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#publisherIdentifierScheme" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Full name", + "rdfs:comment" : "FullName", + "@id" : "openBIS:hasPUBLICATION_CREATOR.FULL_NAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : { + "@id" : "https://schema.org/name" + } + }, { + "@id" : "89f64955-375a-4978-8eda-a1c0d03fe7ac", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.CONTRIBUTOR" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "261b1281-1f90-4202-b725-a1c6ed1eca87", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Publication Year", + "rdfs:comment" : "Publication Year", + "@id" : "openBIS:hasPUBLICATION.PUBLICATION_YEAR", + "schema:rangeIncludes" : { + "@id" : "xsd:dateTime" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publicationYear" + }, { + "@id" : "https://schema.org/datePublished" + } ] + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Affiliation Identifier Scheme URI", + "rdfs:comment" : "Affiliation Identifier Scheme URI", + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME_URI", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Datasets", + "rdfs:comment" : "Datasets", + "@id" : "openBIS:hasPUBLICATION.DATASETS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : { + "@id" : "https://schema.org/hasPart" + } + }, { + "@type" : "rdfs:Property", + "@id" : "openBIS:hasSPACE", + "schema:rangeIncludes" : { + "@id" : "openBIS:Space" + }, + "schema:domainIncludes" : [ { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "PUBLICATION_PUBLISHER" + } ] + }, { + "@id" : "146a6aba-10bd-49f4-a51c-6c450cb60d91", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.URL" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER" : "Science", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION" + }, + "@type" : "PUBLICATION_PUBLISHER" + }, { + "@id" : ":Object", + "@type" : "rdfs:Class" + }, { + "@id" : "COLLECTION", + "@type" : "rdfs:Class", + "owl:restriction" : [ { + "@id" : "66b2dfc2-3ea1-4d85-91a7-f6e2a3690980" + }, { + "@id" : "9a9c4a68-31ae-4e4b-bb5c-9743e40d0fa8" + }, { + "@id" : "bc8c9b69-4c1a-4cfa-91f8-c806a6d910f7" + } ], + "rdfs:subClassOf" : { + "@id" : ":Collection" + } + }, { + "@id" : "77d6d4d6-b90c-4545-952f-8b42426dc04b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.PUBLISHER" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@id" : "788899b6-1365-46eb-9539-3c084011fa1b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Default collection view", + "rdfs:comment" : "Default view for experiments of the type collection", + "@id" : "openBIS:hasDEFAULT_COLLECTION_VIEW", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "COLLECTION" + } + }, { + "@id" : "af9516ee-5a24-42de-acfc-19513b12930a", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "description" : "Public Repositories", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES", + "@type" : "openBIS:Project" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Type", + "rdfs:comment" : "Type", + "@id" : "openBIS:hasPUBLICATION.TYPE", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Identifier Scheme URI", + "rdfs:comment" : "Identifier Scheme URI", + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME_URI", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : { + "@id" : "http://datacite.org/schema/kernel-4#schemeURI" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Family Name", + "rdfs:comment" : "Family Name", + "@id" : "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#familyName" + }, { + "@id" : "https://schema.org/familyName" + } ] + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Publisher Identifier", + "rdfs:comment" : "Publisher Identifier", + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_PUBLISHER" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#publisherIdentifier" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@id" : "275097ea-cd84-496e-ac1a-22581d432ab1", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.DESCRIPTION" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : ":Project", + "@type" : "rdfs:Class" + }, { + "@id" : "PUBLICATIONS", + "@type" : "openBIS:Space" + }, { + "@id" : "PUBLICATION_CREATOR", + "@type" : "rdfs:Class", + "owl:restriction" : [ { + "@id" : "75d20b19-8020-4728-bc16-f3700f9377e2" + }, { + "@id" : "77a00451-b1af-4994-9a65-ecf3cc791e3b" + }, { + "@id" : "019e020d-03c0-4eea-ad11-3a698e486ebe" + }, { + "@id" : "79b88764-999f-47b8-9989-b88f82cc2e9b" + }, { + "@id" : "788899b6-1365-46eb-9539-3c084011fa1b" + }, { + "@id" : "fde51c61-c5c6-4097-89c9-d1acfbf9e417" + }, { + "@id" : "83be7d34-91ac-4d08-9cd5-4f9cb758a967" + }, { + "@id" : "261b1281-1f90-4202-b725-a1c6ed1eca87" + }, { + "@id" : "35db541a-c52c-49f0-bd46-9a8f60b4a537" + } ], + "rdfs:subClassOf" : { + "@id" : ":Object" + }, + "owl:equivalentClass" : [ { + "@id" : "http://datacite.org/schema/kernel-4#creator" + }, { + "@id" : "https://schema.org/author" + }, { + "@id" : "https://schema.org/creator" + } ] + }, { + "@id" : "PUBLICATION", + "@type" : "rdfs:Class", + "owl:restriction" : [ { + "@id" : "275097ea-cd84-496e-ac1a-22581d432ab1" + }, { + "@id" : "c5184a73-c6db-4b38-8b88-21ce9d3a1d95" + }, { + "@id" : "00c7421f-c174-4f52-a8d0-151a9f1a727a" + }, { + "@id" : "8483940c-966c-4269-a521-7adb0a62cc43" + }, { + "@id" : "fdf9de4a-9233-4f9a-beee-b16c85ac7899" + }, { + "@id" : "9c2fedaf-6216-4fd3-8668-d075aa3466b6" + }, { + "@id" : "77d6d4d6-b90c-4545-952f-8b42426dc04b" + }, { + "@id" : "2b7168ea-1595-438c-b4f7-28fa042e5257" + }, { + "@id" : "89f64955-375a-4978-8eda-a1c0d03fe7ac" + }, { + "@id" : "c05e0978-cc96-40b1-8453-a02e6e70b83b" + }, { + "@id" : "58f40086-3cde-463f-8957-d59a5069bbfd" + }, { + "@id" : "146a6aba-10bd-49f4-a51c-6c450cb60d91" + }, { + "@id" : "7c6a44df-1a55-4476-b853-198d12402059" + }, { + "@id" : "00d262cf-ead1-4264-8b0b-475cdd2b42c2" + }, { + "@id" : "7f7e5302-0cc0-4e6e-b9bd-bf266527800b" + } ], + "rdfs:subClassOf" : { + "@id" : ":Object" + }, + "owl:equivalentClass" : { + "@id" : "https://schema.org/creativeWork" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Publication Identifier", + "rdfs:comment" : "Publication Identifier", + "@id" : "openBIS:hasPUBLICATION.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#doi" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@id" : "7f7e5302-0cc0-4e6e-b9bd-bf266527800b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasXMLCOMMENTS" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "c5184a73-c6db-4b38-8b88-21ce9d3a1d95", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.TYPE" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Organization", + "rdfs:comment" : "Organization", + "@id" : "openBIS:hasPUBLICATION.ORGANIZATION", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : { + "@id" : "http://schema.org/Organization" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Abstract", + "rdfs:comment" : "Abstract", + "@id" : "openBIS:hasPUBLICATION.ABSTRACT", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : { + "@id" : "https://schema.org/datePublished" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Identifier Scheme", + "rdfs:comment" : "Identifier", + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Creators", + "rdfs:comment" : "Creators", + "@id" : "openBIS:hasPUBLICATION.CREATOR", + "schema:rangeIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#creator" + }, { + "@id" : "https://schema.org/author" + }, { + "@id" : "https://schema.org/creator" + } ] + }, { + "openBIS:hasPUBLICATION.STATUS" : "Registered", + "openBIS:hasPUBLICATION.URL" : "https://www.nature.com/articles/s41586-020-3010-5#citeas", + "openBIS:hasNAME" : "Global human-made mass exceeds all living biomass", + "openBIS:hasPUBLICATION.TYPE" : "DataPaper", + "openBIS:hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-09 15:43:20 +0100", + "openBIS:hasPUBLICATION.IDENTIFIER" : "https://doi.org/10.1038/s41586-020-3010-5", + "openBIS:hasPUBLICATION.DATASETS" : "https://www.kaggle.com/datasets/uciml/mushroom-classification", + "openBIS:hasPUBLICATION.ABSTRACT" : "Humanity has become a dominant force in shaping the face of Earth1,2,3,4,5,6,7,8,9. An emerging question is how the overall material output of human activities compares to the overall natural biomass. Here we quantify the human-made mass, referred to as ‘anthropogenic mass’, and compare it to the overall living biomass on Earth, which currently equals approximately 1.1 teratonnes10,11. We find that Earth is exactly at the crossover point; in the year 2020 (± 6), the anthropogenic mass, which has recently doubled roughly every 20 years, will surpass all global living biomass. On average, for each person on the globe, anthropogenic mass equal to more than his or her bodyweight is produced every week. This quantification of the human enterprise gives a mass-based quantitative and symbolic characterization of the human-induced epoch of the Anthropocene.", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB25", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, + "openBIS:hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22" + }, + "openBIS:hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB24" + }, + "@type" : "PUBLICATION" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Publication Status", + "rdfs:comment" : "Publication Status", + "@id" : "openBIS:hasPUBLICATION.STATUS", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#stateSelection" + }, { + "@id" : "https://schema.org/creativeWorkStatus" + } ] + }, { + "@id" : "58f40086-3cde-463f-8957-d59a5069bbfd", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.ORGANIZATION" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "URL", + "rdfs:comment" : "URL", + "@id" : "openBIS:hasPUBLICATION.URL", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#url" + }, { + "@id" : "https://schema.org/url" + } ] + }, { + "@id" : "8483940c-966c-4269-a521-7adb0a62cc43", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.CREATOR" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Creator Identifier", + "rdfs:comment" : "Creator Identifier", + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Name", + "rdfs:comment" : "Name", + "@id" : "openBIS:hasNAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : [ { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "PUBLICATION_PUBLISHER" + } ], + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#title" + }, { + "@id" : "https://schema.org/title" + }, { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/name" + }, { + "@id" : "http://datacite.org/schema/kernel-4#title" + }, { + "@id" : "https://schema.org/title" + }, { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/name" + }, { + "@id" : "http://datacite.org/schema/kernel-4#title" + }, { + "@id" : "https://schema.org/title" + }, { + "@id" : "http://datacite.org/schema/kernel-4#nameIdentifier" + }, { + "@id" : "https://schema.org/name" + } ] + }, { + "@id" : "bc8c9b69-4c1a-4cfa-91f8-c806a6d910f7", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasDEFAULT_COLLECTION_VIEW" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Default object type", + "rdfs:comment" : "Enter the code of the object type for which the collection is used", + "@id" : "openBIS:hasDEFAULT_OBJECT_TYPE", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "COLLECTION" + } + }, { + "openBIS:hasPUBLICATION_CREATOR.FULL_NAME" : "Emily Elhacham", + "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" : "Department of Plant and Environmental Sciences, Weizmann Institute of Science, Rehovot, Israel", + "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME" : "Emily", + "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME" : "Elhacham", + "openBIS:hasNAME" : "Emily Elhacham", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA22", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, + "@type" : "PUBLICATION_CREATOR" + }, { + "@id" : "019e020d-03c0-4eea-ad11-3a698e486ebe", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER" : "https://orcid.org/0000-0001-9844-8214", + "openBIS:hasPUBLICATION_CREATOR.FULL_NAME" : "Han-Sen Zhong", + "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER" : "Unknown", + "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME" : "Han-Sen", + "openBIS:hasPUBLICATION_CREATOR.FAMILY_NAME" : "Zhong", + "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" : "https://orcid.org", + "openBIS:hasNAME" : "Han-Sen Zhong", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_CREATOR_COLLECTION" + }, + "@type" : "PUBLICATION_CREATOR" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Affiliation Identifier Scheme", + "rdfs:comment" : "Affiliation Identifier Scheme", + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + } + }, { + "@id" : "9a9c4a68-31ae-4e4b-bb5c-9743e40d0fa8", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasNAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "7c6a44df-1a55-4476-b853-198d12402059", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.IDENTIFIER" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@id" : "79b88764-999f-47b8-9989-b88f82cc2e9b", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasNAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "7b5e347f-e111-44aa-a9ce-9fc2faa567d9", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_PUBLISHER.IDENTIFIER_SCHEME_URI" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasDEFAULT_COLLECTION_VIEW" : "LIST_VIEW", + "openBIS:hasDEFAULT_OBJECT_TYPE" : "PUBLICATION_PUBLISHER", + "openBIS:hasNAME" : "Publications Publisher Collection", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_PUBLISHER_COLLECTION", + "@type" : "COLLECTION" + }, { + "@id" : "openBIS:Space", + "@type" : "rdfs:Class" + }, { + "@type" : "rdfs:Property", + "@id" : "openBIS:hasCOLLECTION", + "schema:rangeIncludes" : { + "@id" : "openBIS:Collection" + }, + "schema:domainIncludes" : [ { + "@id" : "COLLECTION" + }, { + "@id" : "PUBLICATION_CREATOR" + }, { + "@id" : "PUBLICATION" + }, { + "@id" : "PUBLICATION_PUBLISHER" + } ] + }, { + "@id" : "35db541a-c52c-49f0-bd46-9a8f60b4a537", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.FULL_NAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Contributors", + "rdfs:comment" : "Contributors", + "@id" : "openBIS:hasPUBLICATION.CONTRIBUTOR", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#doi" + }, { + "@id" : "https://schema.org/identifier" + } ] + }, { + "openBIS:hasPUBLICATION.STATUS" : "Registered", + "openBIS:hasPUBLICATION.URL" : "https://www.nature.com/articles/s41586-020-03065-y#citeas", + "openBIS:hasNAME" : "Genetic mechanisms of critical illness in COVID-19", + "openBIS:hasPUBLICATION.TYPE" : "DataPaper", + "openBIS:hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-11 15:48:55 +0100", + "openBIS:hasPUBLICATION.IDENTIFIER" : "https://doi.org/10.1038/s41586-020-03065-y", + "openBIS:hasPUBLICATION.DATASETS" : "https://www.kaggle.com/datasets/shahriar26s/malaria-detection", + "openBIS:hasPUBLICATION.ABSTRACT" : "Host-mediated lung inflammation is present1, and drives mortality2, in the critical illness caused by coronavirus disease 2019 (COVID-19). Host genetic variants associated with critical illness may identify mechanistic targets for therapeutic development3. Here we report the results of the GenOMICC (Genetics Of Mortality In Critical Care) genome-wide association study in 2,244 critically ill patients with COVID-19 from 208 UK intensive care units. We have identified and replicated the following new genome-wide significant associations: on chromosome 12q24.13 (rs10735079, P = 1.65 × 10−8) in a gene cluster that encodes antiviral restriction enzyme activators (OAS1, OAS2 and OAS3); on chromosome 19p13.2 (rs74956615, P = 2.3 × 10−8) near the gene that encodes tyrosine kinase 2 (TYK2); on chromosome 19p13.3 (rs2109069, P = 3.98 × 10−12) within the gene that encodes dipeptidyl peptidase 9 (DPP9); and on chromosome 21q22.1 (rs2236757, P = 4.99 × 10−8) in the interferon receptor gene IFNAR2. We identified potential targets for repurposing of licensed medications: using Mendelian randomization, we found evidence that low expression of IFNAR2, or high expression of TYK2, are associated with life-threatening disease; and transcriptome-wide association in lung tissue revealed that high expression of the monocyte–macrophage chemotactic receptor CCR2 is associated with severe COVID-19. Our results identify robust genetic signals relating to key host antiviral defence mechanisms and mediators of inflammatory organ damage in COVID-19. Both mechanisms may be amenable to targeted treatment with existing drugs. However, large-scale randomized clinical trials will be essential before any change to clinical practice.", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB29", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, + "openBIS:hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA23" + }, + "openBIS:hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + }, + "@type" : "PUBLICATION" + }, { + "@type" : "rdfs:Property", + "rdfs:label" : "Given Name", + "rdfs:comment" : "Given Name", + "@id" : "openBIS:hasPUBLICATION_CREATOR.GIVEN_NAME", + "schema:rangeIncludes" : { + "@id" : "xsd:string" + }, + "schema:domainIncludes" : { + "@id" : "PUBLICATION_CREATOR" + }, + "owl:equivalentProperty" : [ { + "@id" : "http://datacite.org/schema/kernel-4#givenName" + }, { + "@id" : "https://schema.org/givenName" + } ] + }, { + "@id" : "fdf9de4a-9233-4f9a-beee-b16c85ac7899", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.PUBLICATION_YEAR" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "@id" : "00c7421f-c174-4f52-a8d0-151a9f1a727a", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION.STATUS" + }, + "owl:minCardinality" : 1, + "owl:maxCardinality" : 1 + }, { + "openBIS:hasPUBLICATION.STATUS" : "Registered", + "openBIS:hasPUBLICATION.URL" : "https://www.science.org/doi/10.1126/science.abe8770", + "openBIS:hasNAME" : "Quantum computational advantage using photons", + "openBIS:hasPUBLICATION.TYPE" : "DataPaper", + "openBIS:hasPUBLICATION.PUBLICATION_YEAR" : "2020-12-11 15:50:44 +0100", + "openBIS:hasPUBLICATION.IDENTIFIER" : "DOI: 10.1126/science.abe8770", + "openBIS:hasPUBLICATION.DATASETS" : "https://www.kaggle.com/datasets/shantanuss/banknote-authentication-uci$", + "openBIS:hasPUBLICATION.ABSTRACT" : "Quantum computational advantage or supremacy is a long-anticipated milestone toward practical quantum computers. Recent work claimed to have reached this point, but subsequent work managed to speed up the classical simulation and pointed toward a sample size–dependent loophole. Quantum computational advantage, rather than being a one-shot experimental proof, will be the result of a long-term competition between quantum devices and classical simulation. Zhong et al. Sent 50 indistinguishable single-mode squeezed states into a 100-mode ultralow-loss interferometer and sampled the output using 100 high-efficiency single-photon detectors. By obtaining up to 76-photon coincidence, yielding a state space dimension of about 1030, they measured a sampling rate that is about 1014-fold faster than using state-of-the-art classical simulation strategies and supercomputers.", + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUB30", + "openBIS:hasSPACE" : { + "@id" : "PUBLICATIONS" + }, + "openBIS:hasPROJECT" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES" + }, + "openBIS:hasCOLLECTION" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBLICATIONS_COLLECTION" + }, + "openBIS:hasPUBLICATION.CREATOR" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBCREA27" + }, + "openBIS:hasPUBLICATION.PUBLISHER" : { + "@id" : "/PUBLICATIONS/PUBLIC_REPOSITORIES/PUBPUB26" + }, + "@type" : "PUBLICATION" + }, { + "@id" : "2b7168ea-1595-438c-b4f7-28fa042e5257", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasNAME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "83be7d34-91ac-4d08-9cd5-4f9cb758a967", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.IDENTIFIER_SCHEME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + }, { + "@id" : "fde51c61-c5c6-4097-89c9-d1acfbf9e417", + "@type" : "owl:restriction", + "owl:onProperty" : { + "@id" : "openBIS:hasPUBLICATION_CREATOR.AFFILITION_IDENTIFIER_SCHEME" + }, + "owl:minCardinality" : 0, + "owl:maxCardinality" : 1 + } ] +} \ No newline at end of file diff --git a/0.2.x/lib/java/bin/lib-ro-crate.jar b/0.2.x/lib/java/bin/lib-ro-crate.jar new file mode 100644 index 0000000..d999869 Binary files /dev/null and b/0.2.x/lib/java/bin/lib-ro-crate.jar differ diff --git a/0.2.x/lib/java/src/build.gradle b/0.2.x/lib/java/src/build.gradle new file mode 100644 index 0000000..7d6816f --- /dev/null +++ b/0.2.x/lib/java/src/build.gradle @@ -0,0 +1,74 @@ +plugins { + id 'java' + id 'application' +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType(JavaCompile) { + options.compilerArgs << '-parameters' +} + +repositories { + ivy { + ivyPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/ivy.xml" + artifactPattern "https://sissource.ethz.ch/openbis/openbis-public/openbis-ivy/-/raw/main/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" + } + mavenCentral() +} + +//'openbis:openbis-v3-api-batteries-included:6.5.0', +//files('libs/openBIS-API-V3-batteries-included-SNAPSHOT-r1718006152.jar'), +dependencies { + implementation 'com.fasterxml.jackson.core:jackson-core' + implementation 'com.fasterxml.jackson.core:jackson-databind' + implementation 'org.slf4j:slf4j-api:2.0.16' + + implementation 'edu.kit.datamanager:ro-crate-java:2.0.1' + testImplementation 'junit:junit:4.13.1' + testImplementation('jmock:jmock:2.5.1') + +} + +configurations.configureEach { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + + // https://docs.gradle.org/current/userguide/resolution_rules.html + if (details.requested.group == 'com.fasterxml.jackson.core' && details.requested.name == 'jackson-databind') { + details.useVersion '2.18.0' + } + if (details.requested.group == 'com.fasterxml.jackson.core' && details.requested.name == 'jackson-core') { + details.useVersion '2.18.0' + } + if (details.requested.group == 'org.slf4j') { + details.useVersion '2.0.16' + } + } +} + + +tasks.register('buildRdfTool', Jar) { + dependsOn tasks.build + duplicatesStrategy 'include' + + archiveBaseName.set('lib-rdf-tool') + includeEmptyDirs = false + + manifest { + attributes( + 'Main-Class': 'ch.ethz.sis.rdf.main.RDFCommandLine' + ) + } + + from(zipTree(tasks.jar.outputs.files.singleFile)) { + include '**/*' + } + + from(configurations.runtimeClasspath.collect { zipTree(it) }) { + include '**/*' + exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA' + } +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/SchemaFacade.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/SchemaFacade.java new file mode 100644 index 0000000..6a1637f --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/SchemaFacade.java @@ -0,0 +1,566 @@ +package ch.eth.sis.rocrate; + +import ch.eth.sis.rocrate.facade.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import edu.kit.datamanager.ro_crate.RoCrate; +import edu.kit.datamanager.ro_crate.entities.data.DataEntity; + +import java.io.Serializable; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class SchemaFacade implements ISchemaFacade +{ + + private final static String RDFS_CLASS = "rdfs:Class"; + + private final static String RDFS_PROPERTY = "rdfs:Property"; + + public static final String EQUIVALENT_CLASS = "owl:equivalentClass"; + + public static final String EQUIVALENT_CONCEPT = "owl:equivalentProperty"; + + public static final String TYPE_RESTRICTION = "owl:restriction"; + + + String rangeIdentifier = "schema:rangeIncludes"; + + String domainIdentifier = "schema:domainIncludes"; + + public static final String OWL_MIN_CARDINALITY = "owl:minCardinality"; + + public static final String OWL_MAX_CARDINALITY = "owl:maxCardinality"; + + public static final String OWL_RESTRICTION = "owl:restriction"; + + public static final String ON_PROPERTY = "owl:onProperty"; + + + public static final String RDFS_LABEL = "rdfs:label"; + + public static final String RDFS_COMMENT = "rdfs:comment"; + + + + Pattern p; + + String localPrefix = ":"; + + private Map types; + + private Map propertyTypes; + + private Map metadataEntries; + + private final RoCrate crate; + + @Override + public RoCrate getCrate() + { + return crate; + } + + public SchemaFacade(String name, String description, String dateString, + String licenseIdentifier, Map context) + { + RoCrate.RoCrateBuilder roCrateBuilder = + new RoCrate.RoCrateBuilder(name, description, dateString, + licenseIdentifier); + roCrateBuilder.addValuePairToContext("schema", + "https://www.w3.org/TR/rdf-schema"); + roCrateBuilder.addValuePairToContext("owl", + "https://www.w3.org/TR/owl-ref"); + for (Map.Entry keyVal : context.entrySet() + ) + { + roCrateBuilder.addValuePairToContext(keyVal.getKey(), keyVal.getValue()); + } + + this.crate = roCrateBuilder.build(); + this.types = new LinkedHashMap<>(); + this.propertyTypes = new LinkedHashMap<>(); + this.metadataEntries = new LinkedHashMap<>(); + } + + public SchemaFacade(RoCrate crate) + { + this.crate = crate; + this.types = new LinkedHashMap<>(); + this.propertyTypes = new LinkedHashMap<>(); + this.metadataEntries = new LinkedHashMap<>(); + } + + public static SchemaFacade of(RoCrate crate) throws JsonProcessingException + { + SchemaFacade schemaFacade = new SchemaFacade(crate); + schemaFacade.parseEntities(); + return schemaFacade; + + } + + @Override + public void addType(IType rdfsClass) + { + + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + builder.addProperty("@id", rdfsClass.getId()); + builder.addProperty("@type", RDFS_CLASS); + builder.addProperty(RDFS_LABEL, rdfsClass.getLabel()); + builder.addProperty(RDFS_COMMENT, rdfsClass.getComment()); + + for (IRestriction restriction : rdfsClass.getResstrictions()) + { + DataEntity.DataEntityBuilder restrictionBuilder = new DataEntity.DataEntityBuilder(); + restrictionBuilder.addProperty("@id", restriction.getId()); + restrictionBuilder.addProperty("@type", TYPE_RESTRICTION); + restrictionBuilder.addIdProperty(ON_PROPERTY, restriction.getPropertyType().getId()); + restrictionBuilder.addProperty(OWL_MIN_CARDINALITY, restriction.getMinCardinality()); + restrictionBuilder.addProperty(OWL_MAX_CARDINALITY, restriction.getMaxCardinality()); + builder.addIdProperty(OWL_RESTRICTION, restriction.getId()); + crate.addDataEntity(restrictionBuilder.build()); + } + + + rdfsClass.getSubClassOf().forEach(x -> builder.addIdProperty("rdfs:subClassOf", x)); + this.types.put(rdfsClass.getId(), rdfsClass); + DataEntity entity = builder.build(); + entity.addIdListProperties(EQUIVALENT_CLASS, rdfsClass.getOntologicalAnnotations()); + crate.addDataEntity(entity); + + } + + @Override + public List getTypes() + { + return this.types.values().stream().toList(); + } + + @Override + public IType getTypes(String id) + { + return this.types.get(id); + } + + @Override + public void addPropertyType(IPropertyType rdfsProperty) + { + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + + builder.setId(rdfsProperty.getId()); + builder.addProperty("@type", RDFS_PROPERTY); + builder.addProperty(RDFS_LABEL, rdfsProperty.getLabel()); + builder.addProperty(RDFS_COMMENT, rdfsProperty.getComment()); + + var stuff = builder.build(); + stuff.addIdListProperties("schema:rangeIncludes", + rdfsProperty.getRange()); + stuff.addIdListProperties("schema:domainIncludes", + rdfsProperty.getDomain().stream().map(x -> x.getId()).collect(Collectors.toList())); + stuff.addIdListProperties(EQUIVALENT_CONCEPT, + rdfsProperty.getOntologicalAnnotations()); + crate.addDataEntity(stuff); + propertyTypes.put(rdfsProperty.getId(), rdfsProperty); + + } + + @Override + public void addRestriction(IRestriction restriction) + { + + } + + @Override + public List getPropertyTypes() + { + return propertyTypes.values().stream().toList(); + } + + @Override + public IPropertyType getPropertyType(String id) + { + return propertyTypes.get(id); + } + + @Override + public void addEntry(IMetadataEntry metaDataEntry) + { + DataEntity.DataEntityBuilder builder = new DataEntity.DataEntityBuilder(); + builder.setId(metaDataEntry.getId()); + for (String type : metaDataEntry.getTypes()) + { + builder.addType(type); + } + ObjectMapper objectMapper = new ObjectMapper(); + + metaDataEntry.getValues().forEach((s, o) -> { + if (o instanceof Double) + { + builder.addProperty(s, (Double) o); + } else if (o instanceof Integer) + { + builder.addProperty(s, (Integer) o); + } else if (o instanceof Boolean) + { + builder.addProperty(s, (Boolean) o); + } else if (o instanceof String) + { + builder.addProperty(s, o.toString()); + } else if (o == null) + { + builder.addProperty(s, objectMapper.nullNode()); + } + }); + DataEntity dataEntity = builder.build(); + metaDataEntry.getReferences().forEach(dataEntity::addIdListProperties); + + crate.addDataEntity(dataEntity); + + } + + @Override + public IMetadataEntry getEntry(String id) + { + return metadataEntries.get(id); + } + + @Override + public List getEntries(String rdfsClassId) + { + return metadataEntries.values().stream() + .filter(x -> matchClasses(resolvePrefixSingleValue(rdfsClassId), x)) + .toList(); + } + + @Override + public List getRestrictions() + { + return null; + } + + private boolean matchClasses(String queryClassId, IMetadataEntry entry) + { + if (entry.getTypes().stream().anyMatch(x -> x.equals(queryClassId))) + { + return true; + } + + return entry.getTypes().stream() + .map(x -> p.matcher(x)) + .map(x -> x.replaceAll("_:")) + .anyMatch(x -> x.equals(queryClassId)); + + } + + private void parseEntities() throws JsonProcessingException + { + + localPrefix = getLocalPrefix(crate.getJsonMetadata()); + Map keyValuePairs = getKeyValPairsFromMetadata(crate.getJsonMetadata()); + for (var keyValPair : keyValuePairs.entrySet()) + { + if (keyValPair.getValue().equals("http://schema.org/rangeIncludes")) + { + rangeIdentifier = keyValPair.getKey(); + } + if (keyValPair.getValue().equals("http://schema.org/domainIncludes")) + { + domainIdentifier = keyValPair.getKey(); + } + } + + + + + Map properties = new LinkedHashMap<>(); + Map classes = new LinkedHashMap<>(); + Map entries = new LinkedHashMap<>(); + + Map restrictionToTypeId = new LinkedHashMap<>(); + + + + for (DataEntity entity : crate.getAllDataEntities()) + { + String type = entity + .getProperty("@type").asText(); + String id = + entity.getProperty("@id") + .asText(); + + switch (type) + { + case "rdfs:Class" -> + { + Type myType = new Type(); + myType.setSubClassOf(parseMultiValued(entity, "rdfs:subClassOf")); + myType.setOntologicalAnnotations( + parseMultiValued(entity, EQUIVALENT_CLASS)); + myType.setId(resolvePrefixSingleValue(id)); + classes.put(resolvePrefixSingleValue(id), myType); + parseMultiValued(entity, OWL_RESTRICTION).forEach( + x -> restrictionToTypeId.put(x, myType)); + + } + + + } + + } + + for (DataEntity entity : crate.getAllDataEntities()) + { + String type = entity + .getProperty("@type").asText(); + String id = + entity.getProperty("@id") + .asText(); + + switch (type) + { + case "rdfs:Property" -> + { + PropertyType rdfsProperty = new PropertyType(); + rdfsProperty.setId(resolvePrefixSingleValue(id)); + + rdfsProperty.setOntologicalAnnotations( + parseMultiValued(entity, EQUIVALENT_CONCEPT)); + + List rawRange = parseMultiValued(entity, rangeIdentifier); + + List dataTypes = rawRange.stream() + .filter(LiteralType::isLiteralType) + .map(LiteralType::getByTypeName) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + List types = rawRange.stream() + .filter(x -> !LiteralType.isLiteralType(x)) + .map(this::resolvePrefixSingleValue) + .map(classes::get) + .collect(Collectors.toList()); + + dataTypes.stream().forEach(rdfsProperty::addDataType); + types.forEach(rdfsProperty::addType); + + rdfsProperty.setDomainIncludes( + parseMultiValued(entity, domainIdentifier).stream() + .map(x -> resolvePrefixSingleValue(x)) + .map(classes::get).collect( + Collectors.toList())); + properties.put(resolvePrefixSingleValue(id), rdfsProperty); + + } + } + + } + + for (DataEntity entity : crate.getAllDataEntities()) + { + String type = entity.getProperty("@type").asText(); + String id = + entity.getProperty("@id") + .asText(); + + if (type.equals(OWL_RESTRICTION)) + { + String onProperty = parseMultiValued(entity, ON_PROPERTY).get(0); + int minCardinality = + entity.getProperty(OWL_MIN_CARDINALITY).numberValue().intValue(); + + int maxCardinality = + entity.getProperty(OWL_MAX_CARDINALITY).numberValue().intValue(); + Restriction restriction = + new Restriction(id, properties.get(onProperty), minCardinality, + maxCardinality); + restrictionToTypeId.get(id).addRestriction(restriction); + } + + } + + + for (var entity : crate.getAllDataEntities()) + { + Set type = parseTypes(entity); + + String id = + entity.getProperty("@id") + .asText(); + if (!doesTypeExist(type, classes, localPrefix)) + { + continue; + } + + Map entryProperties = new LinkedHashMap<>(); + MetadataEntry entry = new MetadataEntry(); + entry.setId(id); + + entry.setTypes(resolvePrefix(type)); + Map> references = new LinkedHashMap<>(); + ObjectMapper objectMapper = new ObjectMapper(); + Map keyVals = + objectMapper.readValue(entity.getProperties().toString(), HashMap.class); + for (Map.Entry a : keyVals.entrySet()) + { + if (properties.containsKey(a.getKey())) + { + IPropertyType property = properties.get(a.getKey()); + if (property.getRange().stream().anyMatch(x -> x.startsWith("xsd:"))) + { + entryProperties.put(a.getKey(), a.getValue().toString()); + } else + { + List refs = parseMultiValued(entity, a.getKey()); + references.put(a.getKey(), refs); + } + } + } + entry.setProps(entryProperties); + entry.setReferences(references); + entries.put(id, entry); + } + System.out.println("Done"); + this.types = classes; + this.propertyTypes = properties; + this.metadataEntries = entries; + + } + + private Set resolvePrefix(Set types) + { + Pattern placeholderPattern = Pattern.compile("^_:"); + + LinkedHashSet newTypes = new LinkedHashSet(); + for (String type : types) + { + newTypes.add(placeholderPattern.matcher(type).replaceAll(localPrefix)); + + } + return newTypes; + } + + private String resolvePrefixSingleValue(String type) + { + Pattern placeholderPattern = Pattern.compile("^_:"); + + return placeholderPattern.matcher(type).replaceAll(localPrefix); + } + + private List parseMultiValued(DataEntity dataEntity, String key) + { + JsonNode node = dataEntity.getProperty(key); + if (node instanceof ObjectNode) + { + return List.of(node.get("@id").textValue()); + } + if (node instanceof ArrayNode arrayNode) + { + List accumulator = new ArrayList<>(); + arrayNode.elements().forEachRemaining( + x -> accumulator.add(x.get("@id").textValue()) + ); + return accumulator; + } + return List.of(); + + } + + private Set parseTypes(DataEntity entity) + { + JsonNode typeResult = entity.getProperty("@type"); + if (typeResult.isTextual()) + { + return Set.of(typeResult.textValue()); + } + if (typeResult.isArray()) + { + ArrayNode arrayNode = (ArrayNode) typeResult; + Set typeroos = new LinkedHashSet<>(); + arrayNode.forEach(x -> typeroos.add(x.textValue())); + return typeroos; + + } + throw new RuntimeException("Unknown node type for @type"); + + } + + Map getKeyValPairsFromMetadata(String metaDataJson) + throws JsonProcessingException + { + ObjectMapper objectMapper = new ObjectMapper(); + LinkedHashMap vals = objectMapper.readValue(metaDataJson, LinkedHashMap.class); + + if (vals.get("@context") instanceof LinkedHashMap) + { + + return (Map) vals.get("@context"); + + } + + if (vals.get("@context") instanceof String) + { + return Map.of(); + } + + List nodes = (List) vals.get("@context"); + Map key_vals = (Map) nodes.get(1); + + Map result = new LinkedHashMap<>(); + for (Object a : key_vals.entrySet()) + { + Map.Entry b = (Map.Entry) a; + result.put(b.getKey().toString(), b.getValue().toString()); + } + + return result; + } + + String getLocalPrefix(String jsonMetaData) throws JsonProcessingException + { + Map keyVals = getKeyValPairsFromMetadata(jsonMetaData); + for (Map.Entry entry : keyVals.entrySet()) + { + if (entry.getValue().equals("_:")) + { + return entry.getKey() + ":"; + } + + } + return ""; + } + + boolean doesTypeExist(Set types, Map classes, String localPrefix) + { + p = Pattern.compile("^" + localPrefix + ":", Pattern.CASE_INSENSITIVE); + + boolean somethingFound = false; + for (String type : types) + { + boolean typeFound = false; + + Matcher m = p.matcher(type); + if (classes.containsKey(type)) + { + typeFound = true; + } + if (classes.containsKey(m.replaceAll("_:"))) + { + typeFound = true; + } + + if (!typeFound) + { + System.out.println("Type " + type + " does not seem to be part of the schema"); + } + somethingFound = somethingFound || typeFound; + } + + return somethingFound; + + } + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/ReadExample.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/ReadExample.java new file mode 100644 index 0000000..f3e3f8f --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/ReadExample.java @@ -0,0 +1,38 @@ +package ch.eth.sis.rocrate.example; + +import ch.eth.sis.rocrate.SchemaFacade; +import com.fasterxml.jackson.core.JsonProcessingException; +import edu.kit.datamanager.ro_crate.RoCrate; +import edu.kit.datamanager.ro_crate.reader.FolderReader; +import edu.kit.datamanager.ro_crate.reader.RoCrateReader; + +public class ReadExample +{ + /** + * This reads an RO-Crate with schema information and prints out + * If you need a compatible RO-Crate, run WriteExample.java first. + * Takes one optional command line argument for an output path, if not provided, it will read from + * ./out + * @param args + * @throws JsonProcessingException + */ + public static void main(String[] args) throws JsonProcessingException + { + String path = args.length >= 1 ? args[0] : "out"; + RoCrateReader roCrateFolderReader = new RoCrateReader(new FolderReader()); + RoCrate crate = roCrateFolderReader.readCrate(path); + SchemaFacade schemaFacade = SchemaFacade.of(crate); + schemaFacade.getTypes().forEach( + x -> System.out.println("RDFS Class " + x.getId()) + ); + schemaFacade.getPropertyTypes().forEach( + x -> System.out.println("RDFS Property " + x.getId()) + ); + schemaFacade.getEntries(schemaFacade.getTypes().get(0).getId()).forEach( + x -> System.out.println("Metadata entry " + x.getId()) + ); + + } + + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/WriteExample.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/WriteExample.java new file mode 100644 index 0000000..9f5fae5 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/example/WriteExample.java @@ -0,0 +1,108 @@ +package ch.eth.sis.rocrate.example; + +import ch.eth.sis.rocrate.SchemaFacade; +import ch.eth.sis.rocrate.facade.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import edu.kit.datamanager.ro_crate.writer.FolderWriter; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class WriteExample +{ + + /** + * This is a small example that adds one type for a textual resource with two properties. One + * of the properties is a literal, date, while the other references the creator. The creator + * type has its own properties. Some of the properties have ontological annotations to clarify + * their meanings. + * Takes one optional command line argument for an output path, if not provided, it will write to + * ./out + * + * @param args + * @throws JsonProcessingException + */ + public static void main(String[] args) throws JsonProcessingException + { + + ISchemaFacade schemaFacade = + new SchemaFacade("name", "description", "2024-12-04T07:53:11Z", "licenceIdentifier", + Map.of()); + + { + Type type = new Type(); + type.setId("TextResource"); + type.setSubClassOf(List.of("https://schema.org/Thing")); + type.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/dcmitype/Text/")); + schemaFacade.addType(type); + + Type creatorType = new Type(); + creatorType.setId("Creator"); + creatorType.setSubClassOf(List.of("https://schema.org/Thing")); + creatorType.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/terms/creator//")); + schemaFacade.addType(type); + schemaFacade.addType(creatorType); + { + + } + + + + PropertyType property = new PropertyType(); + property.setId("hasDateSubmitted"); + property.addDataType(LiteralType.DATETIME); + property.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/terms/dateSubmitted/")); + type.addProperty(property); + + PropertyType propertyCreator = new PropertyType(); + propertyCreator.setId("hasCreator"); + propertyCreator.addType(creatorType); + type.addProperty(propertyCreator); + + PropertyType name = new PropertyType(); + name.setId("hasName"); + name.addDataType(LiteralType.STRING); + creatorType.addProperty(name); + + PropertyType identifier = new PropertyType(); + identifier.setId("hasIdentifier"); + identifier.addDataType(LiteralType.STRING); + identifier.setOntologicalAnnotations( + List.of("https://www.dublincore.org/specifications/dublin-core/dcmi-terms/elements11/identifier/")); + creatorType.addProperty(identifier); + + + schemaFacade.addPropertyType(property); + schemaFacade.addPropertyType(propertyCreator); + schemaFacade.addPropertyType(identifier); + schemaFacade.addPropertyType(name); + + String creatorId = "creator1"; + IMetadataEntry creatorEntry = new MetadataEntry(creatorId, Set.of(creatorType.getId()), + Map.of("hasName", "John Author", "hasIdentifier", + "https://orcid.org/0000-0000-0000-0000"), Map.of()); + + IMetadataEntry metadataEntry = + new MetadataEntry("TextResource1", Set.of("TextResource"), + Map.of("hasDate", "2025-01-21T07:12:20Z"), + Map.of("hasCreator", List.of(creatorId))); + schemaFacade.addEntry(metadataEntry); + schemaFacade.addEntry(creatorEntry); + + } + + String path = args.length >= 1 ? args[0] : "out"; + + + + + FolderWriter folderWriter = new FolderWriter(); + folderWriter.save(schemaFacade.getCrate(), path); + + } + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IDataType.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IDataType.java new file mode 100644 index 0000000..6c9eb38 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IDataType.java @@ -0,0 +1,21 @@ +package ch.eth.sis.rocrate.facade; + +public interface IDataType +{ + String getTypeName(); + + static IDataType getArray(LiteralType literalType) + { //TODO static IDataType getArray(LiteralType literalType) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } + + static IDataType getEnumerationf(String... values) + { //TODO static IDataType getEnumerationf(String... values) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } + + static IDataType getCustomType(LiteralType basicType, String pattern) + { //TODO static IDataType getCustomType(LiteralType basicType, String pattern) + throw new UnsupportedOperationException("Feature incomplete. Contact assistance."); + } +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IMetadataEntry.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IMetadataEntry.java new file mode 100644 index 0000000..3db6160 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IMetadataEntry.java @@ -0,0 +1,30 @@ +package ch.eth.sis.rocrate.facade; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface IMetadataEntry +{ + + /** + * Returns the ID of this entry + */ + String getId(); + + /* Returns the type ID of this entry */ + String getClassId(); + + /* Returns the types of the entry */ + Set getTypes(); + + /* These are key-value pairs for serialization. These are single-valued. + * Serializable classes are: String, Number and Boolean */ + Map getValues(); + + /* These are references to other objects in the graph. + * Each key may have one or more references */ + Map> getReferences(); + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IPropertyType.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IPropertyType.java new file mode 100644 index 0000000..01587d4 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IPropertyType.java @@ -0,0 +1,25 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.List; + +public interface IPropertyType +{ + /* Returns the ID of this property type */ + String getId(); + + /* Return possible values for the subject of this property type */ + List getDomain(); + + /* Return possible values for the object of this property type */ + List getRange(); + + /* Returns the ontological annotations of this property type */ + List getOntologicalAnnotations(); + + /* Returns a human-readable description of this type */ + String getComment(); + + /* Returns a human-readable label of this type */ + String getLabel(); + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IRestriction.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IRestriction.java new file mode 100644 index 0000000..f37d3a7 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IRestriction.java @@ -0,0 +1,13 @@ +package ch.eth.sis.rocrate.facade; + +public interface IRestriction +{ + + String getId(); + + IPropertyType getPropertyType(); + + int getMinCardinality(); + + int getMaxCardinality(); +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/ISchemaFacade.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/ISchemaFacade.java new file mode 100644 index 0000000..f0b54d9 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/ISchemaFacade.java @@ -0,0 +1,45 @@ +package ch.eth.sis.rocrate.facade; + +import edu.kit.datamanager.ro_crate.RoCrate; + +import java.util.List; + +public interface ISchemaFacade +{ + + /* Get the crate being worked on */ + RoCrate getCrate(); + + /* Adds a single class */ + void addType(IType rdfsClass); + + /** Retrieves all Classes */ + List getTypes(); + + /* Get a single type by its ID */ + IType getTypes(String id); + + /* Adds a single property */ + void addPropertyType(IPropertyType property); + + /* Adds a restriction */ + void addRestriction(IRestriction restriction); + + /* Get all Properties */ + List getPropertyTypes(); + + /* Gets a single property by its ID. */ + IPropertyType getPropertyType(String id); + + /* Add a single metadata entry */ + void addEntry(IMetadataEntry entry); + + /* Get a single metadata entry by its ID */ + IMetadataEntry getEntry(String id); + + /* Get all metadata entities */ + List getEntries(String rdfsClassId); + + List getRestrictions(); + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IType.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IType.java new file mode 100644 index 0000000..03053b2 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/IType.java @@ -0,0 +1,27 @@ +package ch.eth.sis.rocrate.facade; + + +import java.util.List; + +public interface IType +{ + /* Returns the ID of this type */ + String getId(); + + /* Returns IDs of the types this type inherits from */ + List getSubClassOf(); + + /* Returns the ontological annotations of this type */ + List getOntologicalAnnotations(); + + /* Returns a human-readable description of this type */ + String getComment(); + + /* Returns a human-readable label of this type */ + String getLabel(); + + /* Get Restrictions placed on the properties of this type */ + List getResstrictions(); + + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/LiteralType.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/LiteralType.java new file mode 100644 index 0000000..fae7240 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/LiteralType.java @@ -0,0 +1,58 @@ +package ch.eth.sis.rocrate.facade; + +/** + * List of primitives as supported by xsd + * https://www.ibm.com/docs/en/jfsm/1.1.2.1?topic=queries-xsd-data-types + */ +public enum LiteralType implements IDataType +{ + + BOOLEAN("xsd:boolean"), + INTEGER("xsd:integer"), + DOUBLE("xsd:double"), + + DECIMAL("xsd:decimal"), + FLOAT("xsd:float"), + DATETIME("xsd:dateTime"), + STRING("xsd:string"), + XML_LITERAL("rdf:XMLLiteral"); + + final String typeName; + + LiteralType(String typeName) + { + this.typeName = typeName; + } + + @Override + public String getTypeName() + { + return typeName; + } + + public static boolean isLiteralType(String typeName) + { + for (LiteralType literalType : LiteralType.values()) + { + if (typeName.equals(literalType.getTypeName())) + { + return true; + } + } + return false; + } + + public static LiteralType getByTypeName(String typeName) + { + for (LiteralType literalType : LiteralType.values()) + { + if (typeName.equals(literalType.getTypeName())) + { + return literalType; + } + } + throw new IllegalArgumentException("Unknown literal type: " + typeName); + + } + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/MetadataEntry.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/MetadataEntry.java new file mode 100644 index 0000000..fc2972f --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/MetadataEntry.java @@ -0,0 +1,118 @@ +package ch.eth.sis.rocrate.facade; + +import java.io.Serializable; +import java.util.*; + +public class MetadataEntry implements IMetadataEntry +{ + String id; + + Set types; + + Map props; + + Map> references; + + List childrenIdentifiers = new ArrayList<>(); + + List parentIdentifiers = new ArrayList<>(); + + public MetadataEntry() + { + } + + public MetadataEntry(String id, Set types, Map props, + Map> references) + { + this.id = id; + this.types = types; + this.props = props; + this.references = references; + } + + public String getId() + { + return id; + } + + @Override + public String getClassId() + { + return null; + } + + @Override + public Map getValues() + { + return props; + } + + @Override + public Map> getReferences() + { + return references; + } + + public void setId(String id) + { + this.id = id; + } + + @Override + public Set getTypes() + { + return types; + } + + public void setTypes(Set types) + { + this.types = types; + } + + public void addChildIdentifier(String a) + { + childrenIdentifiers.add(a); + } + + public void addParentIdentifier(String a) + { + parentIdentifiers.add(a); + } + + public List getChildrenIdentifiers() + { + return childrenIdentifiers; + } + + public List getParentIdentifiers() + { + return parentIdentifiers; + } + + public void setProps(Map props) + { + this.props = props; + } + + public void setReferences(Map> references) + { + this.references = references; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + MetadataEntry entry = (MetadataEntry) o; + return Objects.equals(id, entry.id) && Objects.equals(types, entry.types); + } + + @Override + public int hashCode() + { + return Objects.hash(id, types); + } +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/PropertyType.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/PropertyType.java new file mode 100644 index 0000000..c606f4a --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/PropertyType.java @@ -0,0 +1,132 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class PropertyType implements IPropertyType +{ + List domainIncludes; + + List rangeIncludes; + + List rangeeIndlucesDataType; + + String id; + + List ontologicalAnnotations = new ArrayList<>(); + + + String label; + + String comment; + + public PropertyType() + { + this.rangeIncludes = new ArrayList<>(); + this.rangeeIndlucesDataType = new ArrayList<>(); + this.ontologicalAnnotations = new ArrayList<>(); + + } + + public List getDomainIncludes() + { + return domainIncludes; + } + + public void setDomainIncludes(List domainIncludes) + { + this.domainIncludes = domainIncludes; + } + + + public String getId() + { + return id; + } + + @Override + public List getDomain() + { + return getDomainIncludes(); + } + + @Override + public List getRange() + { + Stream a = rangeIncludes.stream().map(x -> x.getId()); + Stream b = rangeeIndlucesDataType.stream().map(x -> x.getTypeName()); + return Stream.concat(a, b).collect(Collectors.toList()); + + + } + + @Override + public List getOntologicalAnnotations() + { + return ontologicalAnnotations; + } + + @Override + public String getComment() + { + return comment; + } + + @Override + public String getLabel() + { + return label; + } + + public void setId(String id) + { + this.id = id; + } + + public void setOntologicalAnnotations(List ontologicalAnnotations) + { + this.ontologicalAnnotations = ontologicalAnnotations; + } + + public void setTypes(List types) + { + this.rangeeIndlucesDataType = new ArrayList<>(types); + } + + public void addDataType(IDataType type) + { + if (this.rangeeIndlucesDataType == null) + { + this.rangeeIndlucesDataType = new ArrayList<>(); + } + if (!rangeeIndlucesDataType.contains(type)) + { + rangeeIndlucesDataType.add(type); + } + + } + + public void addType(IType type) + { + if (this.rangeIncludes == null) + { + this.rangeIncludes = new ArrayList<>(); + } + if (!this.rangeIncludes.contains(type)) + { + this.rangeIncludes.add(type); + } + } + + public void setLabel(String label) + { + this.label = label; + } + + public void setComment(String comment) + { + this.comment = comment; + } +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/RdfsClass.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/RdfsClass.java new file mode 100644 index 0000000..ce92fd7 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/RdfsClass.java @@ -0,0 +1,86 @@ +ackage ch.eth.sis.rocrate.facade; + +import java.util.ArrayList; +import java.util.List; + +public class RdfsClass implements IType +{ + String id; + + String type; + + List subClassOf; + + List ontologicalAnnotations; + + List rdfsProperties; + + public RdfsClass() + { + this.subClassOf = new ArrayList<>(); + this.ontologicalAnnotations = new ArrayList<>(); + this.rdfsProperties = new ArrayList<>(); + + } + + public String getId() + { + return id; + } + + @Override + public List getSubClassOf() + { + return subClassOf; + } + + @Override + public List getOntologicalAnnotations() + { + return ontologicalAnnotations; + } + + /** + * This is a convenience method for adding a property to a class. + * + */ + public void addProperty(TypeProperty rdfsProperty) + { + List domainIncludes = rdfsProperty.getDomainIncludes(); + if (domainIncludes == null) + { + domainIncludes = new ArrayList<>(); + rdfsProperty.setDomainIncludes(domainIncludes); + } + if (id == null) + { + throw new IllegalArgumentException("Class id is null"); + } + domainIncludes.add(id); + } + + public void setId(String id) + { + this.id = id; + } + + public String getType() + { + return "rdfs:Class"; + } + + public void setType(String type) + { + this.type = type; + } + + public void setSubClassOf(List subClassOf) + { + this.subClassOf = subClassOf; + } + + public void setOntologicalAnnotations(List ontologicalAnnotations) + { + this.ontologicalAnnotations = ontologicalAnnotations; + } +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Restriction.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Restriction.java new file mode 100644 index 0000000..6f7e9e1 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Restriction.java @@ -0,0 +1,48 @@ +package ch.eth.sis.rocrate.facade; + +public class Restriction implements IRestriction +{ + + String id; + + + IPropertyType propertyType; + + int minCardinality; + + int maxCardinality; + + public Restriction(String id, IPropertyType propertyType, int minCardinality, + int maxCardinality) + { + this.id = id; + this.propertyType = propertyType; + this.minCardinality = minCardinality; + this.maxCardinality = maxCardinality; + } + + @Override + public String getId() + { + return id; + } + + @Override + public IPropertyType getPropertyType() + { + return propertyType; + } + + @Override + public int getMinCardinality() + { + return minCardinality; + } + + @Override + public int getMaxCardinality() + { + return maxCardinality; + } + +} diff --git a/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Type.java b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Type.java new file mode 100644 index 0000000..b350e58 --- /dev/null +++ b/0.2.x/lib/java/src/java/ch/ethz/sis/rocrate/facade/Type.java @@ -0,0 +1,144 @@ +package ch.eth.sis.rocrate.facade; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class Type implements IType +{ + String id; + + String type; + + List subClassOf; + + List ontologicalAnnotations; + + List rdfsProperties; + + String comment; + + String label; + + List restrictions; + + public Type() + { + this.subClassOf = new ArrayList<>(); + this.ontologicalAnnotations = new ArrayList<>(); + this.rdfsProperties = new ArrayList<>(); + this.restrictions = new ArrayList<>(); + + } + + public String getId() + { + return id; + } + + @Override + public List getSubClassOf() + { + return subClassOf; + } + + @Override + public List getOntologicalAnnotations() + { + return ontologicalAnnotations; + } + + @Override + public String getComment() + { + return null; + } + + @Override + public String getLabel() + { + return null; + } + + @Override + public List getResstrictions() + { + return restrictions; + } + + /** + * This is a convenience method for adding a property to a class. + * + */ + public void addProperty(PropertyType rdfsProperty) + { + List domainIncludes = rdfsProperty.getDomainIncludes(); + if (domainIncludes == null) + { + domainIncludes = new ArrayList<>(); + rdfsProperty.setDomainIncludes(domainIncludes); + } + if (id == null) + { + throw new IllegalArgumentException("Class id is null"); + } + domainIncludes.add(this); + } + + public void setId(String id) + { + this.id = id; + } + + public String getType() + { + return "rdfs:Class"; + } + + public void setType(String type) + { + this.type = type; + } + + public void setSubClassOf(List subClassOf) + { + this.subClassOf = subClassOf; + } + + public void setOntologicalAnnotations(List ontologicalAnnotations) + { + this.ontologicalAnnotations = ontologicalAnnotations; + } + + public void setComment(String comment) + { + this.comment = comment; + } + + public void setLabel(String label) + { + this.label = label; + } + + public void addRestriction(IRestriction restriction) + { + this.restrictions.add(restriction); + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Type type = (Type) o; + return Objects.equals(id, type.id); + } + + @Override + public int hashCode() + { + return Objects.hash(id); + } +} diff --git a/0.2.x/spec.md b/0.2.x/spec.md new file mode 100644 index 0000000..9d31717 --- /dev/null +++ b/0.2.x/spec.md @@ -0,0 +1,409 @@ +# Profile/Module : RO-Crate Interoperability Profile + +AKA: Convention to include schemas and metadata inside `ro-crate-metadata.json` + +**Index:** + +### ro-crate-metadata.json Convention +- [Version](#version) +- [What's new?](#whats-new) +- [Definitions](#definitions) +- [Background](#background) +- [Goals](#goals) +- [Technologies and Usage](#technologies-and-usage) + - [Schema Representation](#schema-representation) + - [RDFS Class](#rdfs-class) + - [RDFS Property](#rdfs-class) + - [Metadata Representation](#metadata-representation) + - [RDF Metadata Entry](#rdf-metadata-entry) +- [Reference Examples](#reference-examples-for-both-schema-and-entries) + +### Reference API +- [API](#api) + - [Schema Representation DTOs](#schema-representation-dtos) + - [Metadata Representation DTOs](#metadata-representation-dtos) + - [Additional RO-Crate API Methods](#additional-ro-crate-api-methods) +- [Primitive Data Types](#primitive-data-types) +- [API Reference Implementation in Java](#api-reference-implementation-in-java) +- [API Reference Examples in Java](#api-reference-examples-in-java) + +### Organizational Information +- [Ongoing Work](#ongoing-work) +- [Possible Future Directions](#possible-future-directions) +- [People](#people) + +# Changelog + +### 0.2.0, compatible with RO-Crate 1.1 + +#### What's new? + +- Cardinalities [RDFS Class](#rdfs-class), [OWl Restriction](#owl-restriction) +- Mandatory properties [RDFS Class](#rdfs-class), [OWl Restriction](#owl-restriction) +- Labels [RDFS Property](#rdfs-class), [RDFS Class](#rdfs-class) +- Human-readable comments[RDFS Property](#rdfs-class), [RDFS Class](#rdfs-class) +- Intersection types [RDF Metadata Entry](#rdf-metadata-entry) +- Better description of primitive data types [Primitive Data Types](#primitive-data-types) +- Ranges of properties are now built using this library's IType and LiteralType +- Updated future plans! [Possible Future Directions](#possible-future-directions) +- Background section [Background](#background) + +### 0.1.0, compatible with RO-Crate 1.1 + +- Initial version + +# Definitions + +We use the following definitions in our proposal. + +- Schema: A logical design that defines the structure, organization and relationship between data. +- Metadata: data of a database adhering to the schema. +- Ontology: A set of concepts and the relationships between these concepts. + +# Background + + +This convention has its roots in interoperability projects involving established electronic lab notebooks and data repositories. +For historical reasons, schemas for metadata may differ between systems, even if they cover similar concepts. + +# Goals + +This proposal SHOULD allow the means to exchange a database schema and database contents in a +standardized way. + +As consequence, Integrations SHOULD NOT need to parse individual files in non-standardized formats +anymore to obtain such information but MAY use the Ro-Crate API for such purpose. + +Since the goal is that multiple established systems can adhere to it, this poses the +additional problem that are multiple schemas in use for similar concepts. +To address this, we propose a way to annotate our schemas with ontological information. +The ontologies allow identification of shared concepts. +Knowing which concepts are shared allows easier integration for different schemas. + +Establishing such a format for interoperability would also benefit independent interoperability +efforts, as they would be available for reuse in other interoperability projects. + +This specification is made to be usable in Ro-Crate 1.1, as such: +- It SHOULD NOT add new keywords. +- It SHOULD establish a convention that can be used by the RO-Crate API to read/write the information. + +# Technologies and Usage + +- [RDF](https://www.w3.org/RDF/): Resource Description Framework is a specification developed by the + World Wide Web + Consortium (W3C) to provide a framework for representing and exchanging data on the web in a + structured way. RDF allows information to be described in terms of subject-predicate-object + triples, which form a graph of interconnected data. RDF can be serialized in different formats, + including JSON-LD as used by RO-Crate. +- [RDFS](https://www.w3.org/TR/rdf-schema/): Resource Description Framework Schema is a + specification developed by the World Wide Web Consortium (W3C) that extends RDF (Resource + Description Framework). RDFS provides a way to define the structure and relationships of RDF data, + allowing for the creation of vocabularies and the specification of classes, properties, and + hierarchies in an RDF dataset. +- [OWL](https://www.w3.org/OWL/): Web Ontology Language is a formal language used to define and + represent ontologies on the web. +- [XSD](https://www.w3.org/TR/xmlschema11-1/): XML Schema Definition is a language used to define + the structure, content, and constraints of XML documents. It will be used in this specification to + express primitive type. + +## Schema Representation +Because the schema is graph-based this can be easily integrated into the RO-Crate graph. + +The schema could also be included in a separate file in a future version of this specification. + +Ontologies are added using OWL's `equivalentClass` and `equivalentProperty` properties. + +What are the advantages of this? + +- the format is backward compatible +- this only uses features that RO-Crate already provides, no additional keywords are required +- Common format for export that prevents `n * (n - 1)` integration situation +- Thorough description of metadata, better automated checking and read-in + +**Formal description:** + +RO-Crate MUST include a graph description of the schema. +This is expressed using 2 types: + +- RDFS Class +- RDFS Property + +### RDFS Class + +Based on RDFS classes, these can be used as object and subjects of triples. + +| Type/Property | Required? | Description | +|---------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Is `rdfs:Class` | +| owl:equivalentClass | MAY | Ontological annotation https://www.w3.org/TR/owl-ref/#equivalentClass-def | +| rdfs:subClassOf | MUST | Used to indicate inheritance. Each entry has to inherit from something, this can be a base type. https://www.w3.org/TR/rdf-schema/#ch_subclassof | +| rdfs:label | MAY | Label of the class | +| rdfs:comment | MAY | Human-readable description of this class | +| owl:restriction | MAY | OWL restriction, a list of OWL restrictions, see [OWl Restriction](#owl-restriction) | + + +### OWL Restriction + +These represent restrictions on properties. At the moment, they encode cardinalities. +Cardinalities with a max of 0 and a min of 0 can be omitted. +A max cardinality of `0` represents an arbitrary, potentially infinite number of values. + +| Type/Property | Required? | Description | +|--------------------|-----------|------------------------------------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Is `owl:Restriction` | +| owl:onProperty | MUST | Describes the property tye his restriction belongs to | +| owl:minCardinality | MAY | Indicates whether a property is mandatory (1) or not (0). | +| owl:maxCardinality | MAY | Indicates whether a property may have multiple values (0) or only one (1). | + +### RDFS Property + +RDFS Properties, these represent predicates in triples. +They also specify, which classes they can interact with. + +| Type/Property | Required? | Description | +|------------------------|-----------|---------------------------------------------------------------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Is `rdfs:Property` | +| owl:equivalentProperty | MAY | Ontological annotation https://www.w3.org/TR/owl-ref/#equivalentClass-def | +| schema:domainIncludes | MUST | Describes the possible types of the subject. This can be one or many. | +| schema:rangeIncludes | MUST | Describes the possible types of the object. This can be one or many. | +| rdfs:label | MAY | Label of the property | +| rdfs:comment | MAY | Human-readable description of the property | + + +## Metadata Representation + +**Formal description:** + +RO-Crate MUST include a graph description of the metadata entries. +This is expressed using 1 type: + +- Metadata Entry + +### RDF Metadata Entry + +A metadata entry, described by a RDFS class. + +| Type/Property | Required? | Description | +|---------------|-----------|----------------------------------------------------| +| @id | MUST | ID of the entry | +| @type | MUST | Type of the entry, MUST be at least one RDFS Class | + +Further properties are included as specified in the RDFS description as fields. + +# Reference Examples for both Schema and Entries + +We created a small example. It can be found under: +`./examples/ro-crate-1.1/ro-crate-metadata/ro-crate-metadata.json.` +This describes the export +of `./examples/reference-openbis-export`. + +# API + +**Formal description:** + +To be general, the API uses a lot of strings. This allows flexibility in the classes being used. + +The interfaces are shown using Java since is a statically typed language, but they can be +implemented in most languages, +including Python and Javascript. + +## Schema Representation DTOs + +```Java + +/* Represents a class, if we are talking about a schema, it is closely related with the definition of a table or type */ +interface IType +{ + + /* Returns the ID of this type */ + String getId(); + + /* Returns IDs of the types this type inherits from */ + List getSubClassOf(); + + /* Returns the ontological annotations of this type */ + List getOntologicalAnnotations(); + + /* Returns a human-readable description of this type */ + String getComment(); + + /* Returns a human-readable label of this type */ + String getLabel(); + + /* Get Restrictions placed on the properties of this type */ + List getResstrictions(); + +} + +/* Represents a property in a graph, if we are talking about a schema, is closely related with a table column or type property */ +interface IPropertyType +{ + + /* Returns the ID of this property type */ + String getId(); + + /* Return possible values for the subject of this property type */ + List getDomain(); + + /* Return possible values for the object of this property type */ + List getRange(); + + /* Returns the ontological annotations of this property type */ + List getOntologicalAnnotations(); + + /* Returns whether this property has a min cardinality. 0 means optional, 1 means mandatory. */ + int getMinCardinality(); + + /* Returns whether this property has a max cardinality. 0 means many values possible, 1 means only one is possible. */ + int getMaxCardinality(); + + /* Returns a human-readable description of this type */ + String getComment(); + + /* Returns a human-readable label of this type */ + String getLabel(); + + + } +``` + +## Metadata Representation DTOs + +```Java +/* Represents a metadata entity. It is described */ +interface IMetadataEntry +{ + + + /** + * Returns the ID of this entry + */ + String getId(); + + /* Returns the type ID of this entry */ + String getClassId(); + + /* These are key-value pairs for serialization. These are single-valued. + * Serializable classes are: String, Number and Boolean */ + Map getValues(); + + /* These are references to other objects in the graph. + * Each key may have one or more references */ + Map> getReferences(); +} +``` + +## Additional RO-Crate API Methods + + +```Java +/* The API to program against, this wraps around existing RO-Crate APIs. */ +interface ISchemaFacade +{ + + /* Get the crate being worked on */ + RoCrate getCrate(); + + /* Adds a single class */ + void addType(IType rdfsClass); + + /** Retrieves all Classes */ + List getTypes(); + + /* Get a single type by its ID */ + IType getTypes(String id); + + /* Adds a single property */ + void addPropertyType(IPropertyType property); + + /* Get all Properties */ + List getPropertyTypes(); + + /* Gets a single property by its ID. */ + IPropertyType getPropertyType(String id); + + /* Add a single metadata entry */ + void addEntry(IMetadataEntry entry); + + /* Get a single metadata entry by its ID */ + IMetadataEntry getEntry(String id); + + /* Get all metadata entities */ + List getEntries(String rdfsClassId); + +} +``` + +# Primitive Data Types + +The following types from xsd are supported + + +| serialized as | in library | Usage | +|----------------|--------------|-------------------------------| +| xsd:integer | INTEGER | Any length of integer | +| xsd:float | FLOAT | 32-bit floating point number | +| xsd:double | DOUBLE | 64-bit floating point number | +| xsd:decimal | DECIMAL | Arbitrary size decimal number | +| xsd:float | FLOAT | 32-bit floating point number | +| xsd:datetime | DATETIME | Datetime | +| xsd:string | STRING | String | +| rdf:XMLLiteral | DATETIME | XML | + + + + + + +# API Reference Implementation in Java + +A working implementation of the API for Java (source and compiled) can be found +under: `./lib/src`. + +A compiled jar can be found under: `./lib/java/bin`. +The dependencies are specified in the module's `build.gradle` +file: `./lib/java/src/build.gradle`. + +# API Reference Examples in Java + +Working examples of the API in java to read and write can be found +at: `./`, specifically the class +files + +- `./lib/java/src/java/ch/eth/sis/rocrate/example/ReadExample.java` +- `./lib/java/src/java/ch/eth/sis/rocrate/example/WriteExample.java` + + + +# Ongoing Work / Future Plans + +## More serialization formats + +We are planning to investigate different formats for serializing schema, metadata and ontological annotations. + +## Including reference ontologies inside the RO-Crate + +One issue is that ontologies in RO-Crate are links. These can be subject to link rot. +To address this, reference ontologies are included in the RO-Crate. This helps interpretability and allows it to be shared more easily. +Think of it as docker for data! + +## Separate files for schemas + +At the moment, the graph inside the RO-Crate manifest can become large, unwieldy even. +Moving this into one or more separate files and referencing them in the manifest should keep things more manageable. + + + +## Resolve schema.org types automagically + +This allows using the schema.org without explicitly defining them in the schema. +It makes it easier to use the convention that is common in RO-Crate. + + +# People + +- Andreas Meier (andreas.meier@ethz.ch) +- Juan Fuentes (juan.fuentes@id.ethz.ch) diff --git a/README.md b/README.md new file mode 100644 index 0000000..68a0da3 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Ro-Crate SIS Specifications Directory + + +## Purpose + +This repository contains Profiles/Modules specifications to use with RO-Crate. + +It serves as a permanent URL for these specifications. + +## Structure + +Each specification is in a separate directory. + +``` +/specification-name/ +``` + +This directory contains different versions, each identified by a directory names. + +``` +/specification-name/A.B.x/ +``` + +Each version contains a specification file, `spec.md`. + +The specification file indicates which RO-Crate versions it is compatible with. + +PATCH versions are contained in the same directory, PATCHES are intended to fix issues that do not change the workings of the specification, e.g. typos. + +Aside from this, the specifications are not changed after release. + +``` +/specification-name/A.B.x/spec.md +``` + +It may also contain library code in both source and compiled forms, if applicable. + +``` +/specification-name/A.B.x/spec.md/lib/ +``` \ No newline at end of file