/*
* Copyright ThinkTank Maths Limited 2006 - 2008
*
* This file is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this file. If not, see <http://www.gnu.org/licenses/>.
*/
package com.openlapi;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Random;
import thinktank.j2me.TTUtils;
/**
* This implementation of the LocationProvider chooses a random entry from the
* LandmarkStore every time it is called.
*/
class LocationProviderLMS extends LocationProviderSimplified {
/**
* Given a list of locations, and an interval between them, this class will create
* periodic location update events to emulate movement through all the locations in
* order (and back again) indefinitely.
*
* @author Samuel Halliday, ThinkTank Maths Limited
*/
class RandomLocationDaemon implements Runnable {
private volatile boolean end = false;
private final long interval;
private final LandmarkStore lms;
private final Random random = new Random();
/**
* @param lms
* not null
* @param interval
* in milliseconds
*/
RandomLocationDaemon(LandmarkStore lms, long interval) {
this.interval = interval;
this.lms = lms;
}
public void end() {
end = true;
updateState(OUT_OF_SERVICE);
}
public void run() {
while (!end) {
updateLocation(getRandomEntry());
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
}
}
}
private synchronized Location getRandomEntry() {
if (lms == null)
return Location.getInvalid();
try {
// count how many entries there are
int count = 0;
Enumeration en = lms.getLandmarks();
while (en.hasMoreElements()) {
en.nextElement();
count++;
}
// pick a random entry
int entry = random.nextInt(count);
en = lms.getLandmarks();
for (int i = 0; en.hasMoreElements(); i++) {
Landmark landmark = (Landmark) en.nextElement();
if (i == entry)
return landmarkToLocation(landmark);
}
return Location.getInvalid();
} catch (IOException e) {
return Location.getInvalid();
}
}
}
private volatile RandomLocationDaemon daemon;
private final String storeName;
/**
* Create a new LocationProvider that chooses random entries from the LandmarkStore.
*
* @param criteria
* @param storeName
* @throws LocationException
*/
LocationProviderLMS(Criteria criteria, String storeName)
throws LocationException {
TTUtils.log("OpenLAPI LMS mode");
this.storeName = storeName;
startBackend();
}
private Location landmarkToLocation(Landmark landmark) {
Location location = new Location();
location.valid = true;
location.extraInfo_Text = "OpenLAPI LMS mode: " + landmark.getName();
location.addressInfo = landmark.getAddressInfo();
location.qualifiedCoordinates = landmark.getQualifiedCoordinates();
// set the timestamp to now
location.timestamp = System.currentTimeMillis();
return location;
}
protected void startBackend() throws LocationException {
if (daemon != null)
return;
LandmarkStore lms = LandmarkStore.getInstance(storeName);
if (lms == null)
throw new LocationException("LandmarkStore " + lms + " not found.");
// TODO: allow interval to be defined during construction
long interval = 2000;
daemon = new RandomLocationDaemon(lms, interval);
new Thread(daemon).start();
}
protected void stopBackend() {
if (daemon == null)
return;
daemon.end();
daemon = null;
}
}