z/OS Connect

z/OS Connect

z/OS Connect

Truly RESTful APIs to and from your IBM Z mainframe

 View Only

Generating better COBOL Language Structures with z/OS Connect OpenApi 3 for API Requester and API First

By Ian Hodges posted Tue July 25, 2023 06:56 AM

  

In this blog we explore how changing OpenApi 3 document schemas and Gradle Plugin properties affect how the COBOL language structures are produced by the Gradle Plugins.  The tooling does not give us a free hand as there are language constraints to consider, but we can make our language structures more consumable and easier to program with.

We will take a simple OpenApi 3 API document and generate an API Requester, what we talk about here holds equally true for API Providers API First as both are generated starting with the OpenApi3 document.  We will make changes to the API description and the options.yaml properties to see how these affect the language structures we produce.

The OpenApi 3 API document is first and foremost a contract between the API client and the API Service so some things cannot be changed, but if you have control of the API and the client then various aspects of the API can be tweaked, or if the API is loosely defined it can be tightened based on API outputs.

This is our API document that we start with, it’s a simple API with an Employee schema.

---
openapi: 3.0.3
info:
    title: Attributes and Options
    version: 1.0.0
paths:
    /employee/{id}:
        get:
            operationId: employeeGet
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                      type: string
            responses:
                "200":
                    description: Successful operation
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Employee'
components:
    schemas:
        Employee:
            type: object
            properties:
                employeeNumber:
                    type: string
                title:
                    type: string
                firstName:
                    type: string
                middleInitial:
                    type: string
                lastName:
                    type: string
                address:
                    type: array
                    items:
                        type: string
                gender:
                    type: string
                dateOfBirth:
                    type: string
                department:
                    type: object
                    properties:
                        name:
                            type: string
                        managerNumber:
                            type: string
                probationComplete:
                    type: boolean
                phoneNumber:
                    type: string
                hireDate:
                    type: string
                job:
                    type: string
                grade:
                    type: integer
                salary:
                    type: number
                bonus:
                    type: number
                commission:
                    type
: number

We run our Gradle build to generate the API. See the IBM z/OS Connect documentation for details.

We have the following response structure produced.  I have formatted here for consumption in this blog, but the content is the same as produced.

          01 BAQBASE-API00P01.

 

            03 responseCode200-existence     PIC S9(9) COMP-5 SYNC.

            03 responseCode200-dataarea      PIC X(16).

 

 

         01 API00P01-responseCode200.

           03 responseCode200.

             06 employeeNumber-existence     PIC S9(9) COMP-5 SYNC.

             06 employeeNumber.

               09 employeeNumber2-length     PIC S9999 COMP-5 SYNC.

               09 employeeNumber2            PIC X(255).

             06 Xtitle-existence             PIC S9(9) COMP-5 SYNC.

             06 Xtitle.

               09 Xtitle2-length             PIC S9999 COMP-5 SYNC.

               09 Xtitle2                    PIC X(255).

             06 firstName-existence          PIC S9(9) COMP-5 SYNC.

             06 firstName.

               09 firstName2-length          PIC S9999 COMP-5 SYNC.

               09 firstName2                 PIC X(255).

             06 middleInitial-existence      PIC S9(9) COMP-5 SYNC.

             06 middleInitial.

               09 middleInitial2-length      PIC S9999 COMP-5 SYNC.

               09 middleInitial2             PIC X(255).

             06 lastName-existence           PIC S9(9) COMP-5 SYNC.

             06 lastName.

               09 lastName2-length           PIC S9999 COMP-5 SYNC.

               09 lastName2                  PIC X(255).

             06 Xaddress-num                 PIC S9(9) COMP-5 SYNC.

             06 Xaddress-dataarea            PIC X(16).

             06 gender-existence             PIC S9(9) COMP-5 SYNC.

             06 gender.

               09 gender2-length             PIC S9999 COMP-5 SYNC.

               09 gender2                    PIC X(255).

             06 dateOfBirth-existence        PIC S9(9) COMP-5 SYNC.

             06 dateOfBirth.

               09 dateOfBirth2-length        PIC S9999 COMP-5 SYNC.

               09 dateOfBirth2               PIC X(255).

             06 department2-existence        PIC S9(9) COMP-5 SYNC.

             06 department.

               09 name-existence             PIC S9(9) COMP-5 SYNC.

               09 name.

                 12 name2-length             PIC S9999 COMP-5 SYNC.

                 12 name2                    PIC X(255).

               09 managerNumber-existence    PIC S9(9) COMP-5 SYNC.

               09 managerNumber.

                 12 managerNumber2-length    PIC S9999 COMP-5 SYNC.

                 12 managerNumber2           PIC X(255).

             06 probationComplet-existence   PIC S9(9) COMP-5 SYNC.

             06 probationComplete            PIC X DISPLAY.

             06 phoneNumber-existence        PIC S9(9) COMP-5 SYNC.

             06 phoneNumber.

               09 phoneNumber2-length        PIC S9999 COMP-5 SYNC.

               09 phoneNumber2               PIC X(255).

             06 hireDate-existence           PIC S9(9) COMP-5 SYNC.

             06 hireDate.

               09 hireDate2-length           PIC S9999 COMP-5 SYNC.

               09 hireDate2                  PIC X(255).

             06 job-existence                PIC S9(9) COMP-5 SYNC.

             06 job.

               09 job2-length                PIC S9999 COMP-5 SYNC.

               09 job2                       PIC X(255).

             06 grade-existence              PIC S9(9) COMP-5 SYNC.

             06 grade                        PIC S9(18) COMP-5 SYNC.

             06 salary-existence             PIC S9(9) COMP-5 SYNC.

             06 salary                       COMP-2 SYNC.

             06 bonus-existence              PIC S9(9) COMP-5 SYNC.

             06 bonus                        COMP-2 SYNC.

             06 commission-existence         PIC S9(9) COMP-5 SYNC.

             06 commission                   COMP-2 SYNC.

 

         01 API00P01-Xaddress.

           03 Xaddress-length                PIC S9999 COMP-5 SYNC.

           03 Xaddress                       PIC X(255).

           03 filler                         PIC X(1).

So what are the problems? Well, where do I begin! The tooling has done its best, but we can help it to make better decisions. Let’s look at each of the problems:

Problem 1

For a start the two copybooks produced are called API00Q01 and API00P01, these names break down like this, first 3 characters is the copybook prefix then 2 characters of increasing sequence one per operation, then Q for reQuest and P for resPonse and two other digits to pad to 8 characters.

Now if we have a more than a few API’s being developed by the same business area the copybooks may need to exist in the same library and they will clash on name, so what we can do is to provide the copybook prefix.  If we specify the following in options.yaml we can name our copybooks EMP00P01 and EMP00Q01 for the employeeGet operation.

requesterPrefix=EMP.  (Or this is API First providerPrefix=EMP)

No more clashes.

Problem 2

What are all of these -existence flags? 

OpenApi 3 has the concept of required properties within an object, and if required the property must exist in any conforming JSON message.  In the COBOL language structure the -existence flag is used to denote the presence or not of an optional field. Initially all of our fields were optional so lots of -existence flags, but a lot of these optional fields as declared by the OpenApi document are not optional for an Employee object. For example, firstName and lastName must exist.   If we correctly set the required attribute of the Employee object, then not only is our COBOL structure smaller it will be easier to use in the COBOL program. 

openapi.yaml components section.

