From e1d8d95504f5b6b0c35dd136f2a51e05576f2eac Mon Sep 17 00:00:00 2001 From: Marcin Procyk Date: Wed, 13 Jul 2022 10:38:45 +0200 Subject: [PATCH] fix!: transform valueHasUri values from node to string type (DEV-1047) (#2094) * add test data * add plugin and test * add plugin to Upgrade plan + increase knora-base version * cleanup --- .gitignore | 2 +- knora-ontologies/knora-base.ttl | 2 +- test_data/upgrade/pr2094.trig | 12 +++++ .../main/scala/org/knora/webapi/package.scala | 2 +- .../upgrade/RepositoryUpdatePlan.scala | 3 +- .../upgrade/plugins/UpgradePluginPR2079.scala | 2 +- .../upgrade/plugins/UpgradePluginPR2094.scala | 52 +++++++++++++++++++ .../plugins/UpgradePluginPR2094Spec.scala | 51 ++++++++++++++++++ 8 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 test_data/upgrade/pr2094.trig create mode 100644 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094.scala create mode 100644 webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094Spec.scala diff --git a/.gitignore b/.gitignore index a784514809..009d44d69d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ sipi/test *.bak *.rdb .sbtrc -**/*.trig +/*.trig dependencies.txt /client-test-data.zip diff --git a/knora-ontologies/knora-base.ttl b/knora-ontologies/knora-base.ttl index 94fe5047f2..0f58df5986 100644 --- a/knora-ontologies/knora-base.ttl +++ b/knora-ontologies/knora-base.ttl @@ -19,7 +19,7 @@ rdf:type owl:Ontology ; rdfs:label "The Knora base ontology"@en ; :attachedToProject knora-admin:SystemProject ; - :ontologyVersion "knora-base v22" . + :ontologyVersion "knora-base v23" . ################################################################# diff --git a/test_data/upgrade/pr2094.trig b/test_data/upgrade/pr2094.trig new file mode 100644 index 0000000000..42e284b5d2 --- /dev/null +++ b/test_data/upgrade/pr2094.trig @@ -0,0 +1,12 @@ +@prefix rdf: . +@prefix knora-base: . + +# bad valueHasUri value and missing datatype + + rdf:type knora-base:StandoffUriTag ; + knora-base:standoffTagHasEnd 50 ; + knora-base:standoffTagHasStart 20 ; + knora-base:standoffTagHasStartIndex 2 ; + knora-base:standoffTagHasStartParent ; + knora-base:standoffTagHasUUID "dd2e785b-041e-4bcb-a77d-570efe8a068c" ; + knora-base:valueHasUri . diff --git a/webapi/src/main/scala/org/knora/webapi/package.scala b/webapi/src/main/scala/org/knora/webapi/package.scala index 51ef10bd45..1a6739a172 100644 --- a/webapi/src/main/scala/org/knora/webapi/package.scala +++ b/webapi/src/main/scala/org/knora/webapi/package.scala @@ -11,7 +11,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: String = "knora-base v22" + val KnoraBaseVersion: String = "knora-base v23" /** * `IRI` is a synonym for `String`, used to improve code readability. diff --git a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala index 5419eda1ed..f618a5b4bb 100644 --- a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala +++ b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala @@ -49,7 +49,8 @@ object RepositoryUpdatePlan { PluginForKnoraBaseVersion(versionNumber = 14, plugin = new NoopPlugin), // PR 1992 PluginForKnoraBaseVersion(versionNumber = 20, plugin = new UpgradePluginPR2018(log)), PluginForKnoraBaseVersion(versionNumber = 21, plugin = new UpgradePluginPR2079(log)), - PluginForKnoraBaseVersion(versionNumber = 22, plugin = new UpgradePluginPR2081(log)) + PluginForKnoraBaseVersion(versionNumber = 22, plugin = new UpgradePluginPR2081(log)), + PluginForKnoraBaseVersion(versionNumber = 23, plugin = new UpgradePluginPR2094(log)) // KEEP IT ON THE BOTTOM // From "versionNumber = 6" don't use prBasedVersionString! ) diff --git a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2079.scala b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2079.scala index 56a250bfa3..d89939a15e 100644 --- a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2079.scala +++ b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2079.scala @@ -38,7 +38,7 @@ class UpgradePluginPR2079(log: Logger) extends UpgradePlugin { ) log.info( - s"Transformed valueHasIri: $literal to ${newObjectValue(literal.value)}." + s"Transformed valueHasUri: $literal to ${newObjectValue(literal.value)}." ) } diff --git a/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094.scala b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094.scala new file mode 100644 index 0000000000..82dec99e1e --- /dev/null +++ b/webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094.scala @@ -0,0 +1,52 @@ +/* + * Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.store.triplestore.upgrade.plugins + +import com.typesafe.scalalogging.Logger +import org.knora.webapi.messages.OntologyConstants +import org.knora.webapi.messages.util.rdf._ +import org.knora.webapi.store.triplestore.upgrade.UpgradePlugin + +/** + * Transforms a repository for Knora PR 2094. + * Transforms incorrect value of valueHasUri from node to string type adding also + * missing datatype ^^ + */ +class UpgradePluginPR2094(log: Logger) extends UpgradePlugin { + private val nodeFactory: RdfNodeFactory = RdfFeatureFactory.getRdfNodeFactory() + + override def transform(model: RdfModel): Unit = { + val statementsToRemove: collection.mutable.Set[Statement] = collection.mutable.Set.empty + val statementsToAdd: collection.mutable.Set[Statement] = collection.mutable.Set.empty + val newObjectValue: String => DatatypeLiteral = (value: String) => + nodeFactory.makeDatatypeLiteral(value, OntologyConstants.Xsd.Uri) + + for (statement: Statement <- model) { + if (statement.pred.iri == OntologyConstants.KnoraBase.ValueHasUri) { + statement.obj match { + case node: IriNode => + statementsToRemove += statement + + statementsToAdd += nodeFactory.makeStatement( + subj = statement.subj, + pred = statement.pred, + obj = newObjectValue(node.iri), + context = statement.context + ) + + log.info( + s"Transformed valueHasUri $node to ${newObjectValue(node.iri)}." + ) + + case _ => () + } + } + } + + model.removeStatements(statementsToRemove.toSet) + model.addStatements(statementsToAdd.toSet) + } +} diff --git a/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094Spec.scala b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094Spec.scala new file mode 100644 index 0000000000..fd4b51bc5a --- /dev/null +++ b/webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR2094Spec.scala @@ -0,0 +1,51 @@ +/* + * Copyright © 2021 - 2022 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors. + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.knora.webapi.store.triplestore.upgrade.plugins + +import com.typesafe.scalalogging.LazyLogging +import dsp.errors.AssertionException +import org.knora.webapi.messages.OntologyConstants +import org.knora.webapi.messages.util.rdf._ + +class UpgradePluginPR2094Spec extends UpgradePluginSpec with LazyLogging { + private val nodeFactory: RdfNodeFactory = RdfFeatureFactory.getRdfNodeFactory() + + "Upgrade plugin PR2094" should { + "fix the missing valueHasUri datatype" in { + // Parse the input file. + val model: RdfModel = trigFileToModel("../test_data/upgrade/pr2094.trig") + + // Use the plugin to transform the input. + val plugin = new UpgradePluginPR2094(log) + plugin.transform(model) + + // Check that the datatype was fixed. + val subj = + nodeFactory.makeIriNode("http://rdfh.ch/0103/5LE8P57nROClWUxEPJhiug/values/fEbt5NzaSe6GnCqKoF4Nhg/standoff/2") + val pred = nodeFactory.makeIriNode(OntologyConstants.KnoraBase.ValueHasUri) + + model + .find( + subj = Some(subj), + pred = Some(pred), + obj = None + ) + .toSet + .headOption match { + case Some(statement: Statement) => + statement.obj match { + case datatypeLiteral: DatatypeLiteral => + assert(datatypeLiteral.datatype == OntologyConstants.Xsd.Uri) + + case other => + throw AssertionException(s"Unexpected object for $pred: $other") + } + + case None => throw AssertionException(s"No statement found with subject $subj and predicate $pred") + } + } + } +}