How To Use OBOE 
Open Business Objects for EDI From a Java Programmer's Perspective

Version 3.9.0


Copyright 1999-2013 - American Coders, Ltd. Raleigh NC USA


Author: Joe McVerry


WORK IN PROGRESS

Last updated 2013-02-07.



Table Of Contents

  1. Introduction
    1. Why Should You Use OBOE?
    2. Purpose Of This Document
  2. What Is OBOE?
    1. Other Functionality
    2. Why The XML Rules Engine?
  3. An Overview Of Classes
    1. EDI Envelope Hierarchy
    2. Envelope - Abstractly And Concretely
    3. Functional Groups
    4. About Dynamic And Static Classes
    5. Transaction Set Its Template And Factory Classes
    6. Tables and Templates
    7. Loops and Templates
    8. Segments and Templates
    9. Composite Data Elements and Templates
    10. Data Elements and Templates
    11. Other Classes
    12. Utility And Exception Classes
    13. External Classes You Need To Get On Your Own
  4. EDI Structure Rules Are Defined in XML Files.
    1. The XML Rules
    2. The DTD File:TransactionSetRules.dtd
  5. Installation
    1. Where To Place OBOE.properties File
    2. Where To Place The XML And DTD Files
    3. Transaction Set Rules DTD Description (Basic Edition)
    4. Transaction Set Rules DTD Description (Extended Edition)
    5. Validating Methods.
    6. The IDLISTxxx XML Files
    7. The IDListClass Class
    8. The XML File
    9. The OBOE Properties File
      1. The OBOE Properties Description
      2. Where To Define The OBOE Properties File
      3. Defining A Property With The API
  6. Programming
    1. Parsing An EDI Document
      1. Using the Properties File To Specify Specific Rules Files
      2. Using A Non Specific Rules File
      3. Using A Version Specific Rules File
      4. Using A Sender Specific Rules File
      5. Using A Receiver/Vendor/Production Specific Rules File
    2. Building An EDI Document
      1. Building An Envelope
      2. Adding Transaction Sets
        1. Method 1 - Building From A Local File Containing XML Rules
        2. Method 2 - Building from a transaction set object for a specific trading partner
        3. Method 3 - Building from a transaction set object for a specific version and production
        4. Method 4 - Building From A URL, File With XML Rules Are Not Local
        5. Using In Memory Stored Transactions Sets
      3. Instantiating The XML Parser
        1. Local File Example:
        2. Remote File Example:
        3. Returning A Transaction set
        4. How The Transaction Set Is Built
      4. Creating A Table
      5. Loops
      6. Segments
        1. Creating A Segment
        2. Getting To A Segment
      7. Data Elements
        1. Creating A Data Element
        2. Flavors Of Data Elements
        3. Getting To A Data Element
        4. Setting Data Element Values
        5. Assigning Default Value From The Rules File
        6. Setting Value From The Container
        7. Getting Data Element Values
        8. Getting Value From The Container
      8. Creating A Transaction Set XML File
        1. Requesting Other Formats.
    3. Parsing An XML/EDI Document
      1. The XML Rules And Document Files
        1. Transaction Sets And Table Parsing
        2. Tables, Loops And Segment Parsing
        3. Loop Parsing
        4. Segment Parsing
        5. Segment And Data Element Parsing
      2. Creating A Transaction Set XML File
      3. Pulling Data From Segments And Data Elements
        1. Getting To The Data
    4. The OBOE FTP Class
      1. FTP Transmission
      2. Receiving By FTP
    5. Sample Source Programs
      1. viewsamples And viewsample
  7. Other Source Programs
  8. Other Sources Of Information
  9. Acknowledgments
  10. Appendices



Introduction

Why Should You Use OBOE?

OBOE - Open Business Objects for EDI is a collection of Java classes that build and translate EDI documents. By using OBOE, it becomes easier for you to create a powerful and flexible method to handle a variety of different data formats and translate them into EDI/XML documents or legacy EDI definitions. By using an XML-based rules engine to build and parse EDI documents, OBOE allows you the flexibility to respond to EDI/XML standards as they are developed. OBOE allows you to use existing components that are already widely available on the Internet for your Java Development Kit, XML Parser and more.

If you need to create an EDI program that can accept EDI data from other systems that use a different EDI format, or if you need to translate data from an EDI legacy system, OBOE is perfect for you. With OBOE, it is possible to have the OBOE rules files for specific customers, X12 versions or inbound/outbound type files.

The classes you need to run OBOE are available free for a 30 day trial period from this site for download (you will have to download some additional classes yourself). You can also arrange for American Coders, Ltd. to provide expert support for your OBOE development efforts.

The Purpose Of This Document

This document shows how your Java programs and OBOE can be used to build EDI objects. The document explains how to write programs that interact with these objects through the package method calls.

The OBOE package contains several source sample programs. You should read these programs to learn how write OBOE based Java applications and applets. Reading and using the sample programs is the best way to become familiar with the OBOE System.

The sample programs won't teach you Java, or how to write a Java application or applet. The sample programs won't teach EDI implementations. Nor will the programs explain the inner workings of the OBOE classes.

The samples provide a guide on how to write to the OBOE API.

The document explains Open Business Objects for EDI and its inner workings.

Remember, the document does not show how you to write Java programs nor teach EDI. You should be very familiar with the Java programming language and EDI standards prior to using OBOE.

Return to Contents


What Is OBOE?


OBOE uses an XML parser for a rules based engine to create EDI Objects. The EDI objects, in turn, are used to build and parse an EDI document or an EDI/XML file.

OBOE XML files fuels the rules based engine. These XML files define the structure of EDI objects through a base set of classes. These rules files and the Java classes are based on legacy EDI Definitions, primarily ANSI/X12 and UN/EDIFact. OBOE can also be used to build EDI/XML objects. And just as OBOE can translate legacy EDI document, these new EDI/XML objects can translate EDI/XML documents into the EDI objects. Which, by the way, can be used to create legacy EDI objects.

Again, OBOE's primary use for XML is to build Java EDI Objects. The XML files map to existing EDI structures or definitions.

As the OBOE XML rules file is parsed and depending on the type of object, the OBOE runtime package creates literally hundreds of objects of two flavors, fixed and template. The fixed objects created are the TransactionSet object and from one to three Table objects. All other objects - loops, segments, composites and data elements are first defined through the template objects. As an EDI document is parsed the template objects are used to create the fixed objects that they represent.

When an incoming EDI document is passed to the TransactionSet object the  template objects contain methods to parse the document. Using the parsed text and the template characteristics a dynamic EDI object is built and attached to its parent object, an Envelope. So, for example, a template object representing a "name" data element, such as an X12 93 data element or an EDIFact C080, is used to create a DataElement object of the same type. Just as the template data element is attached to its parent segment, the DataElement object will become part of the same parent segment or composite. So, TemplateLoops are used to create Loops, TemplateSegments are used to create Segments; TemplateComposites are used to create CompositeDEs and TemplateDEs are used to create DataElements. So, in turn, Loop and Segment objects are attached to a table object or its parent Loop object by its template. Composite data element objects are attached to its parent segment object by its template. And data element objects are attached to a its parent segment or composite data element object by its template. This all occurs while the core objects parse an EDI document.

When you need to build an EDI object, your program will request that the dynamic objects be built through calls to the objects' parent object and, indirectly, to its template (or fixed) objects. Your program calls methods in the parent object of the to-be-built object. The parent object uses the same template objects, mentioned above, to build the requested object. For instance, if a segment needs a particular data element, a method call is made to the segment object. The method creates the data element object. The segment method knows about all the template data element objects that are part of its hierarchy. The segment method in turn calls a method of the appropriate data element template object. The template data element creates the fixed data element object. The fixed data element object is returned to the requesting segment method.

Other Functionality

What's not implemented in OBOE is an external database interface for storing and retrieving EDI documents. When I designed the system, I knew that most EDI systems have been around for a long time. For you folks that have to deal with legacy systems, there are plenty of available hooks in OBOE to provide an interface between your legacy systems and OBOE. How? Well, most of these systems are using SQL databases, such as MySQL, DB2 and Oracle. By using Java's JDBC classes, connecting to these legacy databases access is easy and already available. For those who don't have a legacy systems to deal with, the design allows you build a OBOE application to your own specifications without requiring OBOE to bind to a specific data store.

Why The XML Rules Based Engine?

