Clicking anywhere else on page will go to "next page".
Table of Contents
Introduction
All the programs/classes used to implement the sample Extract/Sort/Report project are included
in the SHARE procedings. However they are not in the handout. These handout and the program
examples are available on my web site, www.jsrsys.com.
I will include code snippets in my discussion of various features of Java so you won't have to
flip the appendix. I failed to do this on my last presentation of Java SWING, and lost y'alls
attention while you were trying to find the code. I hope this method works better, and will
kill fewer trees.
Your are welcome to use any of the code examples in your own Java applications.
COBOL: | COBOL Concept Description |
Java: | Java/OO Similar Concept |
++: | What Java/OO adds to Concept |
When I began Java, I used to think the OO (Object Orientation) was "just like" good programming
practices, except it was more formal, and the compiler enforced certain restrictions.
I no longer think that way. However, when you are beginning I think certain "is similar to"
examples will help you grasp the concepts.
COBOL: | Load Module/Program |
Java: | Class |
COBOL: | PERFORM |
Java: | method |
++: | can pass parameters to method, more like FUNCTION
other programs/classes can call methods in different classes
if declared public. public/private gives designer much control
over what other classes can see inside a class. |
COBOL: | Working Storage, statically linked sub-routine |
Java: | instance variables |
++: | (see next) |
COBOL: | Working Storge, dynamically loaded sub-routine |
Java: | Class variables |
++: | Java can mix both Class variables (called static, just the reverse of our COBOL example,
and instance variables (the default).
|
Class variables (static) occur only once per Class (really in one JVM run-time environment).
Instance variables are unique to each instance of a class.
Here is an example from class JsrSysout. From my COBOL background I like to debug my code by DISPLAYing
significant data to the SYSOUT data set. There is a Java method for this, System.out.prinln(...). The problem with this
method is that the data you want just scrolls off the Java console, the equivalent of SYSOUT or perhaps
DISPLAY UPON CONSOLE if you had your own stand-alone machine. I needed a way to easily do displays that
would stop when the screen was full. Since there is only one Java console, the line-count for the screen clearly
needs to be a class variable, so all instances (each program/class that logs here has its own instance of JsrSysout)
stop at the bottom of the screen.
static final String COPYRIGHT =
"Copyright 1998-2000, JSR Systems. See: www.Jsrsys.com/copyright.";
static final int MAXLINELEN = 80;
static final int MAXSCREEN = 21;
static int qBig = ' '; // 81 "Q" to terminate all instances
// 82 "R" run, do not query user any more
int qChar = ' '; // 113 "q" to terminate this instance
static int nLines = 0;
static String syslogFileName = "";
// make syslog... static so any program can turn on logging of ALL calls
static JsrLineOut syslogFile = new JsrLineOut("NoLog");
The above illustrates the use of class vs. instance variables. static final is a special case.
This means the code is a constant, and can not be modified. Since it is a constant, making it
static (a class variable) only makes sense. nLines (the line-count) is also static, as is the
syslogFileName. JsrSysout has a nice feature that lets any program/class calling it turn on
a permanent copy of what has been displayed via JsrSysout. This can be a useful audit trail
for production programs, as well as a way to see what happened if a dump clears the screen.
qBig is updated if the user enters a capital Q (or R) in response to a screen full message.
If Q is entered, the program runs, but with no displays. If R is entered the program continues
to run but does not stop when the screen is full. This is useful for a long running program
that might terminate. qChar is updated if a lower-case q is entered. This terminates
output from only this instance of JsrSysout.
Here is the code that implements the DISPLAY function.
void display(String displayString)
{
if (qChar != 113 && qBig != 81) // !=q != Q
{
// System.out.println("Last q="+qChar+", Last Q="+qBig);
nLines += (displayString.length()+MAXLINELEN)/MAXLINELEN;
if (nLines > MAXSCREEN)
getQ(displayString);
else
System.out.println(displayString);
if (syslogFileName.length() > 0)
{
syslogFile.setLine(displayString);
}
}
return;
}
Other methods implented in JsrSysout are accept, speedometer, setNoStop, and syslog.
accept is obvious. speedometer is a way to display without scrolling the screen. setNoStop sets qBig to R, in effect
letting a program prevent scrolling. sysout causes all the displays to be logged to a disk file.
Multiple Instances of same class:
One (calling program) class can create multiple instances of the same class. Why would you want to do this?
One good COBOL example is I/O routines. In COBOL you would need to code one I/O routine for each file you wish
to access. If you want to open a particular file twice in one run-time environment you would need a different I/O routine
with a different name, even if the logic was identical.
With Java you could code just one class for a particular logical file type. Then for each file you wish to read (or write)
you simply create another instance of that class using the new operator. Here are some snippets of code from program IbfExtract
that do exactly that. This program exploits the fact that I have written a class for Line Input, and another class for Line
Output. These are called JsrLineIn and JsrLineOut.
String inputLine = " ";
JsrLineIn input = new JsrLineIn();
JsrLineOut[] output = new JsrLineOut[MAXOUT];
String[] outName = new String[MAXOUT];
This program is going to read from one input file, but will create an undetermined number of output files,
based on the contents of the input file.
input.setName(parm[0]);
while (0 <= (recNum=input.getNext()))
{
inputLine = input.getLine();
fileName = inputLine.substring(0,10).trim();
if (fileName.equals("RP5226")) fileName += "."+inputLine.substring(17,21);
for (i = 0; i < iMax && !fileName.equals(outName[i]); i++) {}
/** alternate: could do Hashtable if had large # of files...
//sysout.display("*"+fileName+i+"*");
if (i == iMax)
{
iMax++;
output[i] = new JsrLineOut();
outName[i] = fileName;
output[i].setName(fileName);
sysout.display("*"+fileName+"["+i+"]");
}
line100++;
if (line100 == 100) /** alternate: if (recNum%100 == 0) <--!!!
{
line100 = 0;
sysout.speedometer("Copying record: "+recNum);
}
output[i].setLine(inputLine);
}
The setName method of class JsrLineIn opens an input file for that name. It then begins a very typical loop.
The getNext method for input positions the file to the next record, and returns the record number.
The getLine method returns the current input record (line). If the input columns 1,10 == RP5226,
the program constructs an output fileName of RP5226+columns(18,21). It then checks to see if this
file is already open (searching the table of file names). If it is not, the new file name is
stored in the table, and a new instance of JsrLineOut is created in the array called output.
This illustrates another dynamic feature of Java. When output is first created, it is an array of
null pointers, it takes very little space. Only when a new object is created, and the pointer to
it implicitly put in the array does storage for the object get allocated. That object can be
anything from a String to an very complex Class.
The setLine method of JsrLineOut writes one record (line) to the output file opened by that instance of JsrLineOut.
The speedometer method of JsrSysout writes a line to the system console with no line feed. This is a convenient
(non GUI) method of monitoring the programs progress.
COBOL: | PICTURE |
Java: | No real equivalent. |
I therefore invented a method to mymic a ZZZ,ZZZ,... mask for integer input. I have generally grouped my
utility functions in JsrUtil. These are methods that really don't related to any type of object.
Here is an example of padLeft that implements this logic. padLeft is also a good example of polymorphism.
In COBOL, if you have different parameter lists you need different entry points. In Java, the types of
parameters are part of the definition. For example:
* paddedString = u.padLeft(oldString,10); // pad left with blanks
* paddedString = u.padLeft(oldInt,10); // comma inserted every 3 bytes.
* paddedString = u.padLeft(oldInt,10,2); // " + .00 (2 is # decimal points).
* paddedString = u.padLeft(oldLong,10); // comma inserted every 3 bytes.
* paddedString = u.padLeft(oldLong,10,2); // " + .00 (2 is # decimal points).
All the padLeft methods do essentially the same function. However, the ones that accept
int or long values, will also insert the comma in every 3 bytes, and suppress leading zeroes.
The number of decimal digits is my way of handling the issue of decimal rounding. This will
work as long as you add or subtract integers with the same assumed decimal precision, and,
if you multiply or divide, you manually handle the scaling.
COBOL: | Decimal arithmetic |
Java: | Not in native Java, but IBM has implemented some BigDecimal classes. |
I consider this the major weakness of Java for accounting type applications. I would have liked to
see the packed decimal data type as part of the native JVM byte architecture. I guess it is not
there because it is not in C or C++. I have only read about the BigDecimal classes.
Based on session 0018 from March 2002 SHARE: "Decimal Arithmetic: e-10 for e-Business",
one pays a significant performance penalty by using BigDecimal.
However, I am not convinced that this is a significant factor in a typical I/O bound application.
BigDecimal is now part of standard Java.
COBOL: | COPY or INCLUDE |
Java: | Inheritance |
++: | Much more powerfull! |
In COBOL, if you change a COPY or INCLUDE member, you must recompile all the programs that use it.
In Java, if program B inherits from program A, a change in program A is automatically inherited by
program B without recompiling! Yes, this really works, and lends great power to Java applications.
I exploited this for my Read/Sort/Report system. Class IbfReport contains all the basic logic
common to the report programs. It has appropriate defaults for all of its methods.
Classes IbfRP#### extend IbfReport, and contain only those methods unique to a particular report.
If a change is made in IbfReport, it is reflected in the IbfRP#### programs (classes) the next time
they are run.
COBOL: | ON EXCEPTION |
Java: | try/throw/catch |
++: | can limit scope of error detection (see following) |
COBOL: | OPEN |
Java: | Input Streams |
++: | Automatic error detection, both a blessing and a curse. |
BufferedWriter outFile;
try {outFile = new BufferedWriter(new OutputStreamWriter
(new FileOutputStream (fileName)),1000000);
} catch ( IOException eIO )
{System.out.println("I/OError! " + fileName);
recNum=-1;
}
return recNum;
The first really useful Java classes I wrote were JsrLineIn and JsrLineOut. These two classes are
the heart of any Java programs/classes I have written (right up there with JsrSysout). And this try/catch
stuff was what forced me into it. My first programs (copied from the Java in 21 days book) had try {} wrapped
around all the code, and placement of the catch was difficult. I realized that I needed to encapsulate
the read logic and the error detection code. If there is an error, I log the error, and return -1.
COBOL: | WRITE |
Java: | write (yes, really). |
int setLine(String parmLine)
{
if (recNum >= 0) /** alternate: if (null !=outFile) <--much better
{
if (fileName.equals("")) fileName = lastName; //2000-07-28
try { outFile.write(parmLine);
outFile.newLine(); // platform dependent line separator
if (flushOn) outFile.flush(); // flush after each line...
} catch ( IOException eIO )
{System.out.println("I/OError! " + fileName); }
}
recNum++;
return recNum;
}
This is the method to actually write a line of output. It only does the write if the
open was successful. JsrLineIn is a good example of the benefit of run time binding
in Java. When I wrote the first versions, Buffered streams were not implemented. Java
wrote a character at a time. This was not an issue for local file systems, but it made
Java so slow on networks as to be unusable. When Buffered streams became available, all
I had to do was modify two classes, and all my programs started running very fast over
the network! However, a downside of that is that if the program abended, I often had
no output, because the buffer size I choose was very large. Thus I implmented the
setFush method which sets the boolean variable flushOn to true or false (default is false).
If it is on, I flush the buffer after each line, which is still much faster than a character
at a time. setLine returns the # of the line written, which can be displayed by speedometer,
and is logged when the file is closed.
COBOL: | CLOSE |
Java: | close method |
int close()
{
if (recNum > 0) /** alternate: if (null !=outFile) <--much better
{
if (displayOn)
sysout.display("Close Output: " + u.padLeft(recNum,10)
+ " Records: "+ fileName
+" ");
try {outFile.close(); // free up resource
}catch ( IOException eIO )
{System.out.println("I/OError! " + fileName); }
}
recNum = - recNum;
lastName = fileName; // save lastName if call w/o setName()
fileName = "";
return recNum;
}
Yup, it is actually called close! All the rest of the code just illustrates my
logging logic, and sets up the return to return minus (-) the number of records written.
The (-) is just my convention for a closed file.
int getNext()
{
if (fileName.equals(""))
{
sysout.display("JsrLineIn--must use setName([name of File])!!!");
sysout.display("JsrLineIn--before reading w/ getNext()!!!!!!!!");
return -1;
}
if (recNum >= 0) /** alternate: if (null !=outFile) <--much better
{
try {fileLine = inFile.readLine();
}
catch ( IOException eIO )
{sysout.display("I/OError! " + fileName); }
if (fileLine == null)
return close();
else
recNum++;
}
// sysout.display ("recNum="+recNum+ "Rec="+ fileLine);
return recNum;
}
String getLine()
{
return fileLine;
}
All I have had occasion to use is readLine. There are other read methods in Java, such as readChar.
Now for the project that is my sample:
COBOL: | Input large file, multiple records types.
Output, file for each record type (but one type had many buying groups).
Several report programs, each reads file of its type records, sorts selected records,
produces report to OUTPUT file.
One file read many times, once per buying group.
|
Java: | Expanded functionality of output by writing each buying group to its own file.
Thus each buying group reads only records for that group. |
++: | Used inheritance to really simplify coding of separate report programs. |
Sample of input:
RP5196COST0140074001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00081400010175AMER REGEN
RP5226 0024074G051001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5226 0020074G150001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750003190 * AMER REGEN
RP5226 0001074G231001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5226 0016074G619001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5226 0098074G748001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5226 0022074G840001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750004350 * AMER REGEN
RP5226 0040074G848001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750003330 * AMER REGEN
RP5226 0002074G850001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5226 0003074G955001172METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA00101750008140 AMER REGEN
RP5196COST0140074001180FLOXIN 400MG TAB 100 0062-1542-01 EA00432510051901J-O-M PHAR
RP5226 0024074G051001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010042386 * J-O-M PHAR
RP5226 0020074G150001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010042386 * J-O-M PHAR
RP5226 0001074G231001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010043251 J-O-M PHAR
RP5226 0016074G619001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010043251 J-O-M PHAR
RP5226 0098074G748001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010043251 J-O-M PHAR
RP5226 0022074G840001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010043251 J-O-M PHAR
RP5226 0040074G848001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010041226 * J-O-M PHAR
RP5226 0002074G850001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010043251 J-O-M PHAR
RP5226 0003074G955001180FLOXIN 400MG TAB 100 0062-1542-01 EA00519010024073 * J-O-M PHAR
RP5196COST0140074001693ATUSS DM LIQ 16OZ 59702-015-16 EA00027500003300ATLEY PHAR 103
RP5226 0024074G051001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0020074G150001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0001074G231001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0016074G619001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0098074G748001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0022074G840001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0040074G848001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0002074G850001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5226 0003074G955001693ATUSS DM LIQ 16OZ 59702-015-16 EA00033000002750 ATLEY PHAR 103
RP5196COST0140074002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00010000001200LILLY ELI 7175
RP5226 0024074G051002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0020074G150002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0001074G231002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0016074G619002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0098074G748002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0022074G840002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0040074G848002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0002074G850002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000001000 LILLY ELI 7175
RP5226 0003074G955002303DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA00012000000206 * LILLY ELI 7175
RP5196COST0140074003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00024340003042LILLY ELI 520
RP5226 0024074G051003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0020074G150003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0001074G231003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0016074G619003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0098074G748003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0022074G840003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0040074G848003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0002074G850003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420002434 LILLY ELI 520
RP5226 0003074G955003228HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA00030420001720 * LILLY ELI 520
Sample Bat file:
%jdkdir%\bin\java -jar Ibf.jar ccTest74.txt ccTemp.txt
and control card input:
IbfExtract
inputSamp.txt
x--output depends on col 1-10 and Group #
x--line 1 is program (Class) to execute, line 2 is input file, line 3 is output file,
x--line 4 is print header line, line 5 is Control Card, line 6 is separator line.
---------------------------
IbfRP5196
RP5196COST
dcost74.txt
COST 74 3 N Y Y DCAT N0140BBDC6300 ST. LOUIS STREET MERIDIAN MS39301 ATTN:MIKE PARTRIDGE
74 Y12X
----------------------------
IbfRP5226
RP5226.G051
dprem74.txt
PREMIER 74 3 N Y Y DCAT N0024BBDC6300 ST. LOUIS STREET MERIDIAN MS39301 ATTN:MIKE PARTRIDGE
74G051 12X
-----------------------------
Part of log file from 25 MB (200 KB record) extract to 9 files and two reports.
IbfDrive--Copyright 2000, Imperial Business Forms & JSR Systems. See: www.Jsrsys.com/copyright.
IbfDrive--usage: IbfDrive
IbfDrive--Begin: 2002-02-28@17:40
Open Input: ccTest74.txt
Open Output: ccTemp.txt
Close Output: 2 Records: ccTemp.txt
Calling IbfExtract: test74
IbfExtract--Copyright 2000, JSR Systems. See: www.Jsrsys.com/copyright.
IbfExtract--usage: IbfExtract
2002-02-28@17:40--RP5196 Begin Extract
Open Input: test74
Open Output: RP5196COST
*RP5196COST[0]
Open Output: RP5226.G051
*RP5226.G051[1]
Open Output: RP5226.G955
*RP5226.G955[9]
Close Input: 198,775 Records: test74
Close Output: 19,869 Records: RP5196COST
Close Output: 19,869 Records: RP5226.G051
Close Output: 19,870 Records: RP5226.G955
2002-02-28@17:40--RP5196 End-- Extract
Open Output: ccTemp.txt
Close Output: 2 Records: ccTemp.txt
Calling IbfRP5196: ccTemp.txt RP5196COST dcost74
IbfRP5196--Copyright 2000, Imperial Business Forms & JSR Systems.
IbfRP5196--usage: IbfRP5196 <Control Card> <input> <output>
Open Input: ccTemp.txt
Open Output: dcost74
Close Input: 2 Records: ccTemp.txt
Open Input: RP5196COST
year=2002 mm=12 Control Card=74 Y12X
year=2002 mm=12
Close Input: 19,869 Records: RP5196COST
2002-02-28@17:40--RP5196COST Begin sort
Sorting table of length: 19869
Column/length/A-D): 95/1/0
Column/length/A-D): 24/31/0
2002-02-28@17:40--RP5196COST End-- sort
Close Output: 20,855 Records: dcost74
Close Input: 18 Records: ccTest74.txt
IbfDrive----End: 2002-02-28@17:40
Sample Report 1:
COST 74 3 N Y Y DCAT N0140BBDC6300 ST. LOUIS STREET MERIDIAN MS39301 ATTN:MIKE PARTRIDGE
1
0 MERIDIAN DIVISION BERGEN BRUNSWIG CATALOG DECEMBER 02 RP5196 PAGE 1
Item Description N D C Unit Cost List CL Vendor Product Code
001-693 ATUSS DM LIQ 16OZ 59702-015-16 EA 27.50 33.00 ATLEY PHAR 103
002-303 DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA 10.00 12.00 LILLY ELI 7175
001-180 FLOXIN 400MG TAB 100 0062-1542-01 EA 432.51 519.01 J-O-M PHAR
003-228 HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA 24.34 30.42 LILLY ELI 520
001-172 METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA 81.40 101.75 AMER REGEN
0Record Total = 5
Sample Report 2:
PREMIER 74 3 N Y Y DCAT N0024BBDC6300 ST. LOUIS STREET MERIDIAN MS39301 ATTN:MIKE PARTRIDGE
1
0 BG-G051 MERIDIAN DIVISION BERGEN BRUNSWIG GROUP CATALOG DECEMBER 02 PAGE 1 RP5226B
Item Description N D C Unit AWP Cost Ind CL Vendor Product Code
001-693 ATUSS DM LIQ 16OZ 59702-015-16 EA 33.00 27.50 ATLEY PHA 103
002-303 DOBUTREX RTU 250MG VL 20ML 0002-7175-01 EA 12.00 10.00 LILLY ELI 7175
001-180 FLOXIN 400MG TAB 100 0062-1542-01 EA 519.01 423.86 * J-O-M PHA
003-228 HEPARIN SOD 10MUN VL 5ML 0002-7217-01 EA 30.42 24.34 LILLY ELI 520
001-172 METHYLENE BLU 1% SDV 10X10ML 0517-0310-10 EA 101.75 81.40 AMER REGE
0Record Total = 5
You have already seen snippets of code from IbfExtract above.
Here is the report shell program (actually a complete program), and one of the classes that extend it.
class IbfReport
{
static final String COPYRIGHT =
"Copyright 2000, Imperial Business Forms & JSR Systems. See: www.Jsrsys.com/copyright.";
static final int MAXREC = 50000;
JsrSysout sysout = new JsrSysout();
JsrUtil u = new JsrUtil();
String[] inputLine = new String[MAXREC];
JsrLineIn input = new JsrLineIn();
JsrSortByKey sort = new JsrSortByKey();
JsrLineOut output = new JsrLineOut();
int line100 = 0;
int recNum = 0;
int i = 0;
int iMax = 0;
int[] keys;
int testMax = 0; //setting to non-zero will process only first n records.
int pageNum = 0;
int lineCount = 99;
int linesPerPage = 84;
String tl1 = u.padRight("1",133);
String tl2 = u.padRight("0",133);
String tl2b = " ";
String hdr1 = u.padRight(" ",133);
String today = u.getDateTime();
String year4 = today.substring(0,4);
String mm2 = today.substring(5,7);
String[] mmName = {" JANUARY",
" FEBRUARY",
" MARCH",
" APRIL",
" MAY",
" JUNE",
" JULY",
" AUGUST",
"SEPTEMBER",
" OCTOBER",
" NOVEMBER",
" DECEMBER"};
int intYear;
int intMonth;
String ccAll;
String ccBrch;
String ccHBGN;
String ccCatType;
String ccCostCode;
String ccMonth;
String ccPrtAcd;
String division = " ";
String costLabel = " ";
String reportName = "IbfReport";
public static void main(String argv[])
{
IbfReport IbfReport = new IbfReport(); /** alternate: */
//ibfReport variable should begin with lower-case!!!!!!
IbfReport.run(argv);
}
public void run(String parm[])
{
lineCount = 99; // repeat of same report starts on new page.
pageNum = 0; // start each report with new page numbers 2000-12-17
setReportName(); // sets reportName for following displays, etc.
setSortKeys(); // set sort keys array values...
sysout.display(reportName+"--"+COPYRIGHT);
sysout.display(reportName+"--usage: "+reportName+" <Control Card> <input> <output> ");
/** alternate: above code should be in constructor */
if (parm.length < 3)
{
sysout.display(reportName+"--requires three parameters");
return;
}
input.setName(parm[0]); // set for control card input
input.getNext(); // read first output "control card"
output.setName(parm[2]);
out133(input.getLine());
input.getNext(); // read control card.
ccAll = u.padRight(input.getLine(),40); // this eliminates IndexOutOfRange errors in setCC!
input.setName(parm[1]); // reset for datafile input
setCC(); // sets Control Card (CC) fields
if (ccBrch.equals("30")) division = "DALLAS DIVISION";
if (ccBrch.equals("37")) division = "HOUSTON DIVISION";
if (ccBrch.equals("72")) division = "MONTGOMERY DIVISION";
if (ccBrch.equals("73")) division = "MOBILE DIVISION";
if (ccBrch.equals("74")) division = "MERIDIAN DIVISION";
if (ccBrch.equals("75")) division = "LAKELAND DIVISION";
/** alternate: above could be a HashTable search */
intYear = u.getInt(year4);
intMonth = u.getInt(ccMonth);
sysout.display("year="+intYear+" mm="+intMonth+" Control Card="+ccAll);
if (intMonth < 1 || intMonth > 12)
{
sysout.display(reportName+"--Invalid month, terminating execution");
System.exit(4);
}
if (mm2.equals("12") && ccMonth.equals("01")) intYear++;
sysout.display("year="+intYear+" mm="+intMonth);
setTl2(); // sets tl2 title line
setHdr1(); // sets hdr2 header
i = 0;
while (0 <= (recNum=input.getNext()))
{
inputLine[i] = input.getLine();
//sysout.display(inputLine[i]);
iMax=i;
i++;
line100++;
if (line100 == 100)
{
line100 = 0;
sysout.speedometer("Loading record: "+recNum);
}//sysout.display("Loading record: "+recNum+" iMax="+iMax);
if (recNum == testMax) break; // set test EOF
}
iMax++;
keys[0] = iMax; // set actual table length.
sysout.display(u.getDateTime()+"--"+parm[1]+" Begin sort");
sort.sort(inputLine, keys);
sysout.display(u.getDateTime()+"--"+parm[1]+" End-- sort");
for (i = 0; i < iMax; i++)
{
//sysout.display(inputLine[i]);
if (lineCount > linesPerPage) newPage();
lineCount++;
setDetail(); // method overridden
}
out133("0"+"Record Total = " + u.padLeft(iMax,10) );
output.close();
}
String picNum(String num)
{
int wholeInt;
wholeInt = u.getInt(num);
if (wholeInt == Integer.MIN_VALUE)
return " "+num.substring(0,5);
else
return u.padLeft(wholeInt,10,2);
}
void out133(String shortLine)
{
output.setLine(u.padRight(shortLine,133));
}
void newPage()
{
pageNum++;
out133(tl1);
out133(tl2+u.padLeft(pageNum,5)+tl2b);
out133(hdr1);
out133(" ");
lineCount = 4;
}
// it is expected the all the following methods will be overridden
/** alternate: these should be defined as abstract methods */
void setReportName()
{
}
void setSortKeys()
{
keys = new int[] {0,1,1,0,}; // set default keys...
//keys [0] = sort table length (actual), rest column,length,A/D triplets
}
void setCC()
{
}
void setTl2()
{
}
void setHdr1()
{
}
void setDetail()
{
out133(" ");
}
}
class IbfRP5196 extends IbfReport
{
public static void main(String argv[])
{
IbfRP5196 IbfRP5196 = new IbfRP5196();
IbfRP5196.run(argv);
}
void setReportName()
{
reportName = "IbfRP5196"; // this should be set to class name
// used in displays
}
void setSortKeys()
{
keys = new int[] {0,95,1,0,24,31,0}; // descending on catalog, ascending on name
//keys [0] = sort table length (actual), rest column,length,A/D triplets
}
void setCC() // this method defines location of Control Card fields.
{
ccBrch = ccAll.substring(0,2);
ccHBGN = " ";
ccCatType = ccAll.substring(2,5);
ccCostCode = ccAll.substring(5,6);
ccMonth = ccAll.substring(6,8);
ccPrtAcd = ccAll.substring(8,9);
}
void setTl2()
{
tl2 = "0 "+u.padRight(division,40)
+u.padRight("BERGEN BRUNSWIG CATALOG",24)
+mmName[intMonth-1]+" "
+u.padZero(intYear,2)
+" RP5196 PAGE "
;
}
void setHdr1()
{
if (ccCostCode.equals("Y")) costLabel = "Cost";
hdr1 = " "+u.padRight("Item",8)
+u.padRight("Description",32)
+u.padRight("N D C",14)
+u.padRight("Unit",5)
+u.padLeft(costLabel,10)+" "
+u.padLeft("List",10)+" CL "
+u.padRight("Vendor",11)
+ "Product Code"
;
}
void setDetail()
{
out133(" "+
inputLine[i].substring(17,20)+"-"+
inputLine[i].substring(20,23)+" "+
inputLine[i].substring(23,54)+" "+
inputLine[i].substring(54,68)+" "+
inputLine[i].substring(68,70)+" "+
picNum(inputLine[i].substring(70,77))+" "+
picNum(inputLine[i].substring(77,84))+" "+
inputLine[i].substring(94,95)+" "+
inputLine[i].substring(84,94)+" "+
inputLine[i].substring(95,107)
);
}
}
Books that were helpful:
"Java in 21 Days " by Laura Lemay (SAMS)
"Java in a Nutshell" by David Flanagan (O'Reilly)
"Java SWING " by Robert Eckstein, Marc Loy & Dave Wood (O'Reilly)
"Java 2D Graphics" by Jonathan Knudsen (O'Reilly)
Return to Table of Contents