GPS like tool in SAP using Google Map API

We saw how we can get the latitude and longitude of any address using Google Map API. Adding to that learning, in this post, we would learn how to get the distance between two addresses. We would also see how we can derive turn by turn directions between two given addresses. To add more to the fun, we would also open a browser from SAP and display the route between two points on the map.

Do you think, this is interesting?

In short, this tool would act like a GPS in SAP, which would help you get the Coordinates (Latitudes/Longitudes), Route and Map with complete direction.

Before we check, how it can be done, let us first see, what we are talking about.

I. First radio button: Coordinates & Distance

We get the Coordinates of two addresses and also the distance between them.

II. Second Radio button: Turn by turn route

The tool would provide you the complete break-up of the route from the source to the destination address. It would also provide you with multiple routes if available.

II. Let’s check the third radio button which says ‘Display Map‘.

As requested, this GPS Tool would display the map along with the routes in a Web Browser. Check this out.

Did you like it?

You can use the code snippet provided at the end of this article and try it yourself. The code provided here would work as it is. The concept was already explained in our earlier post ‘Get Latitude and Longitude of any place using Google Map API in SAP’.

For the three output options, we need to call three APIs. As explained in the earlier article, we concatenate the strings with source and destination address, Latitudes and Longitudes etc to complete the API URL and get the XML data. Reading through the XML data and pinpointing the needed information is the trick which we have already learned.

a) GeoCode API String for Coordinates:

* Prepare the url of the GeoCode API
  CONCATENATE
    'http://maps.google.com/maps/api/geocode/xml?address='
    lv_address
    INTO lv_http_url .

b) Distance Matrix API String for retrieving the distance between Coordinates:

* Prepare the url for the DistanceMatrix API using From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/distancematrix/xml?origins='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f ','
    '&destinations=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .

c) Directions API String to trace the route on the Map:

* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/directions/xml?origin='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f
    '&destination=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .
where:
lv_address               = From/To address
<fs_dest>-place_f = From address
<fs_dest>-lat_f      = From address latitude
<fs_dest>-lng_f     = From address longitude
<fs_dest>-place_t = To address
<fs_dest>-lat_t      = To address latitude
<fs_dest>-lng_t      = To address longitude

Once you have the correct API URL, use this cl_http_client class and create_by_url method to get the detailed information.

Get client from url
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_http_url
IMPORTING
client = p_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.

Please go through the detailed code to check how it works. There might be better ways to read these APIs and XML data but we just wanted to show the possibilities. You can explore more and figure out the best way for you.

If you find any difficulty in understanding the code or concept, please do write to us or leave your question in the comment section. We would surely respond.

If you have doubt whether this tool would work for Non-India address. Be rest assured, it works for any address. Check the output for the address in the USA.

*-----------------------------------------------------------------------
* Author :   SAPSPOT (www.sapspot.com)
* Title  :     Get Latitude and Longitude of a place from Google API
*               Get distance between two addresses
*               Show the turn by turn route of two addresses
*               Show route in map in a browser
*-----------------------------------------------------------------------
* Change History :
* Author         DATE       REQUEST#     DESCRIPTION
*--------------- ---------- ----------- -------------------------------
* SAPSPOT  05/27/2016              Intial Development
*-----------------------------------------------------------------------
REPORT  zsapspot_gps_google_api NO STANDARD PAGE HEADING
                                   LINE-COUNT 132.
*&---------------------------------------------------------------------*
*& TYPE-POOLS
*&---------------------------------------------------------------------*
TYPE-POOLS: truxs, slis.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-t01.
PARAMETERS : p_add_f TYPE c LENGTH 50,
             p_add_t TYPE c LENGTH 50.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE text-t02.
PARAMETERS:
  p_alv   RADIOBUTTON GROUP spot,
  p_route RADIOBUTTON GROUP spot,
  p_map   RADIOBUTTON GROUP spot.
SELECTION-SCREEN END OF BLOCK b2.
 
*&---------------------------------------------------------------------*
*& Types and Data
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_dest,
         place_f TYPE c LENGTH 50,    " From Place
         place_t TYPE c LENGTH 50,    " To Place
         lat_f   TYPE c LENGTH 20,    " From Latitude
         lng_f   TYPE c LENGTH 20,    " From Longitude
         lat_t   TYPE c LENGTH 20,    " To Latitude
         lng_t   TYPE c LENGTH 20,    " To Longitude
         dis     TYPE c LENGTH 30,    " Distance
       END OF ty_dest,
 
       BEGIN OF ty_route,
         route_n TYPE c LENGTH 255,   " Start of New Route
         summary TYPE c LENGTH 120,   " Route Summary
         step    TYPE syst_tabix,     " Turn step
         ins     TYPE c LENGTH 255,   " Instruction
         dis     TYPE c LENGTH 20,    " Distance
       END OF ty_route.
 
