package com.nutiteq.advancedmap3.datasource;
import android.net.Uri;
import android.util.Log;
import com.nutiteq.advancedmap3.Const;
import com.nutiteq.core.MapBounds;
import com.nutiteq.core.MapEnvelope;
import com.nutiteq.core.MapPos;
import com.nutiteq.core.MapTile;
import com.nutiteq.datasources.HTTPTileDataSource;
import com.nutiteq.datasources.VectorDataSource;
import com.nutiteq.geometry.GeoJSONGeometryReader;
import com.nutiteq.geometry.Geometry;
import com.nutiteq.geometry.LineGeometry;
import com.nutiteq.geometry.PointGeometry;
import com.nutiteq.geometry.PolygonGeometry;
import com.nutiteq.projections.Projection;
import com.nutiteq.renderers.components.CullState;
import com.nutiteq.styles.BalloonPopupStyle;
import com.nutiteq.styles.BalloonPopupStyleBuilder;
import com.nutiteq.styles.LineStyle;
import com.nutiteq.styles.MarkerStyle;
import com.nutiteq.styles.PointStyle;
import com.nutiteq.styles.PolygonStyle;
import com.nutiteq.styles.Style;
import com.nutiteq.vectorelements.BalloonPopup;
import com.nutiteq.vectorelements.Line;
import com.nutiteq.vectorelements.Marker;
import com.nutiteq.vectorelements.Point;
import com.nutiteq.vectorelements.Polygon;
import com.nutiteq.vectorelements.VectorElement;
import com.nutiteq.wrappedcommons.VectorElementVector;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Locale;
/**
* A custom vector data source making queries to http://docs.cartodb.com/cartodb-platform/sql-api/
*
*/
public class CartoDBSQLDataSource extends VectorDataSource {
private String baseUrl;
private String query;
private Style style;
public CartoDBSQLDataSource(Projection proj, String baseUrl, String query, Style style) {
super(proj);
this.baseUrl = baseUrl;
this.style = style;
this.query = query;
}
@Override
public VectorElementVector loadElements(CullState cullState) {
VectorElementVector elements = new VectorElementVector();
MapEnvelope mapViewBounds = cullState.getProjectionEnvelope(this.getProjection());
MapPos min = mapViewBounds.getBounds().getMin();
MapPos max = mapViewBounds.getBounds().getMax();
//run query here
loadData(elements, min,max,cullState.getViewState().getZoom());
return elements;
}
private void loadData(VectorElementVector elements, MapPos min, MapPos max, float zoom) {
// load and parse JSON
String bbox = String.format(Locale.US, "ST_SetSRID(ST_MakeEnvelope(%f,%f,%f,%f),3857) && the_geom_webmercator", min.getX(), min.getY(), max.getX(), max.getY());
String unencodedQuery = query.replace("!bbox!", bbox);
Log.d(Const.LOG_TAG, "SQL query: " + query);
unencodedQuery = unencodedQuery.replace("zoom('!scale_denominator!')", String.valueOf(zoom));
String encodedQuery = null;
try {
encodedQuery = URLEncoder.encode(unencodedQuery, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String urlAddress = baseUrl + "?format=GeoJSON&q="+ encodedQuery;
Log.d(Const.LOG_TAG, "SQL API: " + urlAddress);
try {
URL url = new URL(urlAddress);
BufferedReader streamReader = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream(), "UTF-8"));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
JSONObject json = new JSONObject(responseStrBuilder.toString());
GeoJSONGeometryReader geoJsonParser = new GeoJSONGeometryReader();
JSONArray features = json.getJSONArray("features");
for (int i = 0; i < features.length(); i++) {
JSONObject feature = (JSONObject) features.get(i);
JSONObject geometry = feature.getJSONObject("geometry");
// use SDK GeoJSON parser
Geometry ntGeom = geoJsonParser.readGeometry(geometry.toString());
JSONObject properties = feature.getJSONObject("properties");
VectorElement element;
// create object based on given style
if(style instanceof PointStyle){
element = new Point((PointGeometry) ntGeom,(PointStyle) style);
}else if(style instanceof MarkerStyle){
element = new Marker(ntGeom, (MarkerStyle) style);
}else if(style instanceof LineStyle) {
element = new Line((LineGeometry) ntGeom, (LineStyle) style);
}else if(style instanceof PolygonStyle) {
element = new Polygon((PolygonGeometry) ntGeom, (PolygonStyle) style);
}else{
Log.e(Const.LOG_TAG, "Object creation not implemented yet for style: " + style.swigGetClassName());
break;
}
// add all properties as MetaData, so you can use it with click handling
for (Iterator<String> j = properties.keys(); j.hasNext();){
String key = j.next();
String val = properties.getString(key);
element.setMetaDataElement(key,val);
}
elements.add(element);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}