/**
* Filename: LocationRemoteHome.java (in org.repin.android.net.home)
* This file is part of the Redpin project.
*
* Redpin 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
* any later version.
*
* Redpin 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 Redpin. If not, see <http://www.gnu.org/licenses/>.
*
* (c) Copyright ETH Zurich, Pascal Brogle, Philipp Bolliger, 2010, ALL RIGHTS RESERVED.
*
* www.redpin.org
*/
package org.redpin.android.net.home;
import java.util.HashMap;
import java.util.List;
import org.redpin.android.core.Location;
import org.redpin.android.core.Map;
import org.redpin.android.core.Measurement;
import org.redpin.android.db.EntityHomeFactory;
import org.redpin.android.db.LocationHome;
import org.redpin.android.db.MapHome;
import org.redpin.android.net.Request;
import org.redpin.android.net.Response;
import org.redpin.android.net.Request.RequestType;
import android.util.Log;
/**
* RemoteEntityHome for {@link Location}s
*
* @author Pascal Brogle (broglep@student.ethz.ch)
*
*/
public class LocationRemoteHome implements IRemoteEntityHome {
protected LocationHome locHome = EntityHomeFactory.getLocationHome();
protected MapHome mapHome = EntityHomeFactory.getMapHome();
private static final String TAG = LocationRemoteHome.class.getName();
/**
* Performs an getLocationList request without callback
*/
public static void getLocationList() {
RemoteEntityHome.performRequest(RequestType.getLocationList);
}
/**
* Performs an getLocationList request with callback
*
* @param callback
* {@link RemoteEntityHomeCallback}
*/
public static void getLocationList(RemoteEntityHomeCallback callback) {
RemoteEntityHome.performRequest(RequestType.getLocationList, callback);
}
/**
* Performs an getLocation request without callback to estimate the current
* location
*
* @param measurement
* {@link Measurement}
*/
public static void getLocation(Measurement measurement) {
RemoteEntityHome.performRequest(RequestType.getLocation, measurement);
}
/**
* Performs an getLocation request with callback to estimate the current
* location
*
* @param measurement
* {@link Measurement}
* @param callback
* {@link RemoteEntityHomeCallback}
*/
public static void getLocation(Measurement measurement,
RemoteEntityHomeCallback callback) {
RemoteEntityHome.performRequest(RequestType.getLocation, measurement,
callback);
}
/**
* Performs an updateLocation request without callback
*
* @param loc
* {@link Location} to be updated
* @return <code>true</code> if request can be performed, <code>false</code>
* if the {@link Location} has no remote id
*/
public static boolean updateLocation(Location loc) {
return updateLocation(loc, null);
}
/**
* Performs an updateLocation request with callback
*
* @param loc
* {@link Location} to be updated
* @param callback
* {@link RemoteEntityHomeCallback}
* @return <code>true</code> if request can be performed, <code>false</code>
* if the {@link Location} has no remote id
*/
public static boolean updateLocation(Location loc,
RemoteEntityHomeCallback callback) {
if (loc.getRemoteId() == null || loc.getRemoteId() < 0) {
Log
.i(TAG,
"location can't be updated because no remote id is present");
return false;
}
RemoteEntityHome.performRequest(RequestType.updateLocation, loc,
callback);
return true;
}
/**
* Performs a removeLocation request without callback
*
* @param loc
* {@link Location} to be removed
* @return <code>true</code> if request can be performed, <code>false</code>
* if the {@link Location} has no remote id
*/
public static boolean removeLocation(Location loc) {
return removeLocation(loc, null);
}
/**
* Performs a removeLocation request with callback
*
* @param loc
* {@link Location} to be removed
* @param callback
* {@link RemoteEntityHomeCallback}
* @return <code>true</code> if request can be performed, <code>false</code>
* if the {@link Location} has no remote id
*/
public static boolean removeLocation(Location loc,
RemoteEntityHomeCallback callback) {
if (loc.getRemoteId() == null || loc.getRemoteId() < 0) {
Log
.i(TAG,
"location can't be removed because no remote id is present");
return false;
}
RemoteEntityHome.performRequest(RequestType.removeLocation, loc,
callback);
return true;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public void onRequestPerformed(Request<?> request, Response<?> response,
RemoteEntityHome rHome) {
switch (request.getAction()) {
case getLocation:
getLocationPerformed((Request<Measurement>) request,
(Response<Location>) response);
break;
case getLocationList:
getLocationListPerformed((Request<Void>) request,
(Response<List<Location>>) response);
break;
case removeLocation:
removeLocationPerformed((Request<Location>) request,
(Response<Void>) response);
break;
case updateLocation:
updateLocationPerformed((Request<Location>) request,
(Response<Void>) response);
break;
default:
throw new IllegalArgumentException(getClass().getName()
+ " can't handle action " + request.getAction());
}
}
/**
* Updates the local database after the location was updated on the server
*
* @param request
* {@link Request} performed
* @param response
* {@link Response} received
*/
private void updateLocationPerformed(Request<Location> request,
Response<Void> response) {
Location l = request.getData();
if (l == null) {
return;
}
Location dbLoc = locHome.get(l);
if (!l.equals(dbLoc)) {
boolean success = locHome.update(l);
if (!success) {
Log.i(TAG, "update of location " + l + " failed");
}
}
}
/**
* Removes the {@link Location} from the local database after it was removed
* on the server
*
* @param request
* {@link Request} performed
* @param response
* {@link Response} received
*/
private void removeLocationPerformed(Request<Location> request,
Response<Void> response) {
boolean success = locHome.remove(request.getData());
if (!success) {
Log.i(TAG, "removal of location " + request.getData() + " failed");
}
}
/**
* Synchronizes the local {@link Location} database
*
* @param request
* {@link Request} performed
* @param response
* {@link Response} received
*/
private void getLocationListPerformed(Request<Void> request,
Response<List<Location>> response) {
List<Location> dbList = locHome.getAll();
HashMap<Integer, Location> loc = new HashMap<Integer, Location>();
for (Location l : dbList) {
loc.put(l.getRemoteId(), l);
}
List<Location> remote = response.getData();
for (Location l : remote) {
if (loc.containsKey(l.getRemoteId())) {
Location dbLoc = loc.get(l.getRemoteId());
l.setLocalId(dbLoc.getLocalId());
if (dbLoc.getMap() != null && l.getMap() != null) {
((Map) l.getMap()).setLocalId(((Map) dbLoc.getMap())
.getLocalId());
}
if (!l.equals(dbLoc)) {
if (!locHome.update(l)) {
Log.w(TAG, "update of location " + l + " failed");
}
}
} else {
if (l.getMap() == null) {
continue;
}
Map m = mapHome.getByRemoteId(((Map) l.getMap()).getRemoteId());
if (m != null) {
l.setMap(m);
}
locHome.add(l);
}
}
loc.clear();
for (Location l : remote) {
loc.put(l.getRemoteId(), l);
}
for (Location l : dbList) {
if (!loc.containsKey(l.getRemoteId())) {
locHome.remove(l);
}
}
}
/**
* Adds {@link Location} if not yet in local database
*
* @param request
* {@link Request} performed
* @param response
* {@link Response} received
*/
private void getLocationPerformed(Request<Measurement> request,
Response<Location> response) {
Location l = response.getData();
if (l == null) {
return;
}
Location dbLoc = locHome.getByRemoteId(l.getRemoteId());
if (dbLoc != null) {
l.setLocalId(dbLoc.getLocalId());
if (!l.equals(dbLoc)) {
if (!locHome.update(l)) {
Log.w(TAG, "update of location " + l + " failed");
}
}
} else {
locHome.add(l);
}
}
}