Skip to content
Permalink
Browse files

feat(sipi): Improve error message if XSL file not found (#1590)

  • Loading branch information
benjamingeer committed Feb 7, 2020
1 parent d925c85 commit bbb42f6fa5351dd5ec76eb79dc251b6f4f4b3d8c
@@ -1695,3 +1695,25 @@
knora-base:hasRootNode <http://rdfh.ch/lists/0001/treeList>;
knora-base:listNodePosition 1;
rdfs:label "Tree list node 11"@en .

<http://rdfh.ch/0801/608NfPLCRpeYnkXKABC5mg> a knora-base:XSLTransformation;
knora-base:attachedToProject <http://rdfh.ch/projects/yTerZGyxjZVqFMNNKXCDPF>;
knora-base:attachedToUser <http://rdfh.ch/users/root>;
knora-base:creationDate "2020-02-06T11:55:47.860023Z"^^xsd:dateTime;
knora-base:hasPermissions "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser";
knora-base:hasTextFileValue <http://rdfh.ch/0801/608NfPLCRpeYnkXKABC5mg/values/geQNPU4USB61YhNHHarQ5A>;
knora-base:isDeleted false;
rdfs:label "BEOL header XSLT" .

<http://rdfh.ch/0801/608NfPLCRpeYnkXKABC5mg/values/geQNPU4USB61YhNHHarQ5A> a knora-base:TextFileValue;
knora-base:attachedToUser <http://rdfh.ch/users/root>;
knora-base:hasPermissions "CR knora-admin:Creator|M knora-admin:ProjectMember|V knora-admin:KnownUser|RV knora-admin:UnknownUser";
knora-base:internalFilename "missing.xsl";
knora-base:internalMimeType "text/xml";
knora-base:isDeleted false;
knora-base:originalFilename "header.xsl";
knora-base:originalMimeType "text/xml";
knora-base:valueCreationDate "2020-02-06T11:55:47.860023Z"^^xsd:dateTime;
knora-base:valueHasOrder 0;
knora-base:valueHasString "header.xsl";
knora-base:valueHasUUID "geQNPU4USB61YhNHHarQ5A" .
@@ -47,9 +47,9 @@ object KnoraSipiIntegrationV1ITSpec {
}

/**
* End-to-End (E2E) test specification for testing Knora-Sipi integration. Sipi must be running with the config file
* `sipi.knora-docker-config.lua`.
*/
* End-to-End (E2E) test specification for testing Knora-Sipi integration. Sipi must be running with the config file
* `sipi.knora-docker-config.lua`.
*/
class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV1ITSpec.config) with TriplestoreJsonProtocol {

override lazy val rdfDataObjects: List[RdfDataObject] = List(
@@ -74,14 +74,15 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV
private val pathToBEOLLetterMapping = "_test_data/test_route/texts/beol/testLetter/beolMapping.xml"
private val pathToBEOLBulkXML = "_test_data/test_route/texts/beol/testLetter/bulk.xml"
private val letterIri = new MutableTestIri
private val gravsearchTemplateIri = new MutableTestIri

/**
* Adds the IRI of a XSL transformation to the given mapping.
*
* @param mapping the mapping to be updated.
* @param xsltIri the Iri of the XSLT to be added.
* @return the updated mapping.
*/
* Adds the IRI of a XSL transformation to the given mapping.
*
* @param mapping the mapping to be updated.
* @param xsltIri the Iri of the XSLT to be added.
* @return the updated mapping.
*/
private def addXSLTIriToMapping(mapping: String, xsltIri: String): String = {

val mappingXML: Elem = XML.loadString(mapping)
@@ -113,12 +114,12 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV
}

/**
* Given the id originally provided by the client, gets the generated IRI from a bulk import response.
*
* @param bulkResponse the response from the bulk import route.
* @param clientID the client id to look for.
* @return the Knora IRI of the resource.
*/
* Given the id originally provided by the client, gets the generated IRI from a bulk import response.
*
* @param bulkResponse the response from the bulk import route.
* @param clientID the client id to look for.
* @return the Knora IRI of the resource.
*/
private def getResourceIriFromBulkResponse(bulkResponse: JsObject, clientID: String): String = {
val resIriOption: Option[JsValue] = bulkResponse.fields.get("createdResources") match {
case Some(createdResources: JsArray) =>
@@ -447,12 +448,12 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV
// the file first to a place which is shared with sipi
val dest = FileUtil.createTempFile(settings, Some("jpg"))
new FileOutputStream(dest)
.getChannel
.transferFrom(
new FileInputStream(fileToUpload).getChannel,
0,
Long.MaxValue
)
.getChannel
.transferFrom(
new FileInputStream(fileToUpload).getChannel,
0,
Long.MaxValue
)

val absoluteFilePath = dest.getAbsolutePath

@@ -725,12 +726,12 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV

val gravsearchTemplateJSON: JsObject = getResponseJson(gravsearchTemplateRequest)

val gravsearchTemplateIri: IRI = gravsearchTemplateJSON.fields.get("res_id") match {
gravsearchTemplateIri.set(gravsearchTemplateJSON.fields.get("res_id") match {

case Some(JsString(gravsearchIri)) => gravsearchIri

case _ => throw InvalidApiJsonException("expected IRI for Gravsearch template")
}
})

// create an XSL transformation
val headerParams = JsObject(
@@ -774,7 +775,7 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV
val letterTEIRequest: HttpRequest = Get(baseApiUrl + "/v2/tei/" + URLEncoder.encode(letterIri.get, "UTF-8") +
"?textProperty=" + URLEncoder.encode("http://0.0.0.0:3333/ontology/0801/beol/v2#hasText", "UTF-8") +
"&mappingIri=" + URLEncoder.encode("http://rdfh.ch/projects/yTerZGyxjZVqFMNNKXCDPF/mappings/BEOLToTEI", "UTF-8") +
"&gravsearchTemplateIri=" + URLEncoder.encode(gravsearchTemplateIri, "UTF-8") +
"&gravsearchTemplateIri=" + URLEncoder.encode(gravsearchTemplateIri.get, "UTF-8") +
"&teiHeaderXSLTIri=" + URLEncoder.encode(headerXSLTIri, "UTF-8")
)

@@ -785,55 +786,71 @@ class KnoraSipiIntegrationV1ITSpec extends ITKnoraLiveSpec(KnoraSipiIntegrationV

val xmlExpected =
s"""<?xml version="1.0" encoding="UTF-8"?>
|<TEI version="3.3.0" xmlns="http://www.tei-c.org/ns/1.0">
|<teiHeader>
| <fileDesc>
| <titleStmt>
| <title>Testletter</title>
| </titleStmt>
| <publicationStmt>
| <p>This is the TEI/XML representation of the resource identified by the Iri
| ${letterIri.get}.
| </p>
| </publicationStmt>
| <sourceDesc>
| <p>Representation of the resource's text as TEI/XML</p>
| </sourceDesc>
| </fileDesc>
| <profileDesc>
| <correspDesc ref="${letterIri.get}">
| <correspAction type="sent">
| <persName ref="http://d-nb.info/gnd/118607308">Scheuchzer,
| Johann Jacob</persName>
| <date when="1703-06-10"/>
| </correspAction>
| <correspAction type="received">
| <persName ref="http://d-nb.info/gnd/119112450">Hermann,
| Jacob</persName>
| </correspAction>
| </correspDesc>
| </profileDesc>
|</teiHeader>
|
|<text><body>
| <p>[...] Viro Clarissimo.</p>
| <p>Dn. Jacobo Hermanno S. S. M. C. </p>
| <p>et Ph. M.</p>
| <p>S. P. D. </p>
| <p>J. J. Sch.</p>
| <p>En quae desideras, vir Erud.<hi rend="sup">e</hi> κεχαρισμένω θυμῷ Actorum Lipsiensium fragmenta<note>Gemeint sind die im Brief Hermanns von 1703.06.05 erbetenen Exemplare AE Aprilis 1703 und AE Suppl., tom. III, 1702.</note> animi mei erga te prope[n]sissimi tenuia indicia. Dudum est, ex quo Tibi innotescere, et tuam ambire amicitiam decrevi, dudum, ex quo Ingenij Tui acumen suspexi, immo non potui quin admirarer pro eo, quod summam Demonstrationem Tuam de Iride communicare dignatus fueris summas ago grates; quamvis in hoc studij genere, non alias [siquid] μετρικώτατος, propter aliorum negotiorum continuam seriem non altos possim scandere gradus. Perge Vir Clariss. Erudito orbi propalare Ingenij Tui fructum; sed et me amare. </p>
| <p>d. [10] Jun. 1703.<note>Der Tag ist im Manuskript unleserlich. Da der Entwurf in Scheuchzers "Copiae epistolarum" zwischen zwei Einträgen vom 10. Juni 1703 steht, ist der Brief wohl auf den gleichen Tag zu datieren.</note>
| </p>
| </body></text>
|</TEI>
|<TEI version="3.3.0" xmlns="http://www.tei-c.org/ns/1.0">
|<teiHeader>
| <fileDesc>
| <titleStmt>
| <title>Testletter</title>
| </titleStmt>
| <publicationStmt>
| <p>This is the TEI/XML representation of the resource identified by the Iri
| ${letterIri.get}.
| </p>
| </publicationStmt>
| <sourceDesc>
| <p>Representation of the resource's text as TEI/XML</p>
| </sourceDesc>
| </fileDesc>
| <profileDesc>
| <correspDesc ref="${letterIri.get}">
| <correspAction type="sent">
| <persName ref="http://d-nb.info/gnd/118607308">Scheuchzer,
| Johann Jacob</persName>
| <date when="1703-06-10"/>
| </correspAction>
| <correspAction type="received">
| <persName ref="http://d-nb.info/gnd/119112450">Hermann,
| Jacob</persName>
| </correspAction>
| </correspDesc>
| </profileDesc>
|</teiHeader>
|
|<text><body>
| <p>[...] Viro Clarissimo.</p>
| <p>Dn. Jacobo Hermanno S. S. M. C. </p>
| <p>et Ph. M.</p>
| <p>S. P. D. </p>
| <p>J. J. Sch.</p>
| <p>En quae desideras, vir Erud.<hi rend="sup">e</hi> κεχαρισμένω θυμῷ Actorum Lipsiensium fragmenta<note>Gemeint sind die im Brief Hermanns von 1703.06.05 erbetenen Exemplare AE Aprilis 1703 und AE Suppl., tom. III, 1702.</note> animi mei erga te prope[n]sissimi tenuia indicia. Dudum est, ex quo Tibi innotescere, et tuam ambire amicitiam decrevi, dudum, ex quo Ingenij Tui acumen suspexi, immo non potui quin admirarer pro eo, quod summam Demonstrationem Tuam de Iride communicare dignatus fueris summas ago grates; quamvis in hoc studij genere, non alias [siquid] μετρικώτατος, propter aliorum negotiorum continuam seriem non altos possim scandere gradus. Perge Vir Clariss. Erudito orbi propalare Ingenij Tui fructum; sed et me amare. </p>
| <p>d. [10] Jun. 1703.<note>Der Tag ist im Manuskript unleserlich. Da der Entwurf in Scheuchzers "Copiae epistolarum" zwischen zwei Einträgen vom 10. Juni 1703 steht, ist der Brief wohl auf den gleichen Tag zu datieren.</note>
| </p>
| </body></text>
|</TEI>
""".stripMargin

val xmlDiff: Diff = DiffBuilder.compare(Input.fromString(letterResponseBodyXML)).withTest(Input.fromString(xmlExpected)).build()

xmlDiff.hasDifferences should be(false)

}
}
}

"provide a helpful error message if an XSLT file is not found" in {
val missingHeaderXSLTIri = "http://rdfh.ch/0801/608NfPLCRpeYnkXKABC5mg"

val letterTEIRequest: HttpRequest = Get(baseApiUrl + "/v2/tei/" + URLEncoder.encode(letterIri.get, "UTF-8") +
"?textProperty=" + URLEncoder.encode("http://0.0.0.0:3333/ontology/0801/beol/v2#hasText", "UTF-8") +
"&mappingIri=" + URLEncoder.encode("http://rdfh.ch/projects/yTerZGyxjZVqFMNNKXCDPF/mappings/BEOLToTEI", "UTF-8") +
"&gravsearchTemplateIri=" + URLEncoder.encode(gravsearchTemplateIri.get, "UTF-8") +
"&teiHeaderXSLTIri=" + URLEncoder.encode(missingHeaderXSLTIri, "UTF-8")
)

val response: HttpResponse = singleAwaitingRequest(letterTEIRequest)
assert(response.status.intValue == 500)
val responseBodyStr: String = Await.result(response.entity.toStrict(2.seconds).map(_.data.decodeString("UTF-8")), 2.seconds)
assert(responseBodyStr.contains("Unable to get file"))
assert(responseBodyStr.contains("as requested by org.knora.webapi.responders.v2.StandoffResponderV2"))
assert(responseBodyStr.contains("Sipi responded with HTTP status code 404"))
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright © 2015-2018 the contributors (see Contributors.md).
*
* This file is part of Knora.
*
* Knora is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Knora is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with Knora. If not, see <http://www.gnu.org/licenses/>.
*/

package org.knora.webapi.messages

/**
* A request message that knows the name of the sender.
*/
trait RequestWithSender {
val senderName: String
}
@@ -23,6 +23,7 @@ import java.io.File

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import org.knora.webapi._
import org.knora.webapi.messages.RequestWithSender
import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.store.StoreRequest
import org.knora.webapi.messages.v1.responder.usermessages.UserProfileV1
@@ -379,7 +380,8 @@ case class DeleteTemporaryFileRequestV2(internalFilename: String,
* @param requestingUser the user making the request.
*/
case class SipiGetTextFileRequest(fileUrl: String,
requestingUser: UserADM) extends SipiRequestV2
requestingUser: UserADM,
senderName: String) extends SipiRequestV2 with RequestWithSender

/**
* Represents a response for [[SipiGetTextFileRequest]].
@@ -1327,7 +1327,11 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt

for {
gravsearchTemplateUrl <- recoveredGravsearchUrlFuture
response: SipiGetTextFileResponse <- (storeManager ? SipiGetTextFileRequest(fileUrl = gravsearchTemplateUrl, KnoraSystemInstances.Users.SystemUser)).mapTo[SipiGetTextFileResponse]
response: SipiGetTextFileResponse <- (storeManager ? SipiGetTextFileRequest(
fileUrl = gravsearchTemplateUrl,
requestingUser = KnoraSystemInstances.Users.SystemUser,
senderName = this.getClass.getName
)).mapTo[SipiGetTextFileResponse]
gravsearchTemplate: String = response.content

} yield gravsearchTemplate

0 comments on commit bbb42f6

Please sign in to comment.