Anfang des InhaltsbereichsHintergrunddokumentation Dynamische Verarbeitung von BSP-Elementen Dokument im Navigationsbaum lokalisieren

Wenn ein BSP-Element im Layout einer BSP vorkommt, übersetzt ein Compiler die XML-Syntax, die die Schnittstelle zum Element darstellt, in Quellcode, der dann zur Laufzeit tatsächlich ausgeführt wird.

In einem einfachen Beispiel könnte dies (in einfacher Pseudocode-Notation) folgendermaßen aussehen:

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.

 

Jedoch kann ein Element auch seinen eigenen Writer benötigen, und eventuell auch Validierung. Das Element kann entweder nur Body-Text beinhalten, oder es kann innere, eingebettete Elemente beinhalten, die verarbeitet werden müssen.

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.

 

Zusätzlich ist es möglich, dass ein Element angibt, es benötigt Iteration über seinen eigenen Body. Dies lässt darauf schließen, dass der Body des Elements häufiger als einmal prozessiert wird.

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.

 

Es ist klar, dass der Compiler die zusätzlichen Informationen über die Definition des BSP-Elements benutzt, um den optimalen Code für die Verarbeitung des Elements zu generieren.

Nun wird die gleiche Flexibilität für die Verarbeitung von BSP-Elementen außerhalb der eigentlichen BSP, also außerhalb der Seite, benötigt.

 

Ausgehend von den obigen Beispielen kann man sehen, dass für das Setzen der Attribute eines Elements eine Referenz auf der eigentlichen Klasse und nicht auf das Interface IF_BSP_ELEMENT notwendig ist. Auch haben Elemente keine Methoden, um Attribute tatsächlich zu setzen. Die Attribute werden als öffentliche (public) Attribute der Elementklassen gesetzt, und zwar direkt gesetzt.

Es ist nicht effektiv, die eigentliche Elementklassen-Referenz oder die Phase, in der Attribute gesetzt werden, zu kapseln. Wenn ein Element dynamisch verarbeitet wird, muss der Entwickler die Elementklasse kennen (sie ist in der BSP-Extension-Workbench zu sehen). Das restliche Coding kann jedoch in eine oder mehrere Methoden verpackt werden.

Die tatsächliche Verarbeitung des Bodys kann nicht gekapselt werden, da nicht bekannt ist, ob der Body ein String ist oder aus mehreren eingebetteten Elementen besteht, die verarbeitet werden müssen.

Aufgrund dieser Design-Überlegungen kann der folgende Pseudocode geschrieben werden:

        DATA: eX TYPE REF TO CL_LIB_ELEMENTX.

        CREATE OBJECT eX.

        eX->a1 = ‘v1‘.

        processing_before_body( eX ).

          ...body processing...

        processing_after_body( eX ).

Allerdings ist dieser Code immer noch nicht flexibel genug, um Element-Iteration zu handhaben. Nach der Verarbeitung des Bodys muss entschieden werden, ob Iteration durchgeführt wird oder ob sie gestoppt werden soll. Daher kann der Pseudocode nun folgendermaßen geschrieben werden:

        DATA: eX TYPE REF TO CL_LIB_ELEMENTX.

        CREATE OBJECT eX.

        eX->a1 = ‘v1‘.

        WHILE process_element( eX ).

          ...body processing...

        ENDWHILE.

Dies erlaubt dem Benutzer, zuerst die Attribute des Elements zu setzen. Außerdem ist der Benutzer flexibel in der Bestimmung des Einsatzes von inneren Elementen.

 

Eine solche Element-Verarbeitungsmethode mit dem Namen ELEMENT_PROCESS steht im Interface IF_BSP_PAGE_CONTEXT zur Verfügung, das in jedem Element vorhanden ist.

Wenn kein Body benötigt wird oder nur ein einfacher String-Body, wird die Verarbeitung so weit wie möglich weitergeführt (möglichst bis sie beendet ist), sofern der optionale Body-String zur Verfügung steht.

Nun zur Verarbeitung eines „leeren" Elements. In diesem Fall bedeutet „leer", dass das Element in der Workbench als leer gekennzeichnet wurde. Es ist also nicht so, dass lediglich ein optionaler Body vorkommt.

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 ).

Wenn das einfache Element auch einen Body benötigt, kann dies über die Bereitstellung des Body-Strings geschehen.

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‘).

Der Body kann auch dynamisch während des Verarbeitungsschrittes geschrieben werden.

Achtung

Beachten Sie jedoch, dass der jeweils aktive Writer für das Schreiben des Bodys verwendet wird. Jedes Mal, wenn ein neues Element (teilweise) prozessiert wird, besteht die Möglichkeit, dass neue Writer auf den Stack geschoben werden. Hierbei ist es wichtig, dass immer der zuletzt hinzugefügte Writer verwendet wird.

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 ).

 

Innere Elemente können prozessiert werden, indem ihre Verarbeitung ganz einfach innerhalb der Verarbeitung des äußeren Elements gestartet wird.

Achtung

Beachten Sie hierbei, dem Verarbeitungscoding keinen Body zu übergeben. Wenn der Body als Parameter übergeben wird, geht das System davon aus, dass dieser Body den gesamten Body darstellt und beendet daher dann die Verarbeitung des jeweiligen Elements.

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 impliziert, dass derselbe Body so lange verarbeitet wird, bis das Element genug hat.

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.

Empfehlung

Prinzipiell ist es immer korrekt, eine WHILE-Schleife um den ELEMENT_PROCESS()-Aufruf zu schreiben. Dies ist die empfohlene Technik für den Gebrauch dieser Methode.

 

Sobald ein Element prozessiert wurde, kann die Element-Instanz nicht wieder verwendet werden, weil es nicht möglich ist, so wie der BSP-Compiler alle Standardwerte des Elements zurückzusetzen. Daher muss der create-object-Aufruf immer dann durchgeführt werden, wenn das gleiche Element wieder erneut verarbeitet werden soll.

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 ).

 

Erstellen Sie nun die neue BSP-Extension mit den Komposit-Elementen.

Ende des Inhaltsbereichs