components:
    schemas:
        Employee:
            type: object
            required:
                - employeeNumber
                - title
                - firstName
                - lastName
                - address
                - gender
                - dateOfBirth
                - department
                - probationComplete
                - hireDate
                - job
                - grade
                - salary
            properties:
                employeeNumber:
                    type: string
                title:
                    type: string
                firstName:
                    type: string
                middleInitial:
                    type: string
                lastName:
                    type: string
                address:
                    type: array
                    items:
                        type: string
                gender:
                    type: string
                dateOfBirth:
                    type: string
                department:
                    type: object
                    required:
                        - name
                        - managerNumber
                    properties:
                        name:
                            type: string
                        managerNumber:
                            type: string
                probationComplete:
                    type: boolean
                phoneNumber:
                    type: string
                hireDate:
                    type: string
                job:
                    type: string
                grade:
                    type: integer
                salary:
                    type: number
                bonus:
                    type: number
                commission:
                    type
: number

                                                                          

         01 EMP00P01-responseCode200.

           03 responseCode200.

             06 employeeNumber-length        PIC S9999 COMP-5 SYNC.

             06 employeeNumber               PIC X(255).

             06 Xtitle-length                PIC S9999 COMP-5 SYNC.

             06 Xtitle                       PIC X(255).

             06 firstName-length             PIC S9999 COMP-5 SYNC.

             06 firstName                    PIC X(255).

             06 middleInitial-existence      PIC S9(9) COMP-5 SYNC.

             06 middleInitial.

               09 middleInitial2-length      PIC S9999 COMP-5 SYNC.

               09 middleInitial2             PIC X(255).

             06 lastName-length              PIC S9999 COMP-5 SYNC.

             06 lastName                     PIC X(255).

             06 Xaddress-num                 PIC S9(9) COMP-5 SYNC.

             06 Xaddress-dataarea            PIC X(16).

             06 gender-length                PIC S9999 COMP-5 SYNC.

             06 gender                       PIC X(255).

             06 dateOfBirth-length           PIC S9999 COMP-5 SYNC.

             06 dateOfBirth                  PIC X(255).

             06 department.

               09 name-length                PIC S9999 COMP-5 SYNC.

               09 name                       PIC X(255).

               09 managerNumber-length       PIC S9999 COMP-5 SYNC.

               09 managerNumber              PIC X(255).

             06 probationComplete            PIC X DISPLAY.

             06 phoneNumber-existence        PIC S9(9) COMP-5 SYNC.

             06 phoneNumber.

               09 phoneNumber2-length        PIC S9999 COMP-5 SYNC.

               09 phoneNumber2               PIC X(255).

             06 hireDate-length              PIC S9999 COMP-5 SYNC.

             06 hireDate                     PIC X(255).

             06 job-length                   PIC S9999 COMP-5 SYNC.

             06 job                          PIC X(255).

             06 grade                        PIC S9(18) COMP-5 SYNC.

             06 salary                       COMP-2 SYNC.

             06 bonus-existence              PIC S9(9) COMP-5 SYNC.

             06 bonus                        COMP-2 SYNC.

             06 commission-existence         PIC S9(9) COMP-5 SYNC.

             06 commission                   COMP-2 SYNC.

 

         01 EMP00P01-Xaddress.

           03 Xaddress-length                PIC S9999 COMP-5 SYNC.

           03 Xaddress                       PIC X(255).

           03 filler                         PIC X(1).

Our COBOL language structure is now more manageable.

It should be noted however, that the OpenApi document is a contract between client and service it may not always be possible to make changes that will affect the other party.  For example the service may have determined that people may have just one name and firstName is optional and may not always be sent.  If we set it as required and it is not sent in the JSON message, then a runtime error will occur.  See my next forthcoming blog Analysing z/OS Connect runtime transformation errors for details on how to debug runtime Transformation errors.  The takeaway is talk to the service provider and agree to tighten loosely defined API’s together.    

Problem 3

Why is by address field prefixed by an X? 

This is down to the fact that COBOL has over 400 reserved words and should an object property name clash with a COBOL reserved word then that name must be changed to not create a compilation error when the copybook is used.  The tooling will prefix any such names  with an X to create a non-clashing name.  The only way to remove the X is to change the name of the field in the OpenApi document to something that is not part of the COBOL language.   Any change would need to be reflected in the client and service.   Now we know why address is Xaddress we will leave it as it is.

Problem 4

Why are all our strings 255 characters long, when JSON can have strings of any length?

In the dynamic world of JSON, and of JavaScript or Java, a string can be held in memory and it can be dynamically any length, but in COBOL we must predefine the length and type, fixed, or variable, of the string at compilation time.   So COBOL strings are less flexible, but COBOL makes up for this by processing strings very quickly.

So what can we do about it?  We could define a maxLength attribute for the property type for each string to determine how big we will accept it being.   This is the most accurate way to set the string field lengths, but it can be a bit tedious to do this for every field in the API.   A compromise approach is to set the defaultCharacterMaxLength option in options.yaml with a value of 50.  E.g.  defaultCharacterMaxLength=50.   Now our stings will be PIC X(50), but we can examine our API and set specific fields that we know will be smaller or larger to a specific maximum by setting the maxLength property for just those fields.

It's worth noting that any property setting in the options.yaml file is a global setting and will apply to all operations in the complete API described the OpenApi document.

openapi.yaml components section.

components:
    schemas:
        Employee:
            type: object
            required:
                - employeeNumber
                - title
                - firstName
                - lastName
                - address
                - gender
                - dateOfBirth
                - department
                - probationComplete
                - hireDate
                - job
                - grade
                - salary
            properties:
                employeeNumber:
                    type: string
                    maxLength: 10
                title:
                    type: string
                    maxLength: 20
                firstName:
                    type: string
                middleInitial:
                    type: string
                    maxLength: 1
                lastName:
                    type: string
                address:
                    type: array
                    items:
                        type: string
                        maxLength: 200
                gender:
                    type: string
                    maxLength: 10
                dateOfBirth:
                    type: string
                department:
                    type: object
                    required:
                        - name
                        - managerNumber
                    properties:
                        name:
                            type: string
                        managerNumber:
                            type: string
                            maxLength: 4
                probationComplete:
                    type: boolean
                phoneNumber:
                    type: string
                hireDate:
                    type: string
                job:
                    type: string
                grade:
                    type: integer
                salary:
                    type: number
                bonus:
                    type: number
                commission:
                    type
: number

options.yaml

defaultCharacterMaxLength=50

          01 EMP00P01-responseCode200.

           03 responseCode200.

             06 employeeNumber-length         PIC S9999 COMP-5 SYNC.

             06 employeeNumber                PIC X(10).

             06 Xtitle-length                 PIC S9999 COMP-5 SYNC.

             06 Xtitle                        PIC X(20).

             06 firstName-length              PIC S9999 COMP-5 SYNC.

             06 firstName                     PIC X(50).

             06 middleInitial-existence       PIC S9(9) COMP-5 SYNC.

             06 middleInitial.

               09 middleInitial2-length       PIC S9999 COMP-5 SYNC.

               09 middleInitial2              PIC X(1).

             06 lastName-length               PIC S9999 COMP-5 SYNC.

             06 lastName                      PIC X(50).

             06 Xaddress-num                  PIC S9(9) COMP-5 SYNC.

             06 Xaddress-dataarea             PIC X(16).

             06 gender-length                 PIC S9999 COMP-5 SYNC.

             06 gender                        PIC X(10).

             06 dateOfBirth-length            PIC S9999 COMP-5 SYNC.

             06 dateOfBirth                   PIC X(50).

             06 department.

               09 name-length                 PIC S9999 COMP-5 SYNC.

               09 name                        PIC X(50).

               09 managerNumber-length        PIC S9999 COMP-5 SYNC.

               09 managerNumber               PIC X(4).

             06 probationComplete             PIC X DISPLAY.

             06 phoneNumber-existence         PIC S9(9) COMP-5 SYNC.

             06 phoneNumber.

               09 phoneNumber2-length         PIC S9999 COMP-5 SYNC.

               09 phoneNumber2                PIC X(50).

             06 hireDate-length               PIC S9999 COMP-5 SYNC.

             06 hireDate                      PIC X(50).

             06 job-length                    PIC S9999 COMP-5 SYNC.

             06 job                           PIC X(50).

             06 grade                         PIC S9(18) COMP-5 SYNC.

             06 salary                        COMP-2 SYNC.

             06 bonus-existence               PIC S9(9) COMP-5 SYNC.

             06 bonus                         COMP-2 SYNC.

             06 commission-existence          PIC S9(9) COMP-5 SYNC.

             06 commission                    COMP-2 SYNC.

 

         01 EMP00P01-Xaddress.

           03 Xaddress-length                 PIC S9999 COMP-5 SYNC.

           03 Xaddress                        PIC X(200).

    

We now have a COBOL language structure that is using memory more efficiently for its string storage.  However, if the server sends a string that is bigger than the maximum we have defined, this will result in a runtime transformation error so take some care in defining what are realistic maximum sizes.

Problem 5

Not all the strings are variable by nature, some are fixed, so how can we control how they are defined in the COBOL copybook?

Globally we can state how we require strings to be managed by using the options.yaml property setting characterVarying. This can be set at YES, NO, or NULL with YES being the default such that all strings are variable strings so that each string will have a pair of fields e.g. firstName-length and firstName.

If we specify characterVarying=no then all fields will be a fixed length as defined by maxLength or defaultCharacterMaxLength.  Depending on your API this may be useful, but often, as in our case here, only some of our strings are fixed in length.

If we specify characterVarying=null then all fields will be fixed length but the strings within them will be terminated by a null x00 character to denote then end of the string. If we specify this global setting, then all string fields will be increased by 1 to allow space for the null if required for a maximum size string.

The final option and the one that is finer grained is to set minLength and maxLength the same value on a per string property bases where we know the string is fixed, for example, employeeNumber and allow the others to use the default varying style.

openapi.yaml components section.

components:
    schemas:
        Employee:
            type: object
            required:
                - employeeNumber
                - title
                - firstName
                - lastName
                - address
                - gender
                - dateOfBirth
                - department
                - probationComplete
                - hireDate
                - job
                - grade
                - salary
            properties:
                employeeNumber:
                    type: string
                    minLength: 10
                    maxLength: 10
                title:
                    type: string
                    maxLength: 20
                firstName:
                    type: string
                middleInitial:
                    type: string
                    minLength: 1
                    maxLength: 1
                lastName:
                    type: string
                address:
                    type: array
                    items:
                        type: string
                        maxLength: 200
                gender:
                    type: string
                    maxLength: 10
                dateOfBirth:
                    type: string
                department:
                    type: object
                    required:
                        - name
                        - managerNumber
                    properties:
                        name:
                            type: string
                        managerNumber:
                            type: string
                            minLength: 4
                            maxLength: 4
                probationComplete:
                    type: boolean
                phoneNumber:
                    type: string
                hireDate:
                    type: string
                job:
                    type: string
                grade:
                    type: integer
                salary:
                    type: number
                bonus:
                    type: number
                commission:
                    type
: number

options.yaml

characterVarying=yes

