Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.mdb / src / main / java / org / gvsig / fmap / dal / store / mdb / operations / MDBFetchFeatureTypeOperation.java @ 45154

History | View | Annotate | Download (16.1 KB)

1

    
2
package org.gvsig.fmap.dal.store.mdb.operations;
3

    
4
import java.sql.Connection;
5
import java.sql.DatabaseMetaData;
6
import java.sql.ResultSet;
7
import java.sql.ResultSetMetaData;
8
import java.sql.SQLException;
9
import java.sql.Statement;
10
import java.util.ArrayList;
11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.Objects;
15
import org.cresques.cts.IProjection;
16
import org.gvsig.fmap.dal.DataTypes;
17
import org.gvsig.fmap.dal.exception.DataException;
18
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
19
import org.gvsig.fmap.dal.feature.EditableFeatureType;
20
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
21
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
22
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
23
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
24
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
25
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolver;
26
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
27
import org.gvsig.fmap.geom.Geometry;
28
import org.gvsig.fmap.geom.GeometryLocator;
29
import org.gvsig.fmap.geom.GeometryManager;
30
import org.gvsig.fmap.geom.type.GeometryType;
31
import org.gvsig.tools.ToolsLocator;
32
import org.gvsig.tools.dataTypes.DataType;
33

    
34
@SuppressWarnings("UseSpecificCatch")
35
public class MDBFetchFeatureTypeOperation extends FetchFeatureTypeOperation {
36

    
37
    private static Map<String,GeometryType>mdbGeometryTypes = null;
38
    private Map<String,GeometryColumnInfo> geometry_column;
39
    
40
    private static class GeometryColumnInfo {
41
        
42
        public String columnName;
43
        public int geometryType;
44
        public String geometryTypeName;
45
        public int dimensions;
46
        public int srid;
47
        
48
        public GeometryColumnInfo(String columnName, int geometryType, String geometryTypeName, int dimensions, int srid) {
49
            this.columnName = columnName;
50
            this.geometryType = geometryType;
51
            this.geometryTypeName = geometryTypeName;
52
            this.dimensions = dimensions;
53
            this.srid = srid;
54
        }
55
    }
56
    
57
    
58
    public MDBFetchFeatureTypeOperation(
59
            JDBCHelper helper
60
        ) {
61
        super(helper);
62
    }
63

    
64
    private GeometryType getGT(
65
            GeometryManager manager, 
66
            int type, 
67
            int subtype
68
        ) {
69
        try {
70
            return manager.getGeometryType(type, subtype);
71
        } catch (Exception ex) {
72
            return null;
73
        }
74
    }
75
    
76
    public MDBFetchFeatureTypeOperation(
77
            JDBCHelper helper,
78
            EditableFeatureType featureType,
79
            TableReference table,
80
            List<String> primaryKeys,
81
            String defaultGeometryColumn,
82
            IProjection crs
83
        ) {
84
        super(helper, featureType, table, primaryKeys, defaultGeometryColumn, crs);
85
    }            
86

    
87
    private GeometryColumnInfo getGeometryColumnInfo(String name) {
88
        if( geometry_column==null ) {
89
            geometry_column = new HashMap<>();
90
            try {
91
                //
92
                // https://github.com/orbisgis/h2gis/wiki/1.-Spatial-data#geometry-columns-view
93
                //
94
                StringBuilder where = null;
95
                if( table.hasDatabase() ) {
96
                    if( where == null ) {
97
                        where = new StringBuilder();
98
                    } else {
99
                        where.append(" AND ");
100
                    }
101
                    where.append("UPPER(F_TABLE_CATALOG) = '");
102
                    where.append(table.getDatabase().toUpperCase());
103
                    where.append("'");
104
                }
105
                if( table.hasSchema()) {
106
                    if( where == null ) {
107
                        where = new StringBuilder();
108
                    } else {
109
                        where.append(" AND ");
110
                    }
111
                    where.append("UPPER(F_TABLE_SCHEMA) = '");
112
                    where.append(table.getSchema().toUpperCase());
113
                    where.append("'");
114
                }
115
                if( table.hasTable()) {
116
                    if( where == null ) {
117
                        where = new StringBuilder();
118
                    } else {
119
                        where.append(" AND ");
120
                    }
121
                    where.append("UPPER(F_TABLE_NAME) = '");
122
                    where.append(table.getTable().toUpperCase());
123
                    where.append("'");
124
                }            
125
                String sql = "SELECT F_GEOMETRY_COLUMN, GEOMETRY_TYPE, COORD_DIMENSION, SRID, TYPE FROM GEOMETRY_COLUMNS WHERE " + where;
126
                Statement st = this.getConnection().createStatement();
127
                ResultSet rs = JDBCUtils.executeQuery(st,sql);
128
                while( rs.next() ) {
129
                    geometry_column.put(
130
                        rs.getString("F_GEOMETRY_COLUMN"), 
131
                        new GeometryColumnInfo(
132
                            rs.getString("F_GEOMETRY_COLUMN"), 
133
                            rs.getInt("GEOMETRY_TYPE"), 
134
                            rs.getString("TYPE"), 
135
                            rs.getInt("COORD_DIMENSION"), 
136
                            rs.getInt("SRID")
137
                        )
138
                    );
139
                }
140
            } catch (SQLException | AccessResourceException ex) {
141
                LOGGER.warn("Can't read metadata from table '"+table+"'.",ex);
142
            }
143
        }
144
        return this.geometry_column.get(name);
145
    }
146
    
147
    @Override
148
    public void fetch(Connection conn) throws DataException {
149
        super.fetch(conn);
150
    }
151
        
152
    @Override
153
    protected void fetchGeometryTypeAndSRS(
154
            EditableFeatureAttributeDescriptor attr,
155
            ResultSetMetaData rsMetadata,
156
            int colIndex
157
        ) {
158
        try {
159
            if( attr.getType()==DataTypes.GEOMETRY ) {
160
                GeometryColumnInfo column_info = this.getGeometryColumnInfo(attr.getName());
161
                String type = "GEOMETRY";
162
                if( column_info!=null ) {
163
                    // H2GIS solo soporte 2D y 3D no soporta Ms
164
                    if( column_info.dimensions==3 ) {
165
                        type = column_info.geometryTypeName+"Z";
166
                    } else {
167
                        type = column_info.geometryTypeName;
168
                    }
169
                    SRSSolver solver = this.helper.getSRSSolver();
170
                    attr.setSRS(
171
                        solver.getProjection(getConnection(), column_info.srid)
172
                    );
173
                }
174
                GeometryType gt = getGeometryTypeFromMDBType(type);
175
                if( gt != null ) {
176
                    attr.setGeometryType(gt);
177
                }
178
            }
179
        } catch(Exception ex) {
180
            throw new RuntimeException("Can't fetch geometry type and SRS.", ex);
181
        }
182
    }
183

    
184
    private GeometryType getGeometryTypeFromMDBType(String typeName) {
185
        if( mdbGeometryTypes==null ) {
186
            //
187
            // https://github.com/orbisgis/h2gis/wiki/1.-Spatial-data#geometry-columns-view
188
            //
189
            GeometryManager manager = GeometryLocator.getGeometryManager();
190
            mdbGeometryTypes = new HashMap<>();
191
            mdbGeometryTypes.put("POINT", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D));
192
            mdbGeometryTypes.put("POINTZ", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D));
193
            
194
            mdbGeometryTypes.put("LINESTRING", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D));
195
            mdbGeometryTypes.put("LINESTRINGZ", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D));
196
            
197
            mdbGeometryTypes.put("POLYGON", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D));
198
            mdbGeometryTypes.put("POLYGONZ", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D));
199

    
200
            mdbGeometryTypes.put("MULTIPOINT", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D));
201
            mdbGeometryTypes.put("MULTIPOINTZ", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D));
202

    
203
            mdbGeometryTypes.put("MULTILINESTRING", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D));
204
            mdbGeometryTypes.put("MULTILINESTRINGZ", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D));
205

    
206
            mdbGeometryTypes.put("MULTIPOLYGON", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D));
207
            mdbGeometryTypes.put("MULTIPOLYGONZ", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D));
208

    
209
            mdbGeometryTypes.put("GEOMETRY", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D));
210
            mdbGeometryTypes.put("GEOMETRYZ", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D));
211

    
212
            mdbGeometryTypes.put("GEOMCOLLECTION", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D));
213
            mdbGeometryTypes.put("GEOMCOLLECTIONZ", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D));
214
        }
215
        return mdbGeometryTypes.get(typeName);
216
    }
217
    
218
    @Override
219
    protected List<String> getPrimaryKeysFromInformationSchema(Connection conn) throws SQLException {
220

    
221
//        String sql = getSQLToRetrievePrimaryKeysFromInformationSchema(conn.getMetaData());
222
        DatabaseMetaData metadata = conn.getMetaData();
223
       
224
        String tableName = table.getTable();
225
        
226
        ResultSet rs = metadata.getPrimaryKeys(null, null, tableName);
227
        List<String> pks = new ArrayList();
228
        
229
        try {
230
            while (rs.next()) {
231
                pks.add(rs.getString(1));
232
            }
233
            if (pks.isEmpty()) {
234
                return null;
235
            }
236
            return pks;
237

    
238
        } catch (Exception ex) {
239
            return pks;
240
            
241
        } finally {
242
            JDBCUtils.closeQuietly(rs);
243
        }
244
    }
245

    
246
    @Override
247
    public String getSQLToRetrievePrimaryKeysFromInformationSchema() throws SQLException {
248
        JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
249
//        ExpressionBuilder expbuilder = sqlbuilder.expression();
250
//
251
//        sqlbuilder.select().column().name("COLUMN_LIST");
252
//        sqlbuilder.select().column().name("CONSTRAINT_TYPE");
253
//        sqlbuilder.select().from().table().schema("INFORMATION_SCHEMA").name("CONSTRAINTS");
254
//        sqlbuilder.select().where().set(
255
//                expbuilder.like(
256
//                        expbuilder.column("TABLE_NAME"), 
257
//                        expbuilder.constant(table.getTable())
258
//                )
259
//        );
260
//        if( table.hasSchema() ) {
261
//            sqlbuilder.select().where().and(
262
//                    expbuilder.like(
263
//                            expbuilder.column("TABLE_SCHEMA"),
264
//                            expbuilder.constant(table.getSchema())
265
//                    )
266
//            );
267
//        }
268
////        if (catalog != null) {
269
////            sqlbuilder.select().where().and(
270
////                    expbuilder.like(
271
////                            expbuilder.column("CONSTRAINT_CATALOG"),
272
////                            expbuilder.constant(catalog)
273
////                    )
274
////            );
275
////        }
276
//        sqlbuilder.select().where().and(
277
//                expbuilder.eq(
278
//                        expbuilder.column("CONSTRAINT_TYPE"),
279
//                        expbuilder.constant("PRIMARY KEY")
280
//                )
281
//        );
282
        return sqlbuilder.toString();
283
    }
284
    
285
    protected EditableFeatureAttributeDescriptor getAttributeFromMetadata(
286
            EditableFeatureType type,
287
            Connection conn,
288
            ResultSetMetaData rsMetadata,
289
            int colIndex
290
        ) throws SQLException {
291
        int dataType = this.getDataTypeFromMetadata(rsMetadata, colIndex);
292
        if (dataType == DataTypes.DECIMAL &&
293
                rsMetadata.getPrecision(colIndex)==19 &&
294
                rsMetadata.getScale(colIndex)== 0) {
295
            dataType = DataTypes.LONG;
296
        }
297

    
298
        EditableFeatureAttributeDescriptor attr = type.add(
299
                rsMetadata.getColumnName(colIndex),
300
                dataType
301
        );
302
        attr.setAllowNull(
303
            rsMetadata.isNullable(colIndex) == ResultSetMetaData.columnNullable
304
        );
305
        attr.setIsAutomatic(rsMetadata.isAutoIncrement(colIndex));
306
        attr.setIsReadOnly(rsMetadata.isReadOnly(colIndex));
307
        switch(attr.getType()) {
308
            case DataTypes.BOOLEAN:
309
              attr.setAllowNull(false);
310
              break;
311
            case DataTypes.STRING:
312
              DataType myDataType = null;
313
                try {
314
                    myDataType = ToolsLocator.getDataTypesManager().get(DataTypes.STRING).clone();
315
                } catch (CloneNotSupportedException ex) {
316
                    throw new RuntimeException(ex);
317
                }
318
              myDataType.addCoercion(new CoercionGeometryToString());
319
              attr.setDataType(myDataType);
320
              attr.setSize(rsMetadata.getPrecision(colIndex));
321
              attr.setPrecision(DataType.PRECISION_NONE);
322
              attr.setScale(DataType.SCALE_NONE);
323
              break;
324

    
325
            case DataTypes.BYTE:
326
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
327
              attr.setPrecision(DataType.BYTE_DEFAULT_PRECISION);
328
              attr.setScale(DataType.SCALE_NONE);
329
              break;
330
            case DataTypes.INT:
331
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
332
              attr.setPrecision(DataType.INT_DEFAULT_PRECISION);
333
              attr.setScale(DataType.SCALE_NONE);
334
              break;
335
            case DataTypes.LONG:
336
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
337
              attr.setPrecision(DataType.LONG_DEFAULT_PRECISION);
338
              attr.setScale(DataType.SCALE_NONE);
339
              break;
340
            case DataTypes.FLOAT:
341
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
342
              attr.setPrecision(DataType.FLOAT_DEFAULT_PRECISION);
343
              attr.setScale(DataType.SCALE_NONE);
344
              break;
345
            case DataTypes.DOUBLE:
346
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
347
              attr.setPrecision(DataType.DOUBLE_DEFAULT_PRECISION);
348
              attr.setScale(DataType.SCALE_NONE);
349
              break;
350
            case DataTypes.DECIMAL:
351
              attr.setDisplaySize(rsMetadata.getColumnDisplaySize(colIndex));
352
              attr.setScale(rsMetadata.getScale(colIndex));
353
              attr.setPrecision(rsMetadata.getPrecision(colIndex));
354
              break;
355
            case DataTypes.OBJECT:
356
                attr.setAdditionalInfo(
357
                        "SQLType",
358
                        Objects.toString(rsMetadata.getColumnType(colIndex),null)
359
                );
360
                attr.setAdditionalInfo(
361
                        "SQLTypeName",
362
                        rsMetadata.getColumnTypeName(colIndex)
363
                );
364
                break;
365
            case DataTypes.GEOMETRY:
366
                this.fetchGeometryTypeAndSRS(attr, rsMetadata, colIndex);
367
                break;
368
        }
369
        return attr;
370
    }
371
    
372
    @Override
373
       protected int getDataTypeFromMetadata(
374
            ResultSetMetaData rsMetadata,
375
            int colIndex
376
        ) throws SQLException {
377

    
378
        switch (rsMetadata.getColumnType(colIndex)) {
379
            case java.sql.Types.CLOB:
380
                return DataTypes.STRING;
381
            case java.sql.Types.NUMERIC:
382
            case java.sql.Types.DECIMAL:
383
                if (rsMetadata.getPrecision(colIndex)==19 && rsMetadata.getScale(colIndex)== 0) {
384
                   return DataTypes.LONG;
385
                }
386
                return DataTypes.DECIMAL;
387
        }
388
        return super.getDataTypeFromMetadata(rsMetadata, colIndex);
389
    }
390
}