Early in the release of the product, several people noted how some computer systems use rule engines. Not knowing how to write a rules engine, I went ahead and designed the system so that each EDI object had its own Java class source file -- such as a Purchase Order Object, a Request Validation segment, and a Message Direction Code data element. This created a rather large and cumbersome system of several-hundred source programs. Which, in turn, became very difficult to maintain. So, it was time for a rules engine. But what tool to use, a database, a flat file,... ahhh XML. It was an easy choice. XML is a great data definition tool and several web sites offered Java classes for parsing XML files. (see Apache, IBM, SUN, and Microsoft)

Little did I realize that others were doing the same. But I went ahead a designed a DTD and XML file to map to EDI. Thus a XML file is used to create the OBOE objects, from the same objects designed in earlier OBOE releases. These OBOE objects form the basis of the static classes, as mentioned above.

As it turns out, the best thing about XML is that it is so easy to use.

Return to Contents


Overview of Classes

Image


EDI Envelope Hierarchy


Envelope - Abstractly And Concretely


This abstract class represents an entire EDI Document Object.
This class represents a X12 EDI Envelope Object.
This class represents an EDIFact EDI Envelope Object.

This class is a container class for an EDI transmission. It contains 3 primary objects -- Interchange Header segment, Functional Group container and a Interchange Trailer. Note outside the U.S. EDIFact does not require functional groups. The OBOE application still utilizes the concept even though it does not require Functional Group Headers or Trailer segments. Functional groups are stored in a Vector of the Envelope class. An envelope may contain several functional groups. The Envelope class provides methods to add, get and remove functional groups from the Vector as well as return the number of functional groups in the Envelope.

The Envelope class can also contain several other optional segments depending on whether it represents an X12 document or an EDIFact document.

The primary or super Envelope class is actually an abstract class used by the X12Envelope and EDIFactEnvelope classes. The Envelope class contains several attributes related to the internal representation of a message, such as EDI type, delimiters, etc.

X12 Envelope Attributes

Name Type Purpose
ISA_Interchange_Control_Header Segment ISA segment
ISB_Grade_of_Service_Request Segment ISB segment (optional)
IEA_Deferred_Delivery_Request Segment IEA segment (optional)
InterchangeAcknowledgments Vector of Segments TA1 segments (optional)
ISE_Interchange_Control_Trailer Segment ISE Segment

X12 Envelope Constants


Name Value Purpose
SEGMENT_DELIMITER '\n'
End of segment marker. I used cr/lf for debugging. Some use 0x1f while others use '~'.
FIELD_DELIMITER '*'
End of field marker.
GROUP_DELIMITER '<'
End of group marker.


EDIFact Envelope Attributes


Name Type Purpose
UNA_Service_String_Advice Segment UNA segment (optional)
UNB_Interchange_Header Segment UNB segment
UNZ_Interchange_Trailer Segment UNZ Segment

EDIFact Envelope Constants


Name Value Purpose
SEGMENT_DELIMITER '
End of segment marker.
FIELD_DELIMITER +
End of field marker.
GROUP_DELIMITER :
End of group marker.


Functional Groups

The FunctionalGroup object is a carry over from the X12 functional group concept which is grouping Transaction Sets into common groups. The FunctionalGroup object acts as a container for TransactionSet objects by storing them in a Vector object. The class provides methods to add, get and remove transaction sets from the Vector as well as get a count of the number of transaction sets within the functional group.

Functional groups are not required for EDIFact EDI. The OBOE EDIFact Envelope object utilizes this concept even though it does not required. If your application is EDIFact and your trading partners do not use functional groups then your programs can simply ignore the functional Group Headers or Trailer segments.

protected Segment header;
protected Vector transactionSets = new Vector();
protected Segment trailer;

About Dynamic and Static Classes

As mentioned above OBOE creates two sets of classes -- dynamic (the real EDI objects) and static (the template classes).

Template Classes - The Static Classes

Template Classes are the internal representation of the XML rules file. Therefor they represent the structure of an EDI object. The OBOE EDI Objects (the dynamic class) objects are built by calls to the template classes. EDI data is not stored in the template classes. Also a template class know nothing about the status or content of its static counterpart.

The template classes extend java.IO.Serializable or java.IO.Externalizable. Serialization allows the template classes to be stored locally. Storing the classes on the local hard drive allows the package to reuse the objects and thereby reduce the need to reparse the XML rules file. The package date checks both the XML rules file and its serialized object file. If the XML rules file is newer then the package will reparse the XML file and recreate the serialized file. Otherwise the package will read the serialized file to create the template objects.

EDI Object Classes - The Dynamic Classes

The dynamic classes are the internal representation of an EDI document. The document parser or an OBOE program interacts with these classes to store and retrieve document data. The dynamic classes contain references to their static counterpart

Transaction Set Its Template And Factory Classes

This class represents an entire EDI Transaction Object
This class is the base for each transaction contained within an Envelope. It contains the EDI objects: tables, loops, segments, composite data elements, and data elements. The TransactionSet is also represented by its template class. The TemplateTransactionSet class is a container for the sub template classes starting with the TemplateTable class. The TransactionSet class' two primary functions are to parse and get. The parse method is used to parse an incoming EDI document. Get and getFormattedText methods are use to build an EDI document. To access children objects, such as segments, calls are made through the table object's methods.

Note: The OBOE design requires at least one table object within a TransactionSet. If a particular EDI document is defined without a table, meaning only segments, then the XML rule file for the TransactionSet must define a Header table.

TransactionSetFactory

This class builds a preliminary version of all the EDI objects based on an XML file that it parses.

This class reads in an OBOE XML rules file to build EDI objects. Processing is simple. As each element is read from the rules file a template object is built. If an object is contained within another such as a segment within a loop or a data element within a segment, a template object is created and assigned to the owning template object.

This class extends the SAX2 DefaultHandler parser class. The SAX2 parser is an event driven XML file parser.

The TemplateTransaction set class contains all the template objects needed for a particular transaction set. This class, like the other template classes, is an extension of java.io.serializable. To reduce processing time of reading and parsing the XML rules file every time a transaction set needs to be built the factory class does two things.

  1. The template file is stored in an external format. The TransactionSetFactory searches the local directory structure for rules files based on its Transaction set ID and an XML prefix. (for instance 840.xml or ORDERS.xml.) Then the factory class searches for an associated object file with the same filename prefix but with the filename suffix of "object" (for instance 840.object or ORDERS.object.) If the object file is not found the factory class will parse the OBOE rules file and then store the OBOE EDI objects for that particular transaction set into an object file. Thereby allowing the class to simply read in the rules and removing the parsing step the next time the transaction set class is requested to be built.
  2. While the application is active, the TransactionSetFactory stores the parsed template objects in a Hashtable object. When subsequent calls are made for a rules file that has already been parsed or loaded the factory simply passes the in-memory stored object. This one step alone reduces file input processing time considerably.

Tables and Templates

Tables are containers for loops and segments. Tables provide access methods to the loops and segments it holds. Likewise Template Tables are containers for template loops and template segments. TemplateTable provides access methods to the template loops and template segments it holds.

As mentioned above, if an EDI document does not define a table you must define a header table in the XML TransactionSet. The document's segments to this table.

Classes that dynamically represent the 3 EDI tables, header, details, summary.

Classes that contain TemplateSegments and statically represent the dynamic tables.

Loops and Templates

Loop

A class that represents an EDI Loop. Loops are containers for other segments and other loops.

TemplateLoop

Class represents a fixed or static version of an EDI Loop. Used by the TransactionSetFactory class.

Constructed when the XML rules file is read. This class is used to build the dynamic loop class it represents. As a loop and segment container it also contains child TemplateLoops and TemplateSegments.

ITemplateLoopContainer

An interface for describing methods for storing and accessing TemplateSegments. This interface defines TemplateLoops containership

Segments and Templates

Segment

A class that represents an EDI segment. Segments are containers for composites and data elements.

TemplateSegment

Class represents a fixed or static version of an EDI segment. Used by the TransactionSetFactory class.

Constructed when the XML rules file is read. This class is used to build the dynamic segment class it represents. Like its dynamic counter part which contain composite and DataElement objects the TemplateSegment object may contain template composites and template data elements.

ISegmentContainer

An interface for defining how Segments are stored.

This interface defines segment containership

ITemplateSegmentContainer

An interface for describing methods for storing and accessing TemplateSegments. This interface defines TemplateSegments containership

Composite Data Elements and Its Template

CompositeDE

A class to represent an EDI Composite Data Element. A CompositeDE is EDI's way of defining a special type of Data Element container.

A class to statically represent an EDI Composite Data Element. This class is used to create its composite counterpart.

Data Elements

This is a collection of classes used to describe the various data element types defined in EDI. This super class provides for all the externalized methods used by the subordinate classes, DateDE, CharDE...

DataElement

A class to describe all EDI Data Elements. Used as a super class to specific data element types.

TemplateDE

A class to provide preliminary definitions of a data element. Constructed with XML data this class provides no real purpose to the general application. It is used to build its data element counterpart.

IDataElementContainer

An interface describing methods for storing data elements.

This interface defines segment containership

Character Data Elements

A class for EDI Character Data Elements.

Binary Data Elements

A class for EDI Binary Data Elements.

Date Data Elements

A class for EDI Date Data Elements.

ID Data Elements

A class for EDI ID Data Elements.

Numeric Data Elements

A class for EDI Numeric Data Elements.

Real Data Elements

A class for EDI Real Numeric Data Elements

Time Data Elements

A class for EDI Time Data Elements.

Other Classes

ValidXMLEDIParser

This class builds an EDI object from a valid XML file. The OBOE application can create output to represent an EDI object is several formats. One format is in a valid XML format which is validated against by the DTD file. Your application uses this class to parse the XML/EDI file into EDI objects.

This class builds an EDI object from a well formed XML file. Unlike its valid XML counter part a well formed XML file is not validated against a DTD. Your application uses this class to parse the XML/EDI file into EDI objects.

DocumentParser

This abstract class describes how EDI objects are extracted from an EDI Document.

DocumentHandler

This interface describes how the parser class notifies EDI object events when parsing EDI objects from an EDI Document.

X12DocumentParser

This class extracts X12 EDI objects from an EDI Document.

X12DocumentHandler

This class stores X12 EDI objects from an EDI Document in an envelope container. When working with X12 documents you would work with class most of the time.

EDIFactDocumentParser

This class extracts EDIFact EDI objects from an EDI Document.

EDIFactDocumentHandler

This class stores EDIFact EDI objects from an EDI Document in an envelope container. When working with UN/EDIFACT documents you would work with class most of the time.

Tokenizer

Class with methods to break down an EDI Document into tokens.

DocumentErrors

This class is used to track errors while parsing an incoming EDI object. Also it is used in conjunction with the base classes validate method to track errors with an EDI object and the rules defined for that object.

Utility And Exception Classes

Utility classes to format date and time fields.

Also contains an XML normalizer method. You use this method to normalize a String representing XML data. Normalization is the process of replacing XML specific markers, such as '>' with text '>'

Byte Conversion Utility This class provides static methods to convert bytes to base64 characters.

OBOE Exception Class Exception class for throwing OBOE errors. This class extends the Java RuntimeException class. By using runtime exceptions if an exception is uncaught the class allows a failing program to continue.

External Classes You Need To Get On Your Own

OBOE is built using components from other Java package providers. To build code using the OBOE classes you must visit several other web sites to get their classes. I don't provide these external classes with the OBOE product because some of the other package owners do not provide a general license agreement to distribute their development environment. Specifically you will need a Java Developer Kit (JDK) Java2 (for the Swing classes), and a XML parser.

JDK

To compile the OBOE files you will need a Java Developer's Toolkit.

There are several JDKs on the market. At this time I program and test with the Java development tool Eclipse.   This excellent tool is available from The Eclipse Website.

XML Parser

SAX - Simple API

OBOE uses the SAX (Simple API for XML) API (application programming interface) XML parser. By using the TransactionSet DTD and a validating SAX parser your TransactionSet XML file is validated prior to being loaded into OBOE objects.

Why Not DOM?

I didn't choose DOM for two reasons. First, DOM returns a tree structure of your document. Since the OBOE already builds a tree structure of an EDI document This is redundant. Second, SAX has a faster start-up. Since SAX starts returning document objects immediately the objects created by OBOE would share this immediacy also.

Return to Contents


EDI Structure Rules Are Defined in XML Files.

As you have read elsewhere in this document OBOE uses XML files to define the structure and rules of all EDI objects.

The XML Rules

Each element object in an OBOE XML file represents an EDI object. These elements map one-for-one. As OBOE receives an XML element from the SAX parser it creates a Java object. Some objects, such as transaction sets, are used through-out the life of the EDI object life, others use, such as TemplateSegments, are created to create a real or usable object when needed, in this case a segment.

Since a DTD file is used with the validating parser a lot of up-front editing is reduced for the OBOE processor. For instance, the validating parser insures that a data element is correctly related to a transaction set.

The DTD File:TransactionSetRules.dtd

One DTD file is used to define one complete EDI transaction set. The file describes the transaction set, from one to three tables, the loops and segments within tables and other segments, composite data elements and data elements. The description generally includes a name, id, description and xmltag attribute. Some of the elements may have other attributes.

Since the 2.5.0 release a second rules file, envelope.dtd, was introduced. This rules file describes the format of envelopes by the structure of the envelope segments (e.g. ISA or UNB), functional groups and its segments. Do note that the OBOE package still uses the static class definitions for envelopes and the other envelope structures you can create a envelope rules file in case the OBOE definitions do not meet your needs.

Since OBOE is available in two packages, there are two distinct DTD files. While the structure is similar the Extended Edition contains several nodes not found in the Basic Edition.

Installation

Where To Place The OBOE.properties File

The parser looks for the properties file in one of four location in this order:

You should refer to your JDK and Operating System documentation on setting the environment variables.

Where To Place The XML and DTD File

The parser looks for the rules files in a location as specified by the xmlPath in the OBOE.properties file. Refer to

Transaction Set Rules DTD Description (Basic Edition)









Element
Attribute
Description of XML Contents
Required
TransactionSet name see EDI definition. example value 'Request For Quotation'  
  id see EDI definition. example value '840'  
  revision see EDI definition, maybe critical to the Implementation Convention of the sender or receiver. Not required
  functionalGroup see EDI definition Not required
  description if not specified name is used Not required
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
table
child to transactionSet
section Values are header, details, and summary. Each must be unique within the transaction set.  
  xmlTag   Not required
loop
child to table or loop
name see EDI definition, example value 'Data Segment Note'  
  id see EDI definition. example value '2000' or 'HL'  
  occurs use -1 for unlimited how many times the loop occurs.
  required 'M' for mandatory, 'O' for optional or 'C' for computed defaults to 'M', presently 'C' is treated as optional
  used 'Y' used by implementation, 'N' not used.
If marked as 'N' all elements within the loop object are ignored by the OBOE processor
defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
copyloop
child to loop
refid copy a previously defined loop as defined by its id field  
segment
child to table or loop
name see EDI definition, example value 'Data Segment Note'  
  id see EDI definition. example value 'AK3'  
  sequence sequence number as defined by the EDI specifications.  
  description if not specified name is used Not required
  occurs use -1 for unlimited, must be 1 for first segment in loop  
  required 'M' for mandatory, 'O' for optional or 'C' for computed defaults to 'M', presently 'C' is treated as optional
  used 'Y' used by implementation, 'N' not used.
If marked as 'N' all elements within the segment object are ignored by the OBOE processor
defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
copysegment
child to segment
refid copy a previously defined segment as defined by its id field  
compositeDE
child to segment
name see EDI definition  
  id see EDI definition  
  description if not specified name is used Not required
  sequence Sequence with in segment see EDI definitions defaults to position relative to its position with in the segment rule
  required    

occurs
The number of times this composite may repeat.  New for Version 3.1.  Written for X12 version greater that 4010 and EDIFACT 9735-2.
Defaults to '1'
  used 'Y' used by implementation. 'N' not used.
If marked as 'N' all elements within the composite object are ignored by the OBOE processor
defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
dataElement
child to segment and compositeDE
name see EDI definition  
  id see EDI definition  
  type binary, char, date, id, numeric, real, or time.  
  sequence Sequence with in segment or composite see EDI definitions defaults to position relative to its position with in the segment or composite rule
  required    
  description    
  minLength The base package ignores this value. It is used by data element class validate method in the Extended Edition.  
  maxLength The base package ignores this value It is used by data element class validate method in the Extended Edition.  

occurs
The number of times this element may repeat.  New for Version 3.1.  Written for X12 versions greater than 4010 and EDIFACT 9735-2
Defaults to '1'
  used 'Y' used by implementation. 'N' not used. defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
idList
child to dataElement
    defines an in place list of values associated with an ID type field
use only if the dataElement type is defined as "ID"
idCode
child to idList
used 'Y' used by implementation. 'N' not used. defaults to 'Y'.
idValue
child to idList
     
idListClass
child to dataElement
className Specifies a Java class that will provide the idCode and idValue list  
idListFile
child to dataElement
fileName Specifies a XML file containing the idCode and idValue list  
  include a list of codes to only use, example 00,02-05,99 says to validate only 00 02 03 04 05 and 99 that are specified in the idList file  
  exclude a list of codes to ignore, example 00,02-05,99 says to validate all values in file except 00 02 03 04 05 and 99  
copysegment
child to segment
refid copy a previously defined segment as defined by its id field  

Transaction Set Rules DTD Description (Extended Edition)




































Element
Attribute
Description of XML Contents
Required
transactionSet name see EDI definition. example value 'Request For Quotation'  
  id see EDI definition. example value '840'  
  revision see EDI definition Not required
  functionalGroup see EDI definition Not required
  description if not specified name is used Not required

validationMethod
The name of a static Java method called during the validation process. Not required
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
table
child to transactionSet
section Values are header, details, and summary.  
  xmlTag   Not required

validationMethod
The name of a static Java method that is called during the validation process. Not required
loop
child to table or loop
name see EDI definition, example value 'Data Segment Note'  
  id see EDI definition. example value '2000'  

occurs use -1 for unlimited

required 'M' for mandatory, 'O' for optional or 'C' for computed defaults to 'M', presently 'C' is treated as optional

validationMethod
The name of a static Java method that is called during the validation process. Not required
  used 'Y' used by implementation. 'N' not used.
If marked as 'N' all elements within the loop object are ignored by the OBOE processor
defaults to 'Y'.

xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
copyloop
child to loop
refid copy a previously defined loop as defined by its id field  
segment
child to table
name see EDI definition, example value 'Data Segment Note'  
  id see EDI definition. example value 'AK3'  
  sequence Sequence number - see EDI definitions
  description if not specified name is used Not required
  occurs use -1 for unlimited, must be 1 for first segment in loop  
  required 'M' for mandatory, 'O' for optional or 'C' for computed defaults to 'M', presently 'C' is treated as optional
  validatingMethod
Specifies static method to call when validation method is called
Not required
  used 'Y' used by implementation. 'N' not used.
If marked as 'N' all elements within the segment object are ignored by the OBOE processor
defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
compositeDE
child to segment
name see EDI definition  
  id see EDI definition  
  description if not specified name is used Not required
  sequence Sequence with in segment see EDI definitions defaults to position relative to its position with in the segment rule
  required    

occurs
The number of times this composite may repeat.  New for Version 3.1.  Written for X12-4040 and EDIFACT 9735-2. Defaults to 1

validationMethod
The name of a static Java method that is called during the validation process. Not required
  used 'Y' used by implementation. 'N' not used.
If marked as 'N' all elements within the composite object are ignored by the OBOE processor
defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
dataElement
child to segment and compositeDE
name see EDI definition  
  id see EDI definition  
  type char, date, id, numeric, real, or time.  
  sequence Sequence with in segment or composite see EDI definitions defaults to position relative to its position with in the segment or composite rule
  required    
  description    
  minLength The base package ignores this value. It is used by data element class validate method in the Extended Edition.  
  maxLength The base package ignores this value It is used by data element class validate method in the Extended Edition.  

occurs
The number of times this element may repeat.  New for Version 3.1.  Written for X12-4040 and EDIFACT 9735-2. Defaults to '1'

validationMethod
The name of a static Java method that is called during the validation process. Not required
  used 'Y' used by implementation. 'N' not used. defaults to 'Y'.
  xmlTag Used by getFormatted methods when generating XML and the ValidatableXMLParser. If not specified the id field is used as the tag name. Not required
idList
child to dataElement
    defines an in place list of values associated with an ID type field
use only if the dataElement type is defined as "ID"
idCode
child to idList
used 'Y' used by implementation. 'N' not used. defaults to 'Y'.
idValue
child to idList
     
idListClass
child to dataElement
className Specifies a Java class that will provide the idCode and idValue list  
idListFile
child to dataElement
fileName Specifies a XML file containing the idCode and idValue list  
  include a list of codes to only use, example 00,02-05,99 says to validate only 00 02 03 04 05 and 99 that are specified in the idList file  
  exclude a list of codes to ignore, example 00,02-05,99 says to validate all values in file except 00 02 03 04 05 and 99  
default
(not required)
child to dataElement
from Specifies location of default data from one of three places:
  1. constant - use the contents of the #PCDATA value space.
  2. property - using the #PCDATA value, searches the OBOE.properties files for this value as a name and then uses value associated with name in OBOE.properties.
  3. method - using the #PCDATA value, calls a static method is a class to return a value. Structure of #PCDATA value must be xxxxxx#yyyyyyy where xxxxxx is some class name and yyyyyy is a static method in the class. The static method must not accept any input parameters and it must return a String object.
Required. Also uses the #PCDATA XML value space, specifies data or location of data that can go into the value field
elementRule
(not required)
child to Segment
rule Indicates the specific rule for the elements of this segment. Use one of the following values:
  1. oneOrMoreMustExist
  2. ifFirstExistsThenAllMustExist
  3. oneAndOnlyOneMayExist
  4. ifFirstExistsThenAtLeastOneMoreMustExist
  5. allOrNoneMayExist
  6. ifFirstExistsThenNoOthersMayExist
Required
  positions Specifies the position of all the elements associated with the rule, offset value starts at 1. Use the dataElement position. Required
copysegment
child to segment
refid copy a previously defined segment as defined by its id field  

Validation Methods


All of the primary objects in the transaction set: transaction set, table, segment, loop, composite and data element, have an attribute named validationMethod. The validation method is something you write that is called.  Your method is called after during the validation process.  It always called as the last step in the validation process for the particular object. 

How To Write A Validation Method

Basically you write a static method that accepts two arguments and returns a boolean.

The method may reside in any source file and be associated with any package.  For consistency and ease of maintenance Try to keep the validating methods within the same source program.

The source program will need to import at a minimum two OBOE classes:  DocumentErrors and the class that is to be validated, such as Segment.

The validating method must be public and static.

The method must return a boolean to indicate success or failure. By returning a false your method indicates that method found an error.  Conversely a true indicates no error is found.

The method accepts two objects, the object to be validated and a DocumentErrors object.   The object to be validated can be any one of the primary OBOE objects.  The DocumentErrors object is used by the method to explain the error found.  The object is associated when the rules file is parsed.  OBOE will validate that the method conforms to the three requirements.  If  the method can't be found or the argument list is incorrect the TransactionSetFactory class will throw a parsing exception.

Which Object To Associated The Method With.


You should assign the validation method to the container that has access to every object to be checked.  For instance if you need to check the relationships of data elements within a segment then you would assign the method to the segment object.   Or if you needed to check the relationship of two data elements in different parts of a transaction set then you would assign the transaction set to the validating method.

What If I Need More Than One Method For An Object.

Simply make one single common method for that object and have that method call the other methods.

Example
This is an example of a method accepting a table object.    The object is used to search through all of it's segments with the ID of "REF".  The validation process is verifying that at least one of these REF segments has a DataElement with an id of "128" contains a value of "14".  If one is found it returns a true.  If none is found then the DocumentErrors object is populated with meaningful data and a false is returned.

       public static boolean dValidatingMethod820DetailTableRefs(Table inTbl,
                        DocumentErrors des)
                        throws Exception {
       int iRef = inTbl.getCount("REF");
           // there's gotta be one because it's mandatory
       Segment seg = null;
       for (int i = 0; i < iRef; i++)
           {
              seg = inTbl.getSegment("REF", i);
              if (seg.getDataElement("128").get().compareTo("14") == 0)
                return true;
           }

       des.addError( 0,  "128",
           "Required value of \"14\" in 128 field of REF expected in at least one segment",
                inTbl,  "7",     seg);
       return false;
   }


In the rules file the table entry would read as follows:

    



The IDList XML Files


The OBOE data element objects IDDE use a secondary XML rules file called IDList files. These files provide a complete list of used ID and Value pairs associated with the IDDE object. For instance in X12, the ID element 353 defines all the Purpose Code for transaction sets. The name/value pair for 353 are the transaction sets id and the description for the transaction set. In the idlist file there would be an entry for each purpose code
EXAMPLE

                00
                        Original
                01
                        Cancellation
                02
                        Add
        

In the rules file you may use one of three optional nodes to specify the name/value pairs.

The IDListClass Class


OBOE offers another way to externalize IDList Codes and Values. A java class that implements the Interface IDListProcessor can be used to provide the codes and values need for a particular IDDE dataElement. This class could be used when codes and values are stored in a SQL database or some other file system.
The class is loaded when the rules file is parsed.
For further information see the JavaDoc file referring to com.americancoders.edi.IDListProcessor.

The XML File

All OBOE EDI definitions are found in a XML rules file. These XML files use the TransactionSetRules.DTD file for validating their definitions.

The XML file for a particular transaction set can get very large, well over 500k characters long.

There is a XML facility to include, or import, other XML files. Using this import facility will simplify a file but may create a large number of files. If you do use this you should break the files logically along the same lines as the DTD elements.

Return to Contents

The OBOE Properties File

The OBOE.properties files is used to store information that describes your system's environment to the OBOE package.

The OBOE Properties Description

Parser Property


Name Description
xmlpath The location of the xml and dtd files.

If the value of the xmlPath variable begins with the value %classpath% then the rules files is assumed to be in a jar file specified in the classpath environment variable.

It is recommended a full path definition is used (except for the classpath usage).
Microsoft Windows user please note that if the classpath is used along with subdirectory specifications case sensitivity is used.

searchDirective An optional property which instructs the TransactionSetFactory class how to find a specific rules file based on an EDI field value. Specify any combination of VTRSX. An additional value of '|' may be used to create more than one search argument.
  • V - version
  • T - test or production
  • R - receiver id
  • S - sender id
  • X - substring of version
  • , - the comma is used to add additional search arguments
Used in conjunction with either fields from an incoming document or fields specified with the TransactionSetFactory class buildTransactionSet method. Refer to the TransactionSetFactory Javadoc for more information
useObject An optional property which instructs the TransactionSetFactory class to use object files if newer than the XML rules file. If set to any value other than "true" the package will assume false.
One way of speeding up the OBOE load process is for the package to build object files representing the XML files. This property indicates that the package should take advantage of this feature.
no specific property name An optional property that is treated as a variable to parse an incoming a well formed EDI/XML file You must specify the name found in the well formed file with a transaction set id
for example to parse a well formed 840 file, if the XML node name is RequestForQuotation then specify
RequestForQuotation=840
Likewise to parse an EDIFact ORDERS transaction set and if the XML node is PurchaseOrderMessage then specify
PurchaseOrderMessage=orders
YOU DON'T NEED THIS FOR VALIDATIBLE XML FILES SINCE THE TRANSACTION SET ID IS AN ATTRIBUTE OF THE TRANSACTION SET NODE.
x12Delimiters An optional property to set x12 delimiters: segment field group
for example x12Delimiters=|~:
EDIFactDelimiters An optional property to set EDIFact delimiters: segment field group
for example: EDIFactDelimiters=^&*
throwParsingException An optional property to indicate to the two DocumentHandlers if they should throw an Exception if any parsing errors are encountered.
Default value is true. Possible values are true or false.
errorLevelToReport A numeric value indicating a threshold value. The value is tested against when an EDI parser finds an error with a message.
Default value is 1. Possible values are 1 through 10.
realNumbersRetainPrecision An optional property to indicate if Real data elements should keep the incoming decimal precision. If set to false, decimal point character and trailing zeros will be removed if determined to be unnecessary.
Default value is false. Possible values are true or false.
validCharacterSet A optional property to allow testing of valid characters in data element objects.
Standard X12 A...Z0...9 !="&'()*+,-./:';?=
Extended X12 A...Za...z0...9 !="&'()*+,-./:';?=
EDIFACT Level A A...Z0...9 .,-()/='+:?!"%&*;<>
EDIFACT Level B A...Za...z0...9 .,-()/'+:=?!"%&*;<><>

Default value is any character.

Where To Define The OBOE Properties File

The packages searches for the OBOE.properties file in the following order:
  1. local directory
  2. user.home directory
  3. java.home directory
  4. classpath environment variable

Defining A Property With The API

The Util class provides an alternate means to defining a property.
       /*
         * sets a value in the OBOE.properties
         * @param inName
         * @param inValue
         * @throws IOException
         */
        public static void setOBOEProperty(String inName, String inValue)
All property names are defined as static Strings in the Util class. For example to set the valid character set you could use the following:
   Util.setOBOEProperty(Util.validCharacterSet, "A...Za...z0...9 !=\"&'()*+,-./:';?=");

Programming

Parsing An EDI Document

Parsing an EDI document is accomplished by calling one of four parsers that are part of the OBOE package, X12, EDIFact, XML and Well-Formed XML.

All OBOE parsers return an Envelope object.

After parsing an Envelope, either from an X12 document, EDIFact document a well formed EDI/XML file or a valid EDI/XML file, your application will need to work its way through the document tree using the methods available with each tree object, Envelope, FunctionalGroup, TransactionSet, Table, Segment, Composite and DataElement. Below is a very simple example of traversing through an EDI document

/* assume document passed in as a java.io.Reader object inRDR */
com.americancoders.edi.x12.X12DocumentHandler dh1 =
        new com.americancoders.edi.x12.X12DocumentHandler(inRDR);
X12Envelope env = dh1.getEnvelope();
Segment interchangeHeader =
        env.getInterchange_Header();
for (int fgCursor = 0; fgCursor < env.getFunctionalGroupCount(); fgCursor++)
         { /* do not forget to work with the functional group header and trailer */
                FunctionalGroup fg = env.getFunctionalGroup(fgCursor);
                for (int tsCursor = 0; tsCursor < fg.getTransactionSetCount(); tsCursor++)
                        {
                                TransactionSet ts = fg.getTransactionSet(tsCursor);
                                Table tbl = ts.getHeaderTable();
                                Segment seg = tbl.getSegment("BEG");
                                DataElement de = seg.getDataElement(0);
                        }
        }
Segment interchangeHeader = env.getInterchange_Header();

Using the Properties File To Specify Specific Rules Files

Since incoming documents are unknown prior to parsing them OBOE provides a mechanism in which you can specify location of specific Rules files to use. Using a search directive in the OBOE.properties file and specific data of the incoming document, the OBOE package will build a path name to a rules file to use. If the rules file is not found in the built path then the package will look up the directory structure until it finds a matching rules file.

The X12DocumentParser, X12Envelope, EDIFactDocumentParser and EDIFactEnvelope classes are preprogrammed to use this functionality.

The searchDirective.
The OBOE.properties file may contain an optional variable named searchDirective. The variable may use any one of four characters V S R T and/or X and specified in any order. Each character, if used, directs the package to build a path name on the specific contents of the incoming document variables. An additional separator ',' may be used to create more than one search argument. The variable meanings are as follows:

V Version X12 version may come from two data elements
  1. "1705 - Implementation convention reference" from ST03, if present in the Transaction Set Header segment.
  2. "480 - Version Release Industry Identifier Code" from GS08 - Functional Group Header segment

EDIFact: "0052" and "0054" from UNH segment, this will not work with the ValidXMLParser class since this information is not available at the time the transaction set is parsed.
R Receiver X12: "I07 - Interchange Receiver ID" from ISA segment
EDIFact: "0010 - Recipient Identification" from UNB segment
S Sender X12: "I06 - Interchange Sender ID", from ISA segment
EDIFact: "0004 - Sender identification", from UNB segment
T Test or Production X12: "I14 - Test Indicator", values of P or T from ISA segment
EDIFact: "0035 - TEST INDICATOR", from UNB segment
X Version substring Useful for X12 only. Using a substring of the GS08 field to build the path. This was designed for multiple HIPAA version applications; multiple in the meaning of using both 004010 and 005010 and needing to fall back to correct subversion. So if GS08 is 004010X092 and it is not found then package will use 004010 (substring(0,6)) to build the path name.
, (comma) To specify multiple search paths VS,SV will first search using the V and S parameters and finally search using the S and V parameters.


Note: The package uses the values of these fields as directory names.
Note: This logic does not apply to outgoing EDI documents which your application will build. See the TransactionSetFactory buildTransactionSet method for similar type of directory control.
Note: Be consistent with incoming and outgoing directory names to reduce search and storage requirements.
If the searchDirective variable is not specified in the OBOE.properties file then only the xmlPath variable will be used to build a XML rules file path.

Examples

Using A Non Specific Rules File
It's simple. Don't specify the searchDirective variable in the OBOE.properties file.
Using A Version Specific Rules File
In the OBOE.properties file use
searchDirective=V
Using A Sender Specific Rules File
In the OBOE.properties file use
searchDirective=S
Using A Receiver/Vendor/Production Specific Rules File
In the OBOE.properties file use
searchDirective=RVT

Building An EDI Document

Building an Envelope

To start building an EDI document you should first create an Envelope object, either X12Envelope or EDIFactEnvelope. From here you will work with the interface header segment, functional groups and interface trailer segment. Since interface and functional group header/trailer segments are not defined in an XML rules file, OBOE contains classes to create these segments for you.

Functional groups primary purpose is to be a container for transaction sets. In X12 functional groups are an integral part of an EDI document while in EDIFact functional groups are not required. OBOE implements the functional groups for both standards, but is intelligent enough not to generate functional group header/trailers for EDIFact documents.

