Menu

#9 Editing cobol copybook

v1.0_(example)
pending
None
1
2017-12-12
2016-08-09
Anonymous
No

Can I insert a new copybook field to a ExternalRecord instance ?

Discussion

  • Bruce Martin

    Bruce Martin - 2016-08-09

    You can add a new field into a ExternalRecord e.g.

     xRec.getRecordFields().add(...);
    

    But -

    • It will not change the position of other fields; you need to do that your self
    • If you are using IOBuilders, you need to create a new IOBuilder (see bellow) from the updated ExternalRecord.

    Constructing an IOBuilder from an ExternalRecord:

      JRecordInterface1.SchemaIOBuilderProvider
                           .newIOBuilder(xRecord.asLayoutDetail());
    
     
  • Anonymous

    Anonymous - 2016-08-09

    Ok I would like to insert the field in the middle so that the offsets get adjusted automatically. Can this be provided as an enhancement ?

     
  • Bruce Martin

    Bruce Martin - 2016-08-09

    Ok, I will accept that, not sure of the time-table, may be a week; I have just started some other changes;
    also it is easier if you login to sourceforge

     

    Last edit: Bruce Martin 2016-08-09
  • Bruce Martin

    Bruce Martin - 2016-08-10
    • assigned_to: Bruce Martin
     
  • Bruce Martin

    Bruce Martin - 2016-08-10

    How do you want it to work

    • Do you want to provide a field and have it inserted in the correct place with fields shuffled down
    • Do you want to provide an Index and name/type/length
     
  • Immanuel Stephen

    Bruce,
    Thanks for providing the update. I will try it
    To answer your questions
    providing both of the below will be useful
    ---- provide a field and have it inserted in the correct place with fields shuffled down
    ---- provide an Index and name/type/length
    Also one more use case that I can think which may be useful is merging of two copybooks
    essentially a application of add field operation

    • Append fields from 2 ExternalRecord

      public ExternalRecord merge(ExternalRecord ext1, ExternalRecord ext2)

    • Append 2 field lists

      public ExternalRecord merge(ExternalField []ef1, ExternalField []ef2)

    Thanks
    Immanuel

     

    Last edit: Bruce Martin 2016-08-17
  • Bruce Martin

    Bruce Martin - 2016-08-17

    I have provided

    • provide a field and have it inserted in the correct place with fields shuffled down. It provides three shuffle options
      • No shuffle
      • Shuffle by field-length
      • Calculate shuffle amount based on the insert option

    With regards to the first option - Append 2 ExternalRecords, there is the newMultiCopybookIOBuilder builder. It allows multiple Cobol copybooks to be loaded into the one ExternalRecord. Usage:

    ioBulder = JRecordInterface1.COBOL
                             .newMultiCopybookIOBuilder("Merged-Copybooks")
                                 .addCopyBook("Copybook1.cbl")
                                      ....
                                 .addCopyBook("Copybook2.cbl")
                                       ....
                                 .addCopyBook("Copybook3.cbl")
                                       ....;
    

    It will create a multi-record copybook
    not sure if anyone has used that option though..


    Not sure I understand the usage case of "merging" 2 lists or how the merge would work. I can understand adding fields / records
    at a certain point


    I will think about provide an Index and name/type/length

     

    Last edit: Bruce Martin 2016-08-17
  • Immanuel Stephen

    "Append 2 field lists" is similar to newMultiCopybookIOBuilder mentioned in your response.
    say ef1 has 10 fields and ef2 has 5 fields, then the method will create a new ExternalRecord having 15 fields with ef2 added to the end of ef1 with their positions adjusted. But for now I think the newMultiCopybookIOBuilder should suffice for my requirements

     
    • Bruce Martin

      Bruce Martin - 2016-08-18

      Can you explain the situations you are facing ???

      I would like to think about
      the best way to handle it before I start coding ???

       
      • Immanuel Stephen

        Bruce,
        My ask is simple. A single record in a file is represented by 2 copybooks ie., 1 to 200 bytes is copybook A and 201 to 900 bytes is copybook B. So when I have this file as input, I would require to combine these 2 copybooks to format the records. Let me know if you want me to explain further

         

        Last edit: Immanuel Stephen 2016-08-18
        • Bruce Martin

          Bruce Martin - 2016-08-18

          It depends,

          if you have a filler at the start of the second copybook:

              01  Cobpybook-1.
                 ...
          
          
          
          :::cobol
              01  Cobpybook-2.
                  03 filler                     Pic x(200).
          

          Then use newMultiCopybookIOBuilder


          If the second copybook does not contain the 200 byte filler but starts with 03 level
          Read both copybooks into a string variables, concentan

          :::cobol
          03 Cobpybook-2.

          :::java

            String copybook1 = loadFile("copybook1.cbl");
            String copybook2 = loadFile("copybook2.cbl");
          
            JRecordInterface1.COBOL
                             .newIOBuilder(
                                  new StringReader(
                                         copybook1 + "\n" + copybook2),
                                  "Combined-Copybook") ....
          

          if the 2nd copybook starts with 01 and does not contain the filler at the start. Let me know
          and I will look at changes. But You could do

          • use newMultiCopybookIOBuilder
          • Then update all the fields in the second record

            ioBulder = JRecordInterface1.COBOL
            .newMultiCopybookIOBuilder("Merged-Copybooks")
            .addCopyBook("Copybook1.cbl")
            ....
            .addCopyBook("Copybook2.cbl")
            ....;
            xRecord = ioBuilder.getExternalRecord();

            ExternalField[] fields = xRecord.getRecord(1).getRecordFields();

            for (ExternalField f : fields) {
            f.setPos(f.getPos() + 200);
            }

           
          • Immanuel Stephen

            my case is "if the 2nd copybook starts with 01 and does not contain the filler at the start."

             
            • Bruce Martin

              Bruce Martin - 2016-08-19

              I will update the newMultiCopybookIOBuilder so that you can set an initial position for the copybook
              Initially I allow setting an integer starting position; but will ultimately support

              • setStartingPosition(int pos)
              • setStartingPosition(String copybookName, String fieldName)
              • setStartingPositionFromCopybookLength(String copybookName)

              What you some times see in cobol is

               01  Copybook
                   03 Common-Header.
                      ....
                   03  Variable-Part             Pic x(...)
              

              Where the variable part is described by multiple copybooks.
              You seem to have a variation on this. The above changes should
              handle this situation.


              Hopefully have something next week.

               
  • Immanuel Stephen

    Regarding newMultiCopybookIOBuilder you had mentioned that "It will create a multi-record copybook". But I want to create a single record copybook created out of these multiple copybooks. is that possible ?

     
    • Bruce Martin

      Bruce Martin - 2016-08-17

      It returns a multiple record layout, but it should not matter if you are accessing by field / field-name.

      you can do

       v1 = line.getFieldValue("field-in-record-1").asString();
       v3 = line.getFieldValue("field-in-record-3").asString();
      

      Internally JRecord tries to follow Cobol rather than Java. It encodes/decodes fields when they are accessed.

       

      Last edit: Bruce Martin 2016-08-17
      • Immanuel Stephen

        ok I will try using newMultiCopybookIOBuilder and see if it meets my requirements. Have outlined my requirement in my previous response

         
  • Bruce Martin

    Bruce Martin - 2016-08-22

    I have added JRecord_Version_0.81.1_update2.7z at https://sourceforge.net/projects/jrecord/files/jrecord/Version_0.81.1/

    This version allows you to set Starting-Position of a Cobol copy e.g.

       ICobolMultiCopybookIOBuilder iob = JRecordInterface1.COBOL
                 .newMultiCopybookIOBuilder("MultiCopybook")
                     .setDialect(ICopybookDialects.FMT_MAINFRAME)
                     .addCopyBook("DTAR020.cbl")
                     .addCopyBook("SecondRecord.cbl"))
                         .setStartingPosition(120);
    

    or using a field:

        ICobolMultiCopybookIOBuilder iob = JRecordInterface1.COBOL
                 .newMultiCopybookIOBuilder("MultiCopybook")
                     .setDialect(ICopybookDialects.FMT_MAINFRAME)
                     .addCopyBook("Master.cbl")
                     .addCopyBook("Child1.cbl")
                         .setStartingPositionToField("Master.cbl", "Record-Detail");
    

    Do you really need to insert fields and have subsequent fields shuffle down ???
    I do not understand why you need this ???

     
    • Immanuel Stephen

      Will this upgrade (JRecord_Version_0.81.1_update2.7z) provide the following which was mentioned in one of your previous answers

      ioBulder = JRecordInterface1.COBOL
               .newMultiCopybookIOBuilder("Merged-Copybooks")
                   .addCopyBook("Copybook1.cbl")
                        ....
                   .addCopyBook("Copybook2.cbl")
                        ....;
      xRecord = ioBuilder.getExternalRecord();
      ExternalField[] fields = xRecord.getRecord(1).getRecordFields();
      for (ExternalField f : fields) {
           f.setPos(f.getPos() + 200);
      }
      

      How does setStartingPosition help to achieve this ?

       

      Last edit: Bruce Martin 2016-08-23
      • Bruce Martin

        Bruce Martin - 2016-08-23

        What you would do is:

        ioBulder = JRecordInterface1.COBOL
                 .newMultiCopybookIOBuilder("Merged-Copybooks")
                     .addCopyBook("Copybook1.cbl")
                          ....
                     .addCopyBook("Copybook2.cbl")
                          .setStartingPosition(200);      // <<<====
                          ....;
        
         
    • Immanuel Stephen

      "Do you really need to insert fields and have subsequent fields shuffle down ???" ..... this is required in a use case where I visually display a copybook and allow the user insert fields.

       
    • Immanuel Stephen

      I tried something like this :

      public static ExternalRecord appendCopyBooks(String copy1, String copy2) {
      
              ICobolMultiCopybookIOBuilder iob = JRecordInterface1.COBOL
                      .newMultiCopybookIOBuilder("multicopy")
                      .setDialect(ICopybookDialects.FMT_MAINFRAME)
                      .addCopyBook(copy1)
                      .addCopyBook(copy2);
      
              ExternalRecord rec=null;
              try {
                  rec = iob.getExternalRecord();
                  ExternalRecord rec0 = rec.getRecord(0);
                  ExternalRecord rec1 = rec.getRecord(1);
      
                  int cnt1 = rec0.getRecordFields().length;
                  ExternalField last = rec0.getRecordFields()[cnt1 - 1];
                  int len1 = last.getPos() - 1 + last.getLen();
      
                  ExternalField[] ef = rec1.getRecordFields();
                  for (ExternalField efs : ef) {
                      efs.setPos(efs.getPos() + len1);
                      rec0.addRecordField(efs);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
              return rec;
      
          }
      
       

      Last edit: Immanuel Stephen 2016-08-22
  • Bruce Martin

    Bruce Martin - 2016-08-23

    That should pretty much work, The one potential problem is if you have a Copybook like

     01 My-Record
            ....
            03 redefined-field         pic x(500).
                   ....
             03 filler redefines redefined-field.
                    05 last-field          pic xx.
    

    in which case the length is determines by redefined-field which is not the last field.
    you would be better to search for the length

    int length = 0;
    ExternalField[] flds = rec0.getRecordFields();
    for (ExternalField f : flds) {
        length = Math.max(length, f.getPos + f.getLength - 1);
    }
    

    with Update2 you can do

    ISchemaIOBuilder iob = externalRecord.asIOBuilder();
    

    to convert the ExternalRecord back into a IOBuilder.

     
  • Bruce Martin

    Bruce Martin - 2017-12-12
    • status: open --> pending
     

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB