sairn
sairn

Reputation: 490

How can I use Apache Daffodil's DataProcessor.unparse() method to reconstitute the original parsed message?

I am a beginner to Apache Daffodil.

I used Daffodil Java API to parse input text message successfully to XML string i.e.,

        Compiler dfdlCompiler = Daffodil.compiler();
        dfdlCompiler.setValidateDFDLSchemas(true);
        File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
        ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
        DataProcessor dataProcessor = processorFactory.onPath("/");
        java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
        java.io.FileInputStream fis = new java.io.FileInputStream(file);
        InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
        JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
        ParseResult parseResult = dataProcessor.parse(dis, outputter);
        Document doc = outputter.getResult().getDocument();
        XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
        String xmlString = xo.outputString(doc);

        System.out.println("parsed text... resulting xmlString=" + xmlString);

But, now, I am unclear on how to use the unparse() method to reconstitute the original text message (seems there's a dearth of examples on using Daffodil's Java API to unparse to reconstitute the original message).

Trying this:

        SAXBuilder builder = new SAXBuilder();
        Document d2 = builder.build(new StringReader(xmlString));
        JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
        WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
        UnparseResult result = dataProcessor.unparse(inputter, output);

How can I extract the original message? Or, is this approach incorrect?

Apache Daffodil version: 2.3

Java version: jdk8+


Testing with this somewhat cut-down Java app...

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import org.jdom2.Document;
import org.jdom2.output.XMLOutputter;

import org.apache.daffodil.japi.Compiler;
import org.apache.daffodil.japi.Daffodil;
import org.apache.daffodil.japi.DataProcessor;
import org.apache.daffodil.japi.ParseResult;
import org.apache.daffodil.japi.ProcessorFactory;
import org.apache.daffodil.japi.UnparseResult;
import org.apache.daffodil.japi.infoset.JDOMInfosetInputter;
import org.apache.daffodil.japi.infoset.JDOMInfosetOutputter;
import org.apache.daffodil.japi.io.InputSourceDataInputStream;
import org.jdom2.input.SAXBuilder;

public class Blah2 {

    public static void main(String[] args) throws IOException, Exception {
        Blah2 b = new Blah2();
        b.process();
    }

    private void process() throws IOException, Exception {

        Compiler dfdlCompiler = Daffodil.compiler();
        dfdlCompiler.setValidateDFDLSchemas(true);
        File schemaFile = this.getFileFromResources("EDIFACT-SupplyChain-D03B/EDIFACT-SupplyChain-Messages-D.03B.xsd");
        ProcessorFactory processorFactory = dfdlCompiler.compileFile(schemaFile);
        DataProcessor dataProcessor = processorFactory.onPath("/");
        java.io.File file = getFileFromResources("TestData/ORDERS_D.03B_Interchange.txt");
        java.io.FileInputStream fis = new java.io.FileInputStream(file);
        InputSourceDataInputStream dis = new InputSourceDataInputStream(fis);
        JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
        ParseResult parseResult = dataProcessor.parse(dis, outputter);
        Document doc = outputter.getResult().getDocument();
        XMLOutputter xo = new XMLOutputter(org.jdom2.output.Format.getPrettyFormat());
        String xmlString = xo.outputString(doc);

        System.out.println("parsed text... resulting xmlString=" + xmlString);

        SAXBuilder builder = new SAXBuilder();
        Document d2 = builder.build(new StringReader(xmlString));
        JDOMInfosetInputter inputter = new JDOMInfosetInputter(d2);
        WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));
        UnparseResult result = dataProcessor.unparse(inputter, output);

        System.out.println("unparsed xml document.. result.toString()=" + String.valueOf(result));        

        //how can I obtain the original input text???
    }

    private File getFileFromResources(String fileName) throws IOException {
        URL resource = this.getClass().getClassLoader().getResource(fileName);
        return new File(resource.getFile());
    }
}   

Output of parse operation is below.

