Statistics
| Revision:

gvsig-oracle / org.gvsig.oracle / trunk / org.gvsig.oracle / org.gvsig.oracle.provider / src / main / java / org / gvsig / oracle / dal / operations / OracleFetchFeatureTypeOperation.java @ 64

History | View | Annotate | Download (11 KB)

1

    
2
package org.gvsig.oracle.dal.operations;
3

    
4
import java.sql.Connection;
5
import java.sql.ResultSet;
6
import java.sql.ResultSetMetaData;
7
import java.sql.SQLException;
8
import java.sql.Statement;
9
import java.util.ArrayList;
10
import java.util.HashMap;
11
import java.util.List;
12
import java.util.Map;
13

    
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.feature.spi.ExpressionBuilderBase;
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.spi.JDBCSQLBuilderBase;
23
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
24
import org.gvsig.fmap.geom.Geometry;
25
import org.gvsig.fmap.geom.GeometryLocator;
26
import org.gvsig.fmap.geom.GeometryManager;
27
import org.gvsig.fmap.geom.type.GeometryType;
28

    
29
public class OracleFetchFeatureTypeOperation extends FetchFeatureTypeOperation {
30

    
31
    private static Map<String,GeometryType>databaseGeometryTypes = null;
32
    private static Map<Integer,GeometryType>databaseGeometryTypeNumbers = null;
33
    
34
    private static final int UNKNOWN_GEOMETRY = 0;
35
    private static final int POINT = 1;
36
    private static final int LINE_OR_CURVE = 2;
37
    private static final int POLYGON = 3;
38
    private static final int COLLECTION = 4;
39
    private static final int MULTIPOINT = 5;
40
    private static final int MULTILINE_OR_MULTICURVE = 6;
41
    private static final int MULTIPOLYGON = 7;
42
    
43
    public OracleFetchFeatureTypeOperation(
44
            JDBCHelper helper
45
        ) {
46
        super(helper);
47
    }
48

    
49
    private GeometryType getGT(
50
            GeometryManager manager, 
51
            int type, 
52
            int subtype
53
        ) {
54
        try {
55
            return manager.getGeometryType(type, subtype);
56
        } catch (Exception ex) {
57
            return null;
58
        }
59
    }
60
    
61
    public OracleFetchFeatureTypeOperation(
62
            JDBCHelper helper,
63
            EditableFeatureType featureType,
64
            String dbname,
65
            String schema,
66
            String table,
67
            List<String> primaryKeys,
68
            String defaultGeometryColumn,
69
            IProjection crs
70
        ) {
71
        super(helper, featureType, dbname, schema, table, primaryKeys, defaultGeometryColumn, crs);
72
    }            
73

    
74
    @Override
75
    public void fetch(EditableFeatureType featureType, Connection conn, String dbname, String schema, String table, List<String> pks, String defaultGeometryColumn, IProjection crs) throws DataException {
76
        super.fetch(featureType, conn, dbname, schema, table, pks, defaultGeometryColumn, crs);
77
    }
78

    
79
    @Override
80
    protected int getDataTypeFromMetadata(
81
            ResultSetMetaData rsMetadata,
82
            int colIndex
83
        ) throws SQLException {
84
            int type = rsMetadata.getColumnType(colIndex);
85
            if (type>=2000 && type<=4449) {
86
                    return DataTypes.GEOMETRY;
87
            }
88
            String typeName = rsMetadata.getColumnTypeName(colIndex);
89
        if( "MDSYS.SDO_GEOMETRY".equalsIgnoreCase(typeName) ) {
90
            return DataTypes.GEOMETRY;
91
        }
92
        return super.getDataTypeFromMetadata(rsMetadata, colIndex);
93
    }
94

    
95
        
96
    @Override
97
    protected void fetchGeometryTypeAndSRS(
98
            EditableFeatureAttributeDescriptor attr,
99
            ResultSetMetaData rsMetadata,
100
            int colIndex
101
        ) {
102
        if( attr.getType()!=DataTypes.GEOMETRY ) {
103
            return;
104
        }
105
        try {
106
                /**
107
                 * Directly querying the table to get the geometry type and srid.
108
                 * This will perform a full scan on the table :-(
109
                 * 
110
                 * We can also get the SRID and number of dimensions from 
111
                 * MDSYS.USER_SDO_GEOM_METADATA or MDSYS.SDO_GEOM_METADATA_TABLE,
112
                 * but we can't get the geometry type (point, line, etc) from there.
113
                 */
114
            JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
115
            ;
116
            sqlbuilder.select().distinct();
117
            
118
            sqlbuilder.select().column().value(sqlbuilder.function("SDO_GTYPE", "({0}).SDO_GTYPE", sqlbuilder.variable(attr.getName())));
119
            sqlbuilder.select().column().value(sqlbuilder.ST_SRID(sqlbuilder.variable(attr.getName())));
120
            sqlbuilder.select().from().table().schema(this.getSchema());
121
            sqlbuilder.select().from().table().name(this.getTablename());
122

    
123
            Statement st = null;
124
            ResultSet rs = null;
125
            
126
            ArrayList<Integer> sridList = new ArrayList<Integer>();
127
            ArrayList<Integer> geometryCodeList = new ArrayList<Integer>();
128
            try {
129
                st = this.getConnection().createStatement();
130
                rs = JDBCUtils.executeQuery(st, sqlbuilder.toString());
131
                while (rs.next()) {
132
                        geometryCodeList.add(rs.getInt(1));
133
                        sridList.add(rs.getInt(2));
134
                }
135
            } finally {
136
                JDBCUtils.closeQuietly(rs);
137
                JDBCUtils.closeQuietly(st);
138
            }
139
            try {
140
                    if( sridList.size()==1 ) {
141
                        attr.setSRS(this.helper.getProjectionFromDatabaseCode(sridList.get(0).toString()));
142
                    }
143
                    else if (sridList.size()>1)  {
144
                            logger.error("More than one CRS detected on the layer: "+sridList.toString()+". Some geometries will be incorrectly handled.");
145
                    }
146
            } catch (Exception ex) {
147
                logger.debug("Can't get srs from column '"+attr.getName()+"'.",ex);
148
            }
149
            if( geometryCodeList.size() == 1 ) {
150
                GeometryType gt = getGeometryTypeFromDatabaseTypeNumber(geometryCodeList.get(0));
151
                attr.setGeometryType(gt);
152
            }
153
            return;
154
        } catch (Exception ex) {
155
            logger.debug("Can't get geometry type and srs from column '"+attr.getName()+"'.",ex);
156
        }
157
        attr.setGeometryType(getGeometryTypeFromDatabaseTypeName("GEOMETRY"));
158
    }
159

    
160
    private GeometryType getGeometryTypeFromDatabaseTypeName(String typeName) {
161
        if( databaseGeometryTypes==null ) {
162
            GeometryManager manager = GeometryLocator.getGeometryManager();
163
            databaseGeometryTypes = new HashMap<>();
164
            databaseGeometryTypes.put("POINT", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2D));
165
            databaseGeometryTypes.put("POINTZ", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3D));
166
            databaseGeometryTypes.put("POINTM", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM2DM));
