Sunday, January 19, 2014

Prototyping an ABAP OData Entity Data Model Generator: Preparing EDMX XML

Continued from my previous post "Prototyping an ABAP OData Entity Data Model Generator : Table Relationships" :

I’ll now write about the EDMX/CSDL preparation part and completed prototype program. Finally, we’ll do a few test runs to generate edmx/xml files and see how it looks when imported into Eclipse data-modelling plug-in.



Technical Details:

Final task of preparing and populating the entity, relationship data into EDMX/CSDL format is completed in method prepare_data_model.

A few notes are as below:

  • Initially, I encountered some problems with generated xml file - when imported into Eclipse, it was missing correct definition for navigations/associations (these “Navigation Properties” were shown with red cross mark in Eclipse). method prepare_data_model was adapted to take the following into consideration correctly :
    Navigation Properties are special properties on Entity Types which are bound to a specific association (through “Role” attributes) and can be used to refer to associations of an entity.
    As an example, for just two tables ( "SPFLI – Flight Schedule" and "SFLIGHT – Flight Details" ): Navigation Property element and Association elements contain related information and is shown as below :


    Also corresponding model-diagram and XML is given as below for reference:
    <?xml version="1.0" encoding="UTF-8"?>
    <edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" Version="1.0">
        <edmx:DataServices m:DataServiceVersion="2.0">
            <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" xmlns:sap="http://www.sap.com/Protocols/SAPData" Alias="Self" Namespace="pragmatiqa">
                <EntityType Name="SFLIGHT">
                    <Key>
                        <PropertyRef Name="CARRID" />
                        <PropertyRef Name="CONNID" />
                        <PropertyRef Name="FLDATE" />
                    </Key>
                    <Property MaxLength="3" Name="CARRID" Nullable="false" Type="Edm.String" />
                    <Property MaxLength="4" Name="CONNID" Nullable="false" Type="Edm.String" />
                    <Property MaxLength="10" Name="FLDATE" Nullable="false" Type="Edm.DateTime" />
                    <Property MaxLength="20" Name="PRICE" Type="Edm.Decimal" />
                    <Property MaxLength="5" Name="CURRENCY" Type="Edm.String" />
                    <NavigationProperty FromRole="SFLIGHT" Name="NavSFLIGHTtoSPFLI" Relationship="Self.SPFLItoSFLIGHT" ToRole="SPFLI" />
                </EntityType>
                <EntityType Name="SPFLI">
                    <Key>
                        <PropertyRef Name="CARRID" />
                        <PropertyRef Name="CONNID" />
                    </Key>
                    <Property MaxLength="3" Name="CARRID" Nullable="false" Type="Edm.String" />
                    <Property MaxLength="4" Name="CONNID" Nullable="false" Type="Edm.String" />
                    <Property MaxLength="3" Name="COUNTRYFR" Type="Edm.String" />
                    <Property MaxLength="20" Name="CITYFROM" Type="Edm.String" />
                    <Property MaxLength="3" Name="AIRPFROM" Type="Edm.String" />
                    <Property MaxLength="3" Name="COUNTRYTO" Type="Edm.String" />
                    <Property MaxLength="20" Name="CITYTO" Type="Edm.String" />
                    <Property MaxLength="3" Name="AIRPTO" Type="Edm.String" />
                    <NavigationProperty FromRole="SPFLI" Name="NavSPFLItoSFLIGHT" Relationship="Self.SPFLItoSFLIGHT" ToRole="SFLIGHT" />
                </EntityType>
                <Association Name="SPFLItoSFLIGHT">
                    <End Multiplicity="1" Role="SPFLI" Type="Self.SPFLI" />
                    <End Multiplicity="*" Role="SFLIGHT" Type="Self.SFLIGHT" />
                </Association>
                <EntityContainer Name="default" m:IsDefaultEntityContainer="true">
                    <EntitySet EntityType="Self.SFLIGHT" Name="SFLIGHTSet" />
                    <EntitySet EntityType="Self.SPFLI" Name="SPFLISet" />
                    <AssociationSet Association="Self.SPFLItoSFLIGHT" Name="SPFLI_SFLIGHTSet">
                        <End EntitySet="SPFLISet" Role="SPFLI" />
                        <End EntitySet="SFLIGHTSet" Role="SFLIGHT" />
                    </AssociationSet>
                </EntityContainer>
            </Schema>
        </edmx:DataServices>
    </edmx:Edmx>
    



  • The prototype code is in a bit of mess and will hopefully be refactored along-side some useful features e.g. adding a pop-up to restrict related tables - rather than processing all the related tables identified by the program. Also relationship-cardinality logic is very basic and I might need to adjust it further. As of now the code is as below :

    *&---------------------------------------------------------------------*
    * 12.01.2014  PragmatiQa(Ram) Prototype to generate EDMX entity data model
    *                             XML file for a main/header table.
    *                             This program will take header/main database
    *                             table name as input, fetch details of table
    *                             meta-data/foreign-key relationships, populate
    *                             a variable of type structure ZRAM_EDMX_CSDL_SCHEMA
    *                             using selected data and then finally use
    *                             "call transformation" to convert data to XML.
    *----------------------------------------------------------------------*
    * Purpose: Auto-generated entity data model XML can be useful for rapid
    *          prototyping or for a development approach that falls between
    *          outside-in and inside-out approach. For example, if you don't
    *          want to start the data-modelling in Eclipse from scratch then
    *          you can use this utility to generate EDMX file from existing
    *          SAP database table relationships, import it into Eclipse ->
    *          adapt in the graphical modelling tool ->  and then export it
    *          for service generation through Service Builder.
    *          You can also import the file directly in SEGW to generate the
    *          gateway meta/data provider classes as per standard procedure
    *          of importing data-model edmx/xml file.
    *----------------------------------------------------------------------*
    * Documented at http://sapblog.rmtiwari.com
    *&---------------------------------------------------------------------*
    REPORT  Z_RAM_EDMX_FILE_GENERATE_NEW.
    PARAMETERS : P_NAMSP type ZRAM_EDMX_NAMESPACE DEFAULT 'pragmatiqa' LOWER CASE.
    PARAMETERS : P_TABLE type DD02L-TABNAME OBLIGATORY.
    *----------------------------------------------------------------------*
    *       CLASS lcl_edmx_generate_utility DEFINITION
    *----------------------------------------------------------------------*
    CLASS lcl_edmx_generate_utility DEFINITION.
    
      PUBLIC SECTION.
        CLASS-METHODS prepare_edmx_xml IMPORTING i_tabname type DD02L-TABNAME
                                                 i_namespace type ZRAM_EDMX_NAMESPACE
                                       RETURNING VALUE(e_xml_xstring) TYPE xstring.
      PRIVATE SECTION.
    
        CLASS-METHODS get_related_tables IMPORTING i_tabname type DD02L-TABNAME
                                   RETURNING VALUE(et_CHECKTABLES) type SDG1_CHECKTAB.
    
        CLASS-METHODS prepare_data_model IMPORTING it_CHECKTABLES type SDG1_CHECKTAB
                                                   i_namespace    type ZRAM_EDMX_NAMESPACE
                                   RETURNING VALUE(es_data_model) TYPE ZRAM_EDMX_CSDL_SCHEMA.
    
        CLASS-METHODS get_table_metadata IMPORTING i_tabname type DD02L-TABNAME
                                   EXPORTING es_TABLE_HEADER type X030L
                                             et_table_metadata type DFIES_TABLE.
    
    ENDCLASS.                    "lcl_edmx_generate_utility
    *----------------------------------------------------------------------*
    *       CLASS lcl_edmx_generate_utility IMPLEMENTATION
    *----------------------------------------------------------------------*
    CLASS lcl_edmx_generate_utility IMPLEMENTATION.
      METHOD prepare_edmx_xml.
        "IMPORTING i_tabname type DD02L-TABNAME
        "          i_namespace type ZRAM_EDMX_NAMESPACE
        "RETURNING e_xml_xstring TYPE xstring.
        DATA : lt_checktables type SDG1_CHECKTAB.
        DATA : ls_data_model TYPE ZRAM_EDMX_CSDL_SCHEMA.
    
        lt_CHECKTABLES = get_related_tables( i_tabname ).
        ls_data_model = prepare_data_model( it_CHECKTABLES = lt_CHECKTABLES
                                            i_namespace = i_namespace ).
    
    * This is the main ST call to generate EDMX xml from ABAP DATA
        CALL TRANSFORMATION Z_RAM_EDMX_GENERATE_ST
        SOURCE SCHEMA = ls_data_model
        RESULT XML e_xml_xstring.
    
      ENDMETHOD.                    "prepare_edmx_xml
    
    
      METHOD get_related_tables.
        "IMPORTING i_tabname type DD02L-TABNAME
        "RETURNING VALUE(et_CHECKTABLES) type SDG1_CHECKTAB.
    
        DATA : lt_TABLENAMES TYPE SDG1_TABLE,
               wa_tablenames like line of lt_TABLENAMES,
               wa_CHECKTABLES like LINE OF et_CHECKTABLES.
    
        wa_tablenames-tabname = i_tabname.
        APPEND wa_tablenames to lt_TABLENAMES.
    
        CALL FUNCTION 'RS_DD_FOREIGNTABLES_GET'
          EXPORTING
            DIRECTION              = ' '
            LIST_EXCEED            = 100
            TYPE                   = 'TABL'
          TABLES
            TABLENAMES             = lt_TABLENAMES
            CHECKTABLES            = et_CHECKTABLES
    *       TABLENAMES_ALREADY_GOT =
          EXCEPTIONS
            PARAMETERS_FAULT       = 1
            NO_SELECTION           = 2
            OTHERS                 = 3.
        IF SY-SUBRC < >  0.
    * Implement suitable error handling here
          return.
        ENDIF.
        "    Not sure for cases when cord/relationship is not specified in SE11 hence FRKART is blank.
    *    DELETE et_CHECKTABLES WHERE FRKART is INITIAL.
    
        wa_CHECKTABLES-tabname = i_tabname.
        INSERT wa_CHECKTABLES into et_CHECKTABLES index 1.
    
        DATA : lt_CHECKTABLES LIKE et_CHECKTABLES,
               wa_checktables_invert LIKE LINE OF lt_CHECKTABLES.
    
    *   Till this point et_CHECKTABLES has all the relationships.
    *   Adding inverted relations records in the same itab helps later
    *   so that both foreign key and check tables are considerd in 'prepare_data_model' as entity.
    *   That might save a few loop processings later but needs refactoring - not maintainable in this way.
        lt_CHECKTABLES = et_CHECKTABLES.
        LOOP AT lt_CHECKTABLES into wa_CHECKTABLES WHERE checktable ne space and checktable ne i_tabname.
          wa_checktables_invert = wa_CHECKTABLES.
          wa_checktables_invert-tabname = wa_CHECKTABLES-checktable.
          wa_checktables_invert-checktable = wa_CHECKTABLES-tabname.
          wa_checktables_invert-CARDLEFT = wa_CHECKTABLES-CARD.
          wa_checktables_invert-CARD = wa_CHECKTABLES-CARDLEFT.
          wa_checktables_invert-DIRECTION = ' '.
          APPEND wa_checktables_invert To et_CHECKTABLES.
        ENDLOOP.
    
      ENDMETHOD.                    "get_related_tables
    
      METHOD prepare_data_model.
        "IMPORTING it_CHECKTABLES type SDG1_CHECKTAB
        "          i_namespace    type ZRAM_EDMX_NAMESPACE
        "RETURNING VALUE(es_data_model) TYPE ZRAM_EDMX_CSDL_SCHEMA.
        TYPES:
          BEGIN OF ty_s_edm_field_desc,
                     core_type       TYPE  /iwbep/if_mgw_med_odata_types=> ty_e_med_edm_type, "EDM Data Type
                     length          TYPE  i,    "Length (No. of Characters)
                     decimals        TYPE  i,  "Number of Decimal Places
                     internal_type   TYPE  inttype,
                     internal_length TYPE  i,
                     input_mask      TYPE string,
                     conv_exit       TYPE /iwbep/if_mgw_med_odata_types=> ty_e_med_conv_exit,
                     semantic        TYPE /iwbep/if_mgw_med_odata_types=> ty_e_med_semantic,
                   END OF ty_s_edm_field_desc .
    
        DATA : wa_CHECKTABLES like line of it_CHECKTABLES,
               wa_CHECKTABLES_NAV like line of it_CHECKTABLES.
        DATA : lt_CHECKTABLES_distinct type SDG1_CHECKTAB.
    *--
        DATA : lt_table_metadata type table of DFIES,
               wa_table_metadata like line of lt_table_metadata.
        DATA : ls_TABLE_HEADER TYPE X030L.
        DATA : lv_table type DD02L-TABNAME.
    *---
        DATA : lv_namespace_with_dot type ZRAM_EDMX_NAMESPACE.
    *    DATA : ls_data_model TYPE ZRAM_EDMX_CSDL_SCHEMA.
    
        DATA : lt_ENTITYSET type ZRAM_EDMX_ENTITYSET_T,
               wa_ENTITYSET like line of lt_ENTITYSET.
        DATA : lt_ASSOCIATIONSET type ZRAM_EDMX_ASSOCIATIONSET_T,
               wa_ASSOCIATIONSET like line of lt_ASSOCIATIONSET.
        DATA : lt_assoset_end type ZRAM_EDMX_ASSO_END_T,
               wa_assoset_end like line of lt_assoset_end.
        DATA : lt_ENTITYTYPE type ZRAM_EDMX_ENTITYTYPE_T,
               wa_ENTITYTYPE like line of lt_ENTITYTYPE.
        DATA : lt_key type ZRAM_EDMX_KEY,
               wa_key like LINE OF lt_key.
        DATA : lt_property type ZRAM_EDMX_PROPERTY_T,
               wa_property LIKE LINE OF lt_property.
        DATA : lt_NAVIGATIONPROPERTY type ZRAM_EDMX_NAVIGATIONPROPERTY_T,
               wa_NAVIGATIONPROPERTY LIKE LINE OF lt_NAVIGATIONPROPERTY.
        DATA : lt_end type ZRAM_EDMX_END_T,
               wa_end like LINE OF lt_end.
        DATA : lt_ASSOCIATION_T type ZRAM_EDMX_ASSOCIATION_T,
               wa_ASSOCIATION_T like line of lt_ASSOCIATION_T.
    
        DATA : lv_absolute_field_name type RS38L_TYP.
        DATA : lo_type_desc    TYPE REF TO cl_abap_typedescr.
        DATA : ls_edm_type_info  type ty_s_edm_field_desc.
    
        DATA : lv_already_processed type c.
    *---
        CONSTANTS: lc_true type string value 'true'.
        CONSTANTS: lc_false type string value 'false'.
    
    *---
        CONCATENATE i_namespace '.' into lv_namespace_with_dot.
    
        lt_CHECKTABLES_distinct = it_CHECKTABLES.
        SORT lt_CHECKTABLES_distinct by tabname checktable.
    
    * Now populate the model schema structure
        DELETE ADJACENT DUPLICATES FROM lt_CHECKTABLES_distinct COMPARING tabname checktable.
        LOOP AT lt_CHECKTABLES_distinct into wa_CHECKTABLES.
    
          lv_table = wa_CHECKTABLES-tabname.
          CALL METHOD get_table_metadata
            EXPORTING
              i_tabname         = lv_table
            IMPORTING
              es_TABLE_HEADER   = ls_TABLE_HEADER
              et_table_metadata = lt_table_metadata.
    
    * Populate the main structure now
    
    
          CONCATENATE lv_table 'Set' into wa_ENTITYSET-NAME.
          CONCATENATE lv_namespace_with_dot lv_table into wa_ENTITYSET-ENTITYTYPE .
          clear : lv_already_processed.
          READ TABLE lt_ENTITYSET into wa_ENTITYSET with key name = wa_ENTITYSET-NAME.
          if sy-subrc ne 0.
            APPEND wa_ENTITYSET to lt_ENTITYSET.
          else.
            lv_already_processed = 'X'.
          endif.
    
          wa_ENTITYSET-ENTITYTYPE = lv_table . "Correct this stuff later
    *----
          REFRESH : lt_assoset_end.
    *      if wa_CHECKTABLES-CHECKTABLE is not INITIAL.
          if wa_CHECKTABLES-direction is not INITIAL.
            CONCATENATE wa_CHECKTABLES-CHECKTABLE '_' wa_CHECKTABLES-tabname 'Set' into wa_ASSOCIATIONSET-NAME.
            CONCATENATE lv_namespace_with_dot wa_CHECKTABLES-CHECKTABLE 'to' wa_CHECKTABLES-tabname into wa_ASSOCIATIONSET-ASSOCIATION.
    *----------
            wa_assoset_end-ROLE = wa_CHECKTABLES-CHECKTABLE.
            CONCATENATE wa_CHECKTABLES-CHECKTABLE 'Set' into wa_assoset_end-ENTITYSET.
            APPEND wa_assoset_end to lt_assoset_end.
    
            wa_assoset_end-ROLE = wa_ENTITYSET-ENTITYTYPE.
            wa_assoset_end-ENTITYSET = wa_ENTITYSET-NAME.
            APPEND wa_assoset_end to lt_assoset_end.
    
            wa_ASSOCIATIONSET-END = lt_assoset_end.
            APPEND wa_ASSOCIATIONSET to lt_ASSOCIATIONSET.
    *----------
          endif.
    *------
    
          wa_ENTITYTYPE-name = wa_ENTITYSET-ENTITYTYPE .
    
          REFRESH : lt_key, lt_property,lt_NAVIGATIONPROPERTY.
    
          LOOP AT lt_table_metadata into wa_table_metadata.
            if  wa_table_metadata-KEYFLAG eq 'X'.
    
              wa_key-name = wa_table_metadata-FIELDNAME.
              APPEND wa_key to lt_key.
            endif.
    
            wa_property-NAME = wa_table_metadata-FIELDNAME.
            CONCATENATE ls_TABLE_HEADER-TABNAME '-' wa_table_metadata-FIELDNAME
                   into lv_absolute_field_name.
            lo_type_desc = cl_abap_typedescr=> describe_by_name( lv_absolute_field_name ).
            ls_edm_type_info = /iwbep/cl_mgw_med_edm_util=> get_edm_type_from_ddic_type( lo_type_desc ).
            wa_property-TYPE = ls_edm_type_info-core_type.
            wa_property-NULLABLE = lc_true.
    
            wa_property-MAXLENGTH = wa_table_metadata-OUTPUTLEN.
            wa_property-SAP_LABEL = wa_table_metadata-FIELDTEXT.
            if wa_table_metadata-KEYFLAG eq 'X'.
              wa_property-SAP_CREATABLE = lc_true.
              wa_property-SAP_UPDATABLE = lc_true.
            else.
              wa_property-SAP_CREATABLE = lc_false.
              wa_property-SAP_UPDATABLE = lc_false.
            endif.
            wa_property-SAP_SORTABLE = lc_false.
            wa_property-SAP_FILTERABLE = lc_false.
            APPEND wa_property to lt_property.
          ENDLOOP.
    *-----
          if wa_CHECKTABLES-CHECKTABLE is not INITIAL and wa_CHECKTABLES-DIRECTION eq '> '.
    *    wa_NAVIGATIONPROPERTY-NAME = wa_CHECKTABLES-tabname.
    *    CONCATENATE 'Nav' wa_CHECKTABLES-CHECKTABLE into wa_NAVIGATIONPROPERTY-NAME.
    
    *    wa_NAVIGATIONPROPERTY-RELATIONSHIP = wa_ASSOCIATIONSET-ASSOCIATION .
            wa_NAVIGATIONPROPERTY-FROMROLE = wa_CHECKTABLES-TABNAME.
            wa_NAVIGATIONPROPERTY-TOROLE = wa_CHECKTABLES-CHECKTABLE.
            CONCATENATE lv_namespace_with_dot wa_NAVIGATIONPROPERTY-TOROLE 'to' wa_NAVIGATIONPROPERTY-FROMROLE into wa_NAVIGATIONPROPERTY-RELATIONSHIP.
            CONCATENATE 'Nav' wa_NAVIGATIONPROPERTY-FROMROLE 'to' wa_NAVIGATIONPROPERTY-TOROLE into wa_NAVIGATIONPROPERTY-NAME.
            APPEND wa_NAVIGATIONPROPERTY to lt_NAVIGATIONPROPERTY.
          else.
    
            LOOP AT lt_CHECKTABLES_distinct into wa_CHECKTABLES_NAV
              WHERE CHECKTABLE eq wa_CHECKTABLES-tabname .
    
    *      CONCATENATE lv_namespace wa_CHECKTABLES_NAV-CHECKTABLE 'to' wa_CHECKTABLES_NAV-tabname into wa_NAVIGATIONPROPERTY-RELATIONSHIP.
    *    wa_NAVIGATIONPROPERTY-RELATIONSHIP = wa_ASSOCIATIONSET-ASSOCIATION .
              wa_NAVIGATIONPROPERTY-FROMROLE = wa_CHECKTABLES_NAV-CHECKTABLE.
              wa_NAVIGATIONPROPERTY-TOROLE = wa_CHECKTABLES_NAV-TABNAME.
    *      CONCATENATE lv_namespace_with_dot wa_NAVIGATIONPROPERTY-TOROLE 'to' wa_NAVIGATIONPROPERTY-FROMROLE into wa_NAVIGATIONPROPERTY-RELATIONSHIP.
    * Note that this one is different as association name should be the same for "to" and "from" navigation.
              CONCATENATE lv_namespace_with_dot  wa_NAVIGATIONPROPERTY-FROMROLE 'to' wa_NAVIGATIONPROPERTY-TOROLE into wa_NAVIGATIONPROPERTY-RELATIONSHIP.
              CONCATENATE 'Nav' wa_NAVIGATIONPROPERTY-FROMROLE 'to' wa_NAVIGATIONPROPERTY-TOROLE into wa_NAVIGATIONPROPERTY-NAME.
    
              APPEND wa_NAVIGATIONPROPERTY to lt_NAVIGATIONPROPERTY.
            ENDLOOP.
          endif.
    *-----
          REFRESH : lt_end.
          if wa_CHECKTABLES-CHECKTABLE is not INITIAL.
            CONCATENATE lv_namespace_with_dot wa_CHECKTABLES-CHECKTABLE into wa_end-type .
    
            wa_end-role = wa_CHECKTABLES-CHECKTABLE .
            wa_end-multiplicity = wa_CHECKTABLES-CARDLEFT.
            APPEND wa_end to lt_end.
    
            CONCATENATE lv_namespace_with_dot wa_CHECKTABLES-tabname into wa_end-type .
            wa_end-role = wa_CHECKTABLES-tabname .
            if wa_CHECKTABLES-CARD eq '0' or wa_CHECKTABLES-CARD eq '1'.
              wa_end-multiplicity = wa_CHECKTABLES-CARD.
            else.
              wa_end-multiplicity = '*'.
            endif.
            APPEND wa_end to lt_end.
    
            wa_ASSOCIATION_T-ASSOCIATION = lt_end.
            CONCATENATE wa_CHECKTABLES-CHECKTABLE 'to' wa_CHECKTABLES-tabname into wa_ASSOCIATION_T-NAME.
    *    wa_ASSOCIATION_T-NAME = wa_ASSOCIATIONSET-ASSOCIATION.
            APPEND wa_ASSOCIATION_T to lt_ASSOCIATION_T.
          endif.
    *-----
          if lv_already_processed ne 'X'.
            wa_ENTITYTYPE-key = lt_key.
            wa_ENTITYTYPE-property_t = lt_property.
            wa_ENTITYTYPE-NAVIGATIONPROPERTY_T = lt_NAVIGATIONPROPERTY.
            APPEND wa_ENTITYTYPE to lt_ENTITYTYPE.
          endif.
    
        ENDLOOP.
    
        es_data_model-ENTITYCONTAINER-ENTITYSET_T = lt_ENTITYSET.
        es_data_model-ENTITYCONTAINER-ASSOCIATIONSET_T = lt_ASSOCIATIONSET.
        es_data_model-ENTITYTYPE_T = lt_ENTITYTYPE.
        es_data_model-ASSOCIATION_T = lt_ASSOCIATION_T.
        es_data_model-namespace = i_namespace.
      ENDMETHOD.                    "prepare_data_model
    
      METHOD get_table_metadata.
        "IMPORTING i_tabname type DD02L-TABNAME
        "EXPORTING es_TABLE_HEADER type X030L
        "          et_table_metadata type DFIES_TABLE.
        DATA : lv_TABLE_TYPE TYPE DD02V-TABCLASS.
        DATA : lv_table type DDOBJNAME.
    
        lv_table = i_tabname.
    
        CALL FUNCTION 'DDIF_FIELDINFO_GET'
          EXPORTING
            TABNAME        = lv_table
          IMPORTING
            X030L_WA       = es_TABLE_HEADER
            DDOBJTYPE      = lv_TABLE_TYPE
    *       DFIES_WA       =
    *       LINES_DESCR    =
          TABLES
            DFIES_TAB      = et_table_metadata
    *       FIXED_VALUES   =
          EXCEPTIONS
            NOT_FOUND      = 1
            INTERNAL_ERROR = 2
            OTHERS         = 3.
        IF SY-SUBRC < >  0.
    *   handle it.
        ENDIF.
      ENDMETHOD.                    "get_table_metadata
    
    ENDCLASS.                    "lcl_edmx_generate_utility
    
    *> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    START-OF-SELECTION.
      DATA : gv_xml_xstring TYPE xstring.
      DATA : gv_file_name TYPE string.
      CONCATENATE 'z_edmx_' p_table '_file.xml' into gv_file_name.
      gv_xml_xstring = lcl_edmx_generate_utility=> prepare_edmx_xml( i_tabname = p_table
                                                                    i_namespace = p_namsp ).
    
    *  cl_proxy_service=> download_payload(
    *    file_x  = gv_file_name
    *    payload = gv_xml_xstring
    *  ).
    
      /iwfnd/cl_sutil_xml_helper=> xml_download(
        EXPORTING
          iv_xdoc     = gv_xml_xstring
          iv_dialog   = 'X'
        CHANGING
          cv_filename = gv_file_name
      ).
    
    


  • For details on how to import/export edmx/xml file in Eclipse, you can check a few blogs on SCN e.g. Gateway Productivity Accelerator: Hands-On

