package com.nutiteq.services;
import com.mgmaps.utils.Tools;
import com.nutiteq.cache.Cache;
import com.nutiteq.components.KmlPlace;
import com.nutiteq.components.WgsBoundingBox;
import com.nutiteq.components.WgsPoint;
import com.nutiteq.core.MappingCore;
import com.nutiteq.io.ResourceDataWaiter;
import com.nutiteq.io.ResourceRequestor;
import com.nutiteq.kml.KmlElementsWaiter;
import com.nutiteq.kml.KmlReader;
import com.nutiteq.kml.KmlService;
import com.nutiteq.kml.KmlStylesCache;
import com.nutiteq.task.TasksRunner;
import com.nutiteq.utils.Utils;
/**
* <p>
* Default implementation for geocoding services. Uses default Nutiteq backend
* for searching.
* </p>
*
* <p>
* Additional search parameters can be added to search URL by appending these to
* baseurl used in service creation.
* </p>
*/
public class GeocodingService implements Service, KmlElementsWaiter,
KmlService, ResourceRequestor, ResourceDataWaiter {
private static final String ERROR_MESSAGE_START = "Error:";
public static final int NETWORK_ERROR = 0;
public static final int NOT_FOUND = 404;
public static final int SERVER_ERROR = 500;
private static final int ERROR_RESPONSE_LENGTH = 9;
/**
* Search type for geocoding (place search)
*/
public static final String SEARCH_TYPE_GEOCODING = "q";
/**
* Search type for POI search
*/
public static final String SEARCH_TYPE_POI = "l";
private final String searchUrl;
private final int numberOfElements;
private final KmlStylesCache stylesCache;
/**
* URL for default backend.
*/
public static final String DEFAULT_URL = "http://lbs.nutiteq.ee/cloudmade/geocode_kml.php";
private final GeocodingResultWaiter resultWaiter;
private final boolean gzipResponse;
private boolean stopped;
/**
*
* @param resultWaiter
* object waiting for search results
* @param baseurl
* baseurl for service
* @param lang
* search language
* @param searchNear
* location for searching (in WGS84)
* @param query
* query
* @param searchType
* search type (place search or POI search)
* @param categories
* possible categories for search
* @param numberOfElements
* number of elements to ask from server
* @param gzipResponse
* should response be compressed in server. Adds gzip=(yes|no) to
* end of url
*/
public GeocodingService(final GeocodingResultWaiter resultWaiter,
final String baseurl, final String lang, final WgsPoint searchNear,
final String query, final String searchType,
final int[] categories, final int numberOfElements,
final boolean gzipResponse) {
this.resultWaiter = resultWaiter;
this.numberOfElements = numberOfElements;
this.gzipResponse = gzipResponse;
final StringBuffer url = new StringBuffer(Utils
.prepareForParameters(baseurl));
url.append("out=kml");
if (searchNear != null) {
url.append("&near=");
url.append(Tools.urlEncode(searchNear.getLat() + "N, "));
url.append(Tools.urlEncode(searchNear.getLon() + "E"));
}
url.append("&t=").append(Tools.urlEncode(searchType));
url.append("&q=").append(Tools.urlEncode(query));
url.append("&lang=").append(Tools.urlEncode(lang));
if (categories != null) {
url.append("&cat=");
for (int i = 0; i < categories.length; i++) {
url.append(categories[i]);
if (i < categories.length - 1) {
url.append(",");
}
}
}
url.append("&max=").append(numberOfElements);
url.append("&gzip=").append(gzipResponse ? "yes" : "no");
searchUrl = url.toString();
stylesCache = new KmlStylesCache();
}
public void execute() {
enqueueDownload(MappingCore.getInstance().getTasksRunner());
}
protected void enqueueDownload(final TasksRunner d) {
d.enqueueDownload(this, Cache.CACHE_LEVEL_NONE);
}
public String resourcePath() {
return searchUrl;
}
public void notifyError() {
resultWaiter.errors(NETWORK_ERROR);
}
public void dataRetrieved(final byte[] data) {
if (stopped) {
return;
}
if (data.length == 9) {
final String response = new String(data);
if (response.indexOf(ERROR_MESSAGE_START) >= 0) {
resultWaiter.errors(Integer.parseInt(response
.substring(ERROR_MESSAGE_START.length())));
return;
}
}
final KmlReader reader = new KmlReader(this, this, searchUrl,
stylesCache, null, gzipResponse);
reader.dataRetrieved(data);
}
public void addKmlPlaces(final KmlService service, final KmlPlace[] read) {
for (int i = 0; i < read.length; i++) {
final String url = stylesCache.resolveImageUrl(read[i]
.getStyleUrl());
if (url != null) {
read[i].setStyleUrl(url);
}
}
resultWaiter.searchResults(read);
}
public String getServiceUrl(final WgsBoundingBox boundingBox, final int zoom) {
return searchUrl;
}
public int maxResults() {
return numberOfElements;
}
public boolean needsUpdate(final WgsBoundingBox boundingBox, final int zoom) {
return false;
}
public void cancel() {
stopped = true;
}
public int getCachingLevel() {
return Cache.CACHE_LEVEL_NONE;
}
public String getDefaultIcon() {
// TODO Auto-generated method stub
return null;
}
}