Show TOC

Dynamically Processing BSP ElementsLocate this document in the navigation structure

Use

If a BSP element is located in the layout of a BSP, a compiler translates the XML syntax that represents the interface for the element in source code, which is then executed at runtime.

In a simple example, (in simple pseudocode notation) this could be as follows:

Element:  <lib:element a1 = "v1" />

Source:   DATA: e123 TYPE REF TO CL_LIB_ELEMENT.
          CREATE OBJECT e123.
          e123->a1 = 'v1'.
          e123->parent  = page->current_element.
          page->current_element = e123.
          e123->context = page->context.
          e123->DO_AT_BEGINNING( ).
          e123->DO_AT_END( ).
          page->current_element = e123->parent.


         

An element can, however, also require its own writer, and possibly also validation. The element can either contain body text only, or it can include inner, embedded elements that must be processed.

Element:  <lib:element2 a1 = "v1" />
          ...
          </lib:element2>

Source:   DATA: e124 TYPE REF TO CL_LIB_ELEMENT2.
          CREATE OBJECT e124.
          e124->a1 = 'v1'.
          e124->parent  = page->current_element.
          page->current_element = e124.
          e124->context = page->context.
          e124->m_out   = context->PUSH_WRITER( ).
          e124->RUNTIME_VALIDATION( ).
          IF e124->DO_AT_BEGINNING( ) = CO_ELEMENT_CONTINUE.
            context->current_writer->PRINT_STRING( `....` ).
          ENDIF.
          e124->DO_AT_END( ).
          context->POP_WRITER( ).
          page->current_element = e124->parent.


         

Furthermore, an element can specify that its body requires iteration. This suggests that the body of the element is processed more than once.

Element:  <lib:element3 a1 = "v1" />
          ...
          </lib:element3>

Source:   DATA: e125 TYPE REF TO CL_LIB_ELEMENT3.
          CREATE OBJECT e125.
          e125->a1 = 'v1'.
          e125->parent  = page->current_element.
          page->current_element = e125.
          e125->context = page->context.
          e125->m_out   = context->PUSH_WRITER( ).
          e125->RUNTIME_VALIDATION( ).
          rc125 = e125-> DO_AT_BEGINNING( ).
          WHILE e125 = CO_ELEMENT_CONTINUE.
            context->current_writer->PRINT_STRING( `....` ).
            rc125 = e125->DO_AT_ITERATION( ).
          ENDWHILE.
          e125->DO_AT_END( ).
          context->POP_WRITER( ).
          page->current_element = e124->parent.


         

Obviously, the compiler uses the additional information about the BSP element's definition to generate the optimum code for processing the element.

The same flexibility is now required for processing BSP elements externally of the actual BSP, that is, externally of the page.

From the examples above, you can see that to set an element's attributes you need a reference to the actual class, and not to interface IF_BSP_ELEMENT. Also, elements do not have methods to actually set attributes. The attributes are set directly as public attributes of the element classes.

It is not effective to encapsulate the actual element class reference, or the phase in which attributes are set. If an element is processed dynamically, you must know the element class (you can find it in the BSP extension workbench). You can, however, pack the remaining code in one or more methods.

You cannot encapsulate body processing, since it is not known if the body is a string, or if it consists of several embedded elements that have to be processed.

Due to these design constraints, the following pseudocode can be written:

DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
CREATE OBJECT eX.
eX->a1 = 'v1'.
processing_before_body( eX ).
...body processing...
processing_after_body( eX ).


         

This code is still not sufficiently flexible to handle element iteration. After the body has been processed, you must decide whether iteration is carried out, or if it should be stopped. The pseudocode can therefore be written as follows:

DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
CREATE OBJECT eX.
eX->a1 = 'v1'.
WHILE process_element( eX ).
...body processing...
ENDWHILE.


         

This enables users to set the element attributes first of all. Furthermore, users can be flexible when determining how inner elements are to be used.

This type of element processing method with the name ELEMENT_PROCESS is available in interface IF_BSP_PAGE_CONTEXT, which is available in every element.

