The RecordEditor can be extended in a number of ways:
All these examples require you update a Table in the Layout Editor
After starting the LayoutEdit, the menu screen is displayed:
Click on the second option Edit Tables and the Table edit screen is displayed:
You can select a table to be updated by clicking on the Table in the list on the left.
A `Type` acts as an interface between the fields storage in the data record and how it is displayed on the screen. It contains methods to extract a field from the data record (getField) and store it back in the data record
83: /** 84: * Extracts a field out of a data record 85: * 86: * @param data record which is to have the field extracted 87: * @param position position in the record 88: * @param currField Field Details 89: * 90: * @return the request field (formated) 91: */ 92: public abstract Object getField(final byte[] data, 93: final int position, 94: final FieldDetail currField); 95: 96: 97: /** 98: * Sets a field to a new value in the supplied data record 99: * 100: * @param data record which is to be update 101: * @param position position in the record 102: * @param field Field Details 103: * @param val new value 104: * 105: * @return updated record 106: * @throws RecordException any error that occurs during the save 107: */ 108: public abstract byte[] setField(final byte[] data, 109: final int position, 110: final FieldDetail field, 111: Object val) 112: throws RecordException; 113: 114: /** 115: * Format a value for storing in the record, it 116: * has 3 uses 117: * <ol compact> 118: * <li>Format the string for storing in a record. 119: * <li>Format for storing as a String in a comma / tab delimited files. 120: * <li>Validate a value 121: * </ol> 122: * 123: * @param field field definition 124: * @param val value to be formated 125: * 126: * @return value value as it is store in the record 127: * @throws RecordException any conversion errors 128: */ 129: public abstract String formatValueForRecord(FieldDetail field, String val) 130: throws RecordException; 131: 132: 133: /** 134: * wether it is a binary field 135: * 136: * @return wether it is binary field 137: */ 138: public abstract boolean isBinary(); 139: 140: /** 141: * Get the type of field 142: * @return type of field 143: */ 144: public abstract int getFieldType();
A `CellFormat` provides TableCellRenderer's and TableCellEditor's to the RecordEditor. A CellFormat added to the system as part of a Type or as a separately as Formats.
1: /** 2: * Get Table Cell Render 3: * <b>Note:</b> you should always return a new Editor rather than a 4: * the same editor each time 5: * 6: * @param fld field being displayed 7: * 8: * @return Table Cell Render to be used to display the field 9: */ 10: public abstract TableCellRenderer getTableCellRenderer(FieldDetail fld); 11: 12: /** 13: * Get Table Cell Editor 14: * 15: * @param fld field being displayed 16: * 17: * @return Table Cell Editor to be used to edit the field 18: */ 19: public abstract TableCellEditor getTableCellEditor(FieldDetail fld); 20: 21: 22: /** 23: * Get the normal width of a field 24: * 25: * @return field width 26: */ 27: public abstract int getFieldWidth(); 28: 29: 30: /** 31: * Get the normal height of a field 32: * 33: * @return field height 34: */ 35: public abstract int getFieldHeight(); 36:
The TypeManager is used store the Type's and CellFormat's. You can use the static method getSystemTypeManager to get the system TypeManager.
1: TypeManager typeManager = TypeManager.getSystemTypeManager(); 2:
Initially the TypeManager allows user types and user Cell Formats to have Id's of 1000 -> 1050. You can increase the number of User Types/Cell Formats via the setSystemTypeManager method.
1: TypeManager.setSystemTypeManager(new TypeManager(true, 200, 100));
You can define a type to a TypeManager by
1: typeManager.registerType(1000, checkBox); 2:
Alternatively you can also assign a CellFormat to a Type as well by
1: typeManager.registerType(1000, checkBox, checkBox); 2:
Following is the java code to implement a US Style MM/DD/YY date.
1:package net.sf.RecordEditor.examples; 2: 3:import net.sf.RecordEditor.record.types.TypeChar; 4:import net.sf.RecordEditor.record.types.TypeDateWrapper; 5: 6:/** 7: * provide a US style date (mm/dd/yy) 8: * 9: * @author Bruce Martin 10: * 11: */ 12:public class USdate8 extends TypeDateWrapper { 13: 14: /** 15: * provide a US style date (mm/dd/yy) 16: */ 17: public USdate8() { 18: super(new TypeChar(true), "MM/dd/yy"); 19: } 20:}
Following is the code to provide a special Date Editor
1:package net.sf.RecordEditor.examples; 2: 3:import net.sf.RecordEditor.record.format.DateFormat; 4: 5:/** 6: * US date cell format (MM/DD/YY) 7: * 8: * @author Bruce Martin 9: * 10: */ 11:public class USdateFormat8 extends DateFormat { 12: 13: /** 14: * US date cell format (MM/DD/YY) 15: */ 16: public USdateFormat8() { 17: super(true, "MM/dd/yy"); 18: } 19:} 20:
You now need to bundle this Type as a Java Jar file.
Start the Edit RecordEditor Startup Properties and go to the User Types tag and entor the new Type as in the diagram below:
The next step is to define where your type is found, so go to the User Jars tag an enter your new jar as below
You can now use the new Type in both the RecordEditor and the LayoutEditor.
The first step is the type (examples are TypeCheckBoxYN.Java and TypeComboExample.Java)
3: public class TypeCheckBoxYN implements Type, CellFormat { 4: .... Type Code goes here ..... 5: 6: }
There are 2 ways to define a Type to the RecordEditor
Define the Type in the LayoutEditor: Next step is to define the Type to the RecordEditor. This is done in table 1, the Type table (go into LayoutEdit, take option 2 Edit Tables. See "Editting a Table in the LayoutEditor" for details). In the picture below, a new user type 1001 ~ Checkbox Y/N has been defined
Using the new Type: You should now be able to use the Type Checkbox Y/N in the field definition panel (Record Definition screen) as below.
Starting the RecordEditor with the new Type: The final step is to start the RecordEditor with the new Type. Please note that at line 9, the new type checkBox is defined as type number 1001, which is exactly the same as what it was defined in the LayoutEdit (see "Define the Type in the LayoutEditor").
1: 2: TypeManager typeManager = TypeManager.getSystemTypeManager(); 3: CopyBookDbReader copybook = new CopyBookDbReader(); 4: TypeCheckBoxYN checkBox = new TypeCheckBoxYN(); 5: TypeComboExample typeCombo = new TypeComboExample(); 6: 7: try { 8: // register the new types with the type manager 9: typeManager.registerType(1001, checkBox, checkBox); 10: typeManager.registerType(1002, typeCombo, typeCombo); 11: 12: new EditRec("", 1, copybook); // starting the record editor 13: 14: } catch (Exception e) { 15: e.printStackTrace(); 16: } 17:
This java code came from XmplType1.Java
Finally after starting the editor using the java code from "Starting the RecordEditor with the new Type", it should like (with Combobox's and Checkbox's).
or the record view
This section goes through adding and then using a "Adding a Format to the RecordEditor" in the RecordEdit.
The following code was extracted from FormatComboExample.java
33:public class XmplEditSpecificFile1 { 34: 35: private static String filename = Constants.EXAMPLE_FILE_DIRECTORY 36: + "Ams_LocDownload_20041228.txt"; 37: private static String layoutName = "ams Store"; 38: private static int initialRow = 0; 39: 40: /** 41: * This is an example of editing a specific file 42: * (without displaying the RecordEditor File selection screen) 43: * 44: * @param args program args 45: */ 46: public static void main(String[] args) { 47: CopyBookDbReader copyBookInterface = new CopyBookDbReader(); 48: LayoutDetail fileDescription = copyBookInterface.getLayout(layoutName); 49: 50: if (fileDescription == null) { 51: System.out.println( 52: "Record Layout \"" + layoutName + "\" not loaded: " 53: + copyBookInterface.getMessage()); 54: } else { 55: try { 56: FileView file = new FileView(filename, 57: fileDescription, 58: false); 59: 60: new ReMainFrame("Specific file", ""); 61: LineList list = new LineList(fileDescription, file, file); 62: list.setCurrRow(initialRow, -1, -1); 63: list.addInternalFrameListener(new InternalFrameAdapter() { 64: public void internalFrameClosed(final InternalFrameEvent e) { 65: Common.closeConnection(); 66: 67: System.exit(0); 68: } 69: }); 70: 71: } catch (Exception e) { 72: e.printStackTrace(); 73: } 74: } 75: } 76:}
Next step is to define the Format in the Format Table (go into LayoutEdit, take option 2 Edit Tables, finally click on Table 5 ~ Formats. See "Editting a Table in the LayoutEditor" for details) and enter the new format (in this case 1001 ~ ComboBox).
You should now be able to use the format Combobox in Record field definitions.
The final step is to start the RecordEditor with the new Format. Please note
1: String[][] AMS_PO_ITEMS = { 2: {"H1", "Header Record"}, 3: {"D1", "Product Record"}, 4: {"S1", "Allocation Record"}, 5: }; 6: 7: TypeManager typeManager = TypeManager.getSystemTypeManager(); 8: CopyBookDbReader copybook = new CopyBookDbReader(); 9: FormatComboExample comboFormat = new FormatComboExample(); 10: 11: // Register Combo Details 12: comboFormat.register("AMS PO Type", AMS_PO_ITEMS); 13: 14: try { 15: // register the new types with the type manager 16: typeManager.registerFormat(1001, comboFormat); 17: 18: new EditRec("", 1, copybook); // starting the record editor 19: 20: } catch (Exception e) { 21:
Finally after starting the editor using the java code from "Starting the RecordEditor with the new Type"
When there are more than one Record in a Layout, there has to be a way to decide which record should be used. One way of doing this is via a RecordDecider:
1:public interface RecordDecider { 2: 3: /** 4: * Get the prefered Layout 5: * 6: * @param line to decide what the prefered layout is 7: * 8: * @return the prefered layout 9: */ 10: public abstract int getPreferedIndex(Line line); 11:}
Once you have created a RecordDecider, you must register it and start the Editor as follows (example taken from XmplDecider.java):
1: CopyBookDbReader copybook = new CopyBookDbReader(); 2: 3: copybook.registerDecider("ProductExmpl", new XmplDecider()); 4: 5: new EditRec("", 1, copybook);
To add a new file structure, you must:
To create a new file structure, you must create a new LineReader that extends the class AbsLineReader and implements the abstract methods open, read and close.
1: /** 2: * Open file for input 3: * @param inputStream input stream to be read 4: * @param pLayout record layout 5: * @throws IOException any IOerror 6: */ 7: public abstract void open(InputStream inputStream, LayoutDetail pLayout) 8: throws IOException; 9: 10: 11: 12: /** 13: * Read one line from the input file 14: * @return line read in 15: * @throws IOException io error 16: */ 17: public abstract Line read() throws IOException; 18: 19: 20: /** 21: * Closes the file 22: * @throws IOException io error 23: */ 24: public abstract void close() throws IOException; 25:
You must also create a new LineWriter that extends the class AbsLineWriter and implements the abstract methods open, write and close.
1: /** 2: * Open file for input 3: * @param outputStream input stream to write 4: * @throws IOException any IOerror 5: */ 6: public abstract void open(OutputStream outputStream) 7: throws IOException; 8: 9: 10: /** 11: * Read one line from the input file 12: * @param line line to write to the output file 13: * @throws IOException any IOerror 14: */ 15: public abstract void write(Line line) throws IOException; 16: 17: 18: /** 19: * Closes the file 20: * @throws IOException any IOerror 21: */ 22: public abstract void close() throws IOException; 23:
The next step is to add the new file structure to the File Structure table. See "Editting a Table in the LayoutEditor" for details.
You should now be able to use the new file structure in the Record-Definition Extra panel:
Following is a sample LineIOProvider that will create the new LineReader's / LineReader's if the appropriate file structure is supplied.
1:public class XmplFileStructure2 extends LineIOProvider { 2: 3: private static final int MY_FILE_STRUCTURE = 1002; 4: 5: /** 6: * get LineReader for the supplied 7: */ 8: public AbsLineReader getLineReader(int fileStructure) { 9: 10: if (fileStructure == MY_FILE_STRUCTURE) { 11: return new DelimLineReader(super.getLineProvider()); 12: } 13: return super.getLineReader(fileStructure); 14: } 15: 16: 17: /** 18: * get LineWriter for the supplied structure 19: */ 20: public AbsLineWriter getLineWriter(int fileStructure) { 21: 22: if (fileStructure == MY_FILE_STRUCTURE) { 23: return new DelimLineWriter(); 24: } 25: return super.getLineWriter(fileStructure); 26: } 27:
The following code starts the RecordEditor with the LineIOProvider from "Creating a LineIOProvider". This will introduce the new File Structures.
1: CopyBookDbReader copybook = new CopyBookDbReader(); 2: 3: new EditRec("", 1, new XmplFileStructure2(), copybook); 4:
See XmplFileStructure1.java and XmplFileStructure2.java for examples.
If you already have record layouts (Copybooks in Cobol), you should look at the writing your own CopybookLoader. This will allow you to import the record layouts into the RecordEditor as well as use the layouts in the Cobol Editor program
The CopybookLoader Interface describes a class to load a external Record Layout into the RecordEditor's internal DB.
20:/** 21: * description of a class to load a copybook 22: * 23: * @author Bruce Martin 24: * 25: */ 26:public interface CopybookLoader { 27: 28: public static final int FMT_INTEL = 0; 29: public static final int FMT_MAINFRAME = 1; 30: public static final int FMT_BIG_ENDIAN = 1; 31: public static final int FMT_FUJITSU = 2; 32: 33: public static final int SPLIT_NONE = 0; 34: public static final int SPLIT_REDEFINE = 1; 35: public static final int SPLIT_01_LEVEL = 2; 36: 37: /** 38: * Insert a XML Dom Copybook into the Copybook DB 39: * 40: * @param copyBookFile Copy Book file Name 41: * @param splitCopybookOption wether to split a copy book on a redefine 42: * @param dbIdx Database Index 43: * @param font font name to use 44: * @param binFormat binary format to use 45: * @param systemId System Identifier 46: * @param log log where any messages should be written 47: * 48: * @return record to be inserted 49: * 50: * @throws IOException error to be handeled by calling program 51: * @throws SAXException error to be handeled by calling program 52: * @throws ParserConfigurationException error to be handeled by calling program 53: * @throws RecordException general recordeditor exception 54: */ 55: public abstract ExtendedRecord loadCopyBook(final String copyBookFile, 56: final int splitCopybookOption, final int dbIdx, final String font, 57: final int binFormat, 58: final int systemId, 59: final AbsSSLogger log) throws IOException, 60: SAXException, ParserConfigurationException, RecordException; 61:}
Following is a simple class to load a Record Layout (copybook) from a Tab delimited file.
1:/* 2: * @Author Bruce Martin 3: * Created on 7/02/2007 4: * 5: * Purpose: 6: * Demonstrate writing a CopybookLoader (ie a class to read 7: * a record layout or Copybook from> an external file). 8: */ 9:package net.sf.RecordEditor.examples.CsvLayout; 10: 11:import java.io.BufferedReader; 12:import java.io.FileReader; 13:import java.io.IOException; 14:import java.util.HashMap; 15:import java.util.StringTokenizer; 16: 17:import javax.xml.parsers.ParserConfigurationException; 18: 19:import org.xml.sax.SAXException; 20: 21:import net.sf.RecordEditor.fileLayout.CopybookLoader; 22:import net.sf.RecordEditor.layoutEd.Record.ExtendedRecord; 23:import net.sf.RecordEditor.layoutEd.Record.RecordFieldsRec; 24:import net.sf.RecordEditor.record.Common.RecordException; 25:import net.sf.RecordEditor.record.types.Type; 26:import net.sf.RecordEditor.utils.Common; 27:import net.sf.RecordEditor.utils.log.AbsSSLogger; 28: 29:/** 30: * This class reads a Record Layout (Copybook) stored in a tab delimited file. 31: * Fields in the file are<ol> 32: * <li>Starting Position 33: * <li>Length 34: * <li>Number of places after the decimal point 35: * <li>Field Name 36: * <li>Field Type (String [or char], num, mainframe_zoned, fuji_zoned) 37: * </ol> 38: * 39: * @author Bruce Martin 40: * 41: */ 42:public class CsvLayoutReader implements CopybookLoader { 43: 44: private static HashMap typeConv = new HashMap(); 45: 46: static { 47: typeConv.put("string", new Integer(Type.ftChar)); 48: typeConv.put("char", new Integer(Type.ftChar)); 49: typeConv.put("num", new Integer(Type.ftNumRightJustified)); 50: typeConv.put("mainframe_zoned", new Integer(Type.ftZonedNumeric)); 51: typeConv.put("fuji_zoned", new Integer(Type.ftFjZonedNumeric)); 52: } 53: 54: /** 55: * @see net.sf.RecordEditor.fileLayout.CopybookLoader#loadCopyBook(java.lang.String, int, int, java.lang.String, int, int, net.sf.RecordEditor.utils.log.AbsSSLogger) 56: */ 57: public ExtendedRecord loadCopyBook(String copyBookFile, 58: int splitCopybookOption, int dbIdx, String font, int binFormat, 59: int systemId, AbsSSLogger log) throws IOException, SAXException, 60: ParserConfigurationException, RecordException { 61: 62: int rt = Common.rtRecordLayout; 63: if (binFormat == FMT_MAINFRAME) { 64: rt = Common.rtBinaryRecord; 65: } 66: 67: ExtendedRecord rec = ExtendedRecord.getNullRecord(copyBookFile, 68: rt, 69: font); 70: 71: insertFields(rec, copyBookFile); 72: 73: return rec; 74: } 75: 76: /** 77: * Add fields to the copybook 78: * @param rec copybook 79: * @param copyBookFile copybook file 80: */ 81: private void insertFields(ExtendedRecord rec, String copyBookFile) { 82: String s, name, typeStr; 83: StringTokenizer t; 84: RecordFieldsRec field; 85: int pos, len, decimal, type; 86: int i = 1; 87: int inputLine = 1; 88: try { 89: BufferedReader r = new BufferedReader(new FileReader(copyBookFile)); 90: while ((s = r.readLine()) != null) { 91: if (!s.trim().startsWith("#")) { 92: t = new StringTokenizer(s, "\t"); 93: 94: try { 95: pos = Integer.parseInt(t.nextToken()); 96: len = Integer.parseInt(t.nextToken()); 97: decimal = Integer.parseInt(t.nextToken()); 98: name = t.nextToken(); 99: typeStr = t.nextToken(); 100: 101: type = Type.ftChar; 102: if (typeStr != null && ! "".equals(typeStr)) { 103: typeStr = typeStr.toLowerCase(); 104: if (typeConv.containsKey(typeStr)) { 105: type = ((Integer) typeConv.get(typeStr)).intValue(); 106: } 107: } 108: 109: field = new RecordFieldsRec(pos, len, name, "", type, 110: decimal, 0, "", "", "", i); 111: rec.addRecordField(field); 112: i += 1; 113: } catch (Exception e) { 114: System.out.println("Error Adding line " + inputLine 115: + ": " + e.getMessage()); 116: e.printStackTrace(); 117: } 118: inputLine += 1; 119: } 120: } 121: } catch (Exception e) { 122: System.out.println("Error Adding line " + inputLine 123: + " from file " + copyBookFile 124: + ": " + e.getMessage()); 125: e.printStackTrace(); 126: } 127: } 128:}
There are 2 steps to defining your Copybook loader to the RecordEditor
You should now ne able to import your layouts in to the RecordEditor + Edit your files using your Layouts in the Cobol Editor