Functional groups are stored in the Envelope object in a Java.util Vector object there are methods in the Envelope class to get, add, remove functional groups. And likewise, since functional groups are containers for transactions sets, transaction sets are stored in a Vector object within the functional group with similar getter/setter methods.

       /* example to create an envelope with a non-specific 840 transaction set.*/
  X12Envelope xenv = new X12Envelope(EnvelopeFactory.buildEnvelope("x12.envelope", ""));
  xenv.setInterchange_Header(Interchange_Control_Header.getInstance());
  FunctionalGroup fg = X12FunctionalGroup.getInstance();
  xenv.addFunctionalGroup(fg);
  fg.addTransactionSet(TransactionSetFactory.buildTransactionSet("840"))
  xenv.setInterchange_Trailer(Interchange_Control_Trailer.getInstance());
/* example to create an envelope with a partner specific 840 transaction set.
  "R" - look in subdirectory specified by receiver parameter
  null - ignore version parameter
  "0900098" - receiver parameter - look in this subdirectory
  null - ignore sender parameter
  null - ignore test/production parameter
  */
 X12Envelope xenv = new X12Envelope(EnvelopeFactory.buildEnvelope("x12.envelope", ""));
 xenv.setInProcess();
 xenv.setInterchange_Header(Interchange_Control_Header.getInstance());
 FunctionalGroup fg = X12FunctionalGroup.getInstance();
 xenv.addFunctionalGroup(fg);
 fg.addTransactionSet(TransactionSetFactory.buildTransactionSet("840","R",null,"0900098",null,null))
 xenv.setInterchange_Trailer(Interchange_Control_Trailer.getInstance());

Adding Transaction Sets

The TransactionSetFactory class is an extension of the XML SAX handlerBase class. The TransactionSetFactory is not constructed, it contains only static methods and class variables. An OBOE class needing a TransactionSet uses the static method buildTransactionSet in the TransactionSetFactory class. These methods create and return a TransactionSet object.

Method 1 - Building from a local file containing XML rules:

The buildTransactionSet method accepts one parameter the id field of the EDI object to be created. For instance, if the value '840' is passed then a x12 "Request For Quotation" object would be created. Using the input parameter the method determines where the XML file is located. The methods reads from the OBOE.properties file the directory (or folder) location for all XML rules files. Taking this directory name, appending the parameter, and finally appending the suffix '.XML' the method determines the full path name for the XML rules file. OBOE.properties contains one property, which represents the first part of rule file path. The property name is xmlPath.

xmlPath as defined in OBOE.properties
c:/EDIXMLFiles/
argument passed> "840"
file used by the parser
c:/EDIXMLFiles/840.xml


Method 2 - Building from a transaction set object for a specific trading partner:

The second example buildTransactionSet method uses three of seven parameters, an ID field, a searchDirective string and a sender id string.

       TransactionSetFactory.buildTransactionSet("840","S","TESTERONE",null,null,null))
xmlPath as defined in OBOE.properties
c:/EDIXMLFiles/
argument 1 passed
"840"
argument 2 passed - search Directive
"S"
argument 3 passed - version directory
null
argument 4 passed - sender directory
"TESTERONE"
argument 5 passed - receiver directory
null
argument 6 passed - test/production directory
null
file used by the parser
c:/EDIXMLFiles/TESTTERONE/840.xml


Method 3 - Building from a transaction set object for a specific version and production:

The third example of the buildTransactionSet method uses four of seven parameters, an ID field, a searchDirective string and a sender id string.

xmlPath as defined in OBOE.properties
c:/EDIXMLFiles/
argument passed
"840"
argument 2 passed - search Directive - use the test/production parameter first and then the version parameter to build the path
"TV"
argument 3 passed - version directory
004010
argument 4 passed - sender directory
null
argument 5 passed - receiver directory
null
argument 6 passed - test/production directory
"P"
file used by the parser
c:/EDIXMLFiles/P/004010/840.xml


Method 4 - Building From A URL, File With XML Rules Are Not Local

The last buildTransactionSet method accesses two parameters, a URL and an ID field. The URL parameter is a java.net.url object. The id field is a string identifying the EDI transaction set. Using these two parameters and appending a file extension of '.XML', a new URL object is created and passed to the SAX parser.
URL builds do not support the subdirectory search mechanism

java.net.URL object passed
new java.net.URL("www.americancoders.com/xmlFile/")
for applets use getCodeBase method to get the active URL.
argument passed
"840"
URL used by the parser
"www.americancoders.com/xmlFile/840.xml"


Using Memory Stored Transaction Sets

As mentioned earlier, when the TransactionSetFactory has already parsed or loaded a TransactionSetFactory it will pull the template object from Hashtable object stored with in it. Note like the other TransactionSetFactory attributes and variables, the Hashtable is static and is only valid as long as the OBOE package is active in the JVM.

Instantiating the XML Parser.

The buildTransactionSet then creates the SAX parser object; sets the handler base with the newly constructed object and finally calls the parser to parse either the local or remote file.

Local file example
     Properties properties = new Properties();
      FileInputStream inStream = new FileInputStream("OBOE.properties");
      properties.load(inStream);
      String path = properties.getProperty("xmlPath");
      org.xml.sax.Parser parser = new   com.ibm.xml.parsers.ValidatingSAXParser();
      TransactionSetFactory me = new TransactionSetFactory(parser);
      parser.setDocumentHandler(me);
      parser.parse(path + inTSID + ".XML");
Remote file example:
     Properties properties = new Properties();
      URL url = new URL(inURL + inTSID + ".XML");
      System.out.println("URL is " + url );
      org.xml.sax.Parser parser = new com.ibm.xml.parsers.ValidatingSAXParser();
      TransactionSetFactory me = new TransactionSetFactory(parser);
      parser.setDocumentHandler(me);    parser.parse(url.toString());
Returning a TransactionSet

After successfully parsing the XML rules file use the buildTransactionSet method to return a TransactionSet object to your program. This TransactionSet object is built with the SAX parser along with the TransactionSetFactory method. The TransactionSet object contains the tables identified within the TransactionSet rules. Note some TransactionSets do not use all three tables, e.g. 997 Functional Acknowledgment, for these the system requires at least one header table. The table object will contain TemplateSegments, not the real segments, yet. Remember, that templates are static objects. Templates the static objects used to build the dynamic objects. Likewise, the TemplateSegments contain other TemplateSegments, TemplateCompositeDEs and TemplateDEs, which will eventually be used to create their dynamic object. All templates are stored in java.util.Vector objects in their respective owners. Eventually calls through the Table objects or segment objects, to create the necessary segments, composites or data elements.

The TransactionSet object contains no EDI data. The object is the structure for building an EDI document or parsing an EDI document.

How The Transaction Set Is Built.

Every time the SAX parser encounters a new XML element the parser calls the startElement method of the registered handler base. The TransactionSetFactory class contains such a method. This method queries the element, its attributes and values. The OBOE methods starts building a tree of the transaction set, tables, segments, composites and data elements by querying the id field and the associated attributes. The object is then pushed onto a Java.util.Stack object.

Every time the SAX parser encounters an end to an XML element the object is the popped off the stack.

By utilizing this stack mechanism the OBOE parser allows recursion and thereby allows segments to own segments and composites to own composites.

Creating a Table

Logically, tables are automatically built by the TransactionSetFactory as the XML rules file is read.

About Loops

Loops are containers for segments and other loops. Loops are defined in EDI as either loops or groups. The names are synonymous.
Creating A Loop

A table or loop object contains a vector of TemplateLoops. To create a loop object, calls are made by the owning object to a TemplateLoop. The template returns an loop object. The loop object returns this loop object to the caller.

Example from the parse method of Table:

  Loop currentLoop = new Loop((TemplateLoop) templateLoopVector.elementAt(i));
or you could use the TemplateLoop object to create a Loop object using the loop id: Example:
  TemplateLoop tsg = (TemplateLoop) templateLoopVector.elementAt(i);
   Loop currentLoop = tsg.createLoop("AK9");
Eventually you will need to associate a Loop with its owning table or loop. The method addLoop does this by adding the loop object to an internal java.util.Vector. This Vector contains only Loops. Example:
       headerTable.addLoop(currentLoop);
Getting to a Loop

Loops are contained in/owned by Tables, other loops (super loops) or can be stand-alone. Objects that contain Loops implement the ILoopContainer interface. The interface is designed with several methods, most importantly for this discussion to get the loops the object owns. ILoopContainer has four getLoop methods:

Single Occurring Loops:

by the EDI Id within the Table or super Loop public Loop getLoop(String ID)
by its position within the Table or super Loop public Loop getLoop(int iPosNo), position number is relative to 1


Multiple Occurring Loops:

