RPG-XML Suite Header  RPG-XML Suite  RPG-XML Suite Overview of  RPG-XML Suite Download  RPG-XML Suite Today! News and Events for  RPG-XML Suite Get support for  RPG-XML Suite Contact us and learn more about  RPG-XML Suite About RPG-XML Suite

Program:  Geocode

 

      //*******************************************************************************************

      // @Descr: This program receives an address from an external program.  That address is then

      //         sent to googlemaps where the latitude and longitude are returned to this program

      //         in an xml stream.  This program then returns the latitude and longitude to the

      //         calling program.

      //

      //         The google service is accessed with a URL string, not with an xml stream.  It

      //         should also be noted that google requires that google maps be used to display

      //         any output and that the application be accessible to the public. See googles

      //         full terms at http://code.google.com/apis/maps/terms.html#section_10_12

      //         The URL for googles geocoding page is:

      //               http://code.google.com/apis/maps/documentation/geocoding/index.html

      //         And finally, the URL for google maps home page is:

      //               http://code.google.com/apis/maps/

      // @Notes:

      //*******************************************************************************************

     H dftactgrp(*no) bnddir('RXSBND')

 

      /copy rxs,RXSCp

 

     D getcoords       PR

     D  #Address                    256a

     D  #longitude                   15a

     D  #latitude                    15a

     D  #accuracy                     1a

     D  #error                      256a

 

     D getcoords       pi

     D  @Address                    256a

     D  @longitude                   15a

     D  @latitude                    15a

     D  @accuracy                     1a

     D  @error                      256a

 

     D allHandler      pr

     D  pType                              value like(RXS_Type)

     D  pXPath                             value like(RXS_XPath)

     D  pData                              value like(RXS_XmlData)

     D  pDataLen                           value like(RXS_Length)

 

     D errHandler      pr

     D  pCurLine                     10i 0 value

     D  pCurCol                      10i 0 value

     D  pErrStr                    1024a   value varying

 

     d gPoint          s             30a

     d gStrPos         s              2  0

     d gEndPos         s              2  0

 

     D gError          ds                  likeds(RXS_Error)

     D ginCfg          ds                  likeds(RXS_GetUriIn) inz

     D grspData        s                   like(RXS_XmlData)

     D grspHttpHdr     s                   like(RXS_XmlData)

 

 

      /free

       monitor;

 

       // Send request to google (using a URL string)

       ginCfg.URI ='http://maps.google.com/maps/geo?' +

                 'q=' + %trim(@address) +

                 '&output=xml&oe=utf8&sensor=false';

       gInCfg.Port = 80;

 

       RXS_getUri(gInCfg: *omit: grspData: gRspHttpHdr);

 

       exsr parse;

       exsr getPoint;

 

       on-error;

         gError = RXS_catchError();

         @Error = gerror;

       endmon;

       *inlr = *on;

 

       //-----------------------------------------------------------------------

       // Setup event handlers that will get called each time an element content

       // or attribute is encountered. Then call the parser with the xml

       // received in on the request.

       //-----------------------------------------------------------------------

       begsr parse;

 

       RXS_allElemContentHandler(%paddr(allHandler));

       RXS_allAttrHandler(%paddr(allHandler));

       RXS_parse(grspData: RXS_VAR: %paddr(errHandler));

 

       endsr;

 

       //-----------------------------------------------------------------------

       // Get the longitude and latitude out of the gpoint variable

       //-----------------------------------------------------------------------

       begsr GetPoint;

 

       gStrPos = 1;

       gEndPos = %scan(',': gpoint:gStrPos);

       @longitude = %subst(gpoint:gStrPos:gEndPos-1);

 

       gStrPos = gEndPos +1;

       gEndPos = %scan(',': gpoint: gStrPos);

       @latitude = %subst(gpoint:gStrPos:(gEndPos-gStrPos));

 

       endsr;

 

      /end-free

 

      //--------------------------------------------------------------------------------------------

      // @Desc: Handle all events based on specifying RXS_allElemContentHandler.

      //        Note that instead of displaying pData's contents in the job log

      //        one could just as easily place that data in a physical file or

      //        display it back to an interactive green screen display.

      //

      // @Notes: There are four events that your program can be notified of through the allHandler

      //         sub procedure and they are passed in the pEvntType parm. An event is triggered

      //         as the parser reads the document top down, left to right (same way you read the

      //         newspaper).  Note that you will only be notified of events you specified before the

      //         call to RXS_parse by using API's RXS_allElemBegHandler, RXS_allElemContentHandler,

      //         RXS_allElemEndHandler, and RXS_allAttrHandler.

      //

      //         The four events and their values (note that these can all be overidden by

      //         changing the RXSCFG file or by doing a temporary override on the RXS_parse command)

      //

      //         Element Begin   = '>'   -- Placed at end of string (i.e. '/elem>')

      //         Element Content = '/'   -- Placed at end of string (i.e. '/elem/')

      //         Element End     = '/>'  -- Placed at end of string (i.e. '/elem/>')

      //         Attribute       = '@'   -- Placed between the elem and attr (i.e. '/elem@attr')

      //

      //         The most common events you will use are Element Content and Attribute simply

      //         because these are the two that provide business data via the pData parm on the

      //         allHandler procedure interface.  Events Element Begin and Element End are very

      //         helpful when you have repeating XML data.  You can then use the Begin and End

      //         events to do a CLEAR and WRITE to a PF record respectively.  Remember that

      //         in-between the Element Begin and Element End events you will be notified of all the

      //         element content, which means that after the CLEAR (i.e. Element Begin event) you

      //         can place data into the PF record until you reach the Element End event at which

      //         time you can do a WRITE of that record because it has now been populated with data.

      //--------------------------------------------------------------------------------------------

     P allHandler      b

     D allHandler      pi

     D  pType                              value like(RXS_Type)

     D  pXPath                             value like(RXS_XPath)

     D  pData                              value like(RXS_XmlData)

     D  pDataLen                           value like(RXS_Length)

      /free

 

       select;

       when pXPath = '/kml/Response/name/';

         @Address = pData;

 

       when pXPath = '/kml/Response/Status/code/';

         @error = pData;

 

       when pXPath = '/kml/Response/Placemark/AddressDetails@Accuracy';

         @Accuracy = pData;

 

       when pXPath = '/kml/Response/Placemark/address/';

         @Address = pData;

 

       when pXPath = '/kml/Response/Placemark/Point/coordinates/';

         gPoint = pData;

 

       endsl;

 

      /end-free

     P                 e

      //--------------------------------------------------------------------------------------------

      // @Desc: If an error occurs this local sub procedure will be called by the parser.

      //--------------------------------------------------------------------------------------------

     P errHandler      B

     D errHandler      PI

     D  pCurLine                     10i 0 value

     D  pCurCol                      10i 0 value

     D  pErrStr                    1024a   value varying

      /free

 

       gError.code = 'GETCOORDS.1';

       gError.severity = 100;

       gError.pgm = 'GETCOORDS.errHandler';

       gError.text =

         'Line:' + %char(pCurLine) +

         ' Column:' + %char(pCurCol) +

         ' ' + pErrStr;

 

      /end-free

     P                 E

 

