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





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.