/* * GeoSolutions Android Map Library * http://www.geo-solutions.it * * (C) 2012-2014, GeoSolutions S.A.S * * This library 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; * version 2.1 of the License. * * This library 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. */ package it.geosolutions.android.map.utils; import it.geosolutions.android.map.BuildConfig; import it.geosolutions.android.map.database.SpatialDataSourceHandler; import it.geosolutions.android.map.database.SpatialDataSourceManager; import it.geosolutions.android.map.mbtiles.MbTilesLayer; import it.geosolutions.android.map.mbtiles.MbTilesSource; import it.geosolutions.android.map.model.Feature; import it.geosolutions.android.map.model.MSMMap; import it.geosolutions.android.map.spatialite.SpatialiteLayer; import it.geosolutions.android.map.spatialite.SpatialiteSource; import java.util.ArrayList; import java.util.List; import jsqlite.Exception; import org.mapsforge.core.model.GeoPoint; import android.util.Log; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import eu.geopaparazzi.spatialite.database.spatial.core.ISpatialDatabaseHandler; import eu.geopaparazzi.spatialite.database.spatial.core.SpatialRasterTable; import eu.geopaparazzi.spatialite.database.spatial.core.SpatialVectorTable; /** * Utility class for common operations on the Spatial DB * @author Lorenzo Natali */ public class SpatialDbUtils { private static final SpatialDataSourceManager sdbm = SpatialDataSourceManager .getInstance(); /** * Provide a <Feature> object searching in a table that match a particular value * The passed attribute should be an id * @param attributeValue the value searched * @param attributeName the name of the column to check * @param tableName the name of the table * @return a <Feature> creating getting the feature that match attributeName -> attributeValue * @throws Exception */ public static Feature getFeatureById(String attributeValue, String attributeName, String tableName) { ArrayList<Feature> result = null; try { SpatialVectorTable table = sdbm.getVectorTableByName(tableName); SpatialDataSourceHandler handler = sdbm .getSpatialDataSourceHandler(table); if (handler != null) { result = handler.getFeaturesByAttribute("4326", table, attributeName, attributeValue, null, 1, true); } else { Log.e("DATABASE", "unable to retrive table:" + tableName); } } catch (Exception e) { Log.e("DATABASE", "unable to retrive feature:" + attributeName + "->" + attributeValue + "from table: " + tableName); } if (result != null && result.size() > 0) { return result.get(0); } return null; } /** * Provide the <Feature> object iterating over all the tabled in the DataBase. * @param attributeValue value of the column to check * @param attributeName name of the column to check * @return reating getting the feature that match attributeName -> attributeValue */ public static Feature getFeatureById(String attributeValue, String attributeName) { ArrayList<Feature> result = null; List<SpatialVectorTable> tables = null; try { tables = sdbm.getSpatialVectorTables(false); } catch (Exception e) { Log.e("DATABASE", "unable to get tables from the database:"); return null; } for (SpatialVectorTable table : tables) { try { SpatialDataSourceHandler handler = sdbm .getSpatialDataSourceHandler(table); if (handler != null) { result = handler.getFeaturesByAttribute("4326", table, attributeName, attributeValue, null, 1, true); } else { Log.e("DATABASE", "unatable.getName()table:" + table.getName()); } } catch (Exception e) { Log.e("DATABASE", "unable to retrive feature:" + attributeName + "->" + table.getName()); } if (result != null && result.size() > 0) { return result.get(0); } } return null; } /** * Gets a <Geopoint> for the layer with the attributeName = attributeValue. * * @param layer * @param attributeName * @param attributeValue * @param wantGeometry to get also the geometry * @return */ public static GeoPoint getGeopointFromLayer(String layer, String attributeName,String attributeValue) { SpatialDataSourceHandler handler = null; try { SpatialVectorTable table = sdbm.getVectorTableByName(layer); handler = sdbm.getSpatialDataSourceHandler(table); if (handler != null && attributeValue != null) { Log.v("MARKER_SUBSTITUTION", "start getting Feature from the database"); Geometry geom = handler.getGeometryByAttribute("4326", table, attributeName, attributeValue, null, 1, true); GeoPoint gp = GeometryUtils.getGeoPointFromGeometry(layer, geom); if (gp != null) { Log.v("MARKER_SUBSTITUTION", "new Coordinates:" + gp.latitude + "," + gp.longitude); return gp; } else { Log.v("MARKER_SUBSTITUTION", "unable to retrive:" + attributeName + "->" + attributeValue); // TODO request download } } else { Log.e("MARKER_SUBSTITUTION", "error retriving table for layer:" + layer + ". The attribute value for search or the handler is null"); } } catch (jsqlite.Exception e) { Log.e("MARKER_SUBSTITUTION", "error retriving table for layer:" + layer + "error:" + e.getMessage()); } catch (ParseException e) { Log.e("MARKER_SUBSTITUTION", "error retriving geometry for layer:" + layer + "error:" + e.getMessage()); } return null; } /** * Iterates on the database to get the <GeoPoint> from the object that match * @param attributeName the column name * @param attributeValue the value that should match * @return a <GeoPoint> or null */ public static GeoPoint getGeopointFromLayer( String attributeName, String attributeValue) { List<SpatialVectorTable> tables; try{ tables= sdbm.getSpatialVectorTables(false); }catch(Exception e){ Log.v("DATABASE","unable to retrive table list from data source manager"); return null; } for (SpatialVectorTable t :tables){ GeoPoint p = getGeopointFromLayer(t.getName(),attributeName,attributeValue); if(p!=null){ return p; } } return null; } /** * Creates a <MSMMap> getting the whole database configuration. * This should be changed once the db are loaded as sources * @return MSMMap */ public static MSMMap mapFromDb(){ return mapFromDb(false); } /** * Creates a <MSMMap> getting the whole database configuration. * If vectorOnly is true, does not look for raster tables. * This should be changed once the db are loaded as sources * @return MSMMap */ public static MSMMap mapFromDb(boolean vectorOnly){ MSMMap m = new MSMMap(); try { List<ISpatialDatabaseHandler> handlers = SpatialDataSourceManager.getInstance().getSpatialDatabaseHandlers(); //SpatialDataSourceManager.getInstance().getSpatialVectorTables(true); for(ISpatialDatabaseHandler h : handlers){ // get Vector Layers List<SpatialVectorTable> tables = h.getSpatialVectorTables(true); SpatialiteSource s = null; //inspect and create the source if(tables.size()>0){ SpatialDataSourceHandler dsm = SpatialDataSourceManager.getInstance().getSpatialDataSourceHandler(tables.get(0)); if(dsm != null){ s = new SpatialiteSource(dsm); if(BuildConfig.DEBUG){ Log.v("SpatialiteDBload","Created SpatialiteSource from datasource"+s.getTitle()); } }else{ s = new SpatialiteSource(h); } }else{ s = new SpatialiteSource(h); } //add the source to the layers that has the same handler source for (SpatialVectorTable t : tables) { SpatialiteLayer l = new SpatialiteLayer(t); l.setSource(s); m.layers.add(l); } // Lookup for raster tables if(!vectorOnly ){ /* * Geopaparazzi throws jsqlite.Exception if it fails to find metadata */ try { // Get Raster Layers List<SpatialRasterTable> rasterTables = h.getSpatialRasterTables(true); MbTilesSource mbs = null; //inspect and create the source if(tables.size()>0){ ISpatialDatabaseHandler dsm = SpatialDataSourceManager.getInstance().getSpatialDataSourceHandler(rasterTables.get(0)); if(dsm != null){ mbs = new MbTilesSource(dsm); if(BuildConfig.DEBUG){ Log.v("SpatialiteDBload","Created MbTilesSource from datasource"+mbs.getTitle()); } }else{ mbs = new MbTilesSource(h); } }else{ mbs = new MbTilesSource(h); } //add the source to the layers that has the same handler source for (SpatialRasterTable t : rasterTables) { MbTilesLayer l = new MbTilesLayer(t); l.setSource(mbs); m.layers.add(l); } } catch (Exception e) { if(BuildConfig.DEBUG){ Log.e("Spatialite","error retrieving raster tables", e); } } catch (android.database.sqlite.SQLiteException sqe){ if(BuildConfig.DEBUG){ Log.e("SQLite",sqe.getMessage(), sqe); } } } } } catch (Exception e) { if(BuildConfig.DEBUG){ Log.e("Spatialite","error retrieving spatial tables", e); } return m; } return m; } }