If a body is not required, or only a simple string body is required, processing continues as far as possible (until it is complete, if this is possible), provided that the optional body string is available.

Now to processing an "empty" element. In this case, "empty" means that the element is flagged in the Workbench as empty; it does not mean that there is only an optional body.

Element:  <lib:eX a1 = "v1" />

Source:   DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
          CREATE OBJECT eX.
          eX->a1 = 'v1'.
          m_page_context->ELEMENT_PROCESS ( element = eX ).


         

If the simple element requires a body as well, this can be done when the body string is provided.

Element:  <lib:eX a1 = "v1" />
            body string
          </lib.eX>

Source:   DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
            CREATE OBJECT eX.
            eX->a1 = 'v1'.
            m_page_context->ELEMENT_PROCESS ( element = eX body = 'body string').


         

The body can also be written dynamically during the processing step.

Caution

Note however, that the active writer is used for writing the body. Each time a new element is (partly) processed, new writers may be pushed on the stack. The writer that is used must be the last writer that was added.

Element:  <lib:eX a1 = "v1" />
            body string
          </lib.eX>

Source:   DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
            CREATE OBJECT eX.
            eX->a1 = 'v1'.
            m_page_context->ELEMENT_PROCESS ( element = eX ).
              DATA: out TYPE REF TO IF_BSP_WRITER.
              out = m_page_context->GET_OUT( ).
              out->PRINT_STRING( `body string` ).
            m_page_context->ELEMENT_PROCESS( element = eX ).


         

You can process inner elements by starting your processing when the external element is processed.

Caution

Ensure that you do not transfer a body to the processing code. If the body is transferred as a parameter, the system assumes that this body represents the whole body, and therefore then ends processing for that element.


Element:  <lib:eX a1 = "v1">
          body before
          <lib:eY a1 = "v1">
            body inside
          </lib:eY>
            body after
          </lib:eX>

Source:   DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
            CREATE OBJECT eX.
            eX->a1 = 'v1'.
            m_page_context->ELEMENT_PROCESS( element = eX ).

             DATA: out TYPE REF TO IF_BSP_WRITER.
             out = m_page_context->GET_OUT( ).
             out->PRINT_STRING( `body before` ).

             DATA: eY TYPE REF TO CL_LIB_ELEMENTY.
             CREATE OBJECT eY.
             eY->a1 = 'v1'.
             m_page_context->ELEMENT_PROCESS( element = eY body = `body inside` ).

             out = m_page_context->GET_OUT( ).
             out->PRINT_STRING( `body after` ).

             m_page_context->ELEMENT_PROCESS( element = eX ).


         

Iteration implies that the same body is processed until the element has enough.

Element:  <lib:iterator repeat = "3" />
            body string
          </lib:iterator>

Source:   DATA: iterator TYPE REF TO CL_LIB_ITERATIR.
            CREATE OBJECT iterator.
            iteratir->repeat = 3.
            WHILE m_page_context->ELEMENT_PROCESS (
              element = iterator
                 body = 'body string' ) = CO_ELEMENT_CONTINUE.
            ENDWHILE.


         
Recommendation

In principle, it is always correct to write a WHILE loop around the ELEMENT_PROCESS() call. This is the recommended technique for using this method.

As soon as an element has been processed, the element instance can not be reused, since you cannot rest all element default values like the BSP compiler does. The create object call must therefore always be executed when the same element is to be processed again.


Element:  <lib:eX a1 = "v1" />
          <lib:eX a1 = "v1" />

Source:   DATA: eX TYPE REF TO CL_LIB_ELEMENTX.
           CREATE OBJECT eX.
           eX->a1 = 'v1'.
           m_page_context->ELEMENT_PROCESS ( element = eX ).
           CREATE OBJECT eX.
           eX->a1 = 'v1'.
           m_page_context->ELEMENT_PROCESS ( element = eX ).


         

Now create the New BSP Extension with the composite elements.