Preparsers

In this section:

A preparser is a Java class designed to convert an incoming non-XML source into an XML document. This preparsed document then passes through the standard transform services to reach the designated processing business agent. Preparsers are not invoked when the "Accepts non-XML (flat) only' property in listeners is set to true.

The engine calls the preparser with the appropriate data form, if possible. Otherwise, an XDException is thrown. Stream and byte[] format can only be specified for the first preparser in a sequence.

The preparser is called on the worker thread, and one instance exists for each worker operating under the listener.

The preparser must support the appropriate transform method calls.

As of iSM Version 6.1.1, preparsers execute for all documents (flat and XML) as well as streaming listeners.


Top of page

x
public String transform()

All preparsers have at least one transform() method as their main process method. You should return a string suitable for either the standard XML parser, or (if you are depending upon chained preparsers) a string suitable for input to the next preparser. For example,

public String transform(byte[] b) throws Exception
public XDDocument transform(String s) throws Exception
public XDDocument transform(InputStream is) throws Exception

While String and byte[] formats operate on single entities (a complete input from a source) the stream format preparser is different. It receives a stream, which it can read as needed. If the stream is not complete (EOS) when the preparser emits a document, the preparser is called again upon completion of the processing for the emitted document. This provides the ability to split the input stream into several documents. For example, a file source might contain several documents, each of which is processed separately.

On completion of the stream, the preparser is responsible for emitting a "default" dummy document to satisfy the preparser specification (do not emit null) and to call

setStreamProcessed(true);

to signal to the engine that work with this stream is complete.

Note: <BATCH>EOT</BATCH> is emitted as a dummy, which is the format generated automatically by the Preparser Wizard.

Stream preparsers interact with the transaction control system slightly differently than do single entity preparsers. All documents on the stream are treated as a single transaction, and commit is not called until the setStreamProcessed(true) is called by the preparser. The signal to business agents that the stream of related documents is complete is the call to commit() in the business agent XDTx class. For example, an acknowledgment business agent might need to accumulate the acknowledgment until an entire EDI document has been handled. Its commit() method or its rollback() method would be the signal to assemble the final acknowledgment (EDI 997) and emit it to the proper destination.


Top of page

x
public int inputForm()

Returns whether the preparser expects:

Mnemonic

Input Format

XDPreParser.BOTH

Byte array and String are both accepted.

XDPreParser.BYTE

Byte array.

XDPreParser.STREAM

InputStream. Used by splitting preparsers only. Can apply only to the first preparser in a stack.

XDPreParser.STRING

String.



x
public int resultForm()

Returns whether the remainder of the message handling is to treat this document as flat or XML. A flat document is not parsed, but is sent to the business agents in the form returned from the preparser.

Mnemonic

Input Format

XDPreParser.XML_OUTPUT

Treats this message as an XML document to be parsed. This is the default value.

XDPreParser.FLAT_OUTPUT

Prevents parsing of the document and treats the message as flat (non-XML).

XDPreParser.DOCUMENT

Provides an alternate call to transform the message. The result of this call is an XDDocument; this is an XML tree. Preparsers that can automatically construct a tree can avoid the subsequent parse.

The resultForm() value is only checked for the last preparser to be executed. Values returned from preparsers earlier in the chain are ignored.



x
public XDDocument transformToDoc()

The following transformToDoc methods can only be called on the last preparser to execute in the preparser chain. These are analogous to the methods that return Strings, however, these return XDDocuments.

public XDDocument transformToDoc(byte[] b) throws Exception
public XDDocument transformToDoc(String s) throws Exception
public XDDocument transformToDoc(InputStream is) throws Exception

Top of page

x
public String execute(XDDocument indoc, XDDocument outdoc) throws XDException

In iWay Service Manager 5.5.SP2 and higher, the execute() method is available to replace the transform() method. The preparser will need to examine the input document and set the output document appropriately for passing on through the channel.

The return should always be "success" unless the preparser throws an exception.


Top of page

x
Writing a Splitting Preparser

Splitting preparsers enable a message to be divided into sections for processing. A splitting preparser must be the first configured preparser in the message flow. Such a preparser must implement the getInputForm() method, returning XDPreParser.STREAM.

The preparser reads the stream, dividing the message into portions for processing. At the end of stream, it emits an end of stream document <batch>EOT</batch> and signals to the worker that the end of stream has been reached. Your agent or reviewer can optionally elect to "see" the end of stream signal.

This example is taken from the flat document preparser. It uses a method isDelim() to determine whether the character read from the stream is a delimiter. Several delimiters in a row are permitted; for example, if the delimiter were \n, then several blank lines would be treated as a single delimiter.

StringBuffer sb = new StringBuffer(100);
BufferedInputStream bis = null;
boolean delimChar = false;
int lastChar = -1;
public String transform(InputStream is) throws Exception
{
    if (bis == null)   // initial state
    {
        bis = new BufferedInputStream(is);
    }
     String s;
    sb.setLength(0);      // clear out for next message
    int v = -1;
    for (;;)
    {
        if (!delimChar)   // need to read from stream
        {
            v = bis.read();
        }
        else              // filled lastChar trying to swallow delimiters
        {
            v = lastChar;
            delimChar = false;
        }
        if (v == -1)
        {
            break;
        }
        else
        {
            char c = (char)v;
            if (isDelim(c))     // delimiter?
            {
                for (;;)        // swallow any other delimiters
                {
                    v = bis.read();
                    char cc = (char)v;
                    if (!isDelim(cc))    // oops, read a valid char
                    {
                        lastChar = v;    // save it and signal
                        delimChar = true;
                        break;
                    }
                }
                break;
            }
            else       // append to output
            {
                sb.append(c);
            }
        }
    }
    s = sb.toString();       // create output
    if (s.length() == 0)     // end of processing?
    {
        s = "<batch>EOT</batch>";           // eos signal
        worker.setStreamProcessed(true);    // mark end of stream reached
        bis = null;                         // reset
        delimChar = false;                  // reset
    }
    return s;
}

Note the call to setStreamProcessed() on completion of the stream. This is required to instruct the flow to take end of stream actions on the EOT message.


iWay Software