Results:

  • Run the ABAP program Z_RAM_EDMX_FILE_GENERATE_NEW e.g. for table SPFLI ( Flight Schedule ) as below, It should ask you to select the folder where XML file should be downloaded.


  • Downloaded XML file can now be imported to Eclipse and the graphical modelling add-in should be able to display it ( To adjust the display layout -> right click and Choose "Smart Organic Layout" in Eclipse):


  • You can adjust the model as per your requirement ( e.g. delete entities, properties, navigations that are not needed ) and export the final XML to a local folder. This file can now be used by ABAP developer to generate Model/Service Provider classes in Gateway Service Builder Tool ( Transaction SEGW ).
  • A nice by-product of this utility is that you can use/amend the table relationship diagrams - of any DDIC development - for the purpose of embedding the image in your Design or Technical documents.

Further Checks and Enhancements:

TBD but a few are already mentioned in this post. Also, I converted this program into a BSP/SICF URL so that XML file can be delivered directly to Eclipse using Service URL approach. Due to some reason, Eclipse plug-in did not like this fake service meta-data document. So as of now only File import method is possible. Nevertheless, I might write about direct URL approach as well. There is some value in documenting the failures too.

2 comments:

  1. Hi,

    This is really interesting!
    I tried to run your program but stumbled into issues with few elements missing:
    - class /iwbep/if_mgw_med_odata_types is missing in my system (NW 7.01), it this a must-have since I only want to model SAP tables?
    - DDIC : zram_edmx_namespace, zram_edmx_csdl_schema, zram_edmx_property_t, ...
    - transformation z_ram_edmx_generate_st (which looks like the cornerstone to me)

    Do you plan to make it opensource or not?
    Thanks in advance for your answer.

    Best regards,
    Guillaume

    ReplyDelete
    Replies
    1. Thanks for your comment Guillaume.

      NW Gateway class/methods or not really necessary for the purpose - I just used it in the prototype to convert the data-types to OData types - but that can be done without /iwbep/if_mgw_med_odata_types.

      Custom transformation/related structures (ZRAM*) are required and details are given in : Prototyping an ABAP OData Entity Data Model Generator : Simple Transformation

      Also, I am working on SAP integrated version of : XOData : Online OData Visualizer and Explorer . I guess you are looking for a SAP table explorer? - which is also part of SAP Integrated XOData : see a screenshot from my twitter update

      I'll be providing some further details later on this Blog.

      About open source/licensing, I'm still in development phase and have not really thought about it yet. But as soon as I've SAP integrated version packaged and ready for sharing, I will let you know on twitter/this blog.

      Thanks,
      Ram

      Delete

Info : Comments are reviewed before they are published. SPAMs are rejected.

Copyright