by its EDI Id within a sub Loop public Loop getLoop(String ID, int index), index is relative to 0
by its position within a sub Loop public Loop getLoop(int iPosNo, int index), position number is relative to 1, index is relative to 0


About Segments

Loops are containers for dataElements and compositeDEs.
Creating A Segment

A table or loop object contains a vector of TemplateSegments. To create a segment object, calls are made by the owning object to a TemplateSegment. The template returns an segment object. The segment object returns this segment object to the caller.

Example from the parse method of Table:

       Segment currentSegment = new Segment((TemplateSegment) templateSegmentVector.elementAt(i));
or you could use the TemplateSegment object to create a Segment object using the segment id: Example:
       TemplateSegment tsg = (TemplateSegment) templateSegmentVector.elementAt(i);
        Segment currentSegment = tsg.createSegment("AK9");
Eventually you will need to associate a Segment with its owning table or loop. The method addSegment does this by adding the segment object to an internal java.util.Vector. This Vector contains only Segments. Example:
       headerTable.addSegment(currentSegment);
Getting to a Segment

Segments are contained in/owned by Tables, loops or can be stand-alone. Objects that contain Segments implement the ISegmentContainer interface. The interface is designed with several methods, most importantly for this discussion to get the segments the object owns. ISegmentContainer has four getSegment methods:

Single Occurring Segments:

by the EDI Id within the Table or Loop public Segment getSegment(String ID)
by its position within the Table or Loop public Segment getSegment(int iPosNo), position number is relative to 1


Multiple Occurring Segments:

by its EDI Id within a Table Loop public Segment getSegment(String ID, int index), index is relative to 0
by its position within a Table or Loop public Segment getSegment(int iPosNo, int index), position number is relative to 1, index is relative to 0


About Data Elements

Creating A Data Element

As with segments Data Elements are built using a template object. But unlike Segments the owning object does not create a DataElement. DataElements are either created in two ways. When a document is parsed then the element is created. Or when you are creating objects a call to the buildDE method of the owning Segment or Composite must be called. The buildDE method takes one argument, an int, which specifies the position in the Segment or Composite. The buildDE method returns an object so be sure to cast the returned value to the correct type, either a CompositeDE or a DataElement.

       TransactionSet transactionSet = TransactionSetFactory.buildTransactionSet("840");
        Table currentTable = transactionSet.getHeaderTable();
        Segment currentSegment = currentTable.createSegment("ST");
        currentTable.addSegment(currentSegment);
        DataElement currentDE = (DataElement) currentSegment.buildDE(0);
        System.out.println(currentDE);
        currentDE.set("840");
        currentDE = (DataElement) currentSegment.buildDE(1);
Flavors of Data Elements

There are 7 different types of data elements. All are based on the X12 definitions. Some have unique setter/getter methods such as DateDE and TimeDE. All of these classes are based on the super class DataElement.

  1. BinaryDE - used for binary data types.
  2. CharDE - used for alphabetic and alphanumeric data types.
  3. DateDE - used for dates. Stores is value in a java.util.Calendar object. There is logic in the class to force Y2K compliance by pre-pending a '19' on values set with a length of 6 and YY value greater than 50 and pre-pending a '20' for values less than 51. For example, 000419 would become 20000419.
  4. IDDE - almost an extension of CharDE, this class has a list of valid values and description for the values.
  5. NumericDE - numeric data with a specific number of decimal places (0-9).
  6. RealDE - another numeric data type - floating point.
  7. TimeDE - used for times, Stores its value in a java.util.Calendar object.
Getting to a Data Element

Segments and Composite Data Elements own DataElements. Objects that contain or own Data Elements implement the IDataElementContainer interface. This interface is designed with several methods, such as getting to a Data Element. IDataElement container has two getDataElement methods:

by the EDI Id public DataElement getDataElement(String ID)
by its position public DataElement getDataElement(int inSequence), sequence number as defined in the XML rules file which should match the EDI specification


Setting Data Element Values
As of release 3.6.0 there are three methods to set a data element value. The first method is to set it directly with the data element object. The second way is to set it directly from rules file. The third method is to set it from the data element container object. the data element container object.
From the data element object.

All data elements inherit the super class set (String inValue) method. But some do have their own special set method.

DateDE can set a specific part of the date value. With its class variable value as a java.util.Calendar OBOE provides a set method in which specific portions of the date field can be set. This is accomplished by using the java.util.Calendar constants related to dates.

       method: public void set(int field, int value)

TimeDE, like DateDE, can set a specific part of the time value. With its class variable value as a java.util.Calendar OBOE provides a set method in which specific portions of the data field can be set. This is accomplish by using the java.util.Calendar constants related to time.

       method: public void set(int field, int value)
Assigning Default Value From The Rules File
Also see

In the Extended Edition version of OBOE there is a mechanism to assign default values to data element fields. Using one of three possible references in the XML rules file along with the data element setDefault method a data elements value can be assigned globally and programmatically.

In the extended version there is a element named "default" that is a child node of the data element node. The default node has one attribute named "from" which may contain one of three values "constant", "property" or "method." The from attribute used in conjunction with the CDATA value of the default node directs the OBOE package what data to put in or how data is to be put into the related data element object.

Setting Value From The Container - as of Release 3.6.0
The Segment and CompositeDE class provides a method to set the data element value. There are two formats for the method: The second argument is the String value to be set.
Note: at the time of this writing the specialized DateDE and TimeDE set methods are not implemented.
Note: if the data element object will be created if your code has not instantiated it.
   Segment seg = ...
    seg.setDataElementValue(1, "NYNY");
Getting Data Element Values
As of release 3.6.0 there are two methods to retrieve a data element value. The first is to use the get method on the data element object. The second is to get the value from the data element container.

All data elements inherit the super class' String get() method. But some do have their own special get method.

DateDE can get a specific part of the date value.

       method: public int get(int field)
java.util.Calendar.YEAR java.util.Calendar.MONTH java.util.Calendar.DAY_OF_MONTH



TimeDE, like DateDE, can get a specific part of the time value java.util.Calendar.HOUR

        method: public int get(int field)
        
java.util.Calendar.HOUR java.util.Calendar.MINUTE java.util.Calendar.SECOND





Getting Value From The Container - as of Release 3.6.0



The Segment and CompositeDE class provides a method to get the data element value.  There are two formats to the method
 both  return a String.

Note: if the data element has not be instantiated or its value not set a zero-length String will
be returned.


    Segment seg = ...
    String got = seg.getDataElementValue(1);



Creating An EDI Document



Each of the general EDI Objects, TransactionSet, Table, Segments, CompositeDE and DataElement share a common method named get. This method returns a string containing an EDI Object. While the method is publicly available, generally the method would be called from the TransactionSet object.
Requesting other formats.



Like the get method, all the general EDI Objects share a getFormattedText method. This method accepts one argument that determines the format style. Presently there are five styles, plain (or formatted), well formed XML, validated XML, X12 and EDIFact.
The plain format returns a string for each object with its description and any value (data elements only) associated with it. The segment get method appends a cr/lf or '\n' to the end of the string. The plain format is the default format. The output is simply the description field plus a ':' character and the value of the field, if one is present.
Calling getFormattedText with the static variable name Envelope.XML_FORMAT, which has an int value of 1, creates the XML format. An XML formatted string is returned. The XML tag names are defined in the XML rules based file.
Calling getFormattedText with the static variable name Envelope.X12_FORMAT, which has an int value of 2, creates the X12 format. The output from the X12 format is similar to the get methods call. The output contains X12 separators as defined in the TransactionSet source program.
Calling getFormattedText with the static variable name Envelope.EDIFACT_FORMAT, which has an int value of 3, creates the EDIFact format. The output contains EDIFact separators as defined in the TransactionSet source program.
Calling getFormattedText with the static variable name Envelope.VALID_XML_FORMAT, which has an int value of 4, creates a XML file that is validated. An XML formatted string is returned. The associated DTD file is named envelope.dtd. This file has nothing to do with the envelope rules DTD file and should not be confused with the rules file.

























ValidXMLEDIParser.java



This class builds an EDI object from a valid XML file as defined above.

Parsing An XML/EDI Document


 

The XML Rules and Document Files




There is a one for one mapping between the XML rules and the document's transaction set to be parsed.
The first rule is that there must be a TransactionSet element. All EDI Documents contain a line indicating the transaction set within the document. In X12 this is found in the "ISA" segment's first 3 bytes. The DTD rule "<!ATTLIST TransactionSet id CDATA #REQUIRED>"
TransactionSets and Table Parsing



