Skip to content
Snippets Groups Projects
Commit ca1ee0cc authored by OZGCloud's avatar OZGCloud
Browse files

OZG-4865 use nachricht text from Smartdocuments

parent 5e73f606
No related branches found
No related tags found
No related merge requests found
......@@ -81,6 +81,13 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!--dev tools-->
<dependency>
<groupId>org.mapstruct</groupId>
......
package de.ozgcloud.bescheid;
import java.io.File;
import java.util.Optional;
import de.ozgcloud.bescheid.vorgang.Vorgang;
import de.ozgcloud.bescheid.vorgang.VorgangId;
......@@ -25,5 +26,8 @@ public class Bescheid {
private String contentType;
private long size;
@Builder.Default
private Optional<String> nachrichtText = Optional.empty();
private Vorgang.ServiceKonto serviceKonto;
}
package de.ozgcloud.bescheid.smartdocuments;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Optional;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
......@@ -12,6 +20,8 @@ import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -21,6 +31,8 @@ import de.ozgcloud.bescheid.Bescheid;
import de.ozgcloud.bescheid.BescheidRemoteService;
import de.ozgcloud.bescheid.BescheidRequest;
import de.ozgcloud.bescheid.common.callcontext.UserProfile;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentDocument;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentFile;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.BescheidData;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.UserData;
......@@ -40,6 +52,9 @@ import reactor.core.publisher.Mono;
@ConditionalOnProperty("ozgcloud.bescheid.smart-documents.url")
class SmartDocumentsBescheidRemoteService implements BescheidRemoteService {
@SuppressWarnings("deprecation") // SD requires forced UTF-8 encoding
private static final MediaType JSON_MEDIA_TYPE_FOR_SD = MediaType.APPLICATION_JSON_UTF8;
@Autowired
@Qualifier("smartDocuments")
private WebClient smartDocumentsWebClient;
......@@ -53,7 +68,7 @@ class SmartDocumentsBescheidRemoteService implements BescheidRemoteService {
LOG.debug(() -> buildLogRequest(sdRequest));
return smartDocumentsWebClient.post().accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.contentType(JSON_MEDIA_TYPE_FOR_SD)
.bodyValue(sdRequest)
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, this::handleClientError)
......@@ -85,16 +100,50 @@ class SmartDocumentsBescheidRemoteService implements BescheidRemoteService {
.bescheidFileName(smartDocumentsFile.getFilename())
.size(smartDocumentsFile.getDocument().getData().length())
.contentType(MediaType.APPLICATION_PDF_VALUE)
.nachrichtText(getNachrichtText(smartDocumentsResponse))
.genehmigt(request.isGenehmigt())
.createdBy(request.getCreateFor().getId())
.vorgangId(request.getVorgangId())
.build();
}
private SmartDocumentsResponse.SmartDocumentFile getSmartDocumentsFile(SmartDocumentsResponse response) {
private SmartDocumentFile getSmartDocumentsFile(SmartDocumentsResponse response) {
return getSmartDocumentsFile(response, "PDF")
.orElseThrow(() -> new IllegalStateException("No PDF File in SmartDocuments Response found."));
}
Optional<String> getNachrichtText(SmartDocumentsResponse response) {
return getXMLFile(response).flatMap(this::extractTextFormXmlFile);
}
Optional<String> extractTextFormXmlFile(File xmlFile) {
var xPath = XPathFactory.newInstance().newXPath();
try {
var document = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().parse(xmlFile);
var expr = xPath.compile("/root/SmartDocument/Fields/NachrichtenText/text()");
var text = (Text) expr.evaluate(document, XPathConstants.NODE);
return Optional.of(text.getTextContent());
} catch (XPathExpressionException | SAXException | IOException | ParserConfigurationException e) {
LOG.error("XML-Parsing error on extracting Nachricht-Text: {}", e.getMessage(), e);
} catch (ClassCastException e) {
LOG.error("Error on extraction Nachricht-Text. XPath return unexpected Type.", e);
} catch (RuntimeException e) {
LOG.error("Unexpected Error on extracting NachrichtText: {}", e.getMessage(), e);
}
return Optional.empty();
}
Optional<File> getXMLFile(SmartDocumentsResponse response) {
return getSmartDocumentsFile(response, "XML")
.map(SmartDocumentFile::getDocument)
.map(SmartDocumentDocument::getData);
}
Optional<SmartDocumentFile> getSmartDocumentsFile(SmartDocumentsResponse response, String fileType) {
return response.getFile().stream()
.filter(file -> file.getOutputFormat().equals("PDF"))
.findAny().orElseThrow(() -> new IllegalStateException("No PDF File in SmartDocuments Response found."));
.filter(file -> file.getOutputFormat().equals(fileType))
.findFirst();
}
SmartDocumentsRequest createRequest(BescheidRequest request, Vorgang vorgang) {
......
package de.ozgcloud.bescheid.smartdocuments;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.io.File;
import java.util.Optional;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import de.ozgcloud.bescheid.BescheidRequestTestFactory;
import de.ozgcloud.bescheid.BescheidTestFactory;
import de.ozgcloud.bescheid.common.callcontext.UserProfileTestFactory;
import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.UserData;
import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
import de.ozgcloud.common.binaryfile.TempFileUtils;
import de.ozgcloud.common.test.TestUtils;
class SmartDocumentsBescheidRemoteServiceTest {
@Spy
@InjectMocks
private SmartDocumentsBescheidRemoteService service;
......@@ -43,4 +52,37 @@ class SmartDocumentsBescheidRemoteServiceTest {
.extracting(UserData::getEmail).isEqualTo(UserProfileTestFactory.EMAIL);
}
}
@Nested
class TestGetNachrichtText {
private File xmlFile = TempFileUtils.writeTmpFile(TestUtils.loadFile("SD_answer.xml"));
@Test
void shouldCallExtractText() {
doReturn(Optional.of(xmlFile)).when(service).getXMLFile(any());
service.getNachrichtText(SmartDocumentsResponseTestFactory.create());
verify(service).extractTextFormXmlFile(notNull());
}
@Nested
class ExtractingText {
@Test
void shouldReturnText() {
var text = service.extractTextFormXmlFile(xmlFile);
assertThat(text).isPresent().get().isNotNull();
}
@Test
void shouldHandleError() {
var text = service.extractTextFormXmlFile(null);
assertThat(text).isEmpty();
}
}
}
}
This diff is collapsed.
......@@ -48,7 +48,7 @@ abstract class BayernIdPostfachNachrichtMapper {
@Mapping(target = "nachrichtenKopf.absender.gemeindeschluessel.schluessel", source = "bayernIdProperties.absender.gemeindeSchluessel")
@Mapping(target = "nachrichtenKopf.empfaenger.postkorbId", source = "nachricht.postfachAddress")
@Mapping(target = "nachrichtenInhalt.betreff", source = "nachricht.subject")
@Mapping(target = "nachrichtenInhalt.storkQaaLevel", constant = "LEVEL_1")
@Mapping(target = "nachrichtenInhalt.storkQaaLevel", constant = "LEVEL_1") // FIXME aus Vorgang übernehmen
@Mapping(target = "nachrichtenInhalt.zuVorgang.vorgangsId", source = "nachricht.vorgangId")
@Mapping(target = "nachrichtenInhalt.freiText.encoding.schluessel", constant = TEXT_ENCODING_PLAIN_TEXT)
@Mapping(target = "nachrichtenInhalt.freiText.encoding.tabelle", constant = TABELLE_NUMMER_TEXT_ENCODING)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment