package org.activityinfo.geoadmin.model;
import com.bedatadriven.geojson.GeoJsonModule;
import com.google.common.collect.Lists;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
import com.sun.jersey.api.json.JSONConfiguration;
import com.vividsolutions.jts.geom.Point;
import org.codehaus.jackson.map.ObjectMapper;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.ext.ContextResolver;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
/**
* ActivityInfo REST Client
*/
public class ActivityInfoClient {
public static final Logger LOGGER = Logger.getLogger(ActivityInfoClient.class.getName());
private Client client;
private URI root;
public static class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
@Override
public ObjectMapper getContext(Class<?> type) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GeoJsonModule());
return mapper;
}
}
/**
* Creates a new instance using the given endpoint, ActivityInfo username
* and password.
*
* @param endpoint
* Rest endpoint (for example:
* https://www.activityinfo.org/resources)
* @param username
* Email address of user (for example: akbertram@gmail.com)
* @param password
* User's plaintext password
*/
public ActivityInfoClient(String endpoint, String username, String password) {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
clientConfig.getClasses().add(ObjectMapperProvider.class);
// clientConfig.getProperties().put(com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
// new HTTPSProperties(new ActivityInfoHostnameVerifier(), getSSLContext()));
client = Client.create(clientConfig);
client.addFilter(new HTTPBasicAuthFilter(username, password));
root = UriBuilder.fromUri(endpoint).build();
}
/**
* @return the list of Countries in ActivityInfo's geographic reference
* database
*/
public List<Country> getCountries() {
URI uri = UriBuilder.fromUri(root).path("countries").build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(Country[].class));
}
/**
* @return the list of Administrative levels for a given country in
* ActivityInfo's geographic reference database
*/
public List<AdminLevel> getAdminLevels(Country country) {
return getAdminLevelsByCountryCode(country.getCode());
}
public List<AdminLevel> getAdminLevelsByCountryCode(String countryCode) {
URI uri = UriBuilder.fromUri(root)
.path("country")
.path(countryCode)
.path("adminLevels").build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(AdminLevel[].class));
}
public List<LocationType> getLocationTypesByCountryCode(String countryCode) {
URI uri = UriBuilder.fromUri(root)
.path("country")
.path(countryCode)
.path("locationTypes").build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(LocationType[].class));
}
public List<Location> getLocations(int locationType) {
URI uri = UriBuilder.fromUri(root)
.path("locations")
.queryParam("type", locationType)
.build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(Location[].class));
}
public void postNewLocations(int locationType, List<NewLocation> locations) {
URI uri = UriBuilder.fromUri(root)
.path("locations")
.path(Integer.toString(locationType))
.build();
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.type(MediaType.APPLICATION_JSON_TYPE)
.post(locations);
}
public void updateAdminLevel(AdminLevel level) {
URI uri = UriBuilder.fromUri(root)
.path("adminLevel")
.path(Integer.toString(level.getId()))
.build();
client.resource(uri)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.put(level);
}
public void deleteLevel(AdminLevel level) {
URI uri = UriBuilder.fromUri(root)
.path("adminLevel")
.path(Integer.toString(level.getId()))
.build();
client.resource(uri)
.delete();
}
public AdminLevel getAdminLevel(int id) {
URI build = UriBuilder.fromUri(root)
.path("adminLevel")
.path(Integer.toString(id))
.build();
return client.resource(build)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.get(AdminLevel.class);
}
public List<AdminEntity> getAdminEntities(AdminLevel level) {
return getAdminEntities(level.getId());
}
public List<AdminEntity> getAdminEntities(int levelId) {
LOGGER.info("Fetching admin entities for level " + levelId);
URI uri = UriBuilder.fromUri(root)
.path("adminLevel")
.path(Integer.toString(levelId))
.path("entities")
.build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(AdminEntity[].class));
}
/**
* Creates a new root administrative level for a given country
*/
public void postRootLevel(Country country, AdminLevel newLevel) {
URI uri = UriBuilder.fromUri(root)
.path("country")
.path(country.getCode())
.path("adminLevels")
.build();
client.resource(uri)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.post(newLevel);
}
/**
* Creates a new root administrative level for a given country
*/
public void postChildLevel(AdminLevel parentLevel, AdminLevel newLevel) {
URI uri = UriBuilder.fromUri(root)
.path("adminLevel")
.path(Integer.toString(parentLevel.getId()))
.path("childLevels")
.build();
client.resource(uri)
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.post(newLevel);
}
public List<AdminEntity> geocode(double latitude, double longitude) {
URI uri = UriBuilder.fromUri(root)
.path("geocode")
.queryParam("lat", latitude)
.queryParam("lng", longitude)
.build();
return Arrays.asList(
client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(AdminEntity[].class));
}
public List<List<AdminEntity>> geocode(List<Point> points) {
List<LatLng> latLngs = Lists.newArrayList();
for(Point point : points) {
latLngs.add(new LatLng(point));
}
return geocodePoints(latLngs);
}
public List<List<AdminEntity>> geocodePoints(List<LatLng> points) {
URI uri = UriBuilder.fromUri(root)
.path("geocode")
.build();
return client.resource(uri)
.accept(MediaType.APPLICATION_JSON_TYPE)
.type(MediaType.APPLICATION_JSON_TYPE)
.post(new GenericType<List<List<AdminEntity>>>() { }, points);
}
public ObjectMapper getObjectMapper() {
return new ObjectMapperProvider().getContext(ObjectMapper.class);
}
}