167
            databaseGeometryTypes.put("POINTZM", getGT(manager, Geometry.TYPES.POINT,Geometry.SUBTYPES.GEOM3DM));
168
            
169
            databaseGeometryTypes.put("LINESTRING", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2D));
170
            databaseGeometryTypes.put("LINESTRINGZ", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3D));
171
            databaseGeometryTypes.put("LINESTRINGM", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM2DM));
172
            databaseGeometryTypes.put("LINESTRINGZM", getGT(manager, Geometry.TYPES.LINE,Geometry.SUBTYPES.GEOM3DM));
173
            
174
            databaseGeometryTypes.put("POLYGON", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2D));
175
            databaseGeometryTypes.put("POLYGONZ", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3D));
176
            databaseGeometryTypes.put("POLYGONM", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM2DM));
177
            databaseGeometryTypes.put("POLYGONZM", getGT(manager, Geometry.TYPES.POLYGON,Geometry.SUBTYPES.GEOM3DM));
178

    
179
            databaseGeometryTypes.put("MULTIPOINT", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2D));
180
            databaseGeometryTypes.put("MULTIPOINTZ", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3D));
181
            databaseGeometryTypes.put("MULTIPOINTM", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM2DM));
182
            databaseGeometryTypes.put("MULTIPOINTZM", getGT(manager, Geometry.TYPES.MULTIPOINT,Geometry.SUBTYPES.GEOM3DM));
183

    
184
            databaseGeometryTypes.put("MULTILINESTRING", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2D));
185
            databaseGeometryTypes.put("MULTILINESTRINGZ", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3D));
186
            databaseGeometryTypes.put("MULTILINESTRINGM", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM2DM));
187
            databaseGeometryTypes.put("MULTILINESTRINGZM", getGT(manager, Geometry.TYPES.MULTILINE,Geometry.SUBTYPES.GEOM3DM));
188

    
189
            databaseGeometryTypes.put("MULTIPOLYGON", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2D));
190
            databaseGeometryTypes.put("MULTIPOLYGONZ", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3D));
191
            databaseGeometryTypes.put("MULTIPOLYGONM", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM2DM));
192
            databaseGeometryTypes.put("MULTIPOLYGONZM", getGT(manager, Geometry.TYPES.MULTIPOLYGON,Geometry.SUBTYPES.GEOM3DM));
193

    
194
            databaseGeometryTypes.put("GEOMETRY", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2D));
195
            databaseGeometryTypes.put("GEOMETRYZ", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3D));
196
            databaseGeometryTypes.put("GEOMETRYM", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM2DM));
197
            databaseGeometryTypes.put("GEOMETRYZM", getGT(manager, Geometry.TYPES.GEOMETRY,Geometry.SUBTYPES.GEOM3DM));
198
        }
199
        return databaseGeometryTypes.get(typeName);
200
    }
201

    
202
    private GeometryType getGeometryTypeFromDatabaseTypeNumber(int typeCode) {
203
            int dimensions = typeCode/1000;
204
            int typeCodeRemainder = typeCode - 1000*dimensions;
205
            int mDimPos = typeCodeRemainder/100;
206
            int geomType = typeCodeRemainder - 100*mDimPos;
207
            
208
            String baseType;
209
            switch(geomType) {
210
            case POINT:
211
                    baseType = "POINT";
212
                    break;
213
            case LINE_OR_CURVE:
214
                    baseType = "LINESTRING";
215
                    break;
216
            case POLYGON:
217
                    baseType = "POLYGON";
218
                    break;
219
            case MULTIPOINT:
220
                    baseType = "MULTIPOINT";
221
                    break;
222
            case MULTILINE_OR_MULTICURVE:
223
                    baseType = "MULTILINESTRING";
224
                    break;
225
            case MULTIPOLYGON:
226
                    baseType = "MULTIPOLYGON";
227
                    break;
228
            default:
229
                    baseType = "GEOMETRY";
230
                    break;
231
            }
232
                if (dimensions==3) {
233
                        if (mDimPos>0) {
234
                                return getGeometryTypeFromDatabaseTypeName(baseType+"M");
235
                        }
236
                        return getGeometryTypeFromDatabaseTypeName(baseType+"Z");
237
                }
238
                if (dimensions==4) {
239
                        return getGeometryTypeFromDatabaseTypeName(baseType+"ZM");
240
                        
241
                }
242
                return getGeometryTypeFromDatabaseTypeName(baseType);
243

    
244
    }
245

    
246
}