MapQuest Developer Blog

Archives for John Fronckowiak

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 7 - Address Book Integration

    There's nothing that makes you so aware of the improvisation of human existence as a song unfinished. Or an old address book. - Carson McCullers

    In Part 1 I showed you how to get started with the MapQuest Advantage API by getting a developer key. In Part 2 I put that key to use by providing access to a basic map in the Map It! widget. Part 3 showed you how to incorporate basic geocoding. In Part 4 I discussed more advanced geocoding topics - including handling multiple matches and specifying geocode search options. Part 5 discussed adding widget options including the default zoom level, specifying point of interest icons, and the default map type. Part 6 discussed how to add direction capabilities to the widget. In this final installment I'll talk about how easy it is to integrate address searching with the Mac OS X Address Book application.

    Address Book Searching

    The Mac OS X Address Book application is bundled with the OS X operating system, providing a way for users to organize their contacts and associated information including their addresses. Also included with Mac OS X is an Address Book widget, which provides access to the Address Book database from a widget. I've explored the Address Book widget code, and extracted the AddressBookPlugIn. Plug-ins are native code that can be used to access operating system levels features from a widget's JavaScript interface.

    Listing 1 demonstrates how I've modified the address parsing method. If an address is entered that does not match one of the pre-defined formats I will assume that it's a name to retrieve from the Address Book. The address book is searched for the name with the best match. Then the street, city, state, and zip code are retrieved from the best match. The retrieved address is then parsed as discussed in Part 3!

    Listing 1 - Retrieving From the Address Book

    function onAddressSearch(event)
    {
      // user hit a return?
        if(event.keyCode == 13) {
        if(!$(address).value.blank()) {
    
        var street = "";
        var city = "";
        var state = "";
        var zip = "";
        var country = "";
    
         $(lblErrorMsg).innerText = "";
           $(multMatches).style.visibility = "hidden";
         $(lblMultMatch).style.visibility = "hidden";
    
           var splitAddr = $(address).value.split(',');
    
         // if we only get 2 elements assume address, zip
         if(splitAddr.length == 2) {
          street = splitAddr[0];
          zip = splitAddr[1];
    
        // for three elements assume address, city, state
         } else if(splitAddr.length == 3) {
          street = splitAddr[0];
          city = splitAddr[1];
          state = splitAddr[2];
    
        // for 4 elements assume address, city, state, zip
         } else if(splitAddr.length == 4) {
          street = splitAddr[0];
          city = splitAddr[1];
          state = splitAddr[2];
          zip = splitAddr[3];
    
        // for 5 elements assume address, city, state, zip, country
         } else if(splitAddr.length == 5) {
          street = splitAddr[0];
          city = splitAddr[1];
          state = splitAddr[2];
          zip = splitAddr[3];
          country = splitAddr[4];
    
         } else {
            // otherwise assume it's a name to look up in the Address Book
          AddressBookPlugin.searchForStringWithBestMatch($(address).value);
          // retrieve the values from the address book
          street = AddressBookPlugin.displayedValueAtIndex(7);
          city = AddressBookPlugin.displayedValueAtIndex(8)
          state = AddressBookPlugin.displayedValueAtIndex(9);
          zip = AddressBookPlugin.displayedValueAtIndex(10);
         }
    
         var result = widget.system('java -classpath .:mq.jar GetLocations
           -street "' + street + '" -city "' + city + '" -state "' + state +
           '" -zip "' + zip + '" -country "' +country + '"',null).outputString;
    
         // any errors?
         if(result == "ERROR") {
          $(lblErrorMsg).innerText = "Error! Unknown Address Format!";
         // address not found?
         } else if (result == "NOT FOUND") {
          $(lblErrorMsg).innerText = "Address Was Not Found!";
         } else {
          // split on return - a line is printed for each individual result
          var eachresult = result.split('\n');
    
          // just one result returned? - then just plot the point -
          // there are two extra returns so 3 really means 1 item
          if(eachresult.length == 3) {
            // get the coordinates from the returned string
            var coords = eachresult[0].split('|');
            // create a new point based on the coordinates
            newCenter = new MQLatLng(parseFloat(coords[0]),parseFloat(coords[1]));
    
            //create a new icon object
            myIcon = new MQMapIcon();
    
            // set the icon image: icon file location, width, height, recalc infowindow offset,
            // is it a PNG image?
    
            if(defIcon == "pin") {
              myIcon.setImage("images/pinpoint_red.gif",32,32,true,false);
            } else if(defIcon == "star") {
              myIcon.setImage("images/starsmall_red",18,18,true,false);
            } else if(defIcon == "x") {
              myIcon.setImage("images/xspot.gif",17,17,true,false);
            }
    
            // create a point
            myPoint = new MQPoi(newCenter);
    
            // set the custom icon
            myPoint.setIcon(myIcon);
    
            // recenter the map on the point,
            // the second parameter specifies the zoom level
            myMap.setCenter(newCenter,defZoom);
            // add the point as a Point of Interest
            myMap.addPoi(myPoint);
          } else {
            // clear out existing items
            $(multMatches).options.length = 0;
            for(var i=0; i
    
    

    Conclusion

    For your reference, here are some references for the MapQuest Platform:

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 6 - Directions

    Stand in the place where you live, Now face North, Think about direction, Wonder why you haven't before - REM

    In Part 1 I showed you how to get started with the MapQuest Advantage API by getting a developer key. In Part 2 I put that key to use by providing access to a basic map in the Map It! widget. Part 3 showed you how to incorporate basic geocoding. In Part 4 I discussed more advanced geocoding topics - including handling multiple matches and specifying geocode search options. Part 5 discussed adding widget options including the default zoom level, specifying point of interest icons, and the default map type. In this installment I'll discuss how to add direction capabilities to the widget!

    Directions

    Listing 1 demonstrates how to add directions to our widget map. I've added an additional search box where the user can enter the destination address. I've use the Java application developed in Part 3 to obtain the coordinates of the route beginning and destination points. Using the coordinates, I've created the MQGeoAddress object for both points. A new session is created for routing. The starting point and destination are added to the way points. Once the route is calculated through the doRoute method, the highlighted route is added to then added to the map.

    Listing 1 - Adding Directions

    // create the first address point
    var geoAddr1 = new MQGeoAddress();
    
    // create the second address point
    var geoAddr2 = new MQGeoAddress();
    
    // set the cooridinates
    geoAddr1.setMQLatLng(newCenter1);
    geoAddr2.setMQLatLng(newCenter2);
    
    // create a new session
    var session = new MQSession();
    var routeRes = new MQRouteResults();
    var wayPoints = new MQLocationCollection();
    var myBB = new MQRectLL(new MQLatLng(),new MQLatLng());
    
    // add the beginning and ending way points
    wayPoints.add(geoAddr1);
    wayPoints.add(geoAddr2);
    var routeOpt = new MQRouteOptions();
    
    //create sessionID from the route server
    var routeServerName = "route.access.mapquest.com";
    var routeServerPort = "80";
    var routeServerPath = "mq";
    
    // obtain a route
    var routeExec = new MQExec(routeServerName, routeServerPath,
      routeServerPort, routeServerName, routeServerPath, routeServerPort );
    var sessId = routeExec.createSessionEx(session);
    routeExec.doRoute(wayPoints,routeOpt,routeRes,sessId,myBB);
    
    // add the route to the map!
    myMap.addRouteHighlight(myBB,"http://map.access.mapquest.com",sessId,true);
    

    Conclusion

    In Part 7 I'll wrap up the widget by showing you how to retrieve addresses from the Mac OS X Address Book application. For your reference, here are some references to the MapQuest Platform:

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 5 - Enhancing Map It!

    It is not down in any map; true places never are. - Herman Melville

    In Part 1 I showed you how to get started with the MapQuest Platform by getting a developer key. In Part 2, I put that key to use by providing access to a basic map in the Map It! widget. Part 3 showed you how to incorporate basic geocoding. In Part 4 I discussed more advanced geocoding topics - including handling multiple matches and specifying geocode search options. In this installment I'll discuss adding some options to the widget. Specifically I'll discuss setting the default zoom level when adding an API, specifying point of interest icons, and the default map type.

    The Widget Options

    The back of the Map It! widget is shown in Figure 1. The user can set defaults for zooming, map view, and the point of interest icon. Each of these values are saved in the widget's preferences and loaded when the widget is launched.

    Figure 1

    Setting the Options At Startup

    The widget load function is called when the widget is first loaded. The preferences are created if they don't already exist.

    function load()
    {
        setupParts();
    
      // check the current prefrences version -
      // if not available or version changed recreate them
      if(loadPref("version") != "0.1") {
        // store the current version
        createPref("version","0.1");
        createPref("zoom","10");
        createPref("view","map");
        createPref("icon","pin");
      }
    
         defZoom = parseInt(loadPref("zoom"));
      defView = loadPref("view");
      defIcon = loadPref("icon");
    
      // Create the Map...
      myMap = new MQTileMap(document.getElementById('myMap'));
      var myLZControl = new MQLargeZoomControl(myMap);
      myMap.addControl(myLZControl,
        new MQMapCornerPlacement(MQMapCorner.TOP_LEFT, new MQSize(1,1)));
      var myVControl = new MQViewControl(myMap);
      myMap.addControl(myVControl,
        new MQMapCornerPlacement(MQMapCorner.TOP_RIGHT, new MQSize(20,20)));
      // set the default map view
      myMap.setMapType(defView);
    }
    

    When an address is plotted, the code has been changed as reflected:

    //create a new icon object
    myIcon = new MQMapIcon();
    
    // set the icon image: icon file location, width, height,
    // recalc infowindow offset,
    // is it a PNG image?
    if(defIcon == "pin") {
      myIcon.setImage("images/pinpoint_red.gif",32,32,true,false);
    } else if(defIcon == "star") {
      myIcon.setImage("images/starsmall_red",18,18,true,false);
    } else if(defIcon == "x") {
      myIcon.setImage("images/xspot.gif",17,17,true,false);
    }
    
    // create a point
    myPoint = new MQPoi(newCenter);
    
    // set the custom icon
    myPoint.setIcon(myIcon);
    
    // recenter the map on the point, the second parameter
    // specifies the zoom level
    myMap.setCenter(newCenter,defZoom);
    

    A new MQMapIcon object is created to to hold the custom icon. The setImage method is called to load the icon image, and the setIcon method of the MQTileMap object is called to associate the icon with the point of interest. Now when a search is run, the default custom icon is displayed as shown in Figure 2.

    Figure 2

    Conclusion

    In Part 6 I'll discuss adding direction capabilities to the widget. For your reference, here are some references to the MapQuest APIs:

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 4 - Advanced Geocoding

    Younger hackers are hard to classify. They're probably just as diverse as the old hackers are. We're all over the map. - Larry Wall

    In Part 1 I showed you how to get started with the MapQuest Platform by getting a developer key. In Part 2 I put that key to use by providing access to a basic map in the Map It! widget. Part 3 showed you how to incorporate basic geocoding. In this installment I'll discuss more advanced geocoding topics - including handling multiple matches and specifying geocode search options.

    Multiple Matches

    The version of the Map It! widget developed in Part 3 added the ability to plot a point of interest on the map. In the Java application that was developed to return the coordinates of an address, only the first match is returned. What if the user enters a street address without the house number? Geocoding would actually return multiple results. We need to change the getLocation method developed in Part 3 to return each match. On a search without a house number for example, the geocoding process would return points for each range of addresses. Listing 1 shows how the getLocation method has been modified:

    Listing 1

      public static String getLocation(String street, String city,
        String state, String zip, String country)
         {
          String result;
            /*
            MapQuest.Exec is the MapQuest client object.
            All server requests, such as Geocode and Search, are part of the
            Exec object.
            */
            Exec geocodeClient = new Exec();
    
            geocodeClient.setClientId ("** YOUR CLIDENT ID **");
            geocodeClient.setPassword ("** YOUR PASSWORD **");
            geocodeClient.setServerName("geocode.dev.mapquest.com");
    
          // create a new address object
          Address originAddress = new Address();
    
          // create a new location collection to save the results
          LocationCollection geocodeResults = new LocationCollection();
    
          // save the parsed address
            originAddress.setStreet(street);
            originAddress.setCity(city);
            originAddress.setState(state);
            originAddress.setPostalCode(zip);
            originAddress.setCountry(country);
    
            try
            {
               // This is the first communication with the MapQuest server
               // Try converting the address to coordinates
               geocodeClient.geocode(originAddress,geocodeResults);
    
             // create a new GeoAddress
               GeoAddress geoAddress = new GeoAddress();
    
           // any results returned?
           if(geocodeResults.getSize() > 0) {
            // loop through each result
            for(int i=0; i < geocodeResults.getSize(); i++) {
                  geoAddress = (GeoAddress)geocodeResults.getAt(i);
              // append the coordinates and information about that
              // matching location
              result = result +
               String.valueOf(new Double(geoAddress.getLatLng().getLatitude())) +
               "|" + String.valueOf(new
               Double(geoAddress.getLatLng().getLongitude())) + "|" +
                 geoAddress.getStreet() + "|" + geoAddress.getCity()  + "|" +
                   geoAddress.getState() + "|" + geoAddress.getCountry() + "|" +
                 geoAddress.getPostalCode() + "\n";
            }
           }
            }
            catch (Exception e)
          {
          // anything wrong - print an error message
          return "ERROR";
          };
          // if the address is not found - report NOT FOUND
            return "NOT FOUND";
         }
    

    For each match that is returned by geocoding, the result string is appended with the coordinates, and street, city, state, zip, and country of that location. Each parameter is separated by | for easy parsing in JavaScript.

    Geocoding Options

    The API documentation indicates that the default geocoding options will typically be adequate for most developers. However, there are a few options you can specify that ma be of interest. These include:

    • MatchType - A constant that corresponds to the granularity of the desired match.
    • QualityType - The minimum confidence necessary for a match.
    • MaxMatches - the maximum number of matchers to return.

    These options are explained in detail in Chapter 3 of the Java API Developer Guide.

    To specify an option you need to create a GeocodeOptions object, then specify the MatchType, QualityType, or MaxMatches properties. (The constants for each option are specified in Chapter 3). As shown in Listing 2, the GeoCodeOptions object is passed as a parameter to the geocode method.

    Listing 2

    // create a geocode options object
    GeocodeOptions geocodeOptions = new GeocodeOptions();
    
    // return only exact matches
    geocodeOptions.setQualityType(QualityType.EXACT);
    
    // create the options collection object
    // then add the option to the options collection
    GeocodeOptionsCollection geocodeOptionsCollection =
      new GeocodeOptionsCollection();
    geocodeOptionsCollection.add(geocodeOptions);
    try {
      // perform the search
      Client.geocode(originAddress, geocodeResults, geocodeOptionsCollection);
    }
    

    Selecting the Best Match

    Now that multiple locations are returned for a search, those results need to be displayed to the user in a combo box, as shown in Figure 1.

    Figure 1

    When the users selects an address from the combo box that point is displayed on the map. To do this we need to change the onAddressSearch JavaScript function introduced in Part 3, as follows:

    function onAddressSearch(event) {
        // user hit a return?
          if(event.keyCode == 13) {
          if(!$(address).value.blank()) {
    
          var street = "";
          var city = "";
          var state = "";
          var zip = "";
          var country = "";
    
           $(lblErrorMsg).innerText = "";
             $(multMatches).style.visibility = "hidden";
           $(lblMultMatch).style.visibility = "hidden";
    
             var splitAddr = $(address).value.split(',');
    
           // if we only get 2 elements assume address, zip
           if(splitAddr.length == 2) {
            street = splitAddr[0];
            zip = splitAddr[1];
    
            // for three elements assume address, city, state
            } else if(splitAddr.length == 3) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
    
            // for 4 elements assume address, city, state, zip
            } else if(splitAddr.length == 4) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
            zip = splitAddr[3];
    
            // for 5 elements assume address, city, state, zip, country
            } else if(splitAddr.length == 5) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
            zip = splitAddr[3];
            country = splitAddr[4];
    
            } else {
            // error! unknown address
    
            $(lblErrorMsg).innerText = "Error! Unknown Address Format!";
            return;
           }
    
           var result = widget.system('java -classpath .:mq.jar GetLocations
             -street "' + street + '" -city "' + city + '" -state "' + state + '"
             -zip "' + zip + '" -country "' +country + '"',null).outputString;
    
           // any errors?
           if(result == "ERROR") {
            $(lblErrorMsg).innerText = "Error! Unknown Address Format!";
           // address not found?
           } else if (result == "NOT FOUND") {
            $(lblErrorMsg).innerText = "Address Was Not Found!";
           } else {
    
           // *** CHANGED TO SUPPORT MULTIPLE LOCATION ***
    
           // split on return - a line is printed for each individual result
           var eachresult = result.split('\n');
    
           // just one result returned? - then just plot the point
           if(eachresult.length == 1) {
              // get the coordinates from the returned string
              var coords = result.split('|');
              // create a new point based on the coordinates
              newCenter = new MQLatLng(parseFloat(coords[0]),parseFloat(coords[1]));
              // create a point
              myPoint = new MQPoi(newCenter);
              // recenter the map on the point,
              // the second parameter specifies the zoom level
              myMap.setCenter(newCenter,10);
              // add the point as a Point of Interest
              myMap.addPoi(myPoint);
           } else {
              // clear out existing items
              $(multMatches).options.length = 0;
              for(var i=0; i < eachresult.length; i++) {
                // parse each returned location
                var location = eachresult[i].split('|');
                // 7 items on the result line?
                if(location.length == 7) {
                  var locationtext = location[2] + "," + location[3] +
                    "," + location[4] + "," + location[5] + "," + location[6];
                  var objNewOption = document.createElement("OPTION");
                  $(multMatches).options.add(objNewOption);
                  // add the location text
                  objNewOption.text = locationtext;
                  // add the coordinates as a | separate string to the value...
                  objNewOption.value = location[0] + '|' + location[1];
                }
              }
              // show the label and combo box...
              $(multMatches).style.visibility = "visible";
              $(lblMultMatch).style.visibility = "visible";
            }
           }
            }
        }
      }
    

    A separate line is returned for each matching location. The text is displayed for each option, and the value is set to the coordinates. When the user selects an item, the coordinates value is retrieved and the point is plotted on the map.

    Conclusion

    In Part 5 I'll discuss enhancements to the Map It! widget, including setting the default zoom level when adding an API, specifying point of interest icons, and the default map type. For your reference, here are some references to the MapQuest Platform:

  • Map It! - Building a MapQuest Mac OS X Dashboard Widget - Part 3 - Adding Geocoding

    Somewhere there is a map of how it can be done. - Ben Stein

    In Part 1 I showed you how to get started with the MapQuest Advantage API by getting a developer key. In Part 2 I put that key to use by providing access to a basic map in the Map It! widget. In this installment I'll show you how to incorporate basic geocoding.

    About Geocoding

    Geocoding is the process of converting an address into latitude and longitude coordinates that uniquely identify a location, and you can use to plot on a map. Applications using the MapQuest Platform can calculate the latitude and longitude of:

    • Street addresses and intersections, the highest accuracy geocoding methods.
    • Street blocks, including the nearest block to an invalid house number.
    • Postal codes, including ZIP, ZIP+2, and ZIP+4 codes.
    • City centers.
    • US state and Canadian province centers.
    • Country centers.
    • Centers of other administrative areas that are used internationally.

    The Map It! application will allow users to enter an address in one of the following forms:

    • street address, zip
    • street address, city, state
    • street address, city, state, zip
    • street address, city, state, zip, country

    Preparing an Address for Geocoding

    As shown in Figure 1, the user enters the address in the search text box in one of the acceptable forms.

    Figure 1

    The address needs to be separated into its constituent parts for geocoding. Since the user enters a comma separated string, the following JavaScript function is called on every key press. Once a return is entered (key code 13) the address is parsed.

    function onAddressSearch(event)
    {
      // user hit a return?
        if(event.keyCode == 13) {
        if(!$(address).value.blank()) {
    
          var street = "";
          var city = "";
          var state = "";
          var zip = "";
          var country = "";
    
          // clear the error message area
           $(lblErrorMsg).innerText = "";
    
          // the split function splits a string into an array based on a
          // character delimeter...
             var splitAddr = $(address).value.split(',');
    
           // if we only get 2 elements assume address, zip
           if(splitAddr.length == 2) {
            street = splitAddr[0];
            zip = splitAddr[1];
    
          // for three elements assume address, city, state
           } else if(splitAddr.length == 3) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
    
          // for 4 elements assume address, city, state, zip
          } else if(splitAddr.length == 4) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
            zip = splitAddr[3];
    
          // for 5 elements assume address, city, state, zip, country
           } else if(splitAddr.length == 5) {
            street = splitAddr[0];
            city = splitAddr[1];
            state = splitAddr[2];
            zip = splitAddr[3];
            country = splitAddr[4];
    
           } else {
            // error! unknown address
    
            $(lblErrorMsg).innerText = "Error! Unknown Address Format!";
            return;
           }
    .
    .
    .
    

    If the address is blank or not in the proper format and error message is displayed below the search text box. Once the address string has been parsed, it's time to convert the address to a latitude and longitude.

    The Need for a Proxy

    To call the Geocoding routines from your web application you need to install a proxy. The JavaScript API documentation describes the purpose of the proxy as twofold: "Circumvent the XML cross domain security issue. A browser can currently only request XML from the same domain as the HTML page arrived from. In other words, you cannot serve a page that requests XML directly from us, it has to come from you, so the Proxy is therefore a routing mechanism to make that happen. Secondly, the Proxy also adds in your clientID and password on the way through, so that your authorization credentials are not exposed in any manner within the web browser." The JavaScript API provides proxies in Java, PHP 5, .Net, Ruby on Rails, and a client side Flash proxy. Refer to Chapter 3 in the Advantage API Javascript Documentation for instructions on installing the proxy.

    Java Geocoding - Since a Proxy Doesn't Work for Dashboard Widgets

    All of the proxies, including the client side Flash proxy, assume that your application is running on a web server. As I mentioned in Part 2 the Geocoding process presents a limitation with Dashboard widgets, as they don't run on a web server, so proxies won't work. Instead, we'll need to access Geocoding through a Java application that the widget can call. The Java application is simple, it takes an address in command line parameters, and prints the first matching coordinates. You'll need to download the MapQuest Platform: Java SDK from http://developer.mapquest.com/downloads. This will provide the mq.jar file, which is required to access the MapQuest functions from your Java application.

    Getting the First Coordinate Match

    The GetLocation Java program in shown in Listing 1. When run it searches the command line for parameters that specify each component of the address. These components are passed to the getLocation method. A new geocodeClient object is created. You need to specify the username and password you obtained when you signed up for MapQuest access, as I described in Part 1 (link back ). An Address object is created, and initialized with the address specified on the command line. Even if only some of the attributes are specified, the geocoding process will be able to locate the coordinates. If a result is found, a string is created that contains the first matching coordinates. The latitude and longitude is separated by a | character.

    Listing 1

      public class GetLocation
      {
         public static void main (String[] args)
         {
            String street = "";
          String city = "";
          String state = "";
          String zip = "";
          String country = "";
    
          // parse the command line parameters
          if(args.length > 0) {
            for(int i=0; i < args.length; i+=2) {
              if(args[i].equalsIgnoreCase("-street")) {
                street = args[i+1];
              } else if(args[i].equalsIgnoreCase("-city")) {
                city = args[i+1];
              } else if(args[i].equalsIgnoreCase("-state")) {
                state = args[i+1];
              } else if(args[i].equalsIgnoreCase("-zip")) {
                zip = args[i+1];
              } else if(args[i].equalsIgnoreCase("-country")) {
                country = args[i+1];
              } else {
                System.out.printf("ERROR\n");
                return;
              }
            }
            // print the found coordinates
            System.out.printf("%s\n",getLocation(street,city,state,zip,country));
            return;
          } else {
            // if unable to parse the command line arguments
            // print ERROR
            System.out.printf("ERROR\n");
            return;
          }
         }//end main
    
         public static String getLocation(String street, String city, String state,
           String zip, String country)
         {
          String result;
            /*
            MapQuest.Exec is the MapQuest client object.
            All server requests, such as Geocode and Search,
            are part of the Exec object.
            */
            Exec geocodeClient = new Exec();
    
            geocodeClient.setClientId ("** YOUR CLIDENT ID **");
            geocodeClient.setPassword ("** YOUR PASSWORD **");
            geocodeClient.setServerName("geocode.dev.mapquest.com");
    
          // create a new address object
          Address originAddress = new Address();
    
          // create a new location collection to save the results
          LocationCollection geocodeResults = new LocationCollection();
    
          // save the parsed address
            originAddress.setStreet(street);
            originAddress.setCity(city);
            originAddress.setState(state);
            originAddress.setPostalCode(zip);
            originAddress.setCountry(country);
    
            try
            {
               // This is the first communication with the MapQuest server
               // Try converting the address to coordinates
               geocodeClient.geocode(originAddress,geocodeResults);
    
             // create a new GeoAddress
               GeoAddress geoAddress = new GeoAddress();
    
            // any results returned?
          if(geocodeResults.getSize() > 0) {
                // get the first result
                geoAddress = (GeoAddress)geocodeResults.getAt(0);
    
                // create a string to contain the latitude and longitutde
            result = String.valueOf(new Double(geoAddress.getLatLng().getLatitude())) + "|" + String.valueOf(new Double(geoAddress.getLatLng().getLongitude()));
            return result;
           }
            }
            catch (Exception e)
          {
          // anything wrong - print an error message
          return "ERROR";
          }
    
          // if the address is not found - report NOT FOUND
            return "NOT FOUND";
         }
      }//end class GetLocation
    

    Plotting the Point of Interest (POI)

    After parsing the entered address, the following code concludes the onAddressSearch function:

    // call the GetLocation Java Program - note the mq.jar file must be included in
    // classpath
    var result = widget.system('java -classpath .:mq.jar GetLocation -street "'
      + street + '" -city "' + city + '" -state "' + state + '" -zip "'
      + zip + '" -country "' +country + '"',null).outputString;
    
    // get the coordinates from the returned string
    var coords = result.split('|');
    
    // create a new point based on the coordinates
    newCenter = new MQLatLng(parseFloat(coords[0]),parseFloat(coords[1]));
    
    // create a point
    myPoint = new MQPoi(newCenter);
    
    // recenter the map on the point, the second parameter specifies the zoom level
    myMap.setCenter(newCenter,10);
    
    // add the point as a Point of Interest
    myMap.addPoi(myPoint);
    

    Once the coordinates are returned from the GetLocation Java program, a new MQLatLng object is created with the coordinates returned. A MQPoi (point of interest) object is created, then the map is centered on the new point, and an icon is added to mark it with the addPoi method of the MQTileMap object. The result of mapping a point in the Map It! widget is shown in Figure 1.

    Figure 1

    Conclusion

    In Part 4 I'll discuss Geocoding quality and how to handle multiple returned coordinates. For your reference, here are some references to the MapQuest Platform: