package com.nutiteq.location.providers;
import java.util.Timer;
import java.util.TimerTask;
import com.nutiteq.components.WgsPoint;
import com.nutiteq.location.LocationListener;
import com.nutiteq.location.LocationMarker;
import com.nutiteq.location.LocationSource;
import com.nutiteq.location.cellid.CellIdDataReader;
import com.nutiteq.location.cellid.CellIdResponseWaiter;
import com.nutiteq.location.cellid.CellIdService;
import com.nutiteq.location.cellid.OpenCellIdService;
import com.nutiteq.log.Log;
/**
* Generic cell id location positioning handler. Supports single location query
* or polling at given interval. Pushes retrieved location in WGS84 to
* {@link com.nutiteq.location.LocationListener}. If location could not be
* determined, then <code>null</code> will be pushed into marker and status
* changes to {@link LocationSource#STATUS_CANT_LOCATE}.
*/
public class CellIdLocationProvider extends TimerTask implements CellIdResponseWaiter,
LocationSource {
private int status = STATUS_CONNECTING;
private WgsPoint location;
private final CellIdDataReader dataReader;
private LocationMarker marker;
private final long updateInterval;
private final Timer timer = new Timer();
private final CellIdService cellIdService;
private boolean retrievingLocation;
private LocationListener[] listeners = new LocationListener[0];
/**
* Create location provider for single query
*
* @param dataReader
* data reader used for cellid data accessing
*/
public CellIdLocationProvider(final CellIdDataReader dataReader) {
this(dataReader, new OpenCellIdService(), 0);
}
public CellIdLocationProvider(final CellIdDataReader dataReader, final long updateInterval) {
this(dataReader, new OpenCellIdService(), updateInterval);
}
public CellIdLocationProvider(final CellIdDataReader cellIdDataReader,
final CellIdService cellIdService) {
this(cellIdDataReader, cellIdService, 0);
}
/**
* Create location provider that queries for location at given interval
*
* @param dataReader
* data reader used for cellid data access
* @param updateInterval
* update interval for location query
*/
public CellIdLocationProvider(final CellIdDataReader dataReader,
final CellIdService cellIdService, final long updateInterval) {
this.dataReader = dataReader;
this.cellIdService = cellIdService;
this.updateInterval = updateInterval;
}
public void run() {
pushLocation();
}
public void start() {
if (updateInterval != 0) {
timer.schedule(this, 100, updateInterval);
return;
}
pushLocation();
}
private void pushLocation() {
if (dataReader.getCellId() == null) {
status = STATUS_CANT_LOCATE;
} else if (!retrievingLocation) {
status = STATUS_CONNECTING;
cellIdService.setResponseWaiter(this);
final String cellId = dataReader.getCellId();
final String lac = dataReader.getLac();
final String mcc = dataReader.getMcc();
final String mnc = dataReader.getMnc();
Log.debug("cellid > " + cellId + " : lac >" + lac + " : mcc > " + mcc + " : mnc > " + mnc);
cellIdService.retrieveLocation(cellId, lac, mcc, mnc);
retrievingLocation = true;
}
}
public int getStatus() {
return status;
}
public void notifyError() {
status = STATUS_CANT_LOCATE;
}
public LocationMarker getLocationMarker() {
return marker;
}
public void quit() {
timer.cancel();
marker.quit();
}
public void setLocationMarker(final LocationMarker marker) {
this.marker = marker;
addLocationListener(marker);
marker.setLocationSource(this);
}
public void cantLocate() {
status = STATUS_CANT_LOCATE;
}
public void locationRetrieved(final WgsPoint wgsPoint) {
status = STATUS_CONNECTED;
location = wgsPoint;
for (int i = 0; i < listeners.length; i++) {
listeners[i].setLocation(location);
}
retrievingLocation = false;
}
public WgsPoint getLocation() {
return location;
}
public void addLocationListener(final LocationListener listener) {
final LocationListener[] newListeners = new LocationListener[listeners.length + 1];
System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
newListeners[listeners.length] = listener;
listeners = newListeners;
}
}