/*
* GeoSolutions Android map Library - Digital field mapping on Android based devices
* Copyright (C) 2014 GeoSolutions (www.geo-solutions.it)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.geosolutions.android.map.spatialite;
import java.util.ArrayList;
import java.util.List;
import android.util.Log;
import jsqlite.Exception;
import it.geosolutions.android.map.database.SpatialDataSourceHandler;
import it.geosolutions.android.map.database.SpatialDataSourceManager;
import it.geosolutions.android.map.database.spatialite.SpatialiteDataSourceHandler;
import it.geosolutions.android.map.model.Feature;
import it.geosolutions.android.map.model.Layer;
import it.geosolutions.android.map.model.Source;
import it.geosolutions.android.map.model.query.BaseFeatureInfoQuery;
import it.geosolutions.android.map.model.query.CircleTaskQuery;
import it.geosolutions.android.map.model.query.FeatureInfoQuery;
import it.geosolutions.android.map.model.query.FeatureInfoQueryResult;
import it.geosolutions.android.map.model.query.FeatureInfoTaskQuery;
import it.geosolutions.android.map.model.query.PolygonTaskQuery;
import it.geosolutions.android.map.model.query.BBoxTaskQuery;
import it.geosolutions.android.map.style.AdvancedStyle;
import it.geosolutions.android.map.style.StyleManager;
import it.geosolutions.android.map.utils.StyleUtils;
import it.geosolutions.android.map.utils.Coordinates.Coordinates_Query;
import eu.geopaparazzi.spatialite.database.spatial.core.ISpatialDatabaseHandler;
import eu.geopaparazzi.spatialite.database.spatial.core.SpatialVectorTable;
public class SpatialiteSource implements Source {
private String title;
private String dataSourceName;
public SpatialiteSource(SpatialiteDataSourceHandler h) {
title = h.getFileName();
}
public SpatialiteSource(ISpatialDatabaseHandler h) {
title = h.toString();
}
@Override
public String getTitle() {
return title;
}
@Override
public void setTitle(String title) {
this.title = title;
}
public String getDataSourceName() {
return dataSourceName;
}
public void setDataSourceName(String dataSourceName) {
this.dataSourceName = dataSourceName;
}
/* (non-Javadoc)
* @see it.geosolutions.android.map.model.Source#performQuery(it.geosolutions.android.map.model.query.BaseFeatureInfoQuery, it.geosolutions.android.map.model.query.FeatureInfoQueryResult)
*/
@Override
public int performQuery(FeatureInfoTaskQuery q, List<FeatureInfoQueryResult> r) {
//TODO when multiple source available, use the handler of this source
int count = 0;
if(q instanceof BBoxTaskQuery){
count = performQueryBBox((BBoxTaskQuery)q,r);
}
else if(q instanceof CircleTaskQuery){
count = performQuery_circle((CircleTaskQuery)q,r);
}else if(q instanceof PolygonTaskQuery){
count = performQuery_poly((PolygonTaskQuery)q,r);
}else{
Log.w("Spatialite_Source","unrecognized query");
}
//TODO do other types
return count;
}
/**
* Performs a query on A bbox
* @param query
* @param data
*/
public int performQueryBBox(BBoxTaskQuery query,
List<FeatureInfoQueryResult> data){
SpatialDataSourceHandler handler = null;
SpatialVectorTable table = null;
try {
table = getTable(query);
handler = getHandler(table);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("Spatialite_Source", "Unable to parse query");
return 0;
}
if(!checkisVisible(table,query.getZoomLevel())){
return 0;
}
double north = query.getN();
double south = query.getS();
double east = query.getE();
double west = query.getW();
Integer start = query.getStart();
Integer limit = query.getLimit();
// this is empty to skip geometries that returns errors
ArrayList<Feature> features = new ArrayList<Feature>();
try {
features = handler.intersectionToFeatureListBBOX("4326", table, north,
south, east, west, start, limit);
} catch (Exception e) {
Log.e("Spatialite_Source", "unable to retrive data for table'"
+ table.getName() + "\'.Error:" + e.getLocalizedMessage());
return 0;
// TODO now simply skip, do better work
}
// add features
FeatureInfoQueryResult result = new FeatureInfoQueryResult();
result.setLayer( query.getLayer() );
result.setFeatures(features);
Log.v("Spatialite_Source", features.size() + " items found for table "
+ table.getName() );
// publishProgress(result);
data.add(result);
return features.size();
}
/**
* Returns the visibility of the table based on the zoom level
* @param table
* @param zoomLevel
* @return
*/
private boolean checkisVisible(SpatialVectorTable table, byte zoomLevel) {
if(table == null){
return false;
}
AdvancedStyle s = StyleManager.getInstance().getStyle(table.getName());
//Log.v("Spatialite_Source","zoom level:"+zoomLevel);
if ( !StyleUtils.isInVisibilityRange(s, zoomLevel) ) {
return false;
}
return true;
}
/**
* Perform a query on a circle.
* @param query
* @param data
* @return
*/
private int performQuery_circle(CircleTaskQuery query,
List<FeatureInfoQueryResult> data) {
Layer<?> layer = query.getLayer();
SpatialDataSourceHandler handler = null;
SpatialVectorTable table = null;
try {
table = getTable(query);
handler = getHandler(table);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("Spatialite_Source", "Unable to parse query");
return 0;
}
if(!checkisVisible(table,query.getZoomLevel())){
return 0;
}
double x = query.getX();
double y = query.getY();
double radius = query.getRadius();
Integer start = query.getStart();
Integer limit = query.getLimit();
// this is empty to skip geometries that returns errors
ArrayList<Feature> features = new ArrayList<Feature>();
try {
features = handler.intersectionToCircle("4326", table, x, y, radius, start, limit);
} catch (Exception e) {
Log.e("FEATURE_Circle_TASK", "unable to retrive data for table'"
+ table.getName() + "\'.Error:" + e.getLocalizedMessage());
// TODO now simply skip, do better work
}
// add features
FeatureInfoQueryResult result = new FeatureInfoQueryResult();
result.setLayer( query.getLayer() );
result.setFeatures(features);
// publishProgress(result);
data.add(result);
return features.size();
}
/**
* Perform a query on a polygon.
* @param query
* @param data
* @return
*/
private int performQuery_poly(PolygonTaskQuery query,
List<FeatureInfoQueryResult> data) {
Layer<?> layer = query.getLayer();
SpatialDataSourceHandler handler = null;
SpatialVectorTable table = null;
try {
table = getTable(query);
handler = getHandler(table);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.v("Spatialite_Source", "Unable to parse query");
return 0;
}
if(!checkisVisible(table,query.getZoomLevel())){
return 0;
}
ArrayList<Coordinates_Query> polygon_points = query.getPolygonPoints(); //get points in format (long/lat).
Integer start = query.getStart();
Integer limit = query.getLimit();
// this is empty to skip geometries that returns errors
ArrayList<Feature> features = new ArrayList<Feature>();
try {
features = handler.intersectionToPolygon("4326", table, polygon_points, start, limit);
} catch (Exception e) {
Log.e("FEATURE_Polygon_TASK", "unable to retrive data for table'"
+ table.getName() + "\'.Error:" + e.getLocalizedMessage());
// TODO now simply skip, do better work
}
// add features
FeatureInfoQueryResult result = new FeatureInfoQueryResult();
result.setLayer( query.getLayer() );
result.setFeatures(features);
Log.v("FEATURE_Polygon_TASK", features.size() + " items found for table "
+ table.getName());
// publishProgress(result);
data.add(result);
return features.size();
}
/**
* Provide <SpatialDataSourceHandler> for this table
* @param table
* @return
*/
private SpatialDataSourceHandler getHandler(SpatialVectorTable table) {
SpatialDataSourceHandler handler;
SpatialDataSourceManager manager = SpatialDataSourceManager.getInstance();
handler = manager.getSpatialDataSourceHandler(table);
return handler;
}
/**
* Provide the <SpatialVectorTable> of the layer in the query
* @param query
* @return
* @throws Exception
*/
private SpatialVectorTable getTable(FeatureInfoTaskQuery query)
throws Exception {
SpatialVectorTable table;
SpatialiteLayer l = (SpatialiteLayer) query.getLayer();
SpatialDataSourceManager manager = SpatialDataSourceManager.getInstance();
table = manager.getVectorTableByName(l.getTableName());
return table;
}
}