Table of Contents
COBOL batches frequently involves dealing with EBCDIC files using copybooks. Modernizing these batches requires ability to read and write to these files. Two classes have been developed to support EBCDIC Read/Write:
Summer.Batch.Extra.Ebcdic.EbcdicFileReader
: to read from an EBCDIC file;
Summer.Batch.Extra.Ebcdic.EbcdicFileWriter
: to write to an EBCDIC file;
Both classes require a XML version of a COBOL copybook provided at run time.
EbcdicFileReader
To read records from an EBCDIC file, using an EbcdicFileReader, the following elements must be provided :
a XML version of the needed COBOL copybook (Copybook property);
a class in charge of transforming EBCDIC record into a business object (EbcdicReaderMapper property): this class must implement Summer.Batch.Extra.Copybook.IEbcdicReaderMapper<T>
interface ;
a path to EBCDIC file (Resource property).
Caution | |
---|---|
The two elements (copybook XML file and EBCDIC reader mapper class) are mandatory. |
The COBOL copybook is used by reader to extract records from the EBCDIC file.
Example 7.1. Sample XML copybook export
<?xml version="1.0" encoding="ASCII"?> <FileFormat ConversionTable="IBM037" dataFileImplementation="IBM i or z System" distinguishFieldSize="0" newLineSize="0" headerSize="0"> <RecordFormat cobolRecordName="BA_EBCDIC_READER" distinguishFieldValue="0"> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="CODE" Occurs="1" Picture="S9(5)" Signed="true" Size="5" Type="3" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="NAME" Occurs="1" Picture="X(30)" Signed="false" Size="30" Type="X" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="DESCRIPTION" Occurs="1" Picture="X(40)" Signed="false" Size="40" Type="X" Value=""/> <FieldFormat Decimal="0" DependingOn="" ImpliedDecimal="true" Name="DATE" Occurs="1" Picture="S9(8)" Signed="true" Size="4" Type="B" Value=""/> </RecordFormat> </FileFormat>
Note | |
---|---|
ConversionTable (=encoding) is specified in the copybook XML file: this attribute must have a property that can be understood by the C# API.
This requires use the C# encoding names (which differ from java encoding names convention, for example, java uses "Cp037" where C# uses "IBM037").
|
The XML copybook file must be compliant with XSD (full XSD source is given in dedicated appendix section)
Figure 7.1. EBCDIC File Format XML schema
The corresponding bound C# classes are located in Summer.Batch.Extra.Copybook
namespace:
CopybookElement.cs
FieldFormat.cs
FieldsGroup.cs
FileFormat.cs
IFieldsList.cs
RecordFormat.cs
Afterwards the EBCDIC reader mapper is used to transform the records into a business objects. Below is a business object whose properties will be mapped to the EBCDIC record described by the XML copybook above.
Example 7.2. Sample business object to which EBCDIC records will be mapped
using System;
namespace Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos
{
/// <summary>
/// Entity EbcdicFileBO.
/// </summary>
[Serializable]
public class EbcdicFileBO
{
/// <summary>
/// Property Code.
/// </summary>
public int? Code { get; set; }
/// <summary>
/// Property Name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Property Description.
/// </summary>
public string Description { get; set; }
/// <summary>
/// Property Date.
/// </summary>
public DateTime? Date { get; set; }
}
}
Now, Define a mapper in charge of transforming records into business objects. This mapper must implement Summer.Batch.Extra.Ebcdic.IEbcdicReaderMapper<T>
interface.
Summer.Batch.Extra.Ebcdic.AbstractEbcdicReaderMapper<T>
is super class to inherit from in order to craft EBCDIC reader mapper quickly (see example below).
Example 7.3. Sample EBCDIC reader mapper
using Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos; using Summer.Batch.Extra.Ebcdic; using System.Collections.Generic; namespace Com.Netfective.Bluage.Business.Batch.Ebcdic.Bos.Mappers { ///<summary> /// Ebcdic mapper for the EbcdicFileBO class. ///</summary> public class EbcdicFileEbcdicMapper : AbstractEbcdicReaderMapper<EbcdicFileBO> { private const int Code = 0; private const int Name = 1; private const int Description = 2; private const int Date = 3; ///<summary> /// Map a collection of properties to a EbcdicFileBO record. ///</summary> /// <param name="values"> list of values to be mapped</param> /// <param name="itemCount"> item count; will be used as identifier /// if this makes sense for the target class.</param> /// <returns>the EbcdicFileBO record build upon the given list of values.</returns> public override EbcdicFileBO Map(IList<object> values, int itemCount) { var record = new EbcdicFileBO { Code = (int) ((decimal) values[Code]), Name = ((string) values[Name]), Description = ((string) values[Description]), Date = ParseDate(values[Date]), }; return record; } } }
The EbcdicFileReader is then declared as any other reader in the job XML file :
Example 7.4. EbcdicFileReader
declaration in the job XML file
And here is the corresponding Unity configuration part :
Example 7.5. EbcdicFileReader
Unity configuration
… /// <summary> /// Registers the artifacts required for step EbcdicReader. /// </summary> /// <param name="container">the unity container to use for registrations</param> private void RegisterEbcdicReader(IUnityContainer container) { // Reader - EbcdicReader/EbcdicFileReader container.StepScopeRegistration<IItemReader<EbcdicFileBO>, EbcdicFileReader<EbcdicFileBO>> ("EbcdicReader/EbcdicFileReader") .Property("Resource").Resource("#{settings['BA_EBCDIC_READER.EbcdicReader.FILENAME_IN']}") .Property("Copybook").Resource("#{settings['BA_EBCDIC_READER.EbcdicReader.COPYBOOK_IN']}") .Property("EbcdicReaderMapper") .Reference<IEbcdicReaderMapper<EbcdicFileBO>>("EbcdicReader/EbcdicFileReader/Mapper") .Register(); …
Note | |
---|---|
Please note:
|
EbcdicFileWriter
To write records to an EBCDIC file using an EbcdicFileWriter, the following elements should be provided:
list of COBOL copybooks XML versions (Copybooks property);
class in charge of transforming EBCDIC record into business object (EbcdicWriterMapper property): one can use the Summer.Batch.Extra.Ebcdic.EbcdicWriterMapper
class or a custom sub-class inherited from it;
path to the targeted EBCDIC file (Resource property).
Caution | |
---|---|
Writer takes a list of XML copybooks but only uses one copybook at a time; writer has a method ( These three elements (copybook XML files list, EBCDIC writer mapper class and path to targeted resource) are mandatory. |
Let's review the corresponding configurations. The writer must be declared in the job XML file (as any other writer):
Example 7.6. EbcdicFileWriter
declaration in the job XML file
Unity configuration:
Example 7.7. EbcdicFileWriter
Unity configuration
… /// <summary> /// Registers the artifacts required for step EBCDIC_WRITER. /// </summary> /// <param name="container">the unity container to use for registrations</param> private void RegisterEBCDIC_WRITER(IUnityContainer container) { … // Writer - EBCDIC_WRITER/EbcdicFileWriter container .StepScopeRegistration<IItemWriter<EbcdicFileBO>, EbcdicFileWriter<EbcdicFileBO>>("EBCDIC_WRITER/EbcdicFileWriter") .Property("Resource").Resource("#{settings['BA_EBCDIC_WRITER.EBCDIC_WRITER.EbcdicFileWriter.FILENAME_OUT']}") .Property("Copybooks").Resources("#{settings['BA_EBCDIC_WRITER.EBCDIC_WRITER.EbcdicFileWriter.COPYBOOK_OUT']}") .Property("EbcdicWriterMapper").Reference<EbcdicWriterMapper>("EBCDIC_WRITER/EbcdicFileWriter/Mapper") .Register(); // EBCDIC writer mapper for EBCDIC_WRITER/EbcdicFileWriter container .StepScopeRegistration<EbcdicWriterMapper>("EBCDIC_WRITER/EbcdicFileWriter/Mapper") .Register(); …
Note | |
---|---|
|