Skip to content
Permalink
Browse files

feat: Add an RDF processing façade (2nd iteration) (DSP-1083) (#1759)

  • Loading branch information
benjamingeer committed Nov 24, 2020
1 parent e4e16e0 commit 346873d17b994a04b40704f0ea595f55d81db459
Showing with 2,366 additions and 1,462 deletions.
  1. +30 −30 docs/05-internals/design/principles/rdf-api.md
  2. +14 −19 docs/05-internals/development/updating-repositories.md
  3. +30 −43 test_data/test_route/texts/beol/header.xsl
  4. +7 −2 webapi/src/main/scala/org/knora/webapi/app/ApplicationActor.scala
  5. +5 −5 webapi/src/main/scala/org/knora/webapi/exceptions/Exceptions.scala
  6. +12 −3 webapi/src/main/scala/org/knora/webapi/feature/FeatureFactory.scala
  7. +3 −0 webapi/src/main/scala/org/knora/webapi/messages/BUILD.bazel
  8. +2 −2 webapi/src/main/scala/org/knora/webapi/messages/OntologyConstants.scala
  9. +3 −3 webapi/src/main/scala/org/knora/webapi/messages/StringFormatter.scala
  10. +3 −3 .../scala/org/knora/webapi/messages/admin/responder/permissionsmessages/PermissionsMessagesADM.scala
  11. +3 −3 webapi/src/main/scala/org/knora/webapi/messages/admin/responder/usersmessages/UsersMessagesADM.scala
  12. +71 −68 webapi/src/main/scala/org/knora/webapi/messages/store/triplestoremessages/TriplestoreMessages.scala
  13. +22 −22 webapi/src/main/scala/org/knora/webapi/messages/util/ConstructResponseUtilV2.scala
  14. +3 −3 webapi/src/main/scala/org/knora/webapi/messages/util/ErrorHandlingMap.scala
  15. +2 −2 webapi/src/main/scala/org/knora/webapi/messages/util/OntologyUtil.scala
  16. +21 −21 webapi/src/main/scala/org/knora/webapi/messages/util/PermissionUtilADM.scala
  17. +0 −73 webapi/src/main/scala/org/knora/webapi/messages/util/SparqlResultProtocol.scala
  18. +5 −5 webapi/src/main/scala/org/knora/webapi/messages/util/ValueUtilV1.scala
  19. +4 −4 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/JsonLDUtil.scala
  20. +94 −6 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/RdfFormatUtil.scala
  21. +69 −5 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/RdfModel.scala
  22. +72 −0 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/SparqlSelectResult.scala
  23. +122 −12 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/jenaimpl/JenaFormatUtil.scala
  24. +94 −9 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/jenaimpl/JenaModel.scala
  25. +96 −6 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/rdf4jimpl/RDF4JFormatUtil.scala
  26. +90 −9 webapi/src/main/scala/org/knora/webapi/messages/util/rdf/rdf4jimpl/RDF4JModel.scala
  27. +3 −3 ...ala/org/knora/webapi/messages/util/search/gravsearch/mainquery/GravsearchMainQueryGenerator.scala
  28. +12 −12 webapi/src/main/scala/org/knora/webapi/messages/util/standoff/StandoffTagUtilV2.scala
  29. +3 −3 ...i/src/main/scala/org/knora/webapi/messages/v1/responder/resourcemessages/ResourceMessagesV1.scala
  30. +3 −3 webapi/src/main/scala/org/knora/webapi/messages/v1/responder/usermessages/UserMessagesV1.scala
  31. +36 −36 webapi/src/main/scala/org/knora/webapi/messages/v1/responder/valuemessages/ValueMessagesV1.scala
  32. +16 −16 ...i/src/main/scala/org/knora/webapi/messages/v2/responder/ontologymessages/OntologyMessagesV2.scala
  33. +22 −24 ...i/src/main/scala/org/knora/webapi/messages/v2/responder/resourcemessages/ResourceMessagesV2.scala
  34. +1 −3 webapi/src/main/scala/org/knora/webapi/responders/BUILD.bazel
  35. +3 −2 webapi/src/main/scala/org/knora/webapi/responders/Responder.scala
  36. +14 −13 webapi/src/main/scala/org/knora/webapi/responders/admin/GroupsResponderADM.scala
  37. +36 −32 webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala
  38. +17 −16 webapi/src/main/scala/org/knora/webapi/responders/admin/PermissionsResponderADM.scala
  39. +59 −40 webapi/src/main/scala/org/knora/webapi/responders/admin/ProjectsResponderADM.scala
  40. +3 −3 webapi/src/main/scala/org/knora/webapi/responders/admin/SipiResponderADM.scala
  41. +16 −15 webapi/src/main/scala/org/knora/webapi/responders/admin/UsersResponderADM.scala
  42. +5 −4 webapi/src/main/scala/org/knora/webapi/responders/v1/CkanResponderV1.scala
  43. +4 −3 webapi/src/main/scala/org/knora/webapi/responders/v1/ListsResponderV1.scala
  44. +10 −10 webapi/src/main/scala/org/knora/webapi/responders/v1/OntologyResponderV1.scala
  45. +13 −12 webapi/src/main/scala/org/knora/webapi/responders/v1/ProjectsResponderV1.scala
  46. +41 −40 webapi/src/main/scala/org/knora/webapi/responders/v1/ResourcesResponderV1.scala
  47. +12 −11 webapi/src/main/scala/org/knora/webapi/responders/v1/SearchResponderV1.scala
  48. +14 −13 webapi/src/main/scala/org/knora/webapi/responders/v1/UsersResponderV1.scala
  49. +31 −30 webapi/src/main/scala/org/knora/webapi/responders/v1/ValuesResponderV1.scala
  50. +83 −82 webapi/src/main/scala/org/knora/webapi/responders/v2/OntologyResponderV2.scala
  51. +12 −10 webapi/src/main/scala/org/knora/webapi/responders/v2/ResourcesResponderV2.scala
  52. +13 −12 webapi/src/main/scala/org/knora/webapi/responders/v2/SearchResponderV2.scala
  53. +2 −2 webapi/src/main/scala/org/knora/webapi/responders/v2/StandoffResponderV2.scala
  54. +9 −8 webapi/src/main/scala/org/knora/webapi/responders/v2/ValuesResponderV2.scala
  55. +3 −3 webapi/src/main/scala/org/knora/webapi/routing/v1/ResourcesRouteV1.scala
  56. +3 −3 webapi/src/main/scala/org/knora/webapi/routing/v1/ValuesRouteV1.scala
  57. +1 −2 webapi/src/main/scala/org/knora/webapi/store/BUILD.bazel
  58. +11 −1 webapi/src/main/scala/org/knora/webapi/store/StoreManager.scala
  59. +10 −5 webapi/src/main/scala/org/knora/webapi/store/triplestore/TriplestoreManager.scala
  60. +10 −14 webapi/src/main/scala/org/knora/webapi/store/triplestore/embedded/JenaTDBActor.scala
  61. +146 −83 webapi/src/main/scala/org/knora/webapi/store/triplestore/http/HttpTriplestoreConnector.scala
  62. +13 −9 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdatePlan.scala
  63. +86 −73 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/RepositoryUpdater.scala
  64. +4 −3 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/UpgradePlugin.scala
  65. +2 −2 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/NoopPlugin.scala
  66. +90 −75 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1307.scala
  67. +24 −19 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1322.scala
  68. +23 −25 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1367.scala
  69. +24 −20 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1372.scala
  70. +31 −8 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1615.scala
  71. +68 −32 webapi/src/main/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1746.scala
  72. +2 −2 webapi/src/main/twirl/org/knora/webapi/messages/twirl/xsd/v1/xmlImport.scala.xml
  73. +112 −3 webapi/src/test/scala/org/knora/webapi/messages/util/rdf/RdfFormatUtilSpec.scala
  74. +126 −10 webapi/src/test/scala/org/knora/webapi/messages/util/rdf/RdfModelSpec.scala
  75. +0 −1 webapi/src/test/scala/org/knora/webapi/messages/v2/responder/metadatamessages/BUILD.bazel
  76. +2 −1 webapi/src/test/scala/org/knora/webapi/responders/v1/ResourcesResponderV1Spec.scala
  77. +16 −15 webapi/src/test/scala/org/knora/webapi/responders/v1/ValuesResponderV1Spec.scala
  78. +39 −39 webapi/src/test/scala/org/knora/webapi/responders/v2/OntologyResponderV2Spec.scala
  79. +4 −3 webapi/src/test/scala/org/knora/webapi/responders/v2/ResourcesResponderV2Spec.scala
  80. +4 −3 webapi/src/test/scala/org/knora/webapi/responders/v2/ValuesResponderV2Spec.scala
  81. +12 −11 webapi/src/test/scala/org/knora/webapi/store/triplestore/AllTriplestoreSpec.scala
  82. +25 −26 webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/BUILD.bazel
  83. +11 −14 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1307Spec.scala
  84. +6 −10 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1322Spec.scala
  85. +24 −13 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1367Spec.scala
  86. +6 −10 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1372Spec.scala
  87. +6 −10 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1615Spec.scala
  88. +35 −22 ...i/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginPR1746Spec.scala
  89. +17 −76 webapi/src/test/scala/org/knora/webapi/store/triplestore/upgrade/plugins/UpgradePluginSpec.scala
@@ -52,9 +52,37 @@ The API is in the package `org.knora.webapi.messages.util.rdf`. It includes:

To work with RDF models, start with `RdfFeatureFactory`, which returns instances
of `RdfNodeFactory`, `RdfModelFactory`, and `RdfFormatUtil`, using feature toggle
configuration.
configuration. `JsonLDUtil` does not need a feature factory.

`JsonLDUtil` does not need a feature factory.
To iterate efficiently over the statements in an `RdfModel`, use its `iterator` method.
An `RdfModel` cannot be modified while you are iterating over it.
If you are iterating to look for statements to modify, you can
collect a `Set` of statements to remove and a `Set` of statements
to add, and perform these update operations after you have finished
the iteration.

## RDF stream processing

To read or write a large amount of RDF data without generating a large string
object, you can use the stream processing methods in `RdfFormatUtil`.

To parse an `InputStream` to an `RdfModel`, use `inputStreamToRdfModel`.
To format an `RdfModel` to an `OutputStream`, use `rdfModelToOutputStream`.

To parse RDF data from an `InputStream` and process it one statement at a time,
you can write a class that implements the `RdfStreamProcessor` trait, and
use it with the `RdfFormatUtil.parseWithStreamProcessor` method.
Your `RdfStreamProcessor` can also send one statement at a time to a
formatting stream processor, which knows how to write RDF to an `OutputStream`
in a particular format. Use `RdfFormatUtil.makeFormattingStreamProcessor` to
construct one of these.


## SPARQL queries

In tests, it can be useful to run SPARQL queries to check the content of
an `RdfModel`. To do this, use the `RdfModel.asRepository` method, which
returns an `RdfRepository` that can run `SELECT` queries.


## Implementations
@@ -74,38 +102,10 @@ The RDF API uses the feature toggle `jena-rdf-library`:

- `off` (the default): use the RDF4J implementation.


The default setting is used on startup, e.g. to read ontologies from the
repository. After startup, the per-request setting is used.


## What still uses RDF4J directly

Before this API was added, Knora mainly used the RDF4J API directly, and still does
in some places:

- Code that uses RDF4J's streaming API to process large amounts of data, especially to
avoid constructing a large string in TriG format:

- `ProjectsResponderADM.projectDataGetRequestADM`

- `HttpTriplestoreConnector.turtleToTrig`

- `RepositoryUpdater`

- The repository update plugin tests, which use SPARQL.

- `TEIHeader`: uses XSLT that depends on the exact format of the RDF/XML generated by RDF4J.
The XSLT would need to be improved to handle `rdf:Description`.

- `GravsearchParser`: uses RDF4J's SPARQL parser. This is probably
not worth changing.


## TODO

- SHACL validation.

- SPARQL querying.

- A streaming parsing/formatting API for processing large graphs.
@@ -51,18 +51,18 @@ it to `org.knora.webapi.store.triplestore.upgrade.RepositoryUpdater`.

3. Download the entire repository from the triplestore into a TriG file.

4. Read the TriG file into an RDF4J `Model`.
4. Read the TriG file into an `RdfModel`.

5. Update the `Model` by running the necessary transformations, and replacing the
5. Update the `RdfModel` by running the necessary transformations, and replacing the
built-in Knora ontologies with the current ones.

6. Save the `Model` to a new TriG file.
6. Save the `RdfModel` to a new TriG file.

7. Empty the repository in the triplestore.

8. Upload the transformed repository file to the triplestore.

To update the `Model`, `RepositoryUpdater` runs a sequence of upgrade plugins, each of which
To update the `RdfModel`, `RepositoryUpdater` runs a sequence of upgrade plugins, each of which
is a class in `org.knora.webapi.store.triplestore.upgrade.plugins` and is registered
in `RepositoryUpdatePlan`.

@@ -94,32 +94,27 @@ with existing data, the following must happen:
in the string constant `org.knora.webapi.KnoraBaseVersion`.

- A plugin must be added in the package `org.knora.webapi.store.triplestore.upgrade.plugins`,
and registered in `RepositoryUpdatePlan`, to transform
existing repositories so that they are compatible with the code changes
introduced in the pull request.
to transform existing repositories so that they are compatible with the code changes
introduced in the pull request. Each new plugin must be registered
by adding it to the sequence returned by `RepositoryUpdatePlan.makePluginsForVersions`.

The order of version numbers must correspond to the order in which the pull requests
are merged.
The order of version numbers (and the plugins) must correspond to the order in which the
pull requests are merged.

An upgrade plugin is a Scala class that extends `UpgradePlugin`. The name of the plugin
class should refer to the pull request that made the transformation necessary,
using the format `UpgradePluginPRNNNN`, where `NNNN` is the number of the pull request.

A plugin's `transform` method takes an RDF4J `Model` (a mutable object representing
the repository) and modifies it as needed. For details on how to do this, see
[The RDF Model API](https://rdf4j.eclipse.org/documentation/programming/model/)
in the RDF4J documentation.
A plugin's `transform` method takes an `RdfModel` (a mutable object representing
the repository) and modifies it as needed.