(I still don't understand how I can accomplish the reverse - i.e., "unparse")

parsed text... resulting xmlString=<?xml version="1.0" encoding="UTF-8"?>
<D03B:Interchange xmlns:D03B="http://www.ibm.com/dfdl/edi/un/edifact/SupplyChain/D03B">
  <UNB>
    <S001>
      <E0001>UNOA</E0001>
      <E0002>4</E0002>
    </S001>
    <S002>
      <E0004>APPLICATION</E0004>
      <E0007>1</E0007>
    </S002>
    <S003>
      <E0010>COMPANY</E0010>
      <E0007>1</E0007>
    </S003>
    <S004>
      <E0017>20051107</E0017>
      <E0019>1159</E0019>
    </S004>
    <E0020>6002</E0020>
  </UNB>
  <D03B:Message>
    <UNH>
      <E0062>SSDD1</E0062>
      <S009>
        <E0065>ORDERS</E0065>
        <E0052>D</E0052>
        <E0054>03B</E0054>
        <E0051>UN</E0051>
        <E0057>EAN008</E0057>
      </S009>
    </UNH>
    <D03B:BadMessage>
      <Segment>
        <Name>BGM</Name>
        <Data>2B3232302B424B4F4439392B39</Data>
      </Segment>
      <Segment>
        <Name>DTM</Name>
        <Data>2B3133373A32303035313130373A313032</Data>
      </Segment>
      <Segment>
        <Name>NAD</Name>
        <Data>2B42592B353431323334353030303137363A3A39</Data>
      </Segment>
      <Segment>
        <Name>NAD</Name>
        <Data>2B53552B343031323334353030303039343A3A39</Data>
      </Segment>
      <Segment>
        <Name>CTA</Name>
        <Data>2B4141</Data>
      </Segment>
      <Segment>
        <Name>COM</Name>
        <Data>2B7331313A41412A7332313A41412A7333313A4141</Data>
      </Segment>
      <Segment>
        <Name>LIN</Name>
        <Data>2B312B312B303736343536393130343A4942</Data>
      </Segment>
      <Segment>
        <Name>QTY</Name>
        <Data>2B313A3235</Data>
      </Segment>
      <Segment>
        <Name>FTX</Name>
        <Data>2B41464D2B312B2B4C6F7264206F66207468652052696E6773</Data>
      </Segment>
      <Segment>
        <Name>LIN</Name>
        <Data>2B322B312B303736343536393039303A4942</Data>
      </Segment>
      <Segment>
        <Name>QTY</Name>
        <Data>2B313A3235</Data>
      </Segment>
      <Segment>
        <Name>FTX</Name>
        <Data>2B41464D2B312B2B54686520486F62626974</Data>
      </Segment>
      <Segment>
        <Name>LIN</Name>
        <Data>2B332B312B313836313030343635363A4942</Data>
      </Segment>
      <Segment>
        <Name>QTY</Name>
        <Data>2B313A3136</Data>
      </Segment>
      <Segment>
        <Name>FTX</Name>
        <Data>2B41464D2B312B2B5468652053696C6D6172696C6C696F6E</Data>
      </Segment>
      <Segment>
        <Name>LIN</Name>
        <Data>2B342B312B303539363030363735363A4942</Data>
      </Segment>
      <Segment>
        <Name>QTY</Name>
        <Data>2B313A3130</Data>
      </Segment>
      <Segment>
        <Name>FTX</Name>
        <Data>2B41464D2B312B2B546865204368696C6472656E206F6620487572696E</Data>
      </Segment>
      <Segment>
        <Name>UNS</Name>
        <Data>2B53</Data>
      </Segment>
      <Segment>
        <Name>CNT</Name>
        <Data>2B323A34</Data>
      </Segment>
    </D03B:BadMessage>
    <UNT>
      <E0074>22</E0074>
      <E0062>SSDD1</E0062>
    </UNT>
  </D03B:Message>
  <UNZ>
    <E0036>1</E0036>
    <E0020>6002</E0020>
  </UNZ>
</D03B:Interchange>

unparsed xml document.. result.toString()=org.apache.daffodil.japi.UnparseResult@2e734540

Upvotes: 1

Views: 1091

Answers (1)

stevedlawrence
stevedlawrence

Reputation: 480

The UnparseResult actual doesn't contain the result of the unparse (yeah, maybe we could name that better ;). The UnparseResult actually just contains whether or not the unparse succeeded (via the isError method) and any diagnostics when something fails. The unparse data is written to the WritableByteChannel that you pass into unparse() as a parameter.

The problem is that in your case, you have the following to define that channel:

WritableByteChannel output = Channels.newChannel(new DataOutputStream(new ByteArrayOutputStream()));

So the channel you've defined writes to the underlying ByteArrayOutputStream, but you don't have any access to those bytes because it's not assigned to a variable. So really what you want to do is assign a ByteArrayOutputStream to a variable and pass it to your new channel and then access the byte array after the unparse--something like this:

ByteArrayOutputStream boas = new ByteArrayOutputStream();
WritableByteChannel output = Channels.newChannel(new DataOutputStream(boas));
UnparseResult result = dataProcessor.unparse(inputter, output);
System.out.println(boas.toString());

Also, some good resources for Daffodil Java API usage are our Java API tests here:

https://github.com/apache/incubator-daffodil/blob/master/daffodil-japi/src/test/java/org/apache/daffodil/example/TestJavaAPI.java

That has examples of using the ByteArrayOutputStream and WritableByteChannel to unparse bytes and convert to a string.

Upvotes: 2

Related Questions