/* * Geopaparazzi - Digital field mapping on Android based devices * Copyright (C) 2010 HydroloGIS (www.hydrologis.com) * * 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 eu.geopaparazzi.spatialite.database.spatial.core.tables; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import eu.geopaparazzi.library.util.types.EDataType; import eu.geopaparazzi.spatialite.database.spatial.core.enums.GeometryType; import eu.geopaparazzi.library.util.types.ESpatialDataSources; import eu.geopaparazzi.spatialite.database.spatial.core.enums.TableTypes; import eu.geopaparazzi.library.style.Style; import static eu.geopaparazzi.spatialite.database.spatial.util.SpatialiteUtilities.UNIQUENAME_SEPARATOR; // https://www.gaia-gis.it/fossil/libspatialite/wiki?name=metadata-4.0 /** * A vector table from the spatial db. * * @author Andrea Antonello (www.hydrologis.com) */ @SuppressWarnings("nls") public class SpatialVectorTable extends AbstractSpatialTable implements Serializable { private static final long serialVersionUID = 1L; private final String geometryColumn; private final int geomType; private Style style; private boolean checkDone = false; private boolean isPolygon = false; private boolean isLine = false; private boolean isPoint = false; private boolean isGeometryCollection = false; /** * {@link HashMap} of all fields of this table [name,type] */ private HashMap<String, String> fieldName2TypeMap = null; /** * {@link HashMap} of non-geometry fields [name,type] */ private HashMap<String, String> fields_list_non_vector = null; // only non-geometry fields [name] private List<String> labelList = null; // Table field to be used as a label private String labelField = ""; // list of possible primary keys - for more that one: seperated with ';' private String primaryKeyFields = ""; // AbstractSpatialTable=always ROWID ; SpatialView: can also be ROWID - but something else private String ROWID_PK = "ROWID"; private boolean isReadonly = false; private String uniqueNameBasedOnDbFilePath = ""; /** * Constructor. * * @param databasePath the database file the table belongs to. * @param tableName the name of the table to use. * @param geometryColumn the name of the geometry column. * @param geomType the geometry type as off {@link GeometryType}. * @param srid the srid code. * @param center the wgs84 center coordinates. * @param bounds the table bounds in wgs84. * @param tableTypeDescription the table type description. */ public SpatialVectorTable(String databasePath, String tableName, String geometryColumn, int geomType, String srid, double[] center, double[] bounds, String tableTypeDescription) { super(databasePath, tableName, ESpatialDataSources.SQLITE.getTypeName(), srid, 0, 22, center[0], center[1], bounds); this.geometryColumn = geometryColumn; this.geomType = geomType; this.tableTypeDescription = tableTypeDescription; if (this.tableTypeDescription.equals(TableTypes.SPATIALVIEW.getDescription())) { isView = true; } createUniqueNames(); checkType(); } /** * Create a unique names for the table based on db path/name, table and geometry. */ private void createUniqueNames() { uniqueNameBasedOnDbFilePath = databasePath + UNIQUENAME_SEPARATOR + tableName + UNIQUENAME_SEPARATOR + geometryColumn; } @Override public String toString() { return "SpatialVectorTable{" + "\n\tgeometryColumn='" + geometryColumn + '\'' + ",\n\tgeomType=" + geomType + ",\n\tstyle=" + style + ",\n\tisPolygon=" + isPolygon + ",\n\tisLine=" + isLine + ",\n\tisPoint=" + isPoint + ",\n\tisGeometryCollection=" + isGeometryCollection + ",\n\tlabelField='" + labelField + '\'' + ",\n\tprimaryKeyFields='" + primaryKeyFields + '\'' + ",\n\tROWID_PK='" + ROWID_PK + '\'' + ",\n\tisReadonly=" + isReadonly + ",\n\tuniqueNameBasedOnDbFilePath='" + uniqueNameBasedOnDbFilePath + '\'' + "\n}"; } /** * Returns the layer's table tye as of TableTypes. * * @return the tableTypeDescription */ public String getTableTypeDescription() { return this.tableTypeDescription; } /** * @return the geometry column name. */ public String getGeomName() { return geometryColumn; } /** * Unique name for the spatial table. * * @return the unique name. */ public String getUniqueNameBasedOnDbFilePath() { return uniqueNameBasedOnDbFilePath; } /** * @return the geometry type. */ public int getGeomType() { return geomType; } /** * Defines if the layer is enabled. * * @return 1 is enabled. */ public int isTableEnabled() { return style.enabled; } /** * Getter for the style. * * @return the style of this table. */ public Style getStyle() { return style; } /** * Returns a list of non-geometry fields of this table. * * @return list of field names. */ public List<String> getTableFieldNamesList() { return labelList; } /** * Get the data type for a given field name. * * @param fieldName the field name. * @return the {@link EDataType} or <code>null</code>. */ public EDataType getTableFieldType(String fieldName) { String type = fieldName2TypeMap.get(fieldName); // 1;Data-TypeTEXT || DOUBLE || INTEGER || REAL || DATE || BLOB || if (type != null) { type = type.toUpperCase(Locale.US); if (type.contains("TEXT") || type.contains("CHAR")) { return EDataType.TEXT; } else if (type.contains("DOUBLE")) { return EDataType.DOUBLE; } else if (type.contains("INTEGER")) { return EDataType.INTEGER; } else if (type.contains("REAL")) { return EDataType.DOUBLE; } else if (type.contains("DATE")) { return EDataType.DATE; } else if (type.contains("BLOB")) { return EDataType.BLOB; } else if (type.contains("FLOAT")) { return EDataType.FLOAT; } } return null; } /** * Returns Primary Key Fields * <p/> * <p>- separated with ';' when more than one * * @return primary key fields. */ public String getPrimaryKeyFields() { return primaryKeyFields; } /** * Returns Primary Key Field or ROWID for tables * <p/> * <p>- used in SpatialiteUtilities.buildGeometriesInBoundsQuery * * @return primary key field used as ROWID. */ public String getROWID() { return ROWID_PK; } /** * Returns selected label field of this table * <p/> * <p>- to help retrieve the value for a label * * @return the label field. */ public String getLabelField() { return labelField; } /** * Set selected label field of this table * <p/> * <p>- as a result of a ComboBox selection * <p>- to help retrieve the value for a label * * @param labelField the labe field to use. */ public void setLabelField(String labelField) { this.labelField = labelField; } /** * Set Fields map of table * <p/> * <ul> * <li>- a second fields list will be created from non-vector Fields * <li>-- fields_list_non_vector [with name,type] * <li>-- label_list [with name] * <li>- sets selected field from fir charater field * <li>-- if none are found, first field * </ul> * * @param fieldName2TypeMap the fields map to set. * @param s_ROWID_PK the field to replace the default ROWID when SpatialView. */ public void setFieldsList(HashMap<String, String> fieldName2TypeMap, String s_ROWID_PK, int i_view_read_only) { this.fieldName2TypeMap = fieldName2TypeMap; labelField = ""; String s_label_field_alt = ""; if (labelList != null) { labelList.clear(); } else { labelList = new ArrayList<String>(); } if (fields_list_non_vector != null) { fields_list_non_vector.clear(); } else { fields_list_non_vector = new LinkedHashMap<String, String>(); } if (this.fieldName2TypeMap != null) { for (Map.Entry<String, String> fieldList : this.fieldName2TypeMap.entrySet()) { String s_field_name = fieldList.getKey(); // pk: 0 || 1;Data-TypeTEXT || DOUBLE || INTEGER || REAL || DATE || BLOB || // geometry-types // field is a primary-key = '1;Data-Type' // field is NOT a primary-key = '0;Data-Type' String s_field_type = fieldList.getValue(); // GPLog.androidLog(-1,"SpatialVectorTable.setFieldsList["+getName()+"] field_name["+s_field_name+"] field_type["+s_field_type+"]"); if ((!s_field_type.contains("BLOB")) && (!s_field_type.contains("POINT")) && (!s_field_type.contains("LINESTRING")) && (!s_field_type.contains("POLYGON")) && (!s_field_type.contains("GEOMETRYCOLLECTION"))) { fields_list_non_vector.put(s_field_name, s_field_type); labelList.add(s_field_name); if (s_label_field_alt.equals("")) { s_label_field_alt = s_field_name; } // s_primary_key_fields if (s_field_type.contains("1;")) { // list of possible primary keys - for // more that one: seperated with ';' if (!primaryKeyFields.equals("")) primaryKeyFields += ";"; primaryKeyFields += s_field_name; } if ((s_field_type.contains("TEXT")) && (labelField.equals(""))) { // set a charater field as default labelField = s_field_name; } } } if (labelField.equals("")) { // if no charater field was found, set first field as default labelField = s_label_field_alt; } setLabelField(labelField); // GPLog.androidLog(-1,"SpatialVectorTable.setFieldsList["+getName()+"] label_list["+label_list.size()+"] fields_list_non_vector["+fields_list_non_vector.size()+"] fields_list["+this.fields_list.size()+"] selected_name["+s_label_field+"] field_type["+s_primary_key_fields+"]"); } if ((i_view_read_only == 0) || (i_view_read_only == 1)) isReadonly = true; if ((!s_ROWID_PK.equals("")) && (!s_ROWID_PK.contains("ROWID"))) { ROWID_PK = s_ROWID_PK; } } /** * @param style the style to use. */ public void setStyle(Style style) { this.style = style; maxZoom = style.maxZoom; minZoom = style.minZoom; } /** * @return <code>true</code> if it is polygon or multipolygon. */ public boolean isPolygon() { return isPolygon; } /** * @return <code>true</code> if it is line or multiline. */ public boolean isLine() { return isLine; } /** * @return <code>true</code> if it is point or multipoint. */ public boolean isPoint() { return isPoint; } /** * @return <code>true</code> if it is a geometrycollection. */ public boolean isGeometryCollection() { return isGeometryCollection; } private void checkType() { if (checkDone) { return; } GeometryType TYPE = GeometryType.forValue(geomType); switch (TYPE) { case POLYGON_XY: case POLYGON_XYM: case POLYGON_XYZ: case POLYGON_XYZM: case MULTIPOLYGON_XY: case MULTIPOLYGON_XYM: case MULTIPOLYGON_XYZ: case MULTIPOLYGON_XYZM: isPolygon = true; break; case POINT_XY: case POINT_XYM: case POINT_XYZ: case POINT_XYZM: case MULTIPOINT_XY: case MULTIPOINT_XYM: case MULTIPOINT_XYZ: case MULTIPOINT_XYZM: isPoint = true; break; case LINESTRING_XY: case LINESTRING_XYM: case LINESTRING_XYZ: case LINESTRING_XYZM: case MULTILINESTRING_XY: case MULTILINESTRING_XYM: case MULTILINESTRING_XYZ: case MULTILINESTRING_XYZM: isLine = true; break; case GEOMETRYCOLLECTION_XY: case GEOMETRYCOLLECTION_XYM: case GEOMETRYCOLLECTION_XYZ: case GEOMETRYCOLLECTION_XYZM: isGeometryCollection = true; break; default: throw new IllegalArgumentException("No geom type for: " + TYPE + " isGeometryCollection[" + isGeometryCollection + "]"); } checkDone = true; } /** * Create a default style. */ public void makeDefaultStyle() { style = new Style(); style.name = getUniqueNameBasedOnDbFilePath(); } @Override public double[] longLat2Srid(double lon, double lat) { throw new RuntimeException("Not implemented yet"); } @Override public boolean isEditable() { return !isReadonly; } }