Before transforming the data, a plugin can check whether a required manual transformation
has been carried out. If the requirement is not met, the plugin can throw
`InconsistentTriplestoreDataException` to abort the upgrade process.

The plugin must then be appended to the sequence `pluginsForVersions` in
`RepositoryUpdatePlan`.
`InconsistentRepositoryDataException` to abort the upgrade process.

## Testing Update Plugins

Each plugin should have a unit test that extends `UpgradePluginSpec`. A typical
test loads a TriG file containing test data into a `Model`, runs the plugin,
makes an RDF4J `SailRepository` containing the transformed `Model`, and uses
test loads a TriG file containing test data into a `RdfModel`, runs the plugin,
makes an `RdfRepository` containing the transformed `RdfModel`, and uses
SPARQL to check the result.
@@ -1,4 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
An example stylesheet that transforms an RDF/XML representation of a beol:letter into
a TEI/XML header. This stylesheet assumes that the input consists only of
<rdf:Description> elements.
-->
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
@@ -15,25 +22,6 @@
<xsl:sequence select="replace($input, '\(DE-588\)', 'http://d-nb.info/gnd/')"/>
</xsl:function>

<!-- Given a link value IRI and the document root node, returns the IRI of the target resource. -->
<xsl:function name="knora-api:getTargetResourceIri" as="xs:anyURI">
<xsl:param name="linkValueIri" as="xs:anyURI"/>
<xsl:param name="documentRoot" as="item()"/>

