update
This commit is contained in:
parent
32dfa62505
commit
b7d1313dbc
5 changed files with 268 additions and 1 deletions
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
2
pom.xml
2
pom.xml
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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"/>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue