This commit is contained in:
Ralph Soika 2020-11-17 11:57:38 +01:00
parent 32dfa62505
commit b7d1313dbc
5 changed files with 268 additions and 1 deletions

View file

@ -236,6 +236,13 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- Apache PDFBox -->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View file

@ -0,0 +1,219 @@
package com.alexanderlogistics;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.inject.Inject;
import org.apache.pdfbox.cos.COSInputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
import org.apache.pdfbox.pdmodel.common.PDNameTreeNode;
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
import org.imixs.archive.core.SnapshotService;
import org.imixs.workflow.FileData;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.SignalAdapter;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.exceptions.AdapterException;
import org.imixs.workflow.exceptions.PluginException;
/**
* The
*
* @version 1.0
* @author rsoika
*/
public class XMLPDFAdapter implements SignalAdapter {
public static final String FILE_PATTERN_PDF = ".[pP][dD][fF]";
public static final String FILE_PATTERN_XML = ".[xX][mM][lL]";
private static Logger logger = Logger.getLogger(XMLPDFAdapter.class.getName());
@Inject
WorkflowService workflowService;
@Inject
SnapshotService snapshotService;
/**
* This method posts a text from an attachment to the Imixs-ML Analyse service
* endpoint
*/
@SuppressWarnings("unchecked")
@Override
public ItemCollection execute(ItemCollection document, ItemCollection event) throws AdapterException {
logger.info("......starting xml extraction..." );
try {
byte[] xmlData = getXMLFile(document, FILE_PATTERN_PDF);
} catch (PluginException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return document;
}
/**
* This method searches attached PDF files of a workitem and extracts an
* embedded XML file.
* <p>
* The method only returns the first embedded xml file and does not support
* multiple xml files embedded in one pdf file.
*
* @param document
* @param filePattern
* @return
* @throws PluginException
*/
public static byte[] getXMLFile(ItemCollection document, String file_pattern) throws PluginException {
// verify all attached PDF files
List<String> filenames = document.getFileNames();
for (String filename : filenames) {
if (Pattern.compile(file_pattern).matcher(filename).find()) {
logger.info("...extract embedded XML from '" + filename + "'");
// we only support the first embedded XML file here!
FileData pdfFileData = document.getFileData(filename);
return getFirstEmbeddedXML(pdfFileData.getContent());
}
}
// no data found
return null;
}
/**
* Helper method to extract the first XML file from a list of files
*
* @param names
* @return
* @throws IOException
*/
private static byte[] extractFirstXMLFile(Map<String, PDComplexFileSpecification> names) throws IOException {
for (Map.Entry<String, PDComplexFileSpecification> entry : names.entrySet()) {
PDComplexFileSpecification fileSpec = entry.getValue();
String filename = fileSpec.getFile();
// test if file is a xml file
if (Pattern.compile(FILE_PATTERN_XML).matcher(filename).find()) {
// we found an xml file!
PDEmbeddedFile embeddedFile = getEmbeddedFile(fileSpec);
COSInputStream inStream = embeddedFile.createInputStream();
return streamToByteArray(inStream);
}
}
// no XML file found
return null;
}
/**
* This method extract the first XML file form a pdf file content
*
* @param content
* @return a byte array with the xml data or null if no xml file was found in
* the pdf file.
*/
private static byte[] getFirstEmbeddedXML(byte[] content) {
PDDocument doc = null;
byte[] result = null;
try {
doc = PDDocument.load(content);
PDDocumentNameDictionary namesDictionary = new PDDocumentNameDictionary(doc.getDocumentCatalog());
PDEmbeddedFilesNameTreeNode efTree = namesDictionary.getEmbeddedFiles();
if (efTree != null) {
Map<String, PDComplexFileSpecification> names = efTree.getNames();
if (names != null) {
result = extractFirstXMLFile(names);
} else {
List<PDNameTreeNode<PDComplexFileSpecification>> kids = efTree.getKids();
for (PDNameTreeNode<PDComplexFileSpecification> node : kids) {
names = node.getNames();
result = extractFirstXMLFile(names);
}
}
}
} catch (IOException e) {
logger.warning("unable to load embedded xml : " + e.getMessage());
} finally {
if (doc != null) {
try {
doc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* Helper method to extract platform specific embedded file format.
*
* @param fileSpec
* @return
*/
private static PDEmbeddedFile getEmbeddedFile(PDComplexFileSpecification fileSpec) {
PDEmbeddedFile embeddedFile = null;
if (fileSpec != null) {
embeddedFile = fileSpec.getEmbeddedFileUnicode();
if (embeddedFile == null) {
embeddedFile = fileSpec.getEmbeddedFileDos();
}
if (embeddedFile == null) {
embeddedFile = fileSpec.getEmbeddedFileMac();
}
if (embeddedFile == null) {
embeddedFile = fileSpec.getEmbeddedFileUnix();
}
if (embeddedFile == null) {
embeddedFile = fileSpec.getEmbeddedFile();
}
}
return embeddedFile;
}
/**
* This method converts a inputStream into a byte array.
*
* @param ins
* @return
* @throws IOException
*/
public static byte[] streamToByteArray(InputStream ins) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[1024];
int len;
while ((len = ins.read(byteBuffer)) > -1) {
baos.write(byteBuffer, 0, len);
}
baos.flush();
return baos.toByteArray();
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
bean-discovery-mode="all" version="2.0">
</beans>

View file

@ -29,7 +29,7 @@
<org.imixs.marty.version>4.1.8</org.imixs.marty.version> <org.imixs.marty.version>4.1.8</org.imixs.marty.version>
<org.imixs.office.version>4.4.0</org.imixs.office.version> <org.imixs.office.version>4.4.0</org.imixs.office.version>
<org.imixs.adapters.version>2.2.3</org.imixs.adapters.version> <org.imixs.adapters.version>2.2.3</org.imixs.adapters.version>
<org.imixs.archive.version>2.2.4</org.imixs.archive.version> <org.imixs.archive.version>2.2.7</org.imixs.archive.version>
<org.imixs.melman.version>1.0.19</org.imixs.melman.version> <org.imixs.melman.version>1.0.19</org.imixs.melman.version>
<org.imixs.ml.version>1.0.1</org.imixs.ml.version> <org.imixs.ml.version>1.0.1</org.imixs.ml.version>
<microprofile.version>2.2</microprofile.version> <microprofile.version>2.2</microprofile.version>

View file

@ -39,6 +39,7 @@
</bpmn2:extensionElements> </bpmn2:extensionElements>
<bpmn2:signal id="Signal_1" name="org.imixs.archive.documents.OCRDocumentAdapter"/> <bpmn2:signal id="Signal_1" name="org.imixs.archive.documents.OCRDocumentAdapter"/>
<bpmn2:signal id="Signal_2" name="org.imixs.ml.workflow.MLAdapter"/> <bpmn2:signal id="Signal_2" name="org.imixs.ml.workflow.MLAdapter"/>
<bpmn2:signal id="Signal_3" name="com.alexanderlogistics.XMLPDFAdapter"/>
<bpmn2:collaboration id="Collaboration_1" name="Default Collaboration"> <bpmn2:collaboration id="Collaboration_1" name="Default Collaboration">
<bpmn2:participant id="Participant_1" name="Posteingang" processRef="Process_1"/> <bpmn2:participant id="Participant_1" name="Posteingang" processRef="Process_1"/>
<bpmn2:textAnnotation id="TextAnnotation_1"> <bpmn2:textAnnotation id="TextAnnotation_1">
@ -92,6 +93,7 @@ Possible ImageTypes are:
<bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef> <bpmn2:flowNodeRef>StartEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>IntermediateCatchEvent_8</bpmn2:flowNodeRef> <bpmn2:flowNodeRef>IntermediateCatchEvent_8</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>EndEvent_1</bpmn2:flowNodeRef> <bpmn2:flowNodeRef>EndEvent_1</bpmn2:flowNodeRef>
<bpmn2:flowNodeRef>IntermediateCatchEvent_1</bpmn2:flowNodeRef>
</bpmn2:lane> </bpmn2:lane>
</bpmn2:laneSet> </bpmn2:laneSet>
<bpmn2:task id="Task_1" imixs:processid="100" name="Erfassung"> <bpmn2:task id="Task_1" imixs:processid="100" name="Erfassung">
@ -122,6 +124,7 @@ Possible ImageTypes are:
</bpmn2:extensionElements> </bpmn2:extensionElements>
<bpmn2:documentation id="Documentation_3"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation> <bpmn2:documentation id="Documentation_3"><![CDATA[<textblock><itemvalue>$workflowgroup</itemvalue> - <itemvalue>$workflowstatus</itemvalue></textblock>]]></bpmn2:documentation>
<bpmn2:incoming>SequenceFlow_13</bpmn2:incoming> <bpmn2:incoming>SequenceFlow_13</bpmn2:incoming>
<bpmn2:incoming>SequenceFlow_26</bpmn2:incoming>
<bpmn2:outgoing>SequenceFlow_3</bpmn2:outgoing> <bpmn2:outgoing>SequenceFlow_3</bpmn2:outgoing>
</bpmn2:task> </bpmn2:task>
<bpmn2:exclusiveGateway id="ExclusiveGateway_1" gatewayDirection="Diverging"> <bpmn2:exclusiveGateway id="ExclusiveGateway_1" gatewayDirection="Diverging">
@ -1124,6 +1127,26 @@ Betrag: <itemvalue>_amount</itemvalue> (Brutto € <itemvalue>_amount_brutto</it
<bpmn2:sequenceFlow id="SequenceFlow_2" sourceRef="BoundaryEvent_1" targetRef="IntermediateCatchEvent_3"/> <bpmn2:sequenceFlow id="SequenceFlow_2" sourceRef="BoundaryEvent_1" targetRef="IntermediateCatchEvent_3"/>
<bpmn2:sequenceFlow id="SequenceFlow_8" sourceRef="BoundaryEvent_2" targetRef="IntermediateCatchEvent_8"/> <bpmn2:sequenceFlow id="SequenceFlow_8" sourceRef="BoundaryEvent_2" targetRef="IntermediateCatchEvent_8"/>
<bpmn2:sequenceFlow id="SequenceFlow_25" sourceRef="BoundaryEvent_3" targetRef="IntermediateCatchEvent_10"/> <bpmn2:sequenceFlow id="SequenceFlow_25" sourceRef="BoundaryEvent_3" targetRef="IntermediateCatchEvent_10"/>
<bpmn2:intermediateCatchEvent id="IntermediateCatchEvent_1" imixs:activityid="50" name="XML Test">
<bpmn2:extensionElements>
<imixs:item name="txtactivityresult" type="CDATA">
<imixs:value><![CDATA[ <item name="PDFXMLExtractor">
<filename>*.xml</filename>
<report>myReport</report>
</item>]]></imixs:value>
</imixs:item>
</bpmn2:extensionElements>
<bpmn2:outgoing>SequenceFlow_26</bpmn2:outgoing>
<bpmn2:dataOutput id="DataOutput_7" name="Signal_7_Output"/>
<bpmn2:dataOutputAssociation id="DataOutputAssociation_7">
<bpmn2:sourceRef>DataOutput_7</bpmn2:sourceRef>
</bpmn2:dataOutputAssociation>
<bpmn2:outputSet id="OutputSet_7" name="Output Set 7">
<bpmn2:dataOutputRefs>DataOutput_7</bpmn2:dataOutputRefs>
</bpmn2:outputSet>
<bpmn2:signalEventDefinition id="SignalEventDefinition_7" signalRef="Signal_3"/>
</bpmn2:intermediateCatchEvent>
<bpmn2:sequenceFlow id="SequenceFlow_26" sourceRef="IntermediateCatchEvent_1" targetRef="Task_1"/>
</bpmn2:process> </bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Collaboration Diagram"> <bpmndi:BPMNDiagram id="BPMNDiagram_1" name="Default Collaboration Diagram">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
@ -1285,6 +1308,12 @@ Betrag: <itemvalue>_amount</itemvalue> (Brutto € <itemvalue>_amount_brutto</it
<dc:Bounds height="315.0" width="529.0" x="446.0" y="600.0"/> <dc:Bounds height="315.0" width="529.0" x="446.0" y="600.0"/>
</bpmndi:BPMNLabel> </bpmndi:BPMNLabel>
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BPMNShape_IntermediateCatchEvent_1" bpmnElement="IntermediateCatchEvent_1">
<dc:Bounds height="36.0" width="36.0" x="242.0" y="182.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_54">
<dc:Bounds height="14.0" width="50.0" x="235.0" y="218.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="BPMNShape_ExclusiveGateway_1" targetElement="BPMNShape_IntermediateCatchEvent_2"> <bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_1" bpmnElement="SequenceFlow_1" sourceElement="BPMNShape_ExclusiveGateway_1" targetElement="BPMNShape_IntermediateCatchEvent_2">
<di:waypoint xsi:type="dc:Point" x="426.0" y="296.0"/> <di:waypoint xsi:type="dc:Point" x="426.0" y="296.0"/>
<di:waypoint xsi:type="dc:Point" x="426.0" y="188.0"/> <di:waypoint xsi:type="dc:Point" x="426.0" y="188.0"/>
@ -1438,6 +1467,12 @@ Betrag: <itemvalue>_amount</itemvalue> (Brutto € <itemvalue>_amount_brutto</it
<di:waypoint xsi:type="dc:Point" x="739.0" y="438.0"/> <di:waypoint xsi:type="dc:Point" x="739.0" y="438.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_52"/> <bpmndi:BPMNLabel id="BPMNLabel_52"/>
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_SequenceFlow_26" bpmnElement="SequenceFlow_26" sourceElement="BPMNShape_IntermediateCatchEvent_1" targetElement="BPMNShape_Task_1">
<di:waypoint xsi:type="dc:Point" x="278.0" y="200.0"/>
<di:waypoint xsi:type="dc:Point" x="296.0" y="200.0"/>
<di:waypoint xsi:type="dc:Point" x="296.0" y="296.0"/>
<bpmndi:BPMNLabel id="BPMNLabel_55"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
<bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1"> <bpmndi:BPMNLabelStyle id="BPMNLabelStyle_1">
<dc:Font name="arial" size="9.0"/> <dc:Font name="arial" size="9.0"/>