<xsl:choose>
<xsl:when test="boolean($documentRoot//knora-api:LinkValue[@rdf:about=$linkValueIri]//beol:person)">
<!-- The target resource is nested in the LinkValue. -->
<xsl:value-of
select="$documentRoot//knora-api:LinkValue[@rdf:about=$linkValueIri]//beol:person/@rdf:about"/>
</xsl:when>
<xsl:otherwise>
<!-- The target resource is not nested in the LinkValue. -->
<xsl:value-of
select="$documentRoot//knora-api:LinkValue[@rdf:about=$linkValueIri]//knora-api:linkValueHasTarget/@rdf:resource"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>

<!-- https://www.safaribooksonline.com/library/view/xslt-cookbook/0596003722/ch03s03.html?orpq -->
<xsl:function name="knora-api:last-day-of-month" as="xs:string">
<xsl:param name="month"/>
@@ -137,10 +125,9 @@

</xsl:function>

<xsl:template match="rdf:RDF">
<xsl:variable name="resourceIri" select="beol:letter/@rdf:about"/>
<xsl:variable name="label" select="beol:letter/rdfs1:label/text()"/>

<xsl:template match="//rdf:RDF">
<xsl:variable name="resourceIri" select="//rdf:Description[./rdf:type/@rdf:resource='http://0.0.0.0:3333/ontology/0801/beol/v2#letter']/@rdf:about"/>
<xsl:variable name="label" select="//rdf:Description[@rdf:about=$resourceIri]/rdfs1:label/text()"/>

<teiHeader>
<fileDesc>
@@ -164,31 +151,31 @@
<xsl:attribute name="ref">
<xsl:value-of select="$resourceIri"/>
</xsl:attribute>
<xsl:apply-templates/>
<xsl:apply-templates select="//rdf:Description/beol:hasAuthorValue"/>
<xsl:apply-templates select="//rdf:Description/beol:hasRecipientValue"/>
</correspDesc>
</profileDesc>
</teiHeader>
</xsl:template>

<xsl:template match="beol:letter/beol:hasAuthorValue">
<xsl:template match="//rdf:Description/beol:hasAuthorValue">
<xsl:variable name="authorValueIri" select="@rdf:resource"/>
<xsl:variable name="authorIri" select="knora-api:getTargetResourceIri($authorValueIri, /.)"/>
<xsl:variable name="authorIri" select="//rdf:Description[@rdf:about=$authorValueIri]//knora-api:linkValueHasTarget/@rdf:resource"/>

<xsl:variable name="authorIAFValue"
select="//beol:person[@rdf:about=$authorIri]//beol:hasIAFIdentifier/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$authorIri]//beol:hasIAFIdentifier/@rdf:resource"/>
<xsl:variable name="authorFamilyNameValue"
select="//beol:person[@rdf:about=$authorIri]//beol:hasFamilyName/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$authorIri]//beol:hasFamilyName/@rdf:resource"/>
<xsl:variable name="authorGivenNameValue"
select="//beol:person[@rdf:about=$authorIri]//beol:hasGivenName/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$authorIri]//beol:hasGivenName/@rdf:resource"/>

<correspAction type="sent">

<xsl:variable name="authorIAFText"
select="//knora-api:TextValue[@rdf:about=$authorIAFValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$authorIAFValue]/knora-api:valueAsString/text()"/>
<xsl:variable name="authorFamilyNameText"
select="//knora-api:TextValue[@rdf:about=$authorFamilyNameValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$authorFamilyNameValue]/knora-api:valueAsString/text()"/>
<xsl:variable name="authorGivenNameText"
select="//knora-api:TextValue[@rdf:about=$authorGivenNameValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$authorGivenNameValue]/knora-api:valueAsString/text()"/>

<persName>
<xsl:attribute name="ref">
@@ -203,32 +190,32 @@
<xsl:variable name="dateValue" select="//beol:creationDate/@rdf:resource"/>

<xsl:variable name="dateObj"
select="//knora-api:DateValue[@rdf:about=$dateValue]"/>
select="//rdf:Description[@rdf:about=$dateValue]"/>

<xsl:copy-of select="knora-api:dateformat($dateObj)"/>

</correspAction>
</xsl:template>

<xsl:template match="beol:letter/beol:hasRecipientValue">
<xsl:template match="//rdf:Description/beol:hasRecipientValue">
<xsl:variable name="recipientValueIri" select="@rdf:resource"/>
<xsl:variable name="recipientIri" select="knora-api:getTargetResourceIri($recipientValueIri, /.)"/>
<xsl:variable name="recipientIri" select="//rdf:Description[@rdf:about=$recipientValueIri]//knora-api:linkValueHasTarget/@rdf:resource"/>

<xsl:variable name="recipientIAFValue"
select="//beol:person[@rdf:about=$recipientIri]//beol:hasIAFIdentifier/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$recipientIri]//beol:hasIAFIdentifier/@rdf:resource"/>
<xsl:variable name="recipientFamilyNameValue"
select="//beol:person[@rdf:about=$recipientIri]//beol:hasFamilyName/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$recipientIri]//beol:hasFamilyName/@rdf:resource"/>
<xsl:variable name="recipientGivenNameValue"
select="//beol:person[@rdf:about=$recipientIri]//beol:hasGivenName/@rdf:resource"/>
select="//rdf:Description[@rdf:about=$recipientIri]//beol:hasGivenName/@rdf:resource"/>

<correspAction type="received">

<xsl:variable name="recipientIAFText"
select="//knora-api:TextValue[@rdf:about=$recipientIAFValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$recipientIAFValue]/knora-api:valueAsString/text()"/>
<xsl:variable name="recipientFamilyNameText"
select="//knora-api:TextValue[@rdf:about=$recipientFamilyNameValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$recipientFamilyNameValue]/knora-api:valueAsString/text()"/>
<xsl:variable name="recipientGivenNameText"
select="//knora-api:TextValue[@rdf:about=$recipientGivenNameValue]/knora-api:valueAsString/text()"/>
select="//rdf:Description[@rdf:about=$recipientGivenNameValue]/knora-api:valueAsString/text()"/>

<persName>
<xsl:attribute name="ref">
@@ -244,7 +231,7 @@
</xsl:template>

<!-- ignore text if there is no template for the element containing it -->
<xsl:template match="text()"></xsl:template>
<xsl:template match="text()"/>


</xsl:transform>
@@ -31,7 +31,7 @@ import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings
import com.typesafe.scalalogging.LazyLogging
import kamon.Kamon
import org.knora.webapi.core.LiveActorMaker
import org.knora.webapi.exceptions.{InconsistentTriplestoreDataException, SipiException, UnexpectedMessageException, UnsupportedValueException}
import org.knora.webapi.exceptions.{InconsistentRepositoryDataException, SipiException, UnexpectedMessageException, UnsupportedValueException}
import org.knora.webapi.feature.{FeatureFactoryConfig, KnoraSettingsFeatureFactoryConfig}
import org.knora.webapi.http.handler
import org.knora.webapi.http.version.ServerVersion
@@ -143,7 +143,7 @@ class ApplicationActor extends Actor with Stash with LazyLogging with AroundDire
case _: ArithmeticException => Resume
case _: NullPointerException => Restart
case _: IllegalArgumentException => Stop
case e: InconsistentTriplestoreDataException =>
case e: InconsistentRepositoryDataException =>
logger.info(s"Received a 'InconsistentTriplestoreDataException', will shutdown now. Cause: {}", e.message)
Stop
case e: SipiException =>
@@ -552,6 +552,11 @@ class ApplicationActor extends Actor with Stash with LazyLogging with AroundDire
msg += s"DSP-API Server started: http://${knoraSettings.internalKnoraApiHost}:${knoraSettings.internalKnoraApiPort}\n"
msg += "------------------------------------------------\n"

defaultFeatureFactoryConfig.makeToggleSettingsString match {
case Some(toggleSettingsString) => msg += s"Default feature toggle settings: $toggleSettingsString\n"
case None => ()
}

if (allowReloadOverHTTPState | knoraSettings.allowReloadOverHTTP) {
msg += "WARNING: Resetting DB over HTTP is turned ON.\n"
msg += "------------------------------------------------\n"
@@ -324,15 +324,15 @@ object TriplestoreResponseException {
}

/**
* Indicates that the triplestore returned inconsistent data.
* Indicates an inconsistency in repository data.
*
* @param message a description of the error.
*/
case class InconsistentTriplestoreDataException(message: String, cause: Option[Throwable] = None) extends TriplestoreException(message, cause)
case class InconsistentRepositoryDataException(message: String, cause: Option[Throwable] = None) extends InternalServerException(message, cause)

object InconsistentTriplestoreDataException {
def apply(message: String, e: Throwable, log: LoggingAdapter): InconsistentTriplestoreDataException =
InconsistentTriplestoreDataException(message, Some(ExceptionUtil.logAndWrapIfNotSerializable(e, log)))
object InconsistentRepositoryDataException {
def apply(message: String, e: Throwable, log: LoggingAdapter): InconsistentRepositoryDataException =
InconsistentRepositoryDataException(message, Some(ExceptionUtil.logAndWrapIfNotSerializable(e, log)))
}

/**
@@ -227,9 +227,9 @@ abstract class FeatureFactoryConfig(protected val maybeParent: Option[FeatureFac
protected[feature] def getLocalConfig(featureName: String): Option[FeatureToggle]

/**
* Returns an [[HttpHeader]] giving the state of all feature toggles.
* Returns a string giving the state of all feature toggles.
*/
def makeHttpResponseHeader: Option[HttpHeader] = {
def makeToggleSettingsString: Option[String] = {
// Convert each toggle to its string representation.
val enabledToggles: Set[String] = getAllBaseConfigs.map {
baseConfig: FeatureToggleBaseConfig =>
@@ -246,13 +246,22 @@ abstract class FeatureFactoryConfig(protected val maybeParent: Option[FeatureFac
// Are any toggles enabled?
if (enabledToggles.nonEmpty) {
// Yes. Return a header.
Some(RawHeader(FeatureToggle.RESPONSE_HEADER, enabledToggles.mkString(",")))
Some(enabledToggles.mkString(","))
} else {
// No. Don't return a header.
None
}
}

/**
* Returns an [[HttpHeader]] giving the state of all feature toggles.
*/
def makeHttpResponseHeader: Option[HttpHeader] = {
makeToggleSettingsString.map {
settingsStr: String => RawHeader(FeatureToggle.RESPONSE_HEADER, settingsStr)
}
}

/**
* Adds an [[HttpHeader]] to an [[HttpResponse]] indicating which feature toggles are enabled.
*/
@@ -34,6 +34,9 @@ scala_library(
"@maven//:org_apache_commons_commons_text",
"@maven//:org_apache_jena_apache_jena_libs",
"@maven//:org_eclipse_rdf4j_rdf4j_client",
"@maven//:org_eclipse_rdf4j_rdf4j_repository_sail",
"@maven//:org_eclipse_rdf4j_rdf4j_sail_api",
"@maven//:org_eclipse_rdf4j_rdf4j_sail_memory",
"@maven//:org_jodd_jodd",
"@maven//:org_scala_lang_modules_scala_xml_2_12",
"@maven//:org_scala_lang_scala_library",

0 comments on commit 346873d

Please sign in to comment.