The DTD rule "<!ELEMENT TransactionSet (table+)" indicates that a TransactionSet can contain one or more Tables. Though Tables are not identified within an EDI Document they are expressed in the rules file to for logically delineating the document. Here is a code snippet showing all three Tables with in a TransactionSet.

        
                
...

                
...

                
...

        
                
                
Tables and Segment Parsing

                
The second rule is that the Tables must match one of three possible header types.. In most cases an EDI document has three tables, Header, Detail and Trailer. There is only one occurrence of the Header and Trailer tables and multiple occurrences of the Detail table. But sometimes there is only a Header table. For instance, the 997 Functional Acknowledgment has only one Table. Each transaction set must have at least one table. If you are defining a transaction set with no table DEFINE A HEADER TABLE and place all the segments within this one HEADER TABLE.
Tables are not explicitly identified within an EDI Document. So the parser searches for the first occurrence of a valid Segment within the table. So, for instance, when the last valid Segment identifier is found while parsing the Header table the parser knows to jump out and start working on Detail tables.
The DTD rule "<!ELEMENT table (segment*, loop?)" indicates that a table can contain multiple segments and loops. The segments and loops owned by the Table will fall within the bounds of the table

        

                
                
Loop Parsing

                
The DTD rule "<!ELEMENT loop (segment?, loop?)*>" says a loop can contain zero, one or more subLoops and zero or more segments. Segments and loops within a loop are processed as with tables. Here is an example of a N9 loop containing a N9 Segment:

                
                    
                        
                

                
Loop Parsing

                
The DTD rule "<!ELEMENT loop (segment?, loop?)*>" says a loop can contain zero, one or more subLoops and zero or more segments. Segments and loops within a loop are processed as with tables. Here is an example of a N9 loop containing a N9 Segment:

                
                    
                        
                

                Note that the first segment of a loop must specify an occurrence of 1.
                
Segment and Data Element Parsing

                
Data Elements are contained within a Segment or Composite Data Element. The DTD rule "<!ELEMENT segment (compositeDE*|dataElement*)*" indicates that a Segment can contain multiple Composite Data Elements, multiple Data Elements and combinations. All of which is contained within the bounds of the

                        
                                
                        
                


        
        

Creating a Transaction Set XML File


                
When creating a TransactionSet XML file you could use an external EDI Definition file as a starting point. Using the flat file (ASCII) definitions from Secretariat of The Federal (USA) EDI and parse the files with a powerful text parser I have a program that can produce the XML files. These EDI definitions and others map one for one to the TransactionSet XML file.
A second alternative is to take the same flat files and store each type of EDI object in a database file. Then using the database files and a processing program generate the XML file based on the contents and relationships between each database that represent an EDI object. So you would have a TransactionSet (TransactionSets and Table tightly coupled) database, Segment database and a DataElement database. Then a relationship is needed between the TransactionSetTable database to the Segment database, Segment database to it, and Segment database to the DataElement database. As new records are found with each database a new XML element tag is created. Likewise when the program is done with a database record an element termination tag is created.
A third alternative is to do it by hand using an editor.
A fourth alternative is to purchase rules files from American Coders.

Pulling Data From Segments and Data Elements


                
                
Getting To The Data

                
When either building or parsing a TransactionSet and all associated objects, the data is going to have to be fetched. As mentioned in previous sections, a Java program is going to have to have a reference to objects required. This will require the program to move through the EDI objects and to have the ability to know where it is and how it got there. It comes down to this - moving through a tree structure.
The tree structure is starts from the Envelope class. Your program will traverse the tree from the Envelope down to the base data elements. Two tree graphs are shown here. The first is Envelope and Functional Group trees and their nodes. The second shows the tree structure from the transaction set down to the data element.

                        // build a transaction set using the ID
                        TransactionSet reqeustForQuotation = TransactioSetFactory.buildTransactionSet("840");

                        // get all three tables of the transaction set
                        Table header = reqeustForQuotation.getHeaderTable();
                        Table detail = reqeustForQuotation.getDetailTable();
                        Table summary = reqeustForQuotation.getSummaryTable();

                        // get a segment in the header table using the ID
                        Segment TransactionSetHeader = header.getSegment("ST");
                        Segment beginningSegmentForRequestForQuotation = header.getSegment("BQT");

                        // get a segment in the table using its Name - how convenient that this segment's name is Name
                        Segment name = header.getSegment("Name");

                        // get a subsegment of a segment by using the ID
                        Segment requiredResponse = name.getSegment("RRA");

                        // get a data element by using its ID
                        IDDE informationType = requiredResponse.getDataElement("701");

                        // get a data element by using its sequence number
                        CharDE referenceNumber = requiredResponse.getDataElement(2);

                        // get the contents of the data element
                        String informationTypeValue = informationType.get();
                        

Other Considerations for An EDI Document




Of primary concern to someone developing with OBOE is how to store an EDI document. How you store your document is beyond the scope of the current release of OBOE . There are so many ways to do it and if you are on a legacy EDI system it may not be necessary to create a new store for the documents. Java does provide several tools to access files for storage and retrieval. The simplest method would be to store each individual document as a file on local store and create a unique filename for each one. Whenever you need to access the file, simply pass it to the parser and the EDI object is recreated as it is stored. But as said before there are many other valid and possible better ways to store a document.
Return to Contents

 

The OBOE FTP Class




Note: that this class does not provide for secure FTP communication.

When sending or receiving with FTP the application program must create a FTPClient object. Using this object the application calls either upload (or append) or download function.

FTP Transmission

public void sendDocument(String documentText)
        {

        try {
                        // String system id is the ftp server
                        // Strings userid and password must have ftp privileges.
                FTPClient ftp = new FTPClient(system, userid, password);
                        // String systemDirectory is the name on the server where the document will go
                        // String fileName is the name of the file where the document will be placed.
                        // String documentText is the EDI document (or XML document).
                        // boolean false - send it as binary
                ftp.upload(systemDirectory, fileName, documentText, false);
                }
        catch (IOException ioe) // upload can throw this.
                {
                  ioe.printStackTrace();
                        // fail(); what to do when it doesn't work
                }

        }
       

Receiving by FTP

public String receiveDocument()
        {
        try {
                        // String system id is the ftp server
                        // Strings userid and password must have ftp privileges.
                FTPClient ftp = new FTPClient(system, userid, password);
                        // String systemDirectory is the name on the server where the document is located
                        // String fileName is the name of the file where the document will come from.
                        // boolean false - get it as binary
                    return ftp.download(systemDirectory, fileName, false);
                }
                }
        catch (IOException ioe) // download can throw this.
                {
                  ioe.printStackTrace();
                        // fail(); what to do when it doesn't work
                }

        }
       

Return to Contents


Sample Source Programs

viewsamples and viewsample

Included with the package, viewsamples and viewsample were programs that were written for my page. viewsample is a Java applet that calls the viewsamples Java Frame routine. viewsample input is the current URL, which is passed to viewsamples. Note: there is no need for the viewsample program, making viewsamples an applet is for future work.

viewsamples has three constructors. The first is a java.net.URL, the second is an input String and the third is a java.io.InputStream. The String constructor expects the String to be in an EDI document format. This constructor passes its String to the process(String) method. The URL and file constructor created an InputFileStream, URL is hard coded for the web page sample file sample.output.840.1. These constructors pass an InputFileStream to the process(InputFileStream) method. viewsamples can be run as a Java application. The main method expects one parameter, a filename of a file containing an EDI document.

viewsamples.process(InputFileStream) reads the file into a String and passes the String to viewsamples.process(String) .

viewsamples.process(String) creates the Frame with two java.awt.TextAreas and two java.atw.buttons. The first TextArea, intext, is used to display the input EDI document. The second TextArea, outtext, is used to display the formatting process, as requested by pushing one of the four. Button one, "OUTPUT: Format" is used to display the simple formatting function of the getFormattedText methods of the OBOE EDI Objects. Button two, "OUTPUT: XML" is used to display the XML formatting of getFormattedText by passing the Envelope.XML_FORMAT constant. Button three, "OUTPUT: X12" is used to display the document in X12 format. And finally, button four, "OUTPUT: EDIFACT" is used to display the document in EDIFact format.

An internal listener handles all buttons. This listener creates a OBOE parser object, and depending on if there is a URL being used, calls either of the two parser constructors, gets a TransactionSet from the parser, gets the formatted text from the TransactionSet and finally sends the results to the outtext TextArea.

For debugging purposes an internal class, displayMessage, is used when exception conditions are caught by viewsamples.

Other Source Programs

Included in the package is another Java AWT application named viewEDIObjects.java. This program is used for testing purposes. The logic flow is similar to viewSamples.

Return to Contents


Other Sources of Information

Return to Contents


Acknowledgments

Return to Contents


Appendices