Tech Life

Ideaport Riga blog about mobile, web and integration solutions for enterprises

Siebel Open UI and Google Maps integration – Part 3

In the previous article of this series we have done Siebel configuration, as well as presentation model and presentation renderer modifications, required for the bidirectional Siebel OpenUI – Google Maps integration. In this final article, let us have a look at what remains to be done to have a fully-fledged solution.

Plug-in modifications

The original script of the Location Picker plug-in defines the structure of returned address in the following way:

function GMapContext(domElement, options) {
var _map = new google.maps.Map(domElement, options);
var _marker = new google.maps.Marker({
position: new google.maps.LatLng(54.19335, -3.92695),
map: _map,
title: "Drag Me",
draggable: options.draggable
});
return {
map: _map,
marker: _marker,
circle: null,
location: _marker.position,
radius: options.radius,
locationName: options.locationName,
addressComponents: {
formatted_address: null,
addressLine1: null,
addressLine2: null,
streetName: null,
streetNumber: null,
city: null,
state: null,
stateOrProvince: null
},
settings: options.settings,
domContainer: domElement,
geodecoder: new google.maps.Geocoder()
}
}

And here is how the address structure is populated with values returned by the Google Maps engine:

address_component_from_google_geocode: function(address_components) {
var result = {};
for (var i = address_components.length-1; i>=0; i--) {
var component = address_components[i];
// Postal code
if (component.types.indexOf('postal_code') >= 0) {
result.postalCode = component.short_name;
}
// Street number
else if (component.types.indexOf('street_number') >= 0) {
result.streetNumber = component.short_name;
}
// Street name
else if (component.types.indexOf('route') >= 0) {
result.streetName = component.short_name;
}
// City
else if (component.types.indexOf('sublocality') >= 0) {
result.city = component.short_name;
}
// State \ Province
else if (component.types.indexOf('administrative_area_level_1') >= 0) {
result.stateOrProvince = component.short_name;
}
// State \ Province
else if (component.types.indexOf('country') >= 0) {
result.country = component.short_name;
}
}
result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
result.addressLine2 = '';
return result;
}

There are a few things that can potentially be a subject of modification here:

  1. The City is obtained from sublocality type. As a result, for example, we get “Centra Rajons” instead of “Riga” for Latvian addresses, so changing this might be considered.
  2. The addressLine is composed of StreetNumber + StreetName, while in some implementations this might be required to work differently.
  3. The list of returned properties is too short, i.e. it might be different for different countries, so it may need extension.

The complete list of address property types returned by Google Maps API is available here, if you are interested.

In our case, the code shown above has been extended in the following way:

function GMapContext(domElement, options) {
var _map = new google.maps.Map(domElement, options);
var _marker = new google.maps.Marker({
position: new google.maps.LatLng(54.19335, -3.92695),
map: _map,
title: "Drag Me",
draggable: options.draggable
});
return {
map: _map,
marker: _marker,
circle: null,
location: _marker.position,
radius: options.radius,
locationName: options.locationName,
addressComponents: {
formatted_address: null,
addressLine1: null,
addressLine2: null,
streetName: null,
streetNumber: null,
city: null,
state: null,
stateOrProvince: null,
political: null,
administrative_area_level_2: null,
administrative_area_level_3: null,
administrative_area_level_4: null,
administrative_area_level_5: null,
colloquial_area: null,
sublocality_level_1: null,
sublocality_level_2: null,
sublocality_level_3: null,
sublocality_level_4: null,
sublocality_level_5: null
},
settings: options.settings,
domContainer: domElement,
geodecoder: new google.maps.Geocoder()
}
}

