From 2d62dcb6900cb2613b58e3412ead4644adf77524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Kleinb=C3=B6lting?= Date: Fri, 15 Nov 2024 16:36:20 +0100 Subject: [PATCH] feat: Add license and copyright attribution to ontologies (DEV-4347) (#3428) --- .../knoraApiOntologySimple.jsonld | 32 ++++ .../knoraApiOntologyWithValueObjects.jsonld | 176 ++++++++++++++++++ .../knora-ontologies/knora-admin.ttl | 18 +- .../resources/knora-ontologies/knora-base.ttl | 23 ++- .../webapi/messages/OntologyConstants.scala | 38 ++-- ...aseToApiV2ComplexTransformationRules.scala | 114 +++++++----- .../main/scala/org/knora/webapi/package.scala | 2 +- 7 files changed, 326 insertions(+), 77 deletions(-) diff --git a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld index 92990a3815..a012f6a442 100644 --- a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld +++ b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologySimple.jsonld @@ -902,6 +902,22 @@ { "@id": "knora-api:StillImageAbstractFileValue", "@type": "owl:Class", + "rdfs:subClassOf": [ + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1 + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1 + } + ], "rdfs:comment": "A file containing a two-dimensional still image" }, { @@ -1267,6 +1283,14 @@ }, "@id": "knora-api:hasComment" }, + { + "@id": "knora-api:hasCopyrightAttribution", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "rdfs:comment": "The copyright statement that gives credit to the original author." + }, { "rdfs:label": "has 3D-file", "rdfs:subPropertyOf": { @@ -1394,6 +1418,14 @@ }, "@id": "knora-api:hasKeyword" }, + { + "@id": "knora-api:hasLicense", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "rdfs:comment": "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. 'CC BY-SA') or a custom license." + }, { "rdfs:label": "has Link to", "rdfs:subPropertyOf": { diff --git a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld index 39bd56e9b4..667d0eb6aa 100644 --- a/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld +++ b/test_data/generated_test_data/ontologyR2RV2/knoraApiOntologyWithValueObjects.jsonld @@ -234,6 +234,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -517,6 +533,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -1315,6 +1347,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -2270,6 +2318,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -2559,6 +2623,20 @@ }, "owl:cardinality": 1 }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1 + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1 + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -3695,6 +3773,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -5925,6 +6019,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6063,6 +6173,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6208,6 +6334,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -6518,6 +6660,22 @@ "owl:cardinality": 1, "knora-api:isInherited": true }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasCopyrightAttribution" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, + { + "@type": "owl:Restriction", + "owl:onProperty": { + "@id": "knora-api:hasLicense" + }, + "owl:maxCardinality": 1, + "knora-api:isInherited": true + }, { "@type": "owl:Restriction", "owl:onProperty": { @@ -8129,6 +8287,15 @@ }, "rdfs:comment": "Represents a comment on a resource as a knora-base:TextValue" }, + { + "rdfs:label": "has copyright attribution", + "rdfs:comment": "The copyright statement that gives credit to the original author.", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "@id": "knora-api:hasCopyrightAttribution" + }, { "rdfs:label": "has 3D-file", "rdfs:subPropertyOf": { @@ -8287,6 +8454,15 @@ }, "rdfs:comment": "Indicates a keyword of a resource" }, + { + "rdfs:label": "has copyright attribution", + "rdfs:comment": "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. CC BY-SA) or a custom license.", + "@type": "owl:DatatypeProperty", + "knora-api:objectType": { + "@id": "xsd:string" + }, + "@id": "knora-api:hasLicense" + }, { "rdfs:label": "has Link to", "rdfs:subPropertyOf": { diff --git a/webapi/src/main/resources/knora-ontologies/knora-admin.ttl b/webapi/src/main/resources/knora-ontologies/knora-admin.ttl index 5e291d0e58..5368c6e3f7 100644 --- a/webapi/src/main/resources/knora-ontologies/knora-admin.ttl +++ b/webapi/src/main/resources/knora-ontologies/knora-admin.ttl @@ -377,12 +377,18 @@ [ rdf:type owl:Restriction ; owl:onProperty :projectRestrictedViewWatermark ; owl:maxCardinality "1"^^xsd:nonNegativeInteger ], - [ rdf:type owl:Restriction ; - owl:onProperty :status ; - owl:cardinality "1"^^xsd:nonNegativeInteger ], - [ rdf:type owl:Restriction ; - owl:onProperty :hasSelfJoinEnabled ; - owl:cardinality "1"^^xsd:nonNegativeInteger ] ; + [ rdf:type owl:Restriction ; + owl:onProperty :status ; + owl:cardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasSelfJoinEnabled ; + owl:cardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty knora-base:hasCopyrightAttribution ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty knora-base:hasLicense ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ]; rdfs:comment "Represents a project that uses Knora."@en . diff --git a/webapi/src/main/resources/knora-ontologies/knora-base.ttl b/webapi/src/main/resources/knora-ontologies/knora-base.ttl index ac026f6bf5..3e976e6513 100644 --- a/webapi/src/main/resources/knora-ontologies/knora-base.ttl +++ b/webapi/src/main/resources/knora-ontologies/knora-base.ttl @@ -20,7 +20,7 @@ rdf:type owl:Ontology ; rdfs:label "The Knora base ontology"@en ; :attachedToProject knora-admin:SystemProject ; - :ontologyVersion "knora-base v41" . + :ontologyVersion "knora-base v42" . ################################################################# @@ -527,6 +527,19 @@ :subjectClassConstraint :Resource ; :objectClassConstraint :Value . +### http://www.knora.org/ontology/knora-base#hasCopyrightAttribution + +:hasCopyrightAttribution + rdf:type owl:DatatypeProperty ; + rdfs:comment "The copyright statement that gives credit to the original author."@en ; + :objectDatatypeConstraint xsd:string . + +### http://www.knora.org/ontology/knora-base#hasLicense + +:hasLicense + rdf:type owl:DatatypeProperty ; + rdfs:comment "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. 'CC BY-SA') or a custom license."@en ; + :objectDatatypeConstraint xsd:string . ### http://www.knora.org/ontology/knora-base#isAnnotationOf @@ -1479,7 +1492,13 @@ owl:maxCardinality "1"^^xsd:nonNegativeInteger ], [ rdf:type owl:Restriction ; owl:onProperty :originalMimeType ; - owl:maxCardinality "1"^^xsd:nonNegativeInteger ] . + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasCopyrightAttribution ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ], + [ rdf:type owl:Restriction ; + owl:onProperty :hasLicense ; + owl:maxCardinality "1"^^xsd:nonNegativeInteger ]. ### http://www.knora.org/ontology/knora-base#DecimalBase diff --git a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala index 37fa73df89..ed6fc1db1e 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala @@ -263,6 +263,8 @@ object OntologyConstants { val HasTextFileValue: IRI = KnoraBasePrefixExpansion + "hasTextFileValue" val HasDocumentFileValue: IRI = KnoraBasePrefixExpansion + "hasDocumentFileValue" val HasArchiveFileValue: IRI = KnoraBasePrefixExpansion + "hasArchiveFileValue" + val HasCopyrightAttribution: IRI = KnoraBasePrefixExpansion + "hasCopyrightAttribution" + val HasLicense: IRI = KnoraBasePrefixExpansion + "hasLicense" val ResourceIcon: IRI = KnoraBasePrefixExpansion + "resourceIcon" @@ -617,23 +619,25 @@ object OntologyConstants { val ValueHasComment: IRI = KnoraApiV2PrefixExpansion + "valueHasComment" val NewValueVersionIri: IRI = KnoraApiV2PrefixExpansion + "newValueVersionIri" - val User: IRI = KnoraApiV2PrefixExpansion + "User" - val AttachedToUser: IRI = KnoraApiV2PrefixExpansion + "attachedToUser" - val AttachedToProject: IRI = KnoraApiV2PrefixExpansion + "attachedToProject" - val HasStandoffLinkTo: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkTo" - val HasStandoffLinkToValue: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkToValue" - val HasPermissions: IRI = KnoraApiV2PrefixExpansion + "hasPermissions" - val UserHasPermission: String = KnoraApiV2PrefixExpansion + "userHasPermission" - val CreationDate: IRI = KnoraApiV2PrefixExpansion + "creationDate" - val LastModificationDate: IRI = KnoraApiV2PrefixExpansion + "lastModificationDate" - val VersionDate: IRI = KnoraApiV2PrefixExpansion + "versionDate" - val NewModificationDate: IRI = KnoraApiV2PrefixExpansion + "newModificationDate" - val IsDeleted: IRI = KnoraApiV2PrefixExpansion + "isDeleted" - val DeleteDate: IRI = KnoraApiV2PrefixExpansion + "deleteDate" - val DeleteComment: IRI = KnoraApiV2PrefixExpansion + "deleteComment" - val ArkUrl: IRI = KnoraApiV2PrefixExpansion + "arkUrl" - val VersionArkUrl: IRI = KnoraApiV2PrefixExpansion + "versionArkUrl" - val Author: IRI = KnoraApiV2PrefixExpansion + "author" + val User: IRI = KnoraApiV2PrefixExpansion + "User" + val AttachedToUser: IRI = KnoraApiV2PrefixExpansion + "attachedToUser" + val AttachedToProject: IRI = KnoraApiV2PrefixExpansion + "attachedToProject" + val HasStandoffLinkTo: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkTo" + val HasStandoffLinkToValue: IRI = KnoraApiV2PrefixExpansion + "hasStandoffLinkToValue" + val HasPermissions: IRI = KnoraApiV2PrefixExpansion + "hasPermissions" + val HasCopyrightAttribution: IRI = KnoraApiV2PrefixExpansion + "hasCopyrightAttribution" + val HasLicense: IRI = KnoraApiV2PrefixExpansion + "hasLicense" + val UserHasPermission: String = KnoraApiV2PrefixExpansion + "userHasPermission" + val CreationDate: IRI = KnoraApiV2PrefixExpansion + "creationDate" + val LastModificationDate: IRI = KnoraApiV2PrefixExpansion + "lastModificationDate" + val VersionDate: IRI = KnoraApiV2PrefixExpansion + "versionDate" + val NewModificationDate: IRI = KnoraApiV2PrefixExpansion + "newModificationDate" + val IsDeleted: IRI = KnoraApiV2PrefixExpansion + "isDeleted" + val DeleteDate: IRI = KnoraApiV2PrefixExpansion + "deleteDate" + val DeleteComment: IRI = KnoraApiV2PrefixExpansion + "deleteComment" + val ArkUrl: IRI = KnoraApiV2PrefixExpansion + "arkUrl" + val VersionArkUrl: IRI = KnoraApiV2PrefixExpansion + "versionArkUrl" + val Author: IRI = KnoraApiV2PrefixExpansion + "author" val Resource: IRI = KnoraApiV2PrefixExpansion + "Resource" val DeletedResource: IRI = KnoraApiV2PrefixExpansion + "DeletedResource" diff --git a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala index 0801f609e1..c28fa904fa 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/KnoraBaseToApiV2ComplexTransformationRules.scala @@ -152,6 +152,16 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation .withIsResourceProp() .withIsLinkValueProp() + private val HasCopyrightAttribution = makeOwlDatatypeProperty(KA.HasCopyrightAttribution, XSD.STRING) + .withRdfLabelEn("has copyright attribution") + .withRdfCommentEn("The copyright statement that gives credit to the original author.") + + private val HasLicense = makeOwlDatatypeProperty(KA.HasLicense, XSD.STRING) + .withRdfLabelEn("has copyright attribution") + .withRdfCommentEn( + "Specifies the terms under which a work can be used. This statement may be a reference to a well-known license, such as Creative Commons (e.g. CC BY-SA) or a custom license.", + ) + private val ValueAsString = makeOwlDatatypeProperty(KA.ValueAsString, XSD.STRING) .withSubjectType(KA.Value) .withRdfCommentEn("A plain string representation of a value") @@ -625,70 +635,72 @@ object KnoraBaseToApiV2ComplexTransformationRules extends OntologyTransformation * See also [[OntologyConstants.CorrespondingIris]]. */ override val externalPropertiesToAdd: Map[SmartIri, ReadPropertyInfoV2] = Set( - Label, - Result, - MayHaveMoreResults, - Error, - CanDo, - UserHasPermission, - VersionDate, ArkUrl, - VersionArkUrl, Author, - IsShared, - IsBuiltIn, - IsResourceClass, - IsStandoffClass, - IsValueClass, - IsEditable, - IsLinkProperty, - IsLinkValueProperty, - IsInherited, - NewModificationDate, - OntologyName, - MappingHasName, - ValueAsString, - HasIncomingLinkValue, - SubjectType, - ObjectType, - TextValueHasMarkup, - TextValueHasStandoff, - TextValueHasMaxStandoffStartIndex, - NextStandoffStartIndex, - StandoffTagHasStartParentIndex, - StandoffTagHasEndParentIndex, - TextValueHasLanguage, - TextValueAsXml, - TextValueAsHtml, - TextValueHasMapping, - DateValueHasStartYear, - DateValueHasEndYear, - DateValueHasStartMonth, + BooleanValueAsBoolean, + CanDo, + ColorValueAsColor, + DateValueHasCalendar, + DateValueHasEndDay, + DateValueHasEndEra, DateValueHasEndMonth, + DateValueHasEndYear, DateValueHasStartDay, - DateValueHasEndDay, DateValueHasStartEra, - DateValueHasEndEra, - DateValueHasCalendar, - IntervalValueHasStart, + DateValueHasStartMonth, + DateValueHasStartYear, + DecimalValueAsDecimal, + Error, + FileValueAsUrl, + FileValueHasFilename, + GeometryValueAsGeometry, + GeonameValueAsGeonameCode, + HasCopyrightAttribution, + HasIncomingLinkValue, + HasLicense, + IntValueAsInt, IntervalValueHasEnd, + IntervalValueHasStart, + IsBuiltIn, + IsEditable, + IsInherited, + IsLinkProperty, + IsLinkValueProperty, + IsResourceClass, + IsShared, + IsStandoffClass, + IsValueClass, + Label, LinkValueHasSource, LinkValueHasSourceIri, LinkValueHasTarget, LinkValueHasTargetIri, - IntValueAsInt, - DecimalValueAsDecimal, - BooleanValueAsBoolean, - GeometryValueAsGeometry, ListValueAsListNode, - ColorValueAsColor, - UriValueAsUri, - GeonameValueAsGeonameCode, - FileValueAsUrl, - FileValueHasFilename, + MappingHasName, + MayHaveMoreResults, + NewModificationDate, + NextStandoffStartIndex, + ObjectType, + OntologyName, + Result, + StandoffTagHasEndParentIndex, + StandoffTagHasStartParentIndex, StillImageFileValueHasDimX, StillImageFileValueHasDimY, - StillImageFileValueHasIIIFBaseUrl, StillImageFileValueHasExternalUrl, + StillImageFileValueHasIIIFBaseUrl, + SubjectType, + TextValueAsHtml, + TextValueAsXml, + TextValueHasLanguage, + TextValueHasMapping, + TextValueHasMarkup, + TextValueHasMaxStandoffStartIndex, + TextValueHasStandoff, + UriValueAsUri, + UserHasPermission, + ValueAsString, + VersionArkUrl, + VersionDate, ).map(_.build()).map(info => info.entityInfoContent.propertyIri -> info).toMap } diff --git a/webapi/src/main/scala/org/knora/webapi/package.scala b/webapi/src/main/scala/org/knora/webapi/package.scala index ebe9fca3d4..0e40b8f2d7 100644 --- a/webapi/src/main/scala/org/knora/webapi/package.scala +++ b/webapi/src/main/scala/org/knora/webapi/package.scala @@ -14,7 +14,7 @@ package object webapi { * The version of `knora-base` and of the other built-in ontologies that this version of Knora requires. * Must be the same as the object of `knora-base:ontologyVersion` in the `knora-base` ontology being used. */ - val KnoraBaseVersion: Int = 41 + val KnoraBaseVersion: Int = 42 val KnoraBaseVersionString: String = s"$versionPrefix$KnoraBaseVersion" /**