TYPES: t_ty_route TYPE TABLE OF ty_route.
 
DATA:
  gt_dest  TYPE STANDARD TABLE OF ty_dest,
  gt_route TYPE STANDARD TABLE OF ty_route.
 
FIELD-SYMBOLS:
  <fs_dest> TYPE ty_dest.
 
*&---------------------------------------------------------------------*
*& Start of Selection
*&---------------------------------------------------------------------*
START-OF-SELECTION .
 
* Get longitude and latitude of From Address
  PERFORM get_long_lat USING p_add_f.
 
* Get longitude and latitude of To Address
  PERFORM get_long_lat USING p_add_t.
 
*&---------------------------------------------------------------------*
*& End of Selection
*&---------------------------------------------------------------------*
END-OF-SELECTION .
 
* Get distance between two address
  PERFORM measure_distance.
 
* Get detailed turn by turn address
  PERFORM turn_by_turn_route.
 
* Show the output
  PERFORM show_output.
************************************************************************
*&---------------------------------------------------------------------*
*& Sub Routines
*&---------------------------------------------------------------------*
************************************************************************
FORM get_long_lat USING lv_address TYPE char50.
 
  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.
 
* Creation of new IF_HTTP_Client object
  PERFORM create_http_client USING lv_address
                             CHANGING lv_http_client .
 
* Request and Get
  PERFORM http_client_request_get_method USING lv_http_client.
 
* Send the request
  PERFORM http_client_send USING lv_http_client.
 
* Retrieve the result
  PERFORM http_client_receive USING lv_http_client CHANGING lv_content.
 
* Get the actual coordinate using the content string
  PERFORM get_coordinates USING lv_content lv_address.
 
 
ENDFORM. " get_long_lat
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT
*&---------------------------------------------------------------------*
*       Create HTTP Client
*----------------------------------------------------------------------*
FORM create_http_client USING    lv_address TYPE char50
                        CHANGING p_http_client TYPE REF TO if_http_client.
 
  DATA: lv_http_url TYPE string.
 
* Prepare the url of the GeoCode API
  CONCATENATE
    'http://maps.google.com/maps/api/geocode/xml?address='
    lv_address
    INTO lv_http_url .
 
* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_REQUEST_GET_METHOD
*&---------------------------------------------------------------------*
*       Request and Get Method
*----------------------------------------------------------------------*
FORM http_client_request_get_method USING p_http_client TYPE REF TO if_http_client..
* Request and Get
  p_http_client->request->set_header_field( name = '~request_method' value = 'GET' ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_SEND
*&---------------------------------------------------------------------*
*       Send request
*----------------------------------------------------------------------*
FORM http_client_send USING p_http_client TYPE REF TO if_http_client.
* Send the request
  p_http_client->send( ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_RECEIVE
*&---------------------------------------------------------------------*
*       Get the string content
*----------------------------------------------------------------------*
FORM http_client_receive  USING    p_http_client TYPE REF TO if_http_client
                          CHANGING p_p_content   TYPE string.
* Reterive the result
  CALL METHOD p_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      OTHERS                     = 4.
*  CALL METHOD p_http_client->response->get_cdata(
*    RECEIVING
*      data   = p_p_content " Character data
*    EXCEPTIONS
*      OTHERS = 1 ).
 
  p_p_content = p_http_client->response->get_cdata( ).
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_COORDINATES
*&---------------------------------------------------------------------*
*       Get Latitute Longitude Coordinate
*----------------------------------------------------------------------*
FORM get_coordinates  USING    p_p_content TYPE string
                               lv_address  TYPE char50.
* Local data declaration
  DATA: lv_url  TYPE c LENGTH 255,
        ls_dest TYPE ty_dest,
        moff    TYPE syst-tabix,
        moff1   TYPE syst-tabix,
        lv_len  TYPE syst-tabix,
        lv_lat  TYPE c LENGTH 20,
        lv_lng  TYPE c LENGTH 20.
 
* Field symbol
  FIELD-SYMBOLS:
        <lfs_dest> TYPE ty_dest.
*&---------------------------------------------------------------------*
*& Processing string
*&---------------------------------------------------------------------*
  DO .
* Find <location> text in the content string
    FIND '<location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
 
    IF sy-subrc = 0 .
* <location> is a 10 character string, hence adding 10
      moff = moff + 10 .
 
* Find closing tag </location> text in the content string
      FIND '</location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <location> and </location>
      lv_len = moff1 - moff .
 
* We have seen the API string contet, so we know <lat> </lat> <lng> </lng> are there between
* <location> and </location>
*--------------------------------------------------------------------*
* ---------------Find latitude
*--------------------------------------------------------------------*
* Find string <lat>
      FIND '<lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
* <lat> is a 5 character string, hence adding 5
        moff = moff + 5 .
 
* Find closing tag </lat> text in the content string
        FIND '</lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <lat> and </lat>
        lv_len = moff1 - moff .
 
* Characters between <lat> </lat> will have the latitude coorniate
        lv_lat = p_p_content+moff(lv_len) .
 
* From place address
        ls_dest-place_f = lv_address .
 
* Keep latitude in structure
        ls_dest-lat_f = lv_lat.
 
      ENDIF.
 
*--------------------------------------------------------------------*
* ---------------Find longitude
*--------------------------------------------------------------------*
* Find string <lng>
      FIND '<lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
 
* <lng> is a 5 character string, hence adding 5
        moff = moff + 5 .
 
* Find closing tag </lng> text in the content string
        FIND '</lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <lng> and </lng>
        lv_len = moff1 - moff .
 
* Characters between <lng> </lng> will have the latitude coorniate
        lv_lng = p_p_content+moff(lv_len) .
 
* Keep longitude in structure
        ls_dest-lng_f = lv_lng.
 
      ENDIF.
    ELSE.
 
      EXIT.
 
    ENDIF.
 
  ENDDO .
 
  IF gt_dest[] IS INITIAL.
* This part would trigger for From Latitude and Longitude
* Put in internal table to display later
    APPEND ls_dest TO gt_dest.
    CLEAR:ls_dest .
 
  ELSE.
 
* This part would trigger for To Latitude and Longitude
    READ TABLE gt_dest ASSIGNING <lfs_dest> INDEX 1.
    IF sy-subrc EQ 0.
      <lfs_dest>-place_t = lv_address.
      <lfs_dest>-lat_t = ls_dest-lat_f.
      <lfs_dest>-lng_t = ls_dest-lng_f.
    ENDIF.
 
  ENDIF.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_LAT_LONGITUDE
*&---------------------------------------------------------------------*
*       Display Latitude and Longitude
*----------------------------------------------------------------------*
FORM display_lat_longitude .
 
  DATA:
    lr_alv       TYPE REF TO cl_salv_table,
    lr_columns   TYPE REF TO cl_salv_columns_table,
    lr_column    TYPE REF TO cl_salv_column,
    lr_functions TYPE REF TO cl_salv_functions_list,
    lr_display   TYPE REF TO cl_salv_display_settings,
    lr_layout    TYPE REF TO cl_salv_layout,
    ls_key       TYPE salv_s_layout_key,
    lr_sorts     TYPE REF TO cl_salv_sorts.
 
  " Check to make sure the internal table has data.
  IF lines( gt_dest ) > 0.
 
    TRY.
*       Create ALV instance
*       Use CALL METHOD since this is a static method
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = gt_dest.
 
*       Get functions object and then set all the functions to be allowed
        lr_functions = lr_alv->get_functions( ).
        lr_functions->set_all( ).
 
        lr_columns = lr_alv->get_columns( ).
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'PLACE_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Place Name'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LAT_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Latitude'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LNG_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'From Longitude'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'PLACE_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Place Name'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LAT_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Latitude'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LNG_T'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'To Longitude'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'DIS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Distance between From & To Address'.
        lr_columns->set_optimize( ).
 
*       Set sort column
        lr_sorts = lr_alv->get_sorts( ).
        lr_sorts->clear( ).
 
*       This code is to get the layout, save the layout and display the layout
        lr_layout = lr_alv->get_layout( ).
        ls_key-report = sy-repid.
        lr_layout->set_key( ls_key ).
        lr_layout->set_default( ' ' ).
        lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).
 
        lr_display = lr_alv->get_display_settings( ).
        lr_display->set_striped_pattern( cl_salv_display_settings=>true ).
 
*       Now display the report as an ALV grid
        lr_alv->display( ).
 
      CATCH cx_salv_msg.
        WRITE: 'Error displaying grid CX_SALV_MSG!'(001).
 
      CATCH cx_salv_not_found.
        WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'(002).
 
      CATCH cx_salv_data_error.
        WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'(003).
 
      CATCH cx_salv_existing.
        WRITE: 'Error displaying grid CX_SALV_EXISTING!'(004).
 
    ENDTRY.
 
  ELSE.
    MESSAGE 'No data to display' TYPE 'I'.
    LEAVE LIST-PROCESSING.
 
  ENDIF.
 
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  MEASURE_DISTANCE
*&---------------------------------------------------------------------*
*       Get distance between the from and to address
*----------------------------------------------------------------------*
FORM measure_distance .
 
  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.
 
  LOOP AT gt_dest ASSIGNING <fs_dest>.
 
* Creation of new IF_HTTP_Client object
    PERFORM create_http_client_dist CHANGING lv_http_client .
 
* Request and Get
    PERFORM http_client_request_get_method USING lv_http_client.
 
* Send the request
    PERFORM http_client_send USING lv_http_client.
 
* Retrieve the result
    PERFORM http_client_receive USING lv_http_client CHANGING lv_content.
 
* Get the actual coordinate using the content string
    PERFORM get_coordinates_dist USING lv_content.
 
  ENDLOOP.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT_DIST
*&---------------------------------------------------------------------*
*       *       Create HTTP Client
*----------------------------------------------------------------------*
FORM create_http_client_dist  CHANGING p_http_client TYPE REF TO if_http_client.
 
  DATA: lv_http_url TYPE string.
 
* Prepare the url for the DistanceMatrix API From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/distancematrix/xml?origins='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f ','
    '&destinations=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
  '&alternatives=' 'true'
    INTO lv_http_url .
 
* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_COORDINATES_DIST
*&---------------------------------------------------------------------*
*       Get Latitute Longitude Coordinate
*----------------------------------------------------------------------*
FORM get_coordinates_dist  USING    p_p_content TYPE string.
 
* Local data declaration
  DATA: lv_url  TYPE c LENGTH 255,
        ls_dest TYPE ty_dest,
        moff    TYPE syst-tabix,
        moff1   TYPE syst-tabix,
        lv_len  TYPE syst-tabix,
        lv_lat  TYPE c LENGTH 20,
        lv_lng  TYPE c LENGTH 20.
 
* Field symbol
  FIELD-SYMBOLS:
        <lfs_dest> TYPE ty_dest.
*&---------------------------------------------------------------------*
*& Processing string
*&---------------------------------------------------------------------*
  DO .
* Find <distance> text in the content string
    FIND '<distance>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
    IF sy-subrc = 0 .
 
* <distance> is a 10 character string, hence adding 10
      moff = moff + 10 .
 
* Find closing tag </distance> text in the content string
      FIND '</distance>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
** Find the length of string between tag <distance> and </distance>
*      lv_len = moff1 - moff .
 
* We have seen the API string contet, so we know <text> </text> are there between
* <distance> and </distance>
      FIND '<text>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
* <text> is a 6 character string, hence adding 6
        moff = moff + 6 .
 
* Find closing tag </text> text in the content string
        FIND '</text>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <text> and </text>
        lv_len = moff1 - moff .
 
* Characters between <text> </text> will have the distance
        <fs_dest>-dis = p_p_content+moff(lv_len).
 
* Get one distance and exit
        EXIT.
 
      ENDIF.
 
    ELSE.
      EXIT.
    ENDIF.
  ENDDO .
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_OUTPUT
*&---------------------------------------------------------------------*
*       Show output
*----------------------------------------------------------------------*
FORM show_output .
 
  IF p_alv IS NOT INITIAL.
 
* Show Latitute, Longitude and Distance
    PERFORM display_lat_longitude.
 
  ELSEIF p_route IS NOT INITIAL.
 
* Show the complete break down of driving route
    PERFORM display_turn_by_turn_route.
 
  ELSEIF p_map IS NOT INITIAL.
 
* Show direction in map
    PERFORM show_map.
 
  ENDIF.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  TURN_BY_TURN_ROUTE
*&---------------------------------------------------------------------*
*       Get turn by turn ROUTE
*----------------------------------------------------------------------*
FORM turn_by_turn_route .
 
  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string,
    lv_xstring     TYPE xstring,
    li_xml_table   TYPE TABLE OF smum_xmltb.
 
  IF p_route IS NOT INITIAL.
 
    LOOP AT gt_dest ASSIGNING <fs_dest>.
 
* Creation of new IF_HTTP_Client object
      PERFORM create_http_client_direction CHANGING lv_http_client .
 
* Request and Get
      PERFORM http_client_request_get_method USING lv_http_client.
 
* Send the request
      PERFORM http_client_send USING lv_http_client.
 
* Retrieve the result
      PERFORM http_client_receive USING lv_http_client CHANGING lv_content.
 
** Get the actual coordinate using the content string
*      PERFORM get_coordinates_dist USING lv_content.
 
* Convert String to XString
      PERFORM convert_string_to_xstring USING lv_content CHANGING lv_xstring.
 
* Parse XML document into a table structure
      PERFORM parse_xml_to_table USING lv_xstring CHANGING li_xml_table.
 
* Clean XML file
      PERFORM clean_xml_data USING li_xml_table.
    ENDLOOP.
 
  ENDIF.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CONVERT_STRING_TO_XSTRING
*&---------------------------------------------------------------------*
*       Convert sting to xstring
*----------------------------------------------------------------------*
FORM convert_string_to_xstring USING p_p_content TYPE string
                               CHANGING p_p_xstring TYPE xstring.
 
  CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
    EXPORTING
      text   = p_p_content
    IMPORTING
      buffer = p_p_xstring
    EXCEPTIONS
      failed = 1
      OTHERS = 2.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  PARSE_XML_TO_TABLE
*&---------------------------------------------------------------------*
*       Parse XML docment into a table structure
*----------------------------------------------------------------------*
FORM parse_xml_to_table  USING    p_p_xstring    TYPE xstring
                         CHANGING p_li_xml_table TYPE hrpayfr_t_smum_xmltb.
  DATA:
      li_return    TYPE TABLE OF bapiret2.
 
  CALL FUNCTION 'SMUM_XML_PARSE'
    EXPORTING
      xml_input = p_p_xstring
    TABLES
      xml_table = p_li_xml_table
      return    = li_return.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT_DIRECTION
*&---------------------------------------------------------------------*
*       Get Direction API
*----------------------------------------------------------------------*
FORM create_http_client_direction  CHANGING p_http_client TYPE REF TO if_http_client.
 
  DATA: lv_http_url TYPE string.
 
* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'http://maps.googleapis.com/maps/api/directions/xml?origin='
    <fs_dest>-place_f '|' <fs_dest>-lat_f ',' <fs_dest>-lng_f
    '&destination=' <fs_dest>-place_t '|' <fs_dest>-lat_t ',' <fs_dest>-lng_t
    '&alternatives=' 'true'
    INTO lv_http_url .
 
  CONDENSE lv_http_url.
 
* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CLEAN_XML_DATA
*&---------------------------------------------------------------------*
*       Clean XML data to cleaner format
*----------------------------------------------------------------------*
FORM clean_xml_data  USING    p_li_xml_table TYPE hrpayfr_t_smum_xmltb.
  DATA:
    ls_xml  TYPE smum_xmltb,
    ls_path TYPE ty_route.
 
* Deleting time mentioned in the XML. If you want time, you need to
* keep this and manipulate later
  DELETE p_li_xml_table WHERE cvalue CS 'min'.
 
* Remove sub total for partial route. If you want time, you need to
* keep this and manipulate later
  DELETE p_li_xml_table WHERE
  hier = '5' AND
  type = 'V' AND
  cname = 'text'.
 
* Reading the XML data
  LOOP AT p_li_xml_table INTO ls_xml.
 
    AT FIRST.
* First step is new route by default
      ls_path-route_n = abap_true.
    ENDAT.
 
* Remove the XML format tag codes
    REPLACE ALL OCCURRENCES OF '<b>' IN ls_xml-cvalue WITH space.
    REPLACE ALL OCCURRENCES OF '</b>' IN ls_xml-cvalue WITH space.
 
* Remove the XML format tag codes
    REPLACE ALL OCCURRENCES OF '<div style="font-size:0.9em">' IN ls_xml-cvalue WITH '.'.
    REPLACE ALL OCCURRENCES OF '</div>' IN ls_xml-cvalue WITH space.
 
* Check the name
    CASE ls_xml-cname.
 
* Get the summary of the route
      WHEN 'summary'.
        ls_path-summary = ls_xml-cvalue.
 
* Driving instruction
      WHEN 'html_instructions'.
        ls_path-ins = ls_xml-cvalue.
 
* Text would have the distance and unit
      WHEN 'text'.
        ls_path-dis = ls_xml-cvalue.
 
* Copyrights means, start of new path
      WHEN 'copyrights'.
 
        ls_path-route_n = 'X'.
        CLEAR ls_path-step.
 
      WHEN OTHERS.
* do nothing
 
    ENDCASE.
 
* If there is some data, populate the route table
    IF    ls_path-ins     IS NOT INITIAL
      AND ls_path-dis     IS NOT INITIAL.
      ls_path-step = ls_path-step + 1.
 
* This will have the route details
      APPEND ls_path TO gt_route.
 
      CLEAR: ls_path-ins, ls_path-dis, ls_path-route_n, ls_path-summary.
 
    ENDIF.
 
    CLEAR: ls_xml.
 
  ENDLOOP.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_TURN_BY_TURN_ROUTE
*&---------------------------------------------------------------------*
*       Display Turn by Turn route
*----------------------------------------------------------------------*
FORM display_turn_by_turn_route .
 
  DATA:
    lr_alv       TYPE REF TO cl_salv_table,
    lr_columns   TYPE REF TO cl_salv_columns_table,
    lr_column    TYPE REF TO cl_salv_column,
    lr_functions TYPE REF TO cl_salv_functions_list,
    lr_display   TYPE REF TO cl_salv_display_settings,
    lr_layout    TYPE REF TO cl_salv_layout,
    ls_key       TYPE salv_s_layout_key,
    lr_sorts     TYPE REF TO cl_salv_sorts.
 
  " Check to make sure the internal table has data.
  IF lines( gt_route ) > 0.
 
    TRY.
*       Create ALV instance
*       Use CALL METHOD since this is a static method
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = gt_route.
 
*       Get functions object and then set all the functions to be allowed
        lr_functions = lr_alv->get_functions( ).
        lr_functions->set_all( ).
 
        lr_columns = lr_alv->get_columns( ).
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'ROUTE_N'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'New Route Indicator'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'SUMMARY'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Via'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'STEP'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Important Turns'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'INS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Instructions'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'DIS'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Distance'.
 
        lr_columns->set_optimize( ).
 
*       Set sort column
        lr_sorts = lr_alv->get_sorts( ).
        lr_sorts->clear( ).
 
*       This code is to get the layout, save the layout and display the layout
        lr_layout = lr_alv->get_layout( ).
        ls_key-report = sy-repid.
        lr_layout->set_key( ls_key ).
        lr_layout->set_default( ' ' ).
        lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).
 
        lr_display = lr_alv->get_display_settings( ).
        lr_display->set_striped_pattern( cl_salv_display_settings=>true ).
 
