anchor.diff:    ENDMETHOD.  "lif_object~has_changed_since
   
     METHOD lif_object~changed_by.
  -* todo
  -    rv_user = c_user_unknown.
  +
  +    DATA: lv_name   TYPE o2applname,
  +          lt_pages  TYPE STANDARD TABLE OF o2pagdir WITH DEFAULT KEY,
  +          ls_latest LIKE LINE OF lt_pages.
  +
  +
  +    lv_name = ms_item-obj_name.
  +
  +    SELECT * FROM o2pagdir INTO TABLE lt_pages WHERE applname = lv_name.
  +    IF sy-subrc <> 0.
  +      rv_user = c_user_unknown.
  +    ENDIF.
  +
  +    SORT lt_pages BY changedon DESCENDING changetime DESCENDING.
  +
  +    READ TABLE lt_pages INDEX 1 INTO ls_latest.
  +    ASSERT sy-subrc = 0.
  +
  +    rv_user = ls_latest-changedby.
  +
     ENDMETHOD.
   
     METHOD lif_object~get_metadata.
  
positive.code:     INTERFACES lif_object.
      ALIASES mo_files FOR lif_object~mo_files.
  
  ENDCLASS.                    "lcl_object_TRAN DEFINITION
  
  *----------------------------------------------------------------------*
  
negative.code: 
    METHOD lif_object~exists.
  
      DATA: lv_name TYPE o2applname.
  
  
      lv_name = ms_item-obj_name.
  
      cl_o2_api_application=>load(
        EXPORTING
          p_application_name  = lv_name
        EXCEPTIONS
          object_not_existing = 1
          permission_failure  = 2
          error_occured       = 3 ).
      rv_bool = boolc( sy-subrc = 0 ).
  
    ENDMETHOD.                    "lif_object~exists
  
    METHOD lif_object~jump.
      lcx_exception=>raise( 'todo, jump, WAPA' ).
    ENDMETHOD.                    "jump
  
    METHOD lif_object~delete.
  
  * todo, not supported yet
      ASSERT 0 = 1.
  
    ENDMETHOD.                    "delete
  
    METHOD lif_object~deserialize.
  
  * todo, not supported yet
      ASSERT 0 = 1.
  
    ENDMETHOD.                    "deserialize
  
    METHOD lif_object~serialize.
  
      DATA: lv_name       TYPE o2applname,
            ls_attributes TYPE o2applattr,
            lt_navgraph   TYPE o2applgrap_table,
            lt_pages      TYPE o2pagelist,
            lt_pages_info TYPE ty_pages_tt,
            lo_bsp        TYPE REF TO cl_o2_api_application.
  
      FIELD-SYMBOLS: <ls_page> LIKE LINE OF lt_pages.
  
  
      lv_name = ms_item-obj_name.
  
      cl_o2_api_application=>load(
        EXPORTING
          p_application_name = lv_name
        IMPORTING
          p_application = lo_bsp
        EXCEPTIONS
          object_not_existing = 1
          permission_failure  = 2
          error_occured       = 3 ).
      IF sy-subrc <> 0.
        RETURN.
      ENDIF.
  
      lo_bsp->get_attributes(
        EXPORTING
          p_version    = 'A'
        IMPORTING
          p_attributes = ls_attributes ).
  
      CLEAR: ls_attributes-author,
             ls_attributes-createdon,
             ls_attributes-changedby,
             ls_attributes-changedon,
             ls_attributes-devclass.
  
      io_xml->add( iv_name = 'ATTRIBUTES'
                   ig_data = ls_attributes ).
  
      lo_bsp->get_navgraph(
        EXPORTING
          p_version  = 'A'
        IMPORTING
          p_navgraph = lt_navgraph ).
  
      io_xml->add( iv_name = 'NAVGRAPH'
                   ig_data = lt_navgraph ).
  
      cl_o2_api_pages=>get_all_pages(
        EXPORTING
          p_applname = lv_name
          p_version  = 'A'
        IMPORTING
          p_pages    = lt_pages ).
  
      LOOP AT lt_pages ASSIGNING <ls_page>.
        APPEND read_page( <ls_page> ) TO lt_pages_info.
      ENDLOOP.
  
      io_xml->add( iv_name = 'PAGES'
                   ig_data = lt_pages_info ).
  
    ENDMETHOD.                    "serialize
  
    METHOD read_page.
  
      DATA: lv_name    TYPE o2applname,
            ls_pagekey TYPE o2pagkey,
            lv_content TYPE xstring,
            lv_extra   TYPE string,
            lv_ext     TYPE string,
            lo_page    TYPE REF TO cl_o2_api_pages.
  
  
      lv_name = ms_item-obj_name.
  
      ls_pagekey-applname = lv_name.
      ls_pagekey-pagekey = is_page-pagekey.
  
      cl_o2_api_pages=>load(
        EXPORTING
          p_pagekey = ls_pagekey
        IMPORTING
          p_page    = lo_page ).
  * todo, add moar page data into rs_page:
  * event handlers
  * page parameters
  * type definitions
  
      lv_content = get_page_content( lo_page ).
      SPLIT is_page-pagename AT '.' INTO lv_extra lv_ext.
      REPLACE ALL OCCURRENCES OF '/' IN lv_extra WITH '_-'.
      mo_files->add_raw(
        iv_extra = lv_extra
        iv_ext   = lv_ext
        iv_data  = lv_content ).
  
      rs_page-attributes = is_page.
  
      CLEAR: rs_page-attributes-author,
             rs_page-attributes-createdon,
             rs_page-attributes-changedby,
             rs_page-attributes-changedon,
             rs_page-attributes-implclass,
             rs_page-attributes-gendate,
             rs_page-attributes-gentime.
  
    ENDMETHOD.
  
    METHOD get_page_content.
  
      DATA: lt_content TYPE o2pageline_table,
            lv_string  TYPE string.
  
      io_page->get_page(
        IMPORTING
          p_content = lt_content ).
  
      CONCATENATE LINES OF lt_content INTO lv_string SEPARATED BY gc_newline RESPECTING BLANKS.
  
      rv_content = lcl_convert=>string_to_xstring_utf8( lv_string ).
  
    ENDMETHOD.
  
    METHOD lif_object~compare_to_remote_version.
      CREATE OBJECT ro_comparison_result TYPE lcl_null_comparison_result.
  