defaultCharacterMaxLength=50

         01 EMP00P01-responseCode200.

           03 responseCode200.

             06 employeeNumber                PIC X(10).

             06 Xtitle-length                 PIC S9999 COMP-5 SYNC.

             06 Xtitle                        PIC X(20).

             06 firstName-length              PIC S9999 COMP-5 SYNC.

             06 firstName                     PIC X(50).

             06 middleInitial-existence       PIC S9(9) COMP-5 SYNC.

             06 middleInitial                 PIC X(1).

             06 lastName-length               PIC S9999 COMP-5 SYNC.

             06 lastName                      PIC X(50).

             06 Xaddress-num                  PIC S9(9) COMP-5 SYNC.

             06 Xaddress-dataarea             PIC X(16).

             06 gender-length                 PIC S9999 COMP-5 SYNC.

             06 gender                        PIC X(10).

             06 dateOfBirth-length            PIC S9999 COMP-5 SYNC.

             06 dateOfBirth                   PIC X(50).

             06 department.

               09 name-length                 PIC S9999 COMP-5 SYNC.

               09 name                        PIC X(50).

               09 managerNumber               PIC X(4).

             06 probationComplete             PIC X DISPLAY.

             06 phoneNumber-existence         PIC S9(9) COMP-5 SYNC.

             06 phoneNumber.

               09 phoneNumber2-length         PIC S9999 COMP-5 SYNC.

               09 phoneNumber2                PIC X(50).

             06 hireDate-length               PIC S9999 COMP-5 SYNC.

             06 hireDate                      PIC X(50).

             06 job-length                    PIC S9999 COMP-5 SYNC.

             06 job                           PIC X(50).

             06 grade                         PIC S9(18) COMP-5 SYNC.

             06 salary                        COMP-2 SYNC.

             06 bonus-existence               PIC S9(9) COMP-5 SYNC.

             06 bonus                         COMP-2 SYNC.

             06 commission-existence          PIC S9(9) COMP-5 SYNC.

             06 commission                    COMP-2 SYNC.

 

         01 EMP00P01-Xaddress.

           03 Xaddress-length                 PIC S9999 COMP-5 SYNC.

           03 Xaddress                        PIC X(200).

Problem 6

We have noticed in our API service employee database that some address data contains whitespace (spaces and tabs) and in our COBOL application we want to process this data without the complication of whitespace.

Whitespace in strings can be controlled by using the options.yaml property characterWhitespace.  The valid settings are collapse, replace, and preserve.  The default is collapse, at runtime when a JSON string contains whitespace any leading and trailing whitespace is removed, and any embedded whitespace is replaced with a single space character.

This setting is good for our API, but other APIs may require other options. The replace option will replace any tabs and new lines with a single space.  And  preserve will not process whitespace and leave it as is.

Problem 7

We have an address array defined in our Employee object and with support for dynamic length arrays the language structures have been generated to use a separate area of memory, dynamically sized, to contain the array data.  For API Requester these are known as Data Areas or in API First for CICS a Container.   These areas require more programming effort to address the memory and extract or set each array entry from/to the dynamic area.   If we had an API that was returning an array of Employees where we could have thousands of employees, dynamic length arrays are useful and a good way to reduce storage needs because we do not need to define a maximum array space to contain the maximum possible, which we may not know anyway if the OpenAPI document has not set an array maxItems value.

However, when we have an array that will only ever contain a limited set of entries the use of dynamic arrays is a programming overhead compared with the storage used.  The property address is a prime example where we know that any employee address will have 10 address lines as an absolute maximum.   So we could set maxItems for the address array to 10.  If we generate our COBOL language structure, we will see no difference, we will still have a dynamic array, but if we supply the options.yaml property inlineMaxOccursLimit to 20 then any array with a maxItems less than the inlineMaxOccursLimit value will be generated as an in-lined array with an occurs clause in COBOL. For address this would become an in-lined array.

address:
    type: array
    maxItems: 10
    items:
        type: string
        maxLength: 200

options.yaml

inlineMaxOccursLimit=20

Partial generated language structure

             06 Xaddress OCCURS 10.

               09 Xaddress2-length              PIC S9999 COMP-5 SYNC.

               09 Xaddress2                     PIC X(200).

Problem 8

The handling of numbers.  In OpenAPI and the underlying JSON a number can be defined as a floating point number or an integer, but in the COBOL world we can define numbers in a number of ways  COMP-1 (floating point, 4 bytes), COMP-2 (long floating point, 8 bytes), COMP-3 (packed decimal), COMP-4 (binary), or COMP-5 (fixed binary integers 2, 4, or 8 bytes long).

