Version 3.5.7
Author: Joe McVerry
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. OBOE also
allows you to transmit and receive EDI documents by Internet Mail
(Extended Edition only)
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.
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.
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.
Available in the Extended Edition version is another OBOE function is to transmit and receive EDI Documents using Internet Mail. The How To and the Why For is discussed later.
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.
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.

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.
| 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 |
| Name | Value | Purpose |
| SEGMENT_DELIMITER |
|
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. |
| Name | Type | Purpose |
| UNA_Service_String_Advice | Segment | UNA segment (optional) |
| UNB_Interchange_Header | Segment | UNB segment |
| UNZ_Interchange_Trailer | Segment | UNZ Segment |
| Name | Value | Purpose |
| SEGMENT_DELIMITER |
|
End of segment marker. |
| FIELD_DELIMITER |
|
End of field marker. |
| GROUP_DELIMITER |
|
End of group marker. |
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;
As mentioned above OBOE creates two sets of classes -- dynamic (the
real EDI objects) and static (the template 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.
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
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.
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.
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.
A class that represents an EDI Loop. Loops are containers for other segments and other loops.
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.
An interface for describing methods for storing and accessing TemplateSegments. This interface defines TemplateLoops containership
A class that represents an EDI segment. Segments are containers for composites and data elements.
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.
An interface for defining how Segments are stored.
This interface defines segment containership
An interface for describing methods for storing and accessing TemplateSegments. This interface defines TemplateSegments containership
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...
A class to describe all EDI Data Elements. Used as a super class to specific data element types.
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.
An interface describing methods for storing data elements.
This interface defines segment containership
A class for EDI Character Data Elements.
A class for EDI Binary Data Elements.
A class for EDI Date Data Elements.
A class for EDI ID Data Elements.
A class for EDI Numeric Data Elements.
A class for EDI Real Numeric Data Elements
A class for EDI Time Data Elements.
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.
This abstract class describes how EDI objects are extracted from an EDI Document.
This class extracts X12 EDI objects from an EDI Document.
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.
This class extracts EDIFact EDI objects from an EDI Document.
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.
Class with methods to break down an EDI Document into tokens.
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 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. It is only used by the mail classes.
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.
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), the Java Mail package (Extended Edition only), the Java Activation Framework package (Extended Editoin only), the Java Cryptography Extensions (Extended Editoin only), and a XML parser.
To compile the OBOE files you will need a Java Developer's Toolkit. If you plan on using the mail classes supported by OBOE you need the Java2 environment. The mail viewer requires Swing and mail encryption requires the Java Cryptography Extensions of Java2.
There are several JDKs on the market. Some free, some you have to pay for.
At this time I program and test with the Java development tool Eclipse. This excellent tool is available from The Eclipse Website.To use the OBOE Extended Edition, let alone compile the Extended Edition source files, you will need the Java mail jar file from Sun. It is available at http://java.sun.com/products/javam ail/ these classes provide access to SMTP mail server, for outgoing mail, and to IMAP mail server, for incoming mail. If you need access to a POP3 incoming mail server you need to download the POP3 package class at the same site.
One of the requirements for the Java Mail package is another package from Sun called Java Activation Framework or JAF. It is available at http://www.javasoft.com/be ans/glasgow/jaf.html The primary purpose of this class to act as an agent between a MIME specified document and a Java application or class.
One of the requirements for the Java Mail package is another package from Sun called Java Cryptography Extension. It is available at http://www.javasoft.com/products/jce . The primary purpose of this class to support encryption of mail documents. This package may be supplemented by another vendor's cryptography extension.
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.
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.
As you have read elsewhere in this document OBOE uses XML files to define the structure and rules of all EDI objects.
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.
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.
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.
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)
|
|
|
|
|
| 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 inplace 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 |
|
|
|
|
|
| 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 inplace 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:
|
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:
|
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 |
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;
}
<table section="detail"
validatingMethod="com.americancoders.tests.dValidatingClass.dValidatingMethod820DetailTableRefs">
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
<idlist>
<idcode>00</idcode>
<idvalue>Original</idvalue>
<idcode>01</idcode>
<idvalue>Cancellation</idvalue>
<idcode>02</idcode>
<idvalue>Add</idvalue>
</idlist>
In the rules file you may use one of three optional nodes to specify the name/value pairs.
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.
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.
The OBOE.properties files is used to store information that describes your system's environment to the OBOE package.
|
||||||||||||||||||||
|
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++)
{ /* don't 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();
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 and/or T 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. The variable meanings are as follows:
| V | Version | X12: "480 - Version Release Industry Identifier Code" from GS
- 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 transactionset 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 |
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();
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 subdirectroy 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();
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());
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.
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.
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The third example of the buildTransactionSet method uses four of
seven parameters, an ID field, a searchDirective string and a sender id
string.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
for applets use getCodeBase method to get the active URL. |
|
|
|
|
|
|
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.
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.
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");
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());
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.
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.
Logically, tables are automatically built by the TransactionSetFactory as the XML rules file is read.
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 =or you could use the TemplateLoop object to create a Loop object using the loop id: Example:
new Loop((TemplateLoop) templateLoopVector.elementAt(i));
TemplateLoop tsg = (TemplateLoop) templateLoopVector.elementAt(i);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:
Loop currentLoop = tsg.createLoop("AK9");
headerTable.addLoop(currentLoop);
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 |
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 =or you could use the TemplateSegment object to create a Segment object using the segment id: Example:
new Segment((TemplateSegment) templateSegmentVector.elementAt(i));
TemplateSegment tsg = (TemplateSegment) templateSegmentVector.elementAt(i);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:
Segment currentSegment = tsg.createSegment("AK9");
headerTable.addSegment(currentSegment);
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 |
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);
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.
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 |
|
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)
In the Extended Edition version of OBOE there is a mechanism to assign default values to dataelement 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 dataelement 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 dataelement object.
Using
Using
Using
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
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.
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 theXML 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.
<?xml encoding="ISO-8859-1"?> <!-- OBOE release 3.0.0 --> <!-- used by ValidXMLEDIParse --> <!ELEMENT envelope (segment+, functionalgroup+, segment+)> <!ATTLIST envelope format (X12 | EDIFact) #REQUIRED > <!ELEMENT functionalgroup (segment?, transactionset+, segment?)> <!ELEMENT transactionset (table+)> <!ATTLIST transactionset code CDATA #REQUIRED name CDATA #IMPLIED > <!ELEMENT table (loop?, segment?)*> <!ATTLIST table section CDATA #REQUIRED > <!ELEMENT loop (loop?, segment?)*> <!ATTLIST loop code CDATA #REQUIRED name CDATA #IMPLIED > <!ELEMENT segment (composite?, element?)*> <!ATTLIST segment code CDATA #REQUIRED name CDATA #IMPLIED > <!ELEMENT composite (element)+> <!ATTLIST composite code CDATA #REQUIRED name CDATA #IMPLIED > <!ELEMENT element (#PCDATA | value)*> <!ATTLIST element code CDATA #REQUIRED name CDATA #IMPLIED > <!ELEMENT value (#PCDATA)> <!ATTLIST value description CDATA #IMPLIED >
This class builds an EDI object from a valid XML file as defined above.
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>
The DTD rule
<TransactionSet name="Request_for_Quotation" id="840" revision="!!!" functionalGroup="" description="Request_for_Quotation"> <table section="header">... </table> <table section="detail">... </table> <table section="summary">... </table> </TransactionSet>
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<table...</table tags. So while the rules file is being read each Segment and loop found within the bounds gets a TemplateSegment ir TemplateLoop added to the Vector TemplateSegment Vector of the owning table. Here is an example of a Header Table containing two Segments:
<table section="header"></font> <segment name="Transaction Set Header" id="ST" description="Transaction Set Header" ... </segment> <segment name="Beginning Segment for Request For Quotation" id="BQT" description="Beginning Segment for Request For Quotation" ... </segment> </table>
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 name="Identification Reference" id="N9"
occurs="1000"
required='O'
xmlTag="IdentificationReference">
<segment name="Identification Reference" id="N9"
</segment>
</loop>
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 name="Identification Reference" id="N9"
occurs="1000"
required='O'
xmlTag="IdentificationReference">
<segment name="Identification Reference" id="N9"
</segment>
</loop>
Note that the first segment of a loop must specify an occurrence of 1.
Data Elements are contained within a Segment or Composite Data Element. The DTD rule "!