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 @ 45008

History | View | Annotate | Download (16 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 org.cresques.cts.IProjection;
15
import org.gvsig.fmap.dal.DataTypes;
16
import org.gvsig.fmap.dal.exception.DataException;
17
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
18
import org.gvsig.fmap.dal.feature.EditableFeatureType;
19
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
20
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
21
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
22
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
23
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
24
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolver;
25
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
26
import org.gvsig.fmap.geom.Geometry;
27
import org.gvsig.fmap.geom.GeometryLocator;
28
import org.gvsig.fmap.geom.GeometryManager;
29
import org.gvsig.fmap.geom.type.GeometryType;
30
import org.gvsig.tools.ToolsLocator;
31
import org.gvsig.tools.dataTypes.DataType;
32

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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