If the OpenApi document specifies the barest amount of information about a number or an integer the tooling must reserve the maximum amount of storage space required to hold the number, COMP-2 (8 Bytes) for a number and COMP-5 (8 Bytes) for an integer.

To help the tooling make better decisions we can use the format attribute of a type and the maximum attribute  to specify the maximum value of the number we can expect.

For our grade property we have defined this as a type of integer, and we know our grading values range from 1-20. If we then set a maximum of 20 and a minimum of 1

grade:
    type: integer
    minimum: 1
    maximum
: 20

then instead of generating

 06 grade                         PIC S9(18) COMP-5 SYNC.

We generate

06 grade                         PIC 9999 COMP-5 SYNC.

An unsigned 2-byte long integer.

For our real numbers salary and bonus we can use the format type attribute to specify the size, double or float. Double will generate a COMP-2 and float a COMP-1 field.

salary:
    type: number
    format: float
bonus:
    type: number
    format
: double

Generating

             06 salary                        COMP-1 SYNC.

             06 bonus                         COMP-2 SYNC.

What we really want to use in our application is COMP-3 packed decimal for our real numbers.  For this we specify the format attribute of decimal.

salary:
    type: number
    format: decimal
bonus:
    type: number
    format
: decimal

Generating

             06 salary                        PIC S9(15)V9(3) COMP-3.

             06 bonus                         PIC S9(15)V9(3) COMP-3.

We generate a signed COMP-3 field with 15 whole digits and 3 fraction digits.  If we also specify minimum as 0, who will want a negative salary! Then the generated field is not signed.

If we are in a world where we are dealing with very large numbers, we can use the maximum COMP-3 size of 31. Which would generate as

06 bonus                         PIC 9(28)V9(3) COMP-3.

This is achieved by specifying the options.yaml property wideComp3 to YES.

Problem 9

We are now using packed decimal for our real number fields, but we have 3 fraction digits where our currency only has two decimal places.

To change this on a global level we can specify the options.yaml property defaultFractionDigits with a value of 2.

Now salary and bonus are (wideComp3 is now set to no)

             06 salary                        PIC 9(16)V9(2) COMP-3.

             06 bonus                         PIC 9(16)V9(2) COMP-3.

Problem 10

In our Employee object we have two dates, the date of birth, and the hire date of the employee.  Both are of type string, but we can provide further meaning by using the format attribute of the type.

In our Employee object we will make dateOfBirth format date and hireDate format date-time.

dateOfBirth:
    type: string
    format: date
hireDate:
    type: string
    format
: date-time

Now dateOfBirth and hireDate are

 06 dateOfBirth-length            PIC S9999 COMP-5 SYNC.

 06 dateOfBirth                   PIC X(32).

 06 hireDate                      PIC S9(15) COMP-3. 

dateOfBirth has changed from a generic string of PIC X(50) to a string of PIC X(32) and hireDate has changed to PIC S9(15) COMP-3 which is CICS TS ABSTIME format.

If we do not want to use ABSTIME format, then the options.yaml property dateTimeFormat can be set to string.

This would make hireDate a string of PIC X(40) to contain date and time.

             06 hireDate-length               PIC S9999 COMP-5 SYNC.

             06 hireDate                      PIC X(40).

For our example we will use ABSTIME.

Conclusion

With all our changes we have an OpenApi 3 document

---
openapi: 3.0.3
info:
    title: Attributes and Options
    version: 1.0.0
paths:
    /employee/{id}:
        get:
            operationId: employeeGet
            parameters:
                - name: id
                  in: path
                  required: true
                  schema:
                      type: string
            responses:
                "200":
                    description: Successful operation
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Employee'
components:
    schemas:
        Employee:
            type: object
            required:
                - employeeNumber
                - title
                - firstName
                - lastName
                - address
                - gender
                - dateOfBirth
                - department
                - probationComplete
                - hireDate
                - job
                - grade
                - salary
            properties:
                employeeNumber:
                    type: string
                    minLength: 10
                    maxLength: 10
                title:
                    type: string
                    maxLength: 20
                firstName:
                    type: string
                middleInitial:
                    type: string
                    minLength: 1
                    maxLength: 1
                lastName:
                    type: string
                address:
                    type: array
                    maxItems: 10
                    items:
                        type: string
                        maxLength: 200
                gender:
                    type: string
                    maxLength: 10
                dateOfBirth:
                    type: string
                    format: date
                department:
                    type: object
                    required:
                        - name
                        - managerNumber
                    properties:
                        name:
                            type: string
                        managerNumber:
                            type: string
                            minLength: 4
                            maxLength: 4
                probationComplete:
                    type: boolean
                phoneNumber:
                    type: string
                hireDate:
                    type: string
                    format: date-time
                job:
                    type: string
                grade:
                    type: integer
                    minimum: 1
                    maximum: 20
                salary:
                    type: number
                    format: decimal
                    minimum: 0
                bonus:
                    type: number
                    format: decimal
                    minimum: 0
                commission:
                    type: number
                    format
: decimal

And using these options.yaml properties

Language=COBOL
requesterPrefix=EMP
defaultCharacterMaxLength=50
characterVarying=yes
inlineMaxOccursLimit=20
wideComp3=no
defaultFractionDigits=2

We generate the following COBOL language structure which as you can see is much more succinct from what we started with and much easier to programme with.

          01 BAQBASE-EMP00P01.

 

            03 responseCode200-existence     PIC S9(9) COMP-5 SYNC.

            03 responseCode200-dataarea      PIC X(16).

 

 

         01 EMP00P01-responseCode200.

           03 responseCode200.

             06 employeeNumber                PIC X(10).

             06 Xtitle-length                 PIC S9999 COMP-5 SYNC.

             06 Xtitle                        PIC X(20).

             06 firstName-length              PIC S9999 COMP-5 SYNC.

             06 firstName                     PIC X(50).

             06 middleInitial-existence       PIC S9(9) COMP-5 SYNC.

             06 middleInitial                 PIC X(1).

             06 lastName-length               PIC S9999 COMP-5 SYNC.

             06 lastName                      PIC X(50).

             06 Xaddress-num                  PIC S9(9) COMP-5 SYNC.

             06 Xaddress OCCURS 10.

               09 Xaddress2-length            PIC S9999 COMP-5 SYNC.

               09 Xaddress2                   PIC X(200).

             06 gender-length                 PIC S9999 COMP-5 SYNC.

             06 gender                        PIC X(10).

             06 dateOfBirth-length            PIC S9999 COMP-5 SYNC.

             06 dateOfBirth                   PIC X(32).

             06 department.

               09 name-length                 PIC S9999 COMP-5 SYNC.

               09 name                        PIC X(50).

               09 managerNumber               PIC X(4).

             06 probationComplete             PIC X DISPLAY.

             06 phoneNumber-existence         PIC S9(9) COMP-5 SYNC.

             06 phoneNumber.

               09 phoneNumber2-length         PIC S9999 COMP-5 SYNC.

               09 phoneNumber2                PIC X(50).

             06 hireDate                      PIC S9(15) COMP-3.

             06 job-length                    PIC S9999 COMP-5 SYNC.

             06 job                           PIC X(50).

             06 grade                         PIC 9999 COMP-5 SYNC.

             06 salary                        PIC 9(16)V9(2) COMP-3.

             06 bonus-existence               PIC S9(9) COMP-5 SYNC.

             06 bonus                         PIC 9(16)V9(2) COMP-3.

             06 commission-existence          PIC S9(9) COMP-5 SYNC.

             06 commission                    PIC S9(16)V9(2) COMP-3.

             06 filler                        PIC X(2).

 

From this blog we can see defining type attributes in the OpenApi 3 document and options.yaml properties we can change what we generate. Go and explore the OpenApi 3 spec and the Gradle plugin options.yaml properties documentation to see the full range of options available.

0 comments
37 views

Permalink