*       Now display the report as an ALV grid
        lr_alv->display( ).
 
      CATCH cx_salv_msg.
        WRITE: 'Error displaying grid CX_SALV_MSG!'(001).
 
      CATCH cx_salv_not_found.
        WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'(002).
 
      CATCH cx_salv_data_error.
        WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'(003).
 
      CATCH cx_salv_existing.
        WRITE: 'Error displaying grid CX_SALV_EXISTING!'(004).
 
    ENDTRY.
 
  ELSE.
    MESSAGE 'No route data to display' TYPE 'I'.
    LEAVE LIST-PROCESSING.
 
  ENDIF.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  SHOW_MAP
*&---------------------------------------------------------------------*
*       Show direction on the map
*----------------------------------------------------------------------*
FORM show_map .
 
  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.
 
  LOOP AT gt_dest ASSIGNING <fs_dest>.
 
* Call Browser
    PERFORM call_browser.
 
    EXIT.
  ENDLOOP.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  CALL_BROWSER
*&---------------------------------------------------------------------*
*       Route map
*----------------------------------------------------------------------*
FORM call_browser.
 
  DATA: lv_url TYPE c LENGTH 255.
 
* Prepare the url for Directions API for the From Address Coordinates and To Address Coordinates
  CONCATENATE
    'https://www.google.co.in/maps/dir/'
    <fs_dest>-lat_f ',' <fs_dest>-lng_f '/'
    <fs_dest>-lat_t ',' <fs_dest>-lng_t
    INTO lv_url .
 
* Condense the text
  CONDENSE lv_url.
 
* Open the route in browser
  CALL FUNCTION 'CALL_BROWSER'
    EXPORTING
      url                    = lv_url
    EXCEPTIONS
      frontend_not_supported = 1
      frontend_error         = 2
      prog_not_found         = 3
      no_batch               = 4
      unspecified_error      = 5
      OTHERS                 = 6.
ENDFORM.