address_component_from_google_geocode: function(address_components) {
var result = {};
for (var i = address_components.length-1; i>=0; i--) {
var component = address_components[i];
// Postal code
if (component.types.indexOf('postal_code') >= 0) {
result.postalCode = component.short_name;
}
// Street number
else if (component.types.indexOf('street_number') >= 0) {
result.streetNumber = component.short_name;
}
// Street name
else if (component.types.indexOf('route') >= 0) {
result.streetName = component.short_name;
}
// City
else if (component.types.indexOf('locality') >= 0) {
result.city = component.short_name;
}
// State \ Province
else if (component.types.indexOf('administrative_area_level_1') >= 0) {
result.stateOrProvince = component.short_name;
}
// State \ Province
else if (component.types.indexOf('country') >= 0) {
result.country = component.short_name;
}
else if (component.types.indexOf('political') >= 0) {
result.political = component.short_name; // Specially for Finland
}
else if (component.types.indexOf('administrative_area_level_2') >= 0) {
result.administrative_area_level_2 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_3') >= 0) {
result.administrative_area_level_3 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_4') >= 0) {
result.administrative_area_level_4 = component.short_name;
}
else if (component.types.indexOf('administrative_area_level_5') >= 0) {
result.administrative_area_level_5 = component.short_name;
}
else if (component.types.indexOf('colloquial_area') >= 0) {
result.colloquial_area = component.short_name;
}
else if (component.types.indexOf('sublocality_level_1') >= 0) {
result.sublocality_level_1 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_2') >= 0) {
result.sublocality_level_2 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_3') >= 0) {
result.sublocality_level_3 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_4') >= 0) {
result.sublocality_level_4 = component.short_name;
}
else if (component.types.indexOf('sublocality_level_5') >= 0) {
result.sublocality_level_5 = component.short_name;
}
}
result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
result.addressLine2 = '';
return result;
}

As you can clearly see, a number of properties have been introduced – because sublocality and locality were empty in case of, for instance, Finland and it wasn’t really clear, which one will contain municipality or city. So what we did was to include all the properties that seemed suitable, and then to print them to the console; apparently, the city is passed in a property named political, so a little bit of magic has been added to the successGeoloc() function (see Part 2, a piece of code highlighted in red) in order to show the city information correctly for both Latvia and Finland.

Testing and debugging

All in all the kind of changes that are required to integrate Siebel OpenUI with Google Maps  proved to create no additional hassle when it comes to verifying the changes and debugging the code along the way. Basically, everything boils down to some pretty standard JavaScript development tools and techniques.

The development described in this series of articles has been performed on the files residing in folders of a dedicated Siebel client. All the changes applied instantly without any compilation – you just need to remember to press Ctrl-R, so that the browser refreshes the current page.

“Inspect element” feature and JS console of the latest Google Chrome browser provide a rather sufficient set of instruments for debugging, so you probably won’t need anything else on top of that. After everything is OK on a local client, the files can be copied over to the web server, and the results will show even without a server restart.

On handling the country differences

Different countries have different structure of the address used in their application. And the format of address returned by Google Maps API is also different from country to country. The common approach for integrating addresses returned by Google Maps in any country could go along these lines:

  1. Determine specific address structure that is used in the country(-ies), for which Siebel application is implemented.
  2. Find out, which types of properties return necessary information from Google Maps API. May require location picker plug-in modifications like the one outlined above.
  3. Modify location picker plug-in to return the necessary properties as well.
  4. Implement additional logic in the successGeoloc()function – if the mapping turns out to be complex, or if different countries with different address formats are in scope (as was in our case with Finland and Latvia).

The road ahead

Having implemented the bidirectional integration solution outlined above, we now have a fully functional applet that looks like this:

Part3 - pic1

After pressing the Pick Address button, we have an address from Google Maps saved in our new fields in Siebel.

As an idea for further development and improvement, we could check whether such an address already exists in our system, and if it does, save its ID on the component, but if it doesn’t – create a new record in CUT Address and, again, save its ID on our component. That kind of improvement, however, deserves and article of its own, so we’ll leave it at that for now...


IljaDubovskis About the author: Ilja Dubovskis has deep technical expertise in Siebel CRM. For 9 years he has been working for clients in Telecommunications, Finance, Insurance, Industry and Public Sector areas. In addition to working for clients, he leads Siebel Core Developer School at IPR, as well as acts as a coach for newcomers. He has been with Idea Port Riga since September 2009.

OUI Siebel

Subscribe for new posts!

Photo of Katerina Alfimova - System Analyst