Program: GetCoords

 

      //*******************************************************************************************

      // @Descr: Simple program that passes a hard-coded address to a program that

      //         returns latitude and longitude, which are then written to the joblog.

      //         If the address could not be processed an error message is written to the

      //         joblog instead.

      // @Notes:

      //*******************************************************************************************

 

     H dftactgrp(*no) bnddir('RXSBND')  OPTION(*NODEBUGIO)

 

      /copy rxs,RXSCp

 

     D getcoords       PR                  ExtPgm('GETCOORDS')

     D  #Address                    256a

     D  #longitude                   15a

     D  #latitude                    15a

     D  #accuracy                     1a

     D  #error                      256a

 

     d formatAddress   PR           256a

     d  pAddress                    256a   value

 

     D fndRpl          pr

     D  pString                   65535a   varying

     D  pFrom                        10a   value varying

     D  pTo                          10a   value varying

 

     d  gAddress       s            256a

     d  gLongitude     s             15a

     d  gLatitude      s             15a

     d  gAccuracy      s              1a

     d  gError         s            256a

 

      /free

 

       // We load the address to look up below. Google requires that the address

       // be passed in with no blanks, all blanks in the address are to be replaced

       // with plus signs. So I call a subprocedure that replaces the imbedded

       // blanks in the address with plus signs.

       gAddress = '10 civic center plaza, mankato, mn';

       gAddress = formatAddress(gAddress);

 

       clear gLongitude;

       clear gLatitude;

       clear gAccuracy;

       clear gError;

 

       getcoords(gAddress: gLongitude: gLatitude: gAccuracy: gError);

 

       if gError = '200';

         // success

         RXS_log(RXS_INFO: %trim(gAddress));

         RXS_log(RXS_INFO: 'Latitude = ' + gLatitude);

         RXS_log(RXS_INFO: 'Longitude= ' + gLongitude);

        else;

         // error

         RXS_log(RXS_INFO: 'Coordinates could not be retrieved.');

       ENDIF;

 

       *inlr = *on;

       Return;

      /end-free

 

      *===================================================================

      * Replace any blanks in the address with plus signs

      *===================================================================

     P formatAddress   B

     d formatAddress   pi           256a

     d   paddress                   256a   value

     D from            s             10a   dim(10) varying

     D to              s             10a   dim(10) varying

     D str             s          65535a   varying

 

      /free

 

       // we trim pAddress before doing the find/replace to remove any

       // leading or trailing blanks. Since str is a varying length

       // field, when we trim pAddress into it, str will only be as

       // long as the address we want to process.

       str = %trim(pAddress);

 

       fndRpl(str: ' ': '+');

       pAddress = str;

 

       return pAddress;

 

      /end-free

     P                 E

 

      *===================================================================

      * Generic Scan/Replace routine

      *===================================================================

     P fndRpl          b

     D fndRpl          pi

     D  pString                   65535a   varying

     D  pFrom                        10a   value varying

     D  pTo                          10a   value varying

 

     D pos             s             10i 0

     D newStr          s            256a   varying

     D toLen           s             10i 0

      /free

 

       newStr = pString;

       pos = %scan(pFrom: newStr);

       dow pos > *zero;

         newStr = %replace(pTo: newStr: pos: %len(pFrom));

         toLen = %len(pTo);

         if pos + toLen <= %len(newStr);

           pos = %scan(pFrom: newStr: pos + toLen);

         else;

           leave;

         endif;

       enddo;

 

       pString = newStr;

 

      /end-free

     P                 e

Sample output:

                                                                                               

    10 Civic Center Plaza, Mankato, MN 56001, USA                        

    Latitude = 44.1640494                                                

    Longitude= -94.0050065