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

OZG-5156 Make fim mapper more robust. Defaulting instead of throwing

Still work in progress. Not included in architecture.
parent 0a259e81
Branches
Tags
No related merge requests found
Showing
with 132 additions and 47 deletions
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
<artifactId>common</artifactId> <artifactId>common</artifactId>
</dependency> </dependency>
<dependency>
<groupId>de.ozgcloud.eingang</groupId>
<artifactId>semantik-adapter</artifactId>
</dependency>
<!--spring--> <!--spring-->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
...@@ -26,6 +31,7 @@ ...@@ -26,6 +31,7 @@
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!--test --> <!--test -->
<dependency> <dependency>
<groupId>de.ozgcloud.eingang</groupId> <groupId>de.ozgcloud.eingang</groupId>
...@@ -33,6 +39,10 @@ ...@@ -33,6 +39,10 @@
<type>test-jar</type> <type>test-jar</type>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>de.ozgcloud.eingang</groupId>
<artifactId>semantik-adapter</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package de.ozgcloud.eingang.fim;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.TimeZone;
@SpringBootApplication(scanBasePackages = { "de.ozgcloud" })
public class FimAdapterApplication {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
SpringApplication.run(FimAdapterApplication.class, args);
}
}
package de.ozgcloud.eingang.fim;
import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.IncomingFile;
import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
import de.ozgcloud.eingang.semantik.enginebased.EngineBasedMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@Log4j2
public class FimBasedMapper implements EngineBasedMapper {
@Autowired
private FimService fimService = null;
public boolean isResponsible(final FormData formData) {
return true;
}
@Override
public FormData parseFormData(final FormData initialFormData) {
final List<IncomingFileGroup> attachments = initialFormData.getAttachments();
final Optional<IncomingFile> metadataFileOpt = findFile(attachments, "fim_xtaMetadata.xml");
if (metadataFileOpt.isEmpty()) {
LOG.error("Metadata File not found for fim data mapping", initialFormData);
return initialFormData;
}
final Optional<String> entryPointOpt = getEntryPoint(metadataFileOpt.get());
if (entryPointOpt.isEmpty()) {
LOG.error("No entry point found in metadata file for fim data mapping", initialFormData);
return initialFormData;
}
final Optional<IncomingFile> fileOpt = findFile(attachments, entryPointOpt.get());
if (fileOpt.isEmpty()) {
LOG.error("Entry point file not found for fim data mapping", initialFormData);
return initialFormData;
}
try {
final Document document = loadDocument(fileOpt.get());
return fimService.transformDocument(document, initialFormData);
} catch (ParserConfigurationException | SAXException | IOException | FimException e) {
LOG.error("Can't transform document into fim formdata", initialFormData);
return initialFormData;
}
}
private Optional<IncomingFile> findFile(final Collection<IncomingFileGroup> attachments, final String name) {
for (IncomingFileGroup group : attachments) {
for (IncomingFile file : group.getFiles()) {
if (name.equals(file.getName())) {
return Optional.of(file);
}
}
}
return Optional.empty();
}
private Optional<String> getEntryPoint(final IncomingFile incomingFile) {
// TODO sollte über formdata metadaten kommen statt aus dem meta file geparsed zu werden
return Optional.of("antrag.xml");
}
private Document loadDocument(final IncomingFile incomingFile) throws ParserConfigurationException, IOException, SAXException {
final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return builder.parse(incomingFile.getContentStream());
}
}
package de.ozgcloud.eingang.fim;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
@RequestMapping("formData")
@RequiredArgsConstructor
public class FimDataController {
}
package de.ozgcloud.eingang.fim; package de.ozgcloud.eingang.fim;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.function.TriFunction;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
...@@ -9,20 +11,26 @@ import org.w3c.dom.Node; ...@@ -9,20 +11,26 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.w3c.dom.Text; import org.w3c.dom.Text;
import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
@Service @Service
@Log4j2 @Log4j2
public class FimDataMapper implements BiFunction<Document, FimScheme, FormData.FormDataBuilder> { public class FimDataMapper implements TriFunction<Document, FimScheme, Collection<IncomingFileGroup>, FormData.FormDataBuilder> {
private static final String LABEL_KEY = "label";
private static final String VALUE_KEY = "value";
@Override @Override
public FormData.FormDataBuilder apply(final Document document, final FimScheme fimScheme) { public FormData.FormDataBuilder apply(final Document document, final FimScheme fimScheme, final Collection<IncomingFileGroup> attachments) {
final FormData.FormDataBuilder formDataBuilder = FormData.builder(); final FormData.FormDataBuilder formDataBuilder = FormData.builder();
Map<String, Object> data = new LinkedHashMap<>(); Map<String, Object> data = new LinkedHashMap<>();
process(document.getDocumentElement(), fimScheme, data, 0); process(document.getDocumentElement(), fimScheme, data, 0);
formDataBuilder.formData(data); formDataBuilder.formData(data);
formDataBuilder.attachments(attachments);
return formDataBuilder; return formDataBuilder;
} }
...@@ -37,12 +45,17 @@ public class FimDataMapper implements BiFunction<Document, FimScheme, FormData.F ...@@ -37,12 +45,17 @@ public class FimDataMapper implements BiFunction<Document, FimScheme, FormData.F
continue; continue;
} }
if (child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text textNode) { if (child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text textNode) {
data.put(fimScheme.getFieldName(child.getNodeName()), textNode.getTextContent()); insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), textNode.getTextContent());
} else { } else {
final Map<String, Object> childMap = new LinkedHashMap<>(); final Map<String, Object> childMap = new LinkedHashMap<>();
data.put(fimScheme.getFieldName(child.getNodeName()), childMap); insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), childMap);
process((Element) child, fimScheme, childMap, level + 1); process((Element) child, fimScheme, childMap, level + 1);
} }
} }
} }
private void insertValueIntoFormData(final Map<String, Object> data, final Optional<String> fieldName, final String nodeName, final Object obj) {
final Map<String, Object> labelMap = Map.of(LABEL_KEY, fieldName.orElse(nodeName), VALUE_KEY, obj);
data.put(nodeName, labelMap);
}
} }
...@@ -4,4 +4,7 @@ public class FimException extends RuntimeException { ...@@ -4,4 +4,7 @@ public class FimException extends RuntimeException {
public FimException(final String ex) { public FimException(final String ex) {
super(ex); super(ex);
} }
public FimException(final String e, final Throwable th) {
super(e, th);
}
} }
...@@ -9,6 +9,7 @@ import org.w3c.dom.NodeList; ...@@ -9,6 +9,7 @@ import org.w3c.dom.NodeList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
public class FimScheme { public class FimScheme {
...@@ -36,7 +37,7 @@ public class FimScheme { ...@@ -36,7 +37,7 @@ public class FimScheme {
} }
} }
public String getFieldName(final String fieldName) { public Optional<String> getFieldName(final String fieldName) {
return schemeAdapter.getFieldName(fieldIndex, fieldName); return schemeAdapter.getFieldName(fieldIndex, fieldName);
} }
} }
package de.ozgcloud.eingang.fim; package de.ozgcloud.eingang.fim;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.IncomingFileGroup;
import de.ozgcloud.eingang.fim.adapter.FimSchemeAdapter; import de.ozgcloud.eingang.fim.adapter.FimSchemeAdapter;
import io.micrometer.common.util.StringUtils; import io.micrometer.common.util.StringUtils;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
...@@ -17,6 +18,7 @@ import java.io.File; ...@@ -17,6 +18,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
@Service @Service
...@@ -55,16 +57,18 @@ public class FimService implements InitializingBean { ...@@ -55,16 +57,18 @@ public class FimService implements InitializingBean {
return new FimScheme(doc, fimSchemeIdentifier, fimSchemeAdapter); return new FimScheme(doc, fimSchemeIdentifier, fimSchemeAdapter);
} }
public FormData transformDocument(final Document document) { public FormData transformDocument(final Document document, final FormData initialFormData) {
final String schemeName = document.getDocumentElement().getAttribute("xmlns:xfd"); final String schemeName = document.getDocumentElement().getAttribute("xmlns:xfd");
if (StringUtils.isEmpty(schemeName)) { if (StringUtils.isEmpty(schemeName)) {
throw new FimException("XML Document does not provide a scheme"); throw new FimException("XML Document does not provide a scheme");
} }
final FimScheme scheme = getSchemeForIdentifier(schemeName); final FimScheme scheme = getSchemeForIdentifier(schemeName);
final FormData.FormDataBuilder builder = fimDataMapper.apply(document, scheme); final FormData.FormDataBuilder builder = fimDataMapper.apply(document, scheme, initialFormData.getAttachments());
final FimSchemeAdapter adapter = scheme.getSchemeAdapter(); final FimSchemeAdapter adapter = scheme.getSchemeAdapter();
builder.header(initialFormData.getHeader());
adapter.extractAntragsteller(builder); adapter.extractAntragsteller(builder);
adapter.extractZustaendigeStelle(builder); adapter.extractZustaendigeStelle(builder);
......
...@@ -8,6 +8,7 @@ import org.w3c.dom.Element; ...@@ -8,6 +8,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import java.util.Map; import java.util.Map;
import java.util.Optional;
public class FimSchemeAdapter { public class FimSchemeAdapter {
...@@ -18,23 +19,26 @@ public class FimSchemeAdapter { ...@@ -18,23 +19,26 @@ public class FimSchemeAdapter {
return s.trim(); return s.trim();
} }
public String getFieldName(final Map<String, Element> fieldIndex, final String fieldName) { public Optional<String> getFieldName(final Map<String, Element> fieldIndex, final String fieldName) {
final String[] fieldNameParts = fieldName.split(":"); final String[] fieldNameParts = fieldName.split(":");
final String fieldNameWithoutNamespace = fieldNameParts[fieldNameParts.length - 1]; final String fieldNameWithoutNamespace = fieldNameParts[fieldNameParts.length - 1];
if (!fieldIndex.containsKey(fieldNameWithoutNamespace)) { if (!fieldIndex.containsKey(fieldNameWithoutNamespace)) {
throw new FimException("Cannot find Field: " + fieldName); throw new FimException("Cannot find Field: " + fieldName);
} }
final Element nodeNameElement = fieldIndex.get(fieldNameWithoutNamespace); final Element nodeNameElement = fieldIndex.get(fieldNameWithoutNamespace);
final String nodeName = getNameForElement(nodeNameElement); final Optional<String> nodeNameOpt = getNameForElement(nodeNameElement);
return cleanNodeName(nodeName); if (nodeNameOpt.isEmpty()) {
return nodeNameOpt;
}
return Optional.of(cleanNodeName(nodeNameOpt.get()));
} }
public String getNameForElement(final Element element) { public Optional<String> getNameForElement(final Element element) {
final NodeList nameTags = element.getElementsByTagName("name"); final NodeList nameTags = element.getElementsByTagName("name");
if (nameTags.getLength() != 1) { if (nameTags.getLength() != 1) {
throw new FimException("Multiple name tags for element: " + element.getAttribute("name")); return Optional.empty();
} }
return nameTags.item(0).getTextContent(); return Optional.ofNullable(nameTags.item(0).getTextContent());
} }
public void extractAntragsteller(final FormData.FormDataBuilder builder) { public void extractAntragsteller(final FormData.FormDataBuilder builder) {
......
...@@ -31,7 +31,7 @@ public class FimServiceTest { ...@@ -31,7 +31,7 @@ public class FimServiceTest {
void shouldFailOnEmptyScheme() { void shouldFailOnEmptyScheme() {
Exception exception = assertThrows(FimException.class, () -> { Exception exception = assertThrows(FimException.class, () -> {
final Document document = loadDocument("src/test/resources/test.xml"); final Document document = loadDocument("src/test/resources/test.xml");
fimService.transformDocument(document); fimService.transformDocument(document, FormData.builder().build());
}); });
String expectedMessage = "XML Document does not provide a scheme"; String expectedMessage = "XML Document does not provide a scheme";
...@@ -67,14 +67,14 @@ public class FimServiceTest { ...@@ -67,14 +67,14 @@ public class FimServiceTest {
@Test @Test
void shouldTransformSimpleDocument() throws ParserConfigurationException, IOException, SAXException { void shouldTransformSimpleDocument() throws ParserConfigurationException, IOException, SAXException {
final Document document = loadDocument("src/test/resources/test2.xml"); final Document document = loadDocument("src/test/resources/test2.xml");
FormData formData = fimService.transformDocument(document); FormData formData = fimService.transformDocument(document, FormData.builder().build());
Assertions.assertEquals("Testvalue", formData.getFormData().get("Testkey")); Assertions.assertEquals("Testvalue", formData.getFormData().get("Testkey"));
} }
@Test @Test
void shouldTransformDocument() throws ParserConfigurationException, IOException, SAXException { void shouldTransformDocument() throws ParserConfigurationException, IOException, SAXException {
final Document document = loadDocument("src/test/resources/S17000652V1.4_test01.xml"); final Document document = loadDocument("src/test/resources/S17000652V1.4_test01.xml");
FormData formData = fimService.transformDocument(document); FormData formData = fimService.transformDocument(document, FormData.builder().build());
assertNotNull(formData); assertNotNull(formData);
Assertions.assertEquals(true, formData.getFormData().containsKey("EfA|SH Standard")); Assertions.assertEquals(true, formData.getFormData().containsKey("EfA|SH Standard"));
......
...@@ -5,6 +5,8 @@ import org.springframework.stereotype.Service; ...@@ -5,6 +5,8 @@ import org.springframework.stereotype.Service;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import java.util.Optional;
@Service @Service
public class TestNonStandardAdapter extends FimSchemeAdapter { public class TestNonStandardAdapter extends FimSchemeAdapter {
...@@ -12,11 +14,11 @@ public class TestNonStandardAdapter extends FimSchemeAdapter { ...@@ -12,11 +14,11 @@ public class TestNonStandardAdapter extends FimSchemeAdapter {
return FimSchemeIdentifier.fromString("test2"); return FimSchemeIdentifier.fromString("test2");
} }
public String getNameForElement(final Element element) { public Optional<String> getNameForElement(final Element element) {
final NodeList nameTags = element.getElementsByTagName("non-standard-name"); final NodeList nameTags = element.getElementsByTagName("non-standard-name");
if (nameTags.getLength() != 1) { if (nameTags.getLength() != 1) {
throw new FimException("Multiple name tags for element: " + element.getAttribute("non-standard-name")); return Optional.empty();
} }
return nameTags.item(0).getTextContent(); return Optional.ofNullable(nameTags.item(0).getTextContent());
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment