Working with REFER in generated PL/I structures

This topic describes how the REFER option is used to generate a compatible Enterprise PL/I structure for a variable-length XML array in the WSDL2PLI scenario.

The information in this topic applies both to:
  • The PL/I source code that the WSDL2PLI code-generation process creates automatically.
  • PL/I source code that you create to access the automatically generated structures.

A REFER example

A variable-length XSD schema array is one in which maxOccurs="unbounded" or where maxOccurs exceeds the limit set in the batch-processor property inlineMaxOccursLimit (see WSDL2ELSSpec). An example of such an array is shown in Figure 1:

Figure 1. XSD declaration of a variable-length array
<!-- XSD declaration: -->
<element name="planets" type="tns:PlanetsType"/>
<complexType name="PlanetsType">
   <sequence>
      <element name="planet_name" type="string" minOccurs="0" maxOccurs="unbounded"/>
   </sequence>
</complexType>

To implement the equivalent array in PL/I, the WSDL2PLI code-generation process creates two PL/I major structures, one for REFER object declarations and one for REFER subject declarations. Figure 2 and Figure 3 show the structures that would be generated for the XSD schema example in Figure 1:

  • The structure for object declarations specifies the maximum number of array items that can be allocated. For the significance of the suffixes _ref and _lim see Creation of PL/I identifiers:

    Figure 2. Structure for object declarations
    /* PL/I REFER object declarations: */
    01 planets_ref UNALIGNED,
       /* number of planet_name entries to allocate space for */
       02 planet_name_lim SIGNED FIXED BINARY(31);
    

  • The structure for subject declarations maps the allocated space. For the significance of the suffixes _ptr, _lim, and _cnt see Creation of PL/I identifiers:

    Figure 3. Structure for subject declarations
    /* PL/I REFER subject declarations: */
    01 planets UNALIGNED BASED(planets_ptr),
       /* saved number of planet_name refer objects allocated (read-only) */
       02 planet_name_lim SIGNED FIXED BINARY(31),
       /* count of planet_name array entries used */
       02 planet_name_cnt SIGNED FIXED BINARY(31),
       /* planet_name array with limit specified at allocation-time */
       02 planet_name (planets_ref.planet_name_lim REFER (planets.planet_name_lim)) CHAR(255) VARYING;

The source code in the next figure shows how to initialize the structures declared in Figure 2 and Figure 3. First the number of items to allocate is set and the allocation is done. Then four of the items in the allocated array are initialized. Finally the number of allocated elements in use is set.
Note: After the major structure planets is allocated, planets.planet_name_cnt must be set to the actual number of items in the array. Also the value in planets.planet_name_cnt must not exceed the value in planets.planet_name_lim.
Figure 4. Initializing the structures for object declarations and subject declarations
/* Usage: */
planets_ref.planet_name_lim = 10;
allocate (planets) set (planets_ptr);
planets.planet_name(1) = “Mercury”;
planets.planet_name(2) = “Venus”;
planets.planet_name(3) = “Earth”;
planets.planet_name(4) = “Mars”;
planets.planet_name_cnt = 4;

A complex REFER example

This example defines a solar system structure containing an unbounded array of planets, with each planet structure containing an unbounded array of moons:

Figure 5. XSD declarations of a variable-length arrays
<!-- XSD declarations: -->
<element name="solar_system" type="tns:SolarSystemType" />
<complexType name="SolarSystemType">
   <sequence>
      <element name="planet" type="tns:PlanetType" minOccurs="0" maxOccurs="unbounded" />
   </sequence>
</complexType>

<complexType name="PlanetType">
<sequence>
   <element name="planet_name" type="string" minOccurs="1" maxOccurs="1" />
   <element name="moon_name" type="string" minOccurs="1" maxOccurs="unbounded" />
</sequence>
</complexType>

To implement the equivalent arrays in PL/I, the WSDL2PLI code-generation process creates the two REFER object declarations and the two REFER subject declarations shown in Figure 6 and Figure 7:

  • Figure 6. Object declarations
    /* PL/I REFER object declarations: */
    01 solar_system_ref UNALIGNED,
       /* number of planet entries to allocate space for */
       02 planet_lim SIGNED FIXED BINARY(31),
       /* number of moon_name entries to allocate space for */
       2 moon_name_lim SIGNED FIXED BINARY(31);
  • Figure 7. Subject declarations
    /* PL/I REFER subject declarations: */
    01 solar_system UNALIGNED BASED(solar_system_ptr),
       /* saved number of planet refer objects allocated (read-only) */
       02 planet_lim SIGNED FIXED BINARY(31),
       /* saved number of moon_name refer object allocated (read-only) */
       02 moon_name_lim SIGNED FIXED BINARY(31),
       /* count of planet array entries used */
       02 planet_cnt SIGNED FIXED BINARY(31),
       /* planet array with limit specified at allocation-time */
       02 planet(solar_system_ref.planet_lim REFER (solar_system.planet_lim)),
          03 planet_name CHAR(255) VARYING,
          /* count of moon_name[i] array entries used */
          03 moon_name_cnt SIGNED FIXED BINARY(31),
          /* moon_name array with limit specified at allocation */
          10 moon_name(solar_system_ref.moon_name_lim REFER (solar_system.moon_name_lim)) CHAR(255) VARYING;
The source code in Figure 8 shows how to initialize the structures declared in Figure 6 and Figure 7.
Note: After the allocation the count variables planets.planet_cnt, solar_system.planet(1).moon_name_cnt, and solar_system.planet(2).moon_name_cnt must be set to the actual number of items in the respective arrays.
Figure 8. Initializing the structures for object declarations and subject declarations
/*Usage:*/
/* initialize major structure solar_system */
solar_system_ref.planet_lim = 4;
solar_system_ref.moon_name_lim = 2;
allocate (solar_system) set (solar_system_ptr);
solar_system.planet_cnt = 0;

/* create planet entry */
solar_system.planet(1) = “Earth”;
solar_system.planet(1).moon_name_cnt = 0;
solar_system.planet(1).moon_name(1) = “Luna”;
solar_system.planet(1).moon_name_cnt += 1;
solar_system.planet_cnt +=1; // 1

/* create planet entry */
solar_system.planet(2) = “Mars”;
solar_system.planet(2).moon_name_cnt = 0;
solar_system.planet(2).moon_name(1) = “Phobos”;
solar_system.planet(2).moon_name(2) = “Deimos”;
solar_system.planet(2).moon_name_cnt = 2;
solar_system.planet_cnt +=1; // 2
Note: With complex REFER subjects such as moon_name shown above, it is necessary to allocate a limit that satisfies all repetitions of the subject. For example, consider converting the following XML into or out of major structure solar_system:
<solar_system>
   <planet>
      <planet_name>Earth</planet_name>
      <moon_name>Luna</moon_name>
   </planet>
   <planet>
      <planet_name>Mars</planet_name>
      <moon_name>Phobos</moon_name>
      <moon_name>Deimos</moon_name>
   </planet>
</solar_system>

The minimum value of the REFER object solar_system_ref.moon_name_lim that will satisfy all repetitions of planet is 2. Setting the object value to 2 will cause space for two moon_name entries to be allocated for each planet entry. Because moon_name occurs only once in the first occurrence of the first planet entry, the counter solar_system.planet(1).moon_name_cnt should be set to 